@event4u/agent-config 14.17.0 → 14.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.augment-plugin/marketplace.json +3 -3
- package/.augment-plugin/plugin.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +207 -77
- package/README.md +72 -150
- package/dist/agent-src/README.md +1 -1
- package/dist/agent-src/commands/agent-handoff.md +2 -2
- package/dist/agent-src/commands/pr/merge.md +35 -44
- package/dist/agent-src/commands/review/changes.md +19 -19
- package/dist/agent-src/commands/review.md +2 -2
- package/dist/agent-src/contexts/execution/host-capability-manifest.md +30 -3
- package/dist/agent-src/rules/autonomous-execution.md +1 -1
- package/dist/agent-src/rules/git-history-discipline.md +2 -2
- package/dist/agent-src/rules/guidelines.md +1 -1
- package/dist/agent-src/rules/session-canary.md +2 -2
- package/dist/agent-src/rules/token-efficiency.md +1 -1
- package/dist/agent-src/skills/accessibility-auditor/SKILL.md +2 -0
- package/dist/agent-src/skills/adversarial-review/SKILL.md +0 -8
- package/dist/agent-src/skills/ai-code-blindspots/SKILL.md +27 -1
- package/dist/agent-src/skills/canvas-design/SKILL.md +1 -1
- package/dist/agent-src/skills/code-intelligence/SKILL.md +60 -12
- package/dist/agent-src/skills/complexity-first-planning/SKILL.md +27 -0
- package/dist/agent-src/skills/design-intelligence/SKILL.md +1 -1
- package/dist/agent-src/skills/design-intelligence/data/app-interface.csv +1 -1
- package/dist/agent-src/skills/design-intelligence/data/motion.csv +17 -17
- package/dist/agent-src/skills/design-intelligence/data/ux-guidelines.csv +2 -2
- package/dist/agent-src/skills/design-intelligence/references/context-and-registers.md +17 -0
- package/dist/agent-src/skills/design-intelligence/references/design-rules-checklist.md +4 -4
- package/dist/agent-src/skills/design-review/SKILL.md +3 -1
- package/dist/agent-src/skills/design-variations/SKILL.md +1 -1
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +1 -1
- package/dist/agent-src/skills/fe-design/SKILL.md +32 -5
- package/dist/agent-src/skills/fe-design/references/craft-floor.md +7 -0
- package/dist/agent-src/skills/fe-design/references/design-patterns.md +47 -2
- package/dist/agent-src/skills/feature-planning/SKILL.md +34 -0
- package/dist/agent-src/skills/git-workflow/SKILL.md +37 -12
- package/dist/agent-src/skills/git-workflow/references/push-closes-its-loop.md +176 -0
- package/dist/agent-src/skills/laravel-mail/SKILL.md +44 -0
- package/dist/agent-src/skills/laravel-scheduling/SKILL.md +3 -1
- package/dist/agent-src/skills/project-analyzer/SKILL.md +0 -6
- package/dist/agent-src/skills/react-native-setup/SKILL.md +3 -3
- package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +1 -1
- package/dist/agent-src/skills/sequential-thinking/SKILL.md +18 -8
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +1 -1
- package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +40 -0
- package/dist/agent-src/skills/ui-apply-generic/SKILL.md +1 -1
- package/dist/agent-src/skills/ui-component-architect/SKILL.md +1 -1
- package/dist/agent-src/skills/using-git-worktrees/SKILL.md +29 -2
- package/dist/agent-src/skills/verify-repair-loop/SKILL.md +53 -8
- package/dist/agent-src/skills/worktree-lifecycle/SKILL.md +3 -1
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/cli/commands/recordTriggerEval.js +2 -2
- package/dist/cli/main.js +1 -1
- package/dist/cli-delegate/{chunk-AKJGUQNO.js → chunk-GZTMRYCN.js} +405 -341
- package/dist/cli-delegate/{chunk-7RXIKF62.js → chunk-IDHUQIXP.js} +283 -132
- package/dist/cli-delegate/cmd_adr_effective.js +318 -81
- package/dist/cli-delegate/cmd_conformance.js +749 -669
- package/dist/cli-delegate/cmd_doctor.js +1 -1
- package/dist/cli-delegate/cmd_export.js +1 -1
- package/dist/cli-delegate/cmd_handoff.js +1 -1
- package/dist/cli-delegate/cmd_prune.js +1 -1
- package/dist/cli-delegate/cmd_route_audit.js +1 -1
- package/dist/cli-delegate/cmd_settings_migrate.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +1 -1
- package/dist/cli-delegate/cmd_uninstall.js +1 -1
- package/dist/cli-delegate/cmd_validate.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +39 -38
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +1 -1
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +2 -2
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +2 -2
- package/dist/hooks/dispatch.js +2764 -2439
- package/dist/install/install.mjs +588 -527
- package/dist/mcp/registry-manifest.json +2 -2
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +1381 -1138
- package/dist/scripts/_lib/model_tier.js +1 -1
- package/dist/shared/settingsConsent.js +1 -1
- package/docs/guidelines/agent-infra/evaluator-independence-mechanics.md +1 -1
- package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
- package/docs/guidelines/design-antipatterns.md +87 -64
- package/package.json +1 -1
- package/src/agent-src/README.md +1 -1
- package/src/config/ci-local-parity.yml +6 -0
- package/src/config/conformance-claim-baseline.json +9 -0
- package/src/config/gate-coverage.yml +170 -0
- package/src/config/gate-violation-baselines.json +4 -4
- package/src/config/release-gate-locality.yml +141 -0
- package/src/scripts/_cli/cmd_doctor.ts +2 -2
- package/src/scripts/_cli/cmd_handoff.ts +1 -1
- package/src/scripts/_cli/cmd_update.ts +1 -1
- package/src/scripts/_cli/cmd_versions.ts +1 -1
- package/src/scripts/_lib/adr_frontmatter.ts +44 -0
- package/src/scripts/_lib/consequence_objects.ts +152 -0
- package/src/scripts/_lib/exec_evidence.ts +7 -0
- package/src/scripts/_lib/global_deploy_inventory.ts +2 -2
- package/src/scripts/_lib/host_permission_checks.ts +251 -0
- package/src/scripts/_lib/model_tier.ts +1 -1
- package/src/scripts/_lib/obligation_frequency.ts +2 -2
- package/src/scripts/_lib/release_highlights.ts +265 -1
- package/src/scripts/_lib/release_material.ts +129 -0
- package/src/scripts/_lib/repeated_run.ts +77 -0
- package/src/scripts/_lib/runtime_journal.ts +26 -3
- package/src/scripts/_lib/runtime_wiring_checks.ts +12 -1
- package/src/scripts/_lib/session_register.ts +11 -6
- package/src/scripts/_lib/sqlite_schema.ts +22 -0
- package/src/scripts/_lib/surface.ts +86 -0
- package/src/scripts/_lib/tamper_vocabulary.ts +242 -0
- package/src/scripts/_lib/ui_authority.ts +116 -0
- package/src/scripts/_lib/unified_diff.ts +121 -0
- package/src/scripts/adr/regenerate_index.ts +54 -1
- package/src/scripts/adr_cite_check.ts +71 -15
- package/src/scripts/ai_council/clients.ts +1 -1
- package/src/scripts/autonomy_friction_corpus.ts +229 -0
- package/src/scripts/build_proof.ts +15 -2
- package/src/scripts/check_beta_review_markers.ts +141 -17
- package/src/scripts/check_enforcement_coverage.ts +1 -1
- package/src/scripts/check_enforcement_denominator.ts +121 -11
- package/src/scripts/check_finding_dispositions.ts +239 -6
- package/src/scripts/check_gate_coverage.ts +96 -0
- package/src/scripts/check_installed_hooks_fresh.ts +381 -0
- package/src/scripts/check_release_highlights.ts +99 -14
- package/src/scripts/check_skill_activation_claim.ts +179 -0
- package/src/scripts/check_suppression_hygiene.ts +11 -0
- package/src/scripts/check_trigger_evals.ts +1 -1
- package/src/scripts/code_graph/build.ts +230 -33
- package/src/scripts/code_graph/extract.ts +168 -33
- package/src/scripts/code_graph/types.ts +37 -2
- package/src/scripts/code_graph/validate.ts +12 -1
- package/src/scripts/conformance_scan.ts +45 -4
- package/src/scripts/detect_silent_catch.ts +403 -0
- package/src/scripts/detect_verification_tampering.ts +538 -0
- package/src/scripts/explain_run.ts +1 -1
- package/src/scripts/generate_capability_matrix.ts +1 -1
- package/src/scripts/git_authorization_hook.ts +228 -18
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +47 -30
- package/src/scripts/hooks/augment-dispatcher.sh +1 -1
- package/src/scripts/hooks/block_no_verify.ts +3 -3
- package/src/scripts/hooks/category_a.ts +291 -0
- package/src/scripts/hooks/cline-dispatcher.sh +1 -1
- package/src/scripts/hooks/concern_registry.ts +2 -2
- package/src/scripts/hooks/cursor-dispatcher.sh +11 -5
- package/src/scripts/hooks/dispatch_hook.ts +17 -22
- package/src/scripts/hooks/evidence_independence.ts +21 -2
- package/src/scripts/hooks/{block_unauthorized_git.ts → git_command_classifier.ts} +175 -364
- package/src/scripts/hooks/host_lowering.ts +215 -0
- package/src/scripts/hooks/host_lowering.yaml +185 -0
- package/src/scripts/hooks/host_semantics.ts +105 -37
- package/src/scripts/hooks/journal_record_hook.ts +10 -0
- package/src/scripts/hooks/permission_gate.ts +117 -0
- package/src/scripts/hooks/push_settle_hook.ts +250 -0
- package/src/scripts/hooks/ship_diff_volume_hook.ts +1 -1
- package/src/scripts/hooks_status.ts +12 -10
- package/src/scripts/install-hooks.sh +134 -1
- package/src/scripts/install.ts +53 -82
- package/src/scripts/install_anthropic_key.sh +2 -2
- package/src/scripts/language_mirror_hook.ts +27 -5
- package/src/scripts/lint_design_antipattern_parity.ts +80 -0
- package/src/scripts/lint_evidence_artifacts.ts +45 -1
- package/src/scripts/lint_hook_manifest.ts +87 -3
- package/src/scripts/lint_motion_authority_drift.ts +731 -0
- package/src/scripts/lint_readme_size.ts +158 -12
- package/src/scripts/lint_reasoning_fixtures.ts +216 -0
- package/src/scripts/lint_skill_trigger_contradiction.ts +161 -0
- package/src/scripts/measure_sibling_naming.ts +150 -0
- package/src/scripts/redact_hook_capture.ts +1 -1
- package/src/scripts/release.ts +31 -143
- package/src/scripts/release_drill.ts +71 -1
- package/src/scripts/release_publication.ts +243 -3
- package/src/scripts/release_verify.ts +220 -0
- package/src/scripts/report_skill_activation.ts +319 -7
- package/src/scripts/schemas/review-findings.schema.json +6 -1
- package/src/scripts/schemas/skill.schema.json +12 -2
- package/src/scripts/self_review_gate.ts +10 -1
- package/src/scripts/session_canary_hook.ts +1 -1
- package/src/scripts/session_register_hook.ts +4 -3
- package/src/scripts/trigger_eval_grandfather.json +5 -1
- package/src/scripts/validate_agent_settings.ts +1 -1
- package/src/shared/settingsConsent.ts +1 -1
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Release-gate locality registry
|
|
2
|
+
#
|
|
3
|
+
# WHY THIS FILE EXISTS
|
|
4
|
+
#
|
|
5
|
+
# `release-validation.yml` is the last gate a release passes and the first one
|
|
6
|
+
# that costs something to fail: by the time it runs, a branch, a pull request
|
|
7
|
+
# and a CI run already exist. Until 2026-09-05 nothing related its jobs to the
|
|
8
|
+
# commands a maintainer can run BEFORE any of that leaves the machine, and the
|
|
9
|
+
# result was a recurring failure shape rather than a one-off — 14.14.0 (PR
|
|
10
|
+
# #1812) on the curated head, 14.17.0 (PR #1856) on the governance-mix
|
|
11
|
+
# response. Both were discoverable locally in under two seconds. Neither was
|
|
12
|
+
# discovered locally, because nothing asked.
|
|
13
|
+
#
|
|
14
|
+
# The registry is the relation the tree was missing. It is read by two
|
|
15
|
+
# consumers, which is what keeps it from rotting into a comment:
|
|
16
|
+
#
|
|
17
|
+
# 1. `tests/scripts/release_gate_locality.test.ts` — every job in the
|
|
18
|
+
# workflow has a row, every row names a live job, every declared script
|
|
19
|
+
# exists, and every `local: ~` carries a reason with an approved prefix.
|
|
20
|
+
# A new release-validation job therefore cannot land without answering
|
|
21
|
+
# "and how does a maintainer run this before pushing?".
|
|
22
|
+
# 2. `task release:verify` — runs every row marked `verify: true` against the
|
|
23
|
+
# working tree. That is the command the release pipeline points at, and
|
|
24
|
+
# the one to run before `task release`.
|
|
25
|
+
#
|
|
26
|
+
# WHAT A ROW MEANS
|
|
27
|
+
#
|
|
28
|
+
# local: the shell command that reproduces the job's assertion locally.
|
|
29
|
+
# `~` (null) means it genuinely cannot run before the PR exists.
|
|
30
|
+
# reason: REQUIRED when `local` is null. Must start with one of
|
|
31
|
+
# NEEDS_PR: / NEEDS_ARTIFACT: / NEEDS_NETWORK: / NEEDS_TOKEN:
|
|
32
|
+
# so the cause is classified rather than merely narrated.
|
|
33
|
+
# verify: whether `task release:verify` runs it. Cheap and deterministic
|
|
34
|
+
# rows are true; anything that packs or installs is false and stays
|
|
35
|
+
# opt-in.
|
|
36
|
+
# network: marks a row that leaves the machine. Excluded from `--cheap`,
|
|
37
|
+
# which is the set the release pipeline runs on its own, so a
|
|
38
|
+
# registry outage cannot read as a release defect.
|
|
39
|
+
# release_branch_only:
|
|
40
|
+
# the assertion only means anything on a `release/X.Y.Z` head.
|
|
41
|
+
# Skipped with a printed reason elsewhere — never silently, and
|
|
42
|
+
# never reported as a pass.
|
|
43
|
+
# script: the implementing script, when the assertion lives in one. `~`
|
|
44
|
+
# marks an assertion that exists only as inline workflow YAML —
|
|
45
|
+
# which is itself the defect this column makes countable.
|
|
46
|
+
# guard: the local guard site that ALSO refuses this, when one exists.
|
|
47
|
+
# A row with a guard fails before the push, not merely before CI.
|
|
48
|
+
# partial: REQUIRED when the `local` command reproduces only part of what the
|
|
49
|
+
# job asserts. Names the uncovered part. A row silently claiming
|
|
50
|
+
# full coverage it does not have is the defect this file exists to
|
|
51
|
+
# end, so the gap is written down rather than inferred.
|
|
52
|
+
|
|
53
|
+
version: 1
|
|
54
|
+
workflow: .github/workflows/release-validation.yml
|
|
55
|
+
|
|
56
|
+
jobs:
|
|
57
|
+
release-shape:
|
|
58
|
+
local: 'git diff --name-only origin/main...HEAD | ./scripts-run src/scripts/check_release_pr_shape --files -'
|
|
59
|
+
verify: true
|
|
60
|
+
# The assertion is about a RELEASE PR's diff — every ordinary branch fails
|
|
61
|
+
# it by construction, so running it off a release branch would teach a
|
|
62
|
+
# maintainer to ignore this command's red. Skipped with a printed reason
|
|
63
|
+
# instead, which is the difference between a gate that is not applicable
|
|
64
|
+
# and one that passed.
|
|
65
|
+
release_branch_only: true
|
|
66
|
+
script: src/scripts/check_release_pr_shape.ts
|
|
67
|
+
guard: ~
|
|
68
|
+
|
|
69
|
+
changelog-entry:
|
|
70
|
+
# The job asserts three things: a heading for the head version, a non-empty
|
|
71
|
+
# body, and a `Tests: N (+M since PREV)` footer.
|
|
72
|
+
#
|
|
73
|
+
# `check_release_highlights` covers the first two — it exits 2 with
|
|
74
|
+
# "CHANGELOG carries no section for <v>". It does NOT read the footer, and
|
|
75
|
+
# saying otherwise here would be the exact defect this registry exists to
|
|
76
|
+
# end: a row asserting a coverage it does not have. The footer half is
|
|
77
|
+
# covered locally by the guard named below, not by the `local` command, so
|
|
78
|
+
# `partial` states that rather than leaving a reader to grep for it.
|
|
79
|
+
local: './scripts-run src/scripts/check_release_highlights --version ${VERSION}'
|
|
80
|
+
verify: true
|
|
81
|
+
partial: 'heading + non-empty body only; the `Tests: N` footer half is covered by the guard, not by this command'
|
|
82
|
+
script: ~
|
|
83
|
+
guard: guard_release_curation
|
|
84
|
+
|
|
85
|
+
surface-equality:
|
|
86
|
+
local: ~
|
|
87
|
+
reason: 'NEEDS_PR: compares the live PR body against the CHANGELOG section; there is no PR body before `gh pr create`. The body is DERIVED from that same section (`pr_body_from_section`), so the local half is the section check above.'
|
|
88
|
+
verify: false
|
|
89
|
+
script: src/scripts/check_release_surface_equality.ts
|
|
90
|
+
guard: ~
|
|
91
|
+
|
|
92
|
+
highlight-plausibility:
|
|
93
|
+
# The job that failed 14.17.0. All four sub-checks (authoring instruction,
|
|
94
|
+
# unrewritten derived marker, `_none_` contradiction, governance-mix
|
|
95
|
+
# response) run locally from local tags alone — no origin, no HEAD_REF.
|
|
96
|
+
local: './scripts-run src/scripts/check_release_highlights --version ${VERSION}'
|
|
97
|
+
verify: true
|
|
98
|
+
script: src/scripts/check_release_highlights.ts
|
|
99
|
+
guard: guard_release_branch_push
|
|
100
|
+
|
|
101
|
+
version-consistency:
|
|
102
|
+
local: './scripts-run src/scripts/check_template_pin_drift'
|
|
103
|
+
verify: true
|
|
104
|
+
script: src/scripts/check_template_pin_drift.ts
|
|
105
|
+
guard: ~
|
|
106
|
+
|
|
107
|
+
finding-dispositions:
|
|
108
|
+
local: './scripts-run src/scripts/check_finding_dispositions --release ${VERSION}'
|
|
109
|
+
verify: false
|
|
110
|
+
reason: 'NEEDS_PR: the unrecorded-findings half reads live PR review comments. The missing-dispositions half does run locally and is what the `local` command covers.'
|
|
111
|
+
script: src/scripts/check_finding_dispositions.ts
|
|
112
|
+
guard: ~
|
|
113
|
+
|
|
114
|
+
audit-gate:
|
|
115
|
+
local: 'npm audit --omit=dev --audit-level=high'
|
|
116
|
+
verify: true
|
|
117
|
+
# Reaches the registry, so it is excluded from the `--cheap` set the
|
|
118
|
+
# release pipeline runs unattended: a registry outage must not read as a
|
|
119
|
+
# release defect. `task release:verify` (no flag) still runs it.
|
|
120
|
+
network: true
|
|
121
|
+
script: ~
|
|
122
|
+
guard: ~
|
|
123
|
+
|
|
124
|
+
release-install-e2e:
|
|
125
|
+
local: ~
|
|
126
|
+
reason: 'NEEDS_ARTIFACT: needs a packed tarball plus a BASELINE_TARBALL of the upgrade-from version; runnable by hand as `bash tests/test_release_install_e2e.sh`, too slow for a pre-push gate.'
|
|
127
|
+
verify: false
|
|
128
|
+
script: ~
|
|
129
|
+
guard: ~
|
|
130
|
+
|
|
131
|
+
activation-census:
|
|
132
|
+
# The one row where the local command asserts MORE than the job it mirrors,
|
|
133
|
+
# not less, so `partial` does not apply: the transcript store the census
|
|
134
|
+
# reads is keyed on the directory it runs in and does not exist on a runner,
|
|
135
|
+
# so CI can only re-take an empty reading and check the published figure
|
|
136
|
+
# against its record. Run locally, the same command reads the real store,
|
|
137
|
+
# which is the only place the census means anything.
|
|
138
|
+
local: './scripts-run src/scripts/report_skill_activation && ./scripts-run src/scripts/check_skill_activation_claim'
|
|
139
|
+
verify: true
|
|
140
|
+
script: src/scripts/report_skill_activation.ts
|
|
141
|
+
guard: ~
|
|
@@ -2881,7 +2881,7 @@ function _run_checks(
|
|
|
2881
2881
|
'claude-command-wrappers': _check_claude_command_wrappers,
|
|
2882
2882
|
'surface-state': _check_surface_state,
|
|
2883
2883
|
'hook-wiring': _check_hook_wiring,
|
|
2884
|
-
...(runtime_wiring.wiringRunners({ packageRoot: _package_root(), iterOverrides: () => iter_setting_overrides({ cwd: project_root }) }) as unknown as Record<string, CheckRunner>),
|
|
2884
|
+
...(runtime_wiring.wiringRunners({ packageRoot: _package_root(), projectRoot: project_root, iterOverrides: () => iter_setting_overrides({ cwd: project_root }) }) as unknown as Record<string, CheckRunner>),
|
|
2885
2885
|
...(install_reach.reachRunners({ projectRoot: project_root, resolvableVersion: _current_package_version() }) as unknown as Record<string, CheckRunner>),
|
|
2886
2886
|
'stale-orphans': _check_stale_orphans,
|
|
2887
2887
|
overrides: () => _check_overrides(project_root),
|
|
@@ -2967,7 +2967,7 @@ function _run_checks_no_manifest(
|
|
|
2967
2967
|
'claude-command-wrappers': _check_claude_command_wrappers,
|
|
2968
2968
|
'surface-state': _check_surface_state,
|
|
2969
2969
|
'hook-wiring': _check_hook_wiring,
|
|
2970
|
-
...(runtime_wiring.wiringRunners({ packageRoot: _package_root(), iterOverrides: () => iter_setting_overrides({ cwd: project_root }) }) as unknown as Record<string, CheckRunner>),
|
|
2970
|
+
...(runtime_wiring.wiringRunners({ packageRoot: _package_root(), projectRoot: project_root, iterOverrides: () => iter_setting_overrides({ cwd: project_root }) }) as unknown as Record<string, CheckRunner>),
|
|
2971
2971
|
...(install_reach.reachRunners({ projectRoot: project_root, resolvableVersion: _current_package_version() }) as unknown as Record<string, CheckRunner>),
|
|
2972
2972
|
'stale-orphans': _check_stale_orphans,
|
|
2973
2973
|
// BOTH registries need the id. Registering only the first one crashed with
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* file (legacy copy-paste mode)
|
|
18
18
|
* --launch <host> spawn a fresh interactive host session after
|
|
19
19
|
* generating (claude: hook-seeded; codex: handoff as
|
|
20
|
-
* initial prompt — no hook
|
|
20
|
+
* initial prompt — this package binds no hook there)
|
|
21
21
|
* --llm narrative-polish seam; v1: clear not-implemented error
|
|
22
22
|
* --root <path> repo root override (default: cwd)
|
|
23
23
|
*
|
|
@@ -446,7 +446,7 @@ export async function main(argv: string[] | null = null, options: MainOptions =
|
|
|
446
446
|
const installed_version = options.installed_version || _detect_installed_version();
|
|
447
447
|
const state_path = options.state_path || update_check.DEFAULT_STATE_PATH;
|
|
448
448
|
|
|
449
|
-
// AGENT_CONFIG_OFFLINE=1 (set by `install
|
|
449
|
+
// AGENT_CONFIG_OFFLINE=1 (set by `agent-config install --offline`) is honored as an
|
|
450
450
|
// env-level kill-switch. Mirrors cmd_versions.py.
|
|
451
451
|
const offline = args.offline || process.env['AGENT_CONFIG_OFFLINE'] === '1';
|
|
452
452
|
|
|
@@ -426,7 +426,7 @@ export function main(argv: string[] | null = null, options: MainOptions = {}): n
|
|
|
426
426
|
const err = options.err ?? _stderrSink();
|
|
427
427
|
const opts = _parse(argv ?? process.argv.slice(2), out, err);
|
|
428
428
|
|
|
429
|
-
// AGENT_CONFIG_OFFLINE=1 (set by `install
|
|
429
|
+
// AGENT_CONFIG_OFFLINE=1 (set by `agent-config install --offline`) is honored as a
|
|
430
430
|
// global kill-switch even when the per-command --offline flag is absent.
|
|
431
431
|
const offline = opts.offline || process.env['AGENT_CONFIG_OFFLINE'] === '1';
|
|
432
432
|
|
|
@@ -483,3 +483,47 @@ export function readAdrAxisCells(text: string): AdrAxisCells {
|
|
|
483
483
|
: `${strength} (${discovery})`,
|
|
484
484
|
};
|
|
485
485
|
}
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* The one shape this tool decides: a trigger whose condition IS a leading date.
|
|
489
|
+
*
|
|
490
|
+
* Deliberately anchored at the start of the string and deliberately narrow. The
|
|
491
|
+
* boundary is the whole safety property — the moment a trigger is matched on a
|
|
492
|
+
* date found anywhere in its prose, "reopens when N exceeds M" is one edit away
|
|
493
|
+
* and the machine-readable grammar two council seats rejected on 2026-08-19 has
|
|
494
|
+
* been built by increments.
|
|
495
|
+
*/
|
|
496
|
+
export const DATED_TRIGGER_RE = /^\s*(?:expir(?:y|es)\b\s*[:—-]?\s*)?(\d{4})-(\d{2})-(\d{2})(?!\d)/iu;
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* A trigger that ANNOUNCES itself as dated, whether or not the date parses.
|
|
500
|
+
*
|
|
501
|
+
* The gap between this and `DATED_TRIGGER_RE` is the `dated-unparsed` state.
|
|
502
|
+
* Exactly one ADR in the corpus carries a dated expiry, so a parse tuned to its
|
|
503
|
+
* phrasing can fail on the second one — and the failure mode is silence,
|
|
504
|
+
* because the old answer for every trigger was `indeterminate`. This probe is
|
|
505
|
+
* what turns that silence into a reported defect.
|
|
506
|
+
*/
|
|
507
|
+
export const DATED_TRIGGER_PROBE = /^\s*(?:expir(?:y|es)\b|\d{4}-\d{1,2}-\d{1,2}\b)/iu;
|
|
508
|
+
|
|
509
|
+
/** The UTC calendar day of an instant, as `YYYY-MM-DD`. */
|
|
510
|
+
export function iso_day(d: Date): string {
|
|
511
|
+
return d.toISOString().slice(0, 10);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* The calendar day a dated trigger names, or null when there is none to read.
|
|
516
|
+
*
|
|
517
|
+
* Round-tripping through `Date.UTC` rejects `2026-13-45`, which matches the
|
|
518
|
+
* shape and is not a date.
|
|
519
|
+
*/
|
|
520
|
+
export function dated_trigger_day(trigger: string): string | null {
|
|
521
|
+
const m = DATED_TRIGGER_RE.exec(trigger);
|
|
522
|
+
if (m === null) return null;
|
|
523
|
+
const [y, mo, d] = [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
524
|
+
const at = new Date(Date.UTC(y, mo - 1, d));
|
|
525
|
+
if (at.getUTCFullYear() !== y || at.getUTCMonth() !== mo - 1 || at.getUTCDate() !== d) {
|
|
526
|
+
return null;
|
|
527
|
+
}
|
|
528
|
+
return iso_day(at);
|
|
529
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* consequence_objects — the consequence vocabulary's prose half.
|
|
3
|
+
*
|
|
4
|
+
* Two things live here: the phrase rows that recognise a consequence
|
|
5
|
+
* authorization, and the extraction of the OBJECT such an authorization names.
|
|
6
|
+
* An authorization for one table, one environment or one recipient class is not
|
|
7
|
+
* an authorization for another, and until this existed the ledger could express
|
|
8
|
+
* the difference for nothing but pull-request numbers.
|
|
9
|
+
*
|
|
10
|
+
* IT IS RECOGNITION AND EXTRACTION, NOT MATCHING. Nothing here decides
|
|
11
|
+
* anything; the one consumer that acts on the vocabulary is `conformance_scan`,
|
|
12
|
+
* which counts after the fact. Making the object a matching condition is the
|
|
13
|
+
* ledger item ADR-254 left to the owner.
|
|
14
|
+
*
|
|
15
|
+
* It sits beside `git_authorization_hook` rather than inside it because that
|
|
16
|
+
* file is against the per-file source-size budget, which charges every line
|
|
17
|
+
* above 1500. The split is along a real seam: the hook owns the machinery —
|
|
18
|
+
* sentence bounds, negation, fenced-paste handling — and this module owns the
|
|
19
|
+
* consequence vocabulary that machinery is applied to.
|
|
20
|
+
*/
|
|
21
|
+
import type { GitOp } from "../git_authorization_hook.js";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Prose phrases, German and English, that authorize a consequence operation.
|
|
25
|
+
*
|
|
26
|
+
* Spliced into `PHRASES` at its definition, so every row inherits the
|
|
27
|
+
* interrogative filter, the clause-scoped negation check and the fenced-paste
|
|
28
|
+
* split rather than reimplementing them.
|
|
29
|
+
*
|
|
30
|
+
* Every row REQUIRES ITS OBJECT NOUN, and that is why the patterns are long. A
|
|
31
|
+
* bare verb cannot tell an authorization from a mention, and for this class the
|
|
32
|
+
* mention is the common case: "deploy" appears in a hundred sentences that
|
|
33
|
+
* authorize nothing, while "deploy nach production" appears only when someone
|
|
34
|
+
* means it.
|
|
35
|
+
*
|
|
36
|
+
* German verb endings are `(e|en)?` because the imperative drops its `-e`, and
|
|
37
|
+
* both word orders are covered — the house style stated above `PHRASES`. The
|
|
38
|
+
* leading boundary is an explicit character class rather than `\b`: JavaScript's
|
|
39
|
+
* `\b` is ASCII-only, so a word STARTING with an umlaut ("Ändere") has no
|
|
40
|
+
* boundary before it and the row silently never fires.
|
|
41
|
+
*/
|
|
42
|
+
export const CONSEQUENCE_PHRASES: ReadonlyArray<{ op: GitOp; re: RegExp }> = [
|
|
43
|
+
{
|
|
44
|
+
op: "prod-deploy",
|
|
45
|
+
re: /(?<![A-Za-z0-9_À-ɏ])(deploy(e|en|t|st)?|ausroll(e|en)?|ship(pe|pen)?|live\s*schalt(e|en)?|rollout)\b[^.\n]{0,30}\b(produktion|production|prod|live|prod-umgebung)\b|\b(produktion|production|prod|live)\b[^.\n]{0,30}\b(deploy(e|en)?|ausrollen|ausroll(e|en)?|live\s*schalten|rollout)\b/i,
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
op: "prod-data-destroy",
|
|
49
|
+
re: /(?<![A-Za-z0-9_À-ɏ])(l(ö|oe)sch(e|en)?|entfern(e|en)?|leer(e|en)?|verwerf(e|en)?|drop|truncate|delete|wipe|purge|zerst(ö|oe)r(e|en)?)\b[^.\n]{0,40}\b(tabelle|tabellen|datenbank|daten|bucket|collection|zeilen|rows|table|database|dataset)\b|\b(tabelle|tabellen|datenbank|daten|bucket|collection|table|database)\b[^.\n]{0,40}\b(l(ö|oe)schen|leeren|verwerfen|droppen|truncaten|entfernen|drop|truncate|delete|wipe|purge)\b/i,
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
op: "prod-infra-change",
|
|
53
|
+
re: /(?<![A-Za-z0-9_À-ɏ])((ver)?(ä|ae)nder(e|n)?|anpass(e|en)?|umbau(e|en)?|apply|destroy|(neu\s*)?provisionier(e|en)?)\b[^.\n]{0,40}\b(infrastruktur|infrastructure|cluster|terraform|iam|dns|netzwerk|network|firewall|policy|policies|security[-\s]group)\b|\b(infrastruktur|infrastructure|cluster|terraform|iam|dns|netzwerk|firewall)\b[^.\n]{0,40}\b((ver)?(ä|ae)ndern|anpassen|umbauen|zerst(ö|oe)ren|apply|destroy)\b/i,
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
op: "external-send",
|
|
57
|
+
re: /(?<![A-Za-z0-9_À-ɏ])(schick(e|en)?|verschick(e|en)?|send(e|en|et)?|mail(e|en)?|raussend(e|en)?|versend(e|en)?|post|publish)\b[^.\n]{0,40}\b(mail|mails|email|e-mail|nachricht|nachrichten|newsletter|webhook|kunden|kundin|kunde|empf(ä|ae)nger|customers?|recipients?|message)\b|\b(mail|email|e-mail|nachricht|newsletter|kunden|customers?)\b[^.\n]{0,40}\b(schicken|verschicken|senden|versenden|rausschicken|send|deliver)\b/i,
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
op: "money-movement",
|
|
61
|
+
re: /(?<![A-Za-z0-9_À-ɏ])(erstatt(e|en)?|r(ü|ue)ckerstatt(e|en)?|zahl(e|en)?|(ü|ue)berweis(e|en)?|abbuch(e|en)?|belast(e|en)?|refund|charge|payout|transfer|bill)\b[^.\n]{0,40}\b(betrag|geld|rechnung|zahlung|euro|dollar|kunde|kunden|karte|konto|invoice|payment|customer|card|account)\b|\b(betrag|geld|rechnung|zahlung|invoice|payment)\b[^.\n]{0,40}\b(erstatten|zur(ü|ue)ckzahlen|(ü|ue)berweisen|abbuchen|belasten|refund|charge|transfer)\b/i,
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
op: "trunk-force-push",
|
|
65
|
+
re: /(?<![A-Za-z0-9_À-ɏ])(force[-\s]?push(e|en|t)?|force[-\s]?pushen|(ü|ue)berschreib(e|en)?)\b[^.\n]{0,40}\b(main|master|trunk|produktions?[-\s]?branch|production|release[-\s]?branch)\b|\b(main|master|trunk|production)\b[^.\n]{0,40}\b(force[-\s]?pushen|force[-\s]?push|(ü|ue)berschreiben)\b/i,
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
op: "out-of-scope-destruction",
|
|
69
|
+
re: /(?<![A-Za-z0-9_À-ɏ])(l(ö|oe)sch(e|en)?|entfern(e|en)?|r(ä|ae)um(e|en)?\s*auf|aufr(ä|ae)um(e|en)?|delete|remove|wipe)\b[^.\n]{0,40}\b(au(ß|ss)erhalb|ausserhalb|unabh(ä|ae)ngig|nicht\s+zur\s+aufgabe|outside\s+(the\s+)?(task|scope)|unrelated|everything\s+else|alles\s+andere)\b|\b(au(ß|ss)erhalb|outside\s+(the\s+)?(task|scope)|unrelated)\b[^.\n]{0,40}\b(l(ö|oe)schen|entfernen|aufr(ä|ae)umen|delete|remove|wipe)\b/i,
|
|
70
|
+
},
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Operations whose authorization is meaningless without its object.
|
|
75
|
+
*
|
|
76
|
+
* "Delete the table" is not an authorization to delete a table; it is an
|
|
77
|
+
* authorization to delete THAT table. The same holds for a recipient class and
|
|
78
|
+
* for a payment. The other four consequence operations are environment-scoped
|
|
79
|
+
* rather than object-scoped, so an object is recorded for them when the prose
|
|
80
|
+
* names one and never required.
|
|
81
|
+
*/
|
|
82
|
+
export const OBJECT_REQUIRED_OPS: ReadonlySet<GitOp> = new Set<GitOp>([
|
|
83
|
+
"prod-data-destroy",
|
|
84
|
+
"external-send",
|
|
85
|
+
"money-movement",
|
|
86
|
+
]);
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Words that can follow an object noun and are never the object's NAME.
|
|
90
|
+
*
|
|
91
|
+
* "Lösch die Tabelle bitte" names no table; the extractor's next-token rule
|
|
92
|
+
* captures `bitte` unless something says otherwise. A stop list is the honest
|
|
93
|
+
* shape for that — the same reviewable-keyword-list discipline the negation and
|
|
94
|
+
* pasted-output vocabularies above use, and for the same reason: a parser that
|
|
95
|
+
* guessed here would record a fabricated object, and a fabricated object is
|
|
96
|
+
* worse than a missing one because the conformance count treats a recorded
|
|
97
|
+
* object as an authorization the turn actually gave.
|
|
98
|
+
*/
|
|
99
|
+
const OBJECT_STOP_WORDS: ReadonlySet<string> = new Set([
|
|
100
|
+
"bitte", "doch", "mal", "nicht", "jetzt", "gleich", "auch", "noch", "wieder",
|
|
101
|
+
"in", "im", "aus", "von", "vom", ": ", "der", "die", "das", "den", "dem",
|
|
102
|
+
"und", "oder", "mit", "auf", "zu", "komplett", "ganz", "alle", "allen",
|
|
103
|
+
"please", "now", "again", "too", "also", "from", "and", "or", "the", "a",
|
|
104
|
+
"an", "there", "here", "completely", "all", "with", "on", "to", "in",
|
|
105
|
+
]);
|
|
106
|
+
|
|
107
|
+
/** Lower-case, strip surrounding quotes and trailing punctuation. */
|
|
108
|
+
function _normalizeObject(raw: string): string {
|
|
109
|
+
return raw.trim().replace(/^["'`]+|["'`]+$/g, "").replace(/[.,;:]+$/, "").toLowerCase();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Per-operation object patterns, each with the capture group that holds it. */
|
|
113
|
+
const OBJECT_PATTERNS: Readonly<Record<string, readonly RegExp[]>> = {
|
|
114
|
+
"prod-data-destroy": [
|
|
115
|
+
/\b(?:tabelle|table|datenbank|database|schema|collection|index)\s+["'`]?([A-Za-z_][\w.$-]*)/gi,
|
|
116
|
+
/\bs3:\/\/([\w.-]+)/gi,
|
|
117
|
+
/\b(?:bucket)\s+["'`]?([A-Za-z_][\w.-]*)/gi,
|
|
118
|
+
],
|
|
119
|
+
"external-send": [
|
|
120
|
+
/([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,})/g,
|
|
121
|
+
/\bhttps?:\/\/([^\s/"'`]+)/gi,
|
|
122
|
+
/\b(?:an\s+(?:die|den|alle)|to\s+(?:the|all))\s+([A-Za-z][\w-]*)/gi,
|
|
123
|
+
],
|
|
124
|
+
"money-movement": [
|
|
125
|
+
/(\d[\d.,]*)\s*(?:€|eur\b|euro\b|\$|usd\b)/gi,
|
|
126
|
+
/(?:€|\$)\s*(\d[\d.,]*)/g,
|
|
127
|
+
/\b(?:kunde|kunden|customer|account|konto)\s+["'`]?([A-Za-z0-9][\w.-]*)/gi,
|
|
128
|
+
],
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* The objects a sentence names for one operation.
|
|
133
|
+
*
|
|
134
|
+
* Returns `[]` when the prose names none — which is a real answer and the one
|
|
135
|
+
* `conformance_scan` reads as "the record does not name this object". An empty
|
|
136
|
+
* list is never widened into a wildcard.
|
|
137
|
+
*/
|
|
138
|
+
export function extractObjects(op: GitOp, text: string): string[] {
|
|
139
|
+
const patterns = OBJECT_PATTERNS[op];
|
|
140
|
+
if (!patterns) return [];
|
|
141
|
+
const out: string[] = [];
|
|
142
|
+
for (const re of patterns) {
|
|
143
|
+
const local = new RegExp(re.source, re.flags.includes("g") ? re.flags : `${re.flags}g`);
|
|
144
|
+
let m: RegExpExecArray | null;
|
|
145
|
+
while ((m = local.exec(text)) !== null) {
|
|
146
|
+
const value = _normalizeObject(m[1] ?? "");
|
|
147
|
+
if (value && !OBJECT_STOP_WORDS.has(value) && !out.includes(value)) out.push(value);
|
|
148
|
+
if (m.index === local.lastIndex) local.lastIndex++;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return out;
|
|
152
|
+
}
|
|
@@ -68,6 +68,13 @@ export const ALLOWLIST_PREFIXES: readonly (readonly string[])[] = [
|
|
|
68
68
|
// a name. Read-only, deterministic, model-free, and already run in CI for its
|
|
69
69
|
// own reasons — the same class as its neighbours here.
|
|
70
70
|
['check_no_external_sources'],
|
|
71
|
+
// Compares two COMMITTED files — the skill-activation census record against
|
|
72
|
+
// the sentence `docs/CLAIMS.md` publishes — so its exit code IS the verdict
|
|
73
|
+
// for that claim rather than evidence that some report exists. The census
|
|
74
|
+
// itself is deliberately NOT here: it reads a transcript store under `$HOME`
|
|
75
|
+
// that is absent on a runner, which would make the verdict an artifact of
|
|
76
|
+
// where it ran.
|
|
77
|
+
['check_skill_activation_claim'],
|
|
71
78
|
['check_token_regression'],
|
|
72
79
|
['lint_agent_security'],
|
|
73
80
|
['measure_lexical_ranking'],
|
|
@@ -356,7 +356,7 @@ function as_posix(p: string): string {
|
|
|
356
356
|
*
|
|
357
357
|
* `dry_run=true` computes and returns the would-delete set (only paths that
|
|
358
358
|
* currently exist on disk) WITHOUT unlinking anything or pruning empty
|
|
359
|
-
* directories — the preview surface for `install
|
|
359
|
+
* directories — the preview surface for `agent-config install --dry-run`. The selection
|
|
360
360
|
* logic (orphan diff, containment proof, directory guard) is identical to the
|
|
361
361
|
* live path, so the preview is exact.
|
|
362
362
|
*/
|
|
@@ -456,7 +456,7 @@ export function reap_stale(
|
|
|
456
456
|
*
|
|
457
457
|
* `dry_run=true` returns the would-delete set (tagged orphans actually present
|
|
458
458
|
* on disk) WITHOUT unlinking or pruning — the preview surface for
|
|
459
|
-
* `install
|
|
459
|
+
* `agent-config install --dry-run`. Selection logic is identical to the live path.
|
|
460
460
|
*/
|
|
461
461
|
export function reap_tagged_orphans(
|
|
462
462
|
anchor: string,
|