@event4u/agent-config 14.6.0 → 14.7.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/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +260 -7
- package/README.md +1 -1
- package/dist/agent-src/commands/analyze/inbox.md +264 -10
- package/dist/agent-src/commands/analyze.md +1 -1
- package/dist/agent-src/commands/roadmap/process-full.md +116 -30
- package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +31 -0
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +135 -104
- package/dist/agent-src/rules/context-hygiene.md +2 -0
- package/dist/agent-src/rules/decision-revisit-gate.md +3 -0
- package/dist/agent-src/rules/fix-what-you-see.md +108 -0
- package/dist/agent-src/rules/no-roadmap-references.md +0 -5
- package/dist/agent-src/rules/recurring-criticism.md +110 -0
- package/dist/agent-src/rules/roadmap-progress-sync.md +1 -1
- package/dist/agent-src/rules/rule-type-governance.md +0 -2
- package/dist/agent-src/rules/self-repair-loop.md +17 -0
- package/dist/agent-src/rules/skill-quality.md +0 -2
- package/dist/agent-src/rules/source-confidentiality.md +37 -7
- package/dist/agent-src/scripts/archival_sweep.ts +117 -0
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +19 -3
- package/dist/agent-src/scripts/gate_budget.ts +282 -0
- package/dist/agent-src/scripts/gate_execute.ts +72 -31
- package/dist/agent-src/scripts/roadmap_gates.ts +74 -3
- package/dist/agent-src/scripts/update_roadmap_progress.ts +251 -7
- package/dist/agent-src/skills/ai-council/SKILL.md +48 -807
- package/dist/agent-src/skills/ai-council/references/advanced-modes.md +320 -0
- package/dist/agent-src/skills/ai-council/references/cost-and-redaction.md +99 -0
- package/dist/agent-src/skills/ai-council/references/execution-modes.md +162 -0
- package/dist/agent-src/skills/ai-council/references/output-and-synthesis.md +125 -0
- package/dist/agent-src/skills/ai-council/references/procedure.md +143 -0
- package/dist/agent-src/skills/quality-tools/SKILL.md +34 -326
- package/dist/agent-src/skills/quality-tools/references/js-ts-tools.md +113 -0
- package/dist/agent-src/skills/quality-tools/references/php-tools.md +222 -0
- package/dist/agent-src/skills/roadmap-management/SKILL.md +15 -409
- package/dist/agent-src/skills/roadmap-management/references/archival.md +226 -0
- package/dist/agent-src/skills/roadmap-management/references/authoring.md +107 -0
- package/dist/agent-src/skills/roadmap-management/references/dashboard.md +47 -0
- package/dist/agent-src/skills/roadmap-management/references/lifecycle.md +58 -0
- package/dist/agent-src/skills/skill-writing/SKILL.md +34 -570
- package/dist/agent-src/skills/skill-writing/references/procedure.md +275 -0
- package/dist/agent-src/skills/skill-writing/references/read-only-scripts.md +18 -0
- package/dist/agent-src/skills/skill-writing/references/section-patterns.md +298 -0
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +45 -2
- package/dist/agent-src/templates/scripts/telemetry/flush_sender.mjs +163 -0
- package/dist/agent-src/templates/scripts/telemetry/remote.ts +160 -7
- package/dist/agent-src/templates/scripts/telemetry/transport.ts +169 -0
- package/dist/cli/registry.js +1 -1
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/chunk-2GNWGMAL.js +172 -0
- package/dist/cli-delegate/{chunk-RLN73PR5.js → chunk-4VR4ORQ6.js} +10 -7
- package/dist/cli-delegate/chunk-6EOCNQAM.js +402 -0
- package/dist/cli-delegate/{chunk-XURJ4AQC.js → chunk-74E3TKWV.js} +381 -280
- package/dist/cli-delegate/{chunk-3UCJWMMP.js → chunk-7F3VYSM2.js} +4 -4
- package/dist/cli-delegate/{chunk-BKO2AZ7Z.js → chunk-B2ERU2VA.js} +1 -1
- package/dist/cli-delegate/{chunk-NXFWFAYV.js → chunk-G23AT6GD.js} +1 -0
- package/dist/cli-delegate/{chunk-63WSP6YZ.js → chunk-GJ5BVHXM.js} +72 -165
- package/dist/cli-delegate/{chunk-P6LQDIWK.js → chunk-JZ4NR2TW.js} +338 -0
- package/dist/cli-delegate/chunk-MWRD5YOH.js +100 -0
- package/dist/cli-delegate/{chunk-GRRPEPRN.js → chunk-T7L2QK3K.js} +24 -5
- package/dist/cli-delegate/{chunk-EVTY7ISR.js → chunk-YM4GZDJG.js} +9 -1
- package/dist/cli-delegate/cmd_conformance.js +459 -709
- package/dist/cli-delegate/cmd_doctor.js +6 -6
- package/dist/cli-delegate/cmd_explain.js +1 -1
- package/dist/cli-delegate/cmd_export.js +7 -6
- package/dist/cli-delegate/cmd_handoff.js +6 -6
- package/dist/cli-delegate/cmd_packs_active.js +1 -1
- package/dist/cli-delegate/cmd_preflight.js +2 -2
- package/dist/cli-delegate/cmd_prune.js +7 -6
- package/dist/cli-delegate/cmd_session_recycle.js +840 -30
- package/dist/cli-delegate/cmd_settings_migrate.js +7 -6
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +7 -6
- package/dist/cli-delegate/cmd_uninstall.js +9 -7
- package/dist/cli-delegate/cmd_update.js +1 -1
- package/dist/cli-delegate/cmd_upgrade.js +1 -1
- package/dist/cli-delegate/cmd_validate.js +7 -6
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +68 -25
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +4 -4
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +10 -8
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +8 -6
- package/dist/hooks/dispatch.js +2901 -2053
- package/dist/install/claudePathsPlan.js +187 -0
- package/dist/install/claudePathsPlan.js.map +1 -0
- package/dist/install/hostLayerFingerprint.js +136 -0
- package/dist/install/hostLayerFingerprint.js.map +1 -0
- package/dist/install/install.mjs +553 -425
- package/dist/install/partitionEligibility.js +276 -0
- package/dist/install/partitionEligibility.js.map +1 -0
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +1744 -1191
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/agent_src.js +41 -0
- package/dist/scripts/_lib/agent_src.js.map +1 -1
- package/dist/scripts/_lib/install_layout.js +83 -0
- package/dist/scripts/_lib/install_layout.js.map +1 -0
- package/dist/scripts/_lib/installed_lock.js +444 -0
- package/dist/scripts/_lib/installed_lock.js.map +1 -0
- package/dist/scripts/condense.js +13 -164
- package/dist/scripts/condense.js.map +1 -1
- package/dist/server/schemas/settings.js +4 -0
- package/dist/server/schemas/settings.js.map +1 -1
- package/docs/contracts/settings-classes.md +12 -6
- package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +8 -3
- package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +26 -0
- package/docs/guidelines/agent-infra/memory-access.md +17 -0
- package/docs/guidelines/agent-infra/recurring-criticism-mechanics.md +96 -0
- package/package.json +1 -1
- package/src/agent-src/scripts/archival_sweep.ts +117 -0
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +19 -3
- package/src/agent-src/scripts/gate_budget.ts +282 -0
- package/src/agent-src/scripts/gate_execute.ts +72 -31
- package/src/agent-src/scripts/roadmap_gates.ts +74 -3
- package/src/agent-src/scripts/update_roadmap_progress.ts +251 -7
- package/src/agent-src/templates/scripts/telemetry/flush_sender.mjs +163 -0
- package/src/agent-src/templates/scripts/telemetry/remote.ts +160 -7
- package/src/agent-src/templates/scripts/telemetry/transport.ts +169 -0
- package/src/config/agent-settings.template.yml +27 -2
- package/src/config/ci-local-parity.yml +18 -0
- package/src/config/estate-count-budget.json +339 -3
- package/src/config/gate-violation-baselines.json +41 -41
- package/src/config/rule-activation-census.json +14 -6
- package/src/config/rule-stub-ceilings.json +19 -6
- package/src/install/claudePathsPlan.ts +196 -0
- package/src/install/hostLayerFingerprint.ts +145 -0
- package/src/install/partitionEligibility.ts +325 -0
- package/src/scripts/_cli/cmd_session_recycle.ts +9 -1
- package/src/scripts/_dispatch.bash +6 -1
- package/src/scripts/_lib/ac_heading.ts +30 -0
- package/src/scripts/_lib/agent_src.ts +42 -0
- package/src/scripts/_lib/bench_ab_pinned_repo.ts +162 -0
- package/src/scripts/_lib/bench_ab_workspace.ts +10 -1
- package/src/scripts/_lib/envelope_grounding.ts +38 -8
- package/src/scripts/_lib/installed_lock.ts +50 -5
- package/src/scripts/_lib/md_section.ts +129 -0
- package/src/scripts/_lib/scope_guard.sh +26 -3
- package/src/scripts/_lib/self_repair.ts +19 -0
- package/src/scripts/_lib/self_repair_class_b.ts +171 -0
- package/src/scripts/ai_council/cli_help.ts +55 -0
- package/src/scripts/before_complete_hook.ts +153 -28
- package/src/scripts/bench_ab_v2_complexity.ts +27 -7
- package/src/scripts/check_references.ts +60 -0
- package/src/scripts/check_release_published.ts +32 -11
- package/src/scripts/check_single_delivery.ts +59 -15
- package/src/scripts/ci_settle.ts +170 -0
- package/src/scripts/condense.ts +20 -170
- package/src/scripts/council_cli.ts +3 -3
- package/src/scripts/dispatch_r2_reviewer.ts +6 -14
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +77 -14
- package/src/scripts/hooks/block_no_verify.ts +61 -10
- package/src/scripts/hooks/block_unauthorized_git.ts +1 -1
- package/src/scripts/hooks/concern_registry.ts +4 -0
- package/src/scripts/hooks/rtk_wrap_hook.ts +8 -3
- package/src/scripts/hooks/run_continuation_hook.ts +8 -5
- package/src/scripts/hooks/ship_diff_volume_hook.ts +81 -15
- package/src/scripts/hooks/source_first_gate_hook.ts +464 -0
- package/src/scripts/hooks/state_io.ts +782 -20
- package/src/scripts/hooks/subagent_ledger_hook.ts +44 -15
- package/src/scripts/hooks/telemetry_flush_hook.ts +139 -0
- package/src/scripts/hooks/telemetry_self_repair.ts +128 -0
- package/src/scripts/hooks/telemetry_usage_hook.ts +22 -4
- package/src/scripts/hooks/turn_end_gate_hook.ts +81 -15
- package/src/scripts/install.ts +16 -11
- package/src/scripts/language_mirror_hook.ts +561 -25
- package/src/scripts/lint_framework_leakage_allowlist.json +2 -2
- package/src/scripts/lint_plan_risk_register.ts +4 -3
- package/src/scripts/lint_skill_router_head.ts +4 -4
- package/src/scripts/mcp_server/tools.ts +2 -2
- package/src/scripts/new_roadmap.ts +136 -0
- package/src/scripts/pack_mcp_content.ts +20 -5
- package/src/scripts/release.ts +37 -38
- package/src/scripts/report_layer_overlap.ts +6 -0
- package/src/scripts/self_repair_hook.ts +37 -5
- package/src/scripts/session_register_hook.ts +11 -0
- package/src/scripts/skill_usage_collect.ts +11 -1
- package/src/scripts/skill_usage_report.ts +278 -8
- package/src/scripts/sync_pr_branch.ts +7 -0
- package/src/server/schemas/settings.ts +8 -0
- package/dist/cli-delegate/chunk-EJITJBJX.js +0 -172
- package/dist/cli-delegate/chunk-PZWRPRWP.js +0 -38
- /package/dist/cli-delegate/{chunk-RYNADUFG.js → chunk-LWTYTX6F.js} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"fingerprint":"4834904a:65187","manifest":{"schema_version":1,"concerns":{"chat-history":{"script":"src/scripts/chat_history.ts","args":["hook-dispatch"],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["result"]},"hot-context":{"script":"src/scripts/hot_context_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"handoff-context":{"script":"src/scripts/handoff_context_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"roadmap-progress":{"script":"src/scripts/roadmap_progress_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"onboarding-gate":{"script":"src/scripts/onboarding_gate_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"context-hygiene":{"script":"src/scripts/context_hygiene_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"verify-before-complete":{"script":"src/scripts/before_complete_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input","result"]},"ship-diff-volume":{"script":"src/scripts/hooks/ship_diff_volume_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"minimal-safe-diff":{"script":"src/scripts/minimal_safe_diff_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"injection-scan":{"script":"src/scripts/injection_scan_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input","result"]},"block-no-verify":{"script":"src/scripts/hooks/block_no_verify.ts","args":[],"fail_closed":true,"severity":"blocking","needs_payload_bodies":["input"]},"block-kernel-rule-writes":{"script":"src/scripts/hooks/block_kernel_rule_writes.ts","args":[],"fail_closed":true,"severity":"blocking","needs_payload_bodies":["input"]},"block-config-weakening":{"script":"src/scripts/hooks/block_config_weakening.ts","args":[],"fail_closed":false,"severity":"blocking","needs_payload_bodies":["input"]},"rtk-wrap":{"script":"src/scripts/hooks/rtk_wrap_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"design-slop":{"script":"src/scripts/hooks/design_slop_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"ui-route-nudge":{"script":"src/scripts/hooks/ui_route_nudge_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"code-graph-nudge":{"script":"src/scripts/hooks/code_graph_nudge_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Grep","Glob","Read"],"needs_payload_bodies":["input"]},"memory-learn":{"script":"src/scripts/memory_learn_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"first-run-gate":{"script":"src/scripts/first_run_gate_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"profile-staleness":{"script":"src/scripts/profile_staleness_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"wrapper-freshness":{"script":"src/scripts/wrapper_freshness_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"surface-probe":{"script":"src/scripts/surface_probe_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"team-review-gate":{"script":"src/scripts/team_review_gate_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"pr-url-reminder":{"script":"src/scripts/pr_url_reminder_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input","result"]},"language-mirror":{"script":"src/scripts/language_mirror_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"git-authorization":{"script":"src/scripts/git_authorization_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"block-unauthorized-git":{"script":"src/scripts/hooks/block_unauthorized_git.ts","args":[],"fail_closed":true,"severity":"blocking","needs_payload_bodies":["input"]},"evidence-independence":{"script":"src/scripts/hooks/evidence_independence.ts","args":[],"fail_closed":false,"severity":"blocking","needs_payload_bodies":["input"]},"session-canary":{"script":"src/scripts/session_canary_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"council-availability":{"script":"src/scripts/council_availability_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"telemetry-disclosure":{"script":"src/scripts/telemetry_disclosure_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"self-repair":{"script":"src/scripts/self_repair_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"session-register":{"script":"src/scripts/session_register_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"orchestration-record":{"script":"src/scripts/hooks/orchestration_record_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Agent","Task"],"needs_payload_bodies":["input","result"]},"telemetry-usage":{"script":"src/scripts/hooks/telemetry_usage_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Skill"],"needs_payload_bodies":["input"]},"delegation-nudge":{"script":"src/scripts/hooks/delegation_nudge_hook.ts","args":[],"fail_closed":false,"severity":"advisory","nudge_rank":1},"skill-route":{"script":"src/scripts/hooks/skill_route_hook.ts","args":[],"fail_closed":false,"severity":"advisory","nudge_rank":2},"end-review-nudge":{"script":"src/scripts/hooks/end_review_nudge_hook.ts","args":[],"fail_closed":false,"severity":"advisory","skip_on_refusal_retry":true},"turn-end-gate":{"script":"src/scripts/hooks/turn_end_gate_hook.ts","args":[],"fail_closed":false,"severity":"blocking"},"edit-shape":{"script":"src/scripts/hooks/edit_shape_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Write"],"needs_payload_bodies":["input"]},"reread-guard":{"script":"src/scripts/hooks/reread_guard_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Read","Edit","Write"],"needs_payload_bodies":["input"]},"session-eol":{"script":"src/scripts/hooks/session_eol_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"run-continuation":{"script":"src/scripts/hooks/run_continuation_hook.ts","args":[],"fail_closed":false,"severity":"blocking"},"interruption-ledger":{"script":"src/scripts/hooks/interruption_ledger_hook.ts","args":[],"fail_closed":false,"severity":"advisory","skip_on_refusal_retry":true},"subagent-ledger":{"script":"src/scripts/hooks/subagent_ledger_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"tool-result-bytes":{"script":"src/scripts/hooks/tool_result_bytes_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"spawn-guard-shadow":{"script":"src/scripts/hooks/spawn_guard_shadow_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Agent","Task"]}},"roles":{"worker":{"drop":["delegation-nudge","skill-route","end-review-nudge","council-availability","team-review-gate","self-repair","session-eol","interruption-ledger"]}},"platforms":{"augment":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress"],"pre_tool_use":["block-no-verify","block-unauthorized-git","evidence-independence","block-kernel-rule-writes","block-config-weakening","rtk-wrap","design-slop","ui-route-nudge","code-graph-nudge","ship-diff-volume","reread-guard"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape"]},"claude":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress"],"stop":["chat-history","hot-context","verify-before-complete","team-review-gate","end-review-nudge","turn-end-gate","self-repair","session-register","session-eol","interruption-ledger","roadmap-progress","run-continuation"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","delegation-nudge","skill-route","git-authorization","session-canary","self-repair","session-register"],"pre_tool_use":["block-no-verify","block-unauthorized-git","evidence-independence","block-kernel-rule-writes","block-config-weakening","rtk-wrap","design-slop","ui-route-nudge","code-graph-nudge","ship-diff-volume","reread-guard","spawn-guard-shadow"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","language-mirror"],"pre_compact":["language-mirror","hot-context"],"subagent_start":["subagent-ledger"],"subagent_stop":["subagent-ledger"]},"cowork":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","git-authorization","session-canary","self-repair","session-register"],"pre_tool_use":["block-no-verify","block-unauthorized-git","evidence-independence","block-kernel-rule-writes","block-config-weakening","rtk-wrap","design-slop","ui-route-nudge","code-graph-nudge","ship-diff-volume","reread-guard","spawn-guard-shadow"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape"],"subagent_start":["subagent-ledger"],"subagent_stop":["subagent-ledger"]},"cursor":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","git-authorization","session-canary","self-repair","session-register"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape"]},"cline":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","git-authorization","session-canary","self-repair","session-register"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape"]},"windsurf":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","profile-staleness","wrapper-freshness","surface-probe","session-register"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register"],"user_prompt_submit":["chat-history","verify-before-complete","language-mirror","git-authorization","session-canary","self-repair","session-register"]},"gemini":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","git-authorization","session-canary","self-repair","session-register"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape"]},"copilot":{"fallback_only":true}},"native_event_aliases":{"augment":{"SessionStart":"session_start","SessionEnd":"session_end","Stop":"stop","PostToolUse":"post_tool_use","PreToolUse":"pre_tool_use"},"claude":{"SessionStart":"session_start","SessionEnd":"session_end","Stop":"stop","UserPromptSubmit":"user_prompt_submit","PostToolUse":"post_tool_use","PreToolUse":"pre_tool_use","PreCompact":"pre_compact","SubagentStart":"subagent_start","SubagentStop":"subagent_stop"},"cowork":{"SessionStart":"session_start","SessionEnd":"session_end","Stop":"stop","UserPromptSubmit":"user_prompt_submit","PostToolUse":"post_tool_use","PreToolUse":"pre_tool_use","PreCompact":"pre_compact","SubagentStart":"subagent_start","SubagentStop":"subagent_stop"},"cursor":{"sessionStart":"session_start","sessionEnd":"session_end","stop":"stop","beforeSubmitPrompt":"user_prompt_submit","postToolUse":"post_tool_use","preToolUse":"pre_tool_use","preCompact":"pre_compact"},"cline":{"TaskStart":"session_start","TaskResume":"session_start","TaskComplete":"session_end","TaskCancel":"stop","UserPromptSubmit":"user_prompt_submit","PostToolUse":"post_tool_use","PreToolUse":"pre_tool_use","PreCompact":"pre_compact"},"windsurf":{"pre_user_prompt":"user_prompt_submit","post_cascade_response":"stop","post_setup_worktree":"session_start"},"gemini":{"SessionStart":"session_start","SessionEnd":"session_end","BeforeAgent":"user_prompt_submit","AfterAgent":"stop","BeforeTool":"pre_tool_use","AfterTool":"post_tool_use"}}}}
|
|
1
|
+
{"fingerprint":"f4a2905d:68966","manifest":{"schema_version":1,"concerns":{"chat-history":{"script":"src/scripts/chat_history.ts","args":["hook-dispatch"],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["result"]},"hot-context":{"script":"src/scripts/hot_context_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"handoff-context":{"script":"src/scripts/handoff_context_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"roadmap-progress":{"script":"src/scripts/roadmap_progress_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"onboarding-gate":{"script":"src/scripts/onboarding_gate_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"context-hygiene":{"script":"src/scripts/context_hygiene_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"verify-before-complete":{"script":"src/scripts/before_complete_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input","result"]},"ship-diff-volume":{"script":"src/scripts/hooks/ship_diff_volume_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"minimal-safe-diff":{"script":"src/scripts/minimal_safe_diff_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"injection-scan":{"script":"src/scripts/injection_scan_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input","result"]},"block-no-verify":{"script":"src/scripts/hooks/block_no_verify.ts","args":[],"fail_closed":true,"severity":"blocking","needs_payload_bodies":["input"]},"block-kernel-rule-writes":{"script":"src/scripts/hooks/block_kernel_rule_writes.ts","args":[],"fail_closed":true,"severity":"blocking","needs_payload_bodies":["input"]},"block-config-weakening":{"script":"src/scripts/hooks/block_config_weakening.ts","args":[],"fail_closed":false,"severity":"blocking","needs_payload_bodies":["input"]},"rtk-wrap":{"script":"src/scripts/hooks/rtk_wrap_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"design-slop":{"script":"src/scripts/hooks/design_slop_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"ui-route-nudge":{"script":"src/scripts/hooks/ui_route_nudge_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"code-graph-nudge":{"script":"src/scripts/hooks/code_graph_nudge_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Grep","Glob","Read"],"needs_payload_bodies":["input"]},"memory-learn":{"script":"src/scripts/memory_learn_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"first-run-gate":{"script":"src/scripts/first_run_gate_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"profile-staleness":{"script":"src/scripts/profile_staleness_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"wrapper-freshness":{"script":"src/scripts/wrapper_freshness_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"surface-probe":{"script":"src/scripts/surface_probe_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"team-review-gate":{"script":"src/scripts/team_review_gate_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"pr-url-reminder":{"script":"src/scripts/pr_url_reminder_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input","result"]},"language-mirror":{"script":"src/scripts/language_mirror_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"git-authorization":{"script":"src/scripts/git_authorization_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"block-unauthorized-git":{"script":"src/scripts/hooks/block_unauthorized_git.ts","args":[],"fail_closed":true,"severity":"blocking","needs_payload_bodies":["input"]},"evidence-independence":{"script":"src/scripts/hooks/evidence_independence.ts","args":[],"fail_closed":false,"severity":"blocking","needs_payload_bodies":["input"]},"session-canary":{"script":"src/scripts/session_canary_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"council-availability":{"script":"src/scripts/council_availability_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"telemetry-disclosure":{"script":"src/scripts/telemetry_disclosure_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"telemetry-flush":{"script":"src/scripts/hooks/telemetry_flush_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"self-repair":{"script":"src/scripts/self_repair_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"session-register":{"script":"src/scripts/session_register_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"orchestration-record":{"script":"src/scripts/hooks/orchestration_record_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Agent","Task"],"needs_payload_bodies":["input","result"]},"telemetry-usage":{"script":"src/scripts/hooks/telemetry_usage_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Skill"],"needs_payload_bodies":["input"]},"delegation-nudge":{"script":"src/scripts/hooks/delegation_nudge_hook.ts","args":[],"fail_closed":false,"severity":"advisory","nudge_rank":1},"skill-route":{"script":"src/scripts/hooks/skill_route_hook.ts","args":[],"fail_closed":false,"severity":"advisory","nudge_rank":2},"end-review-nudge":{"script":"src/scripts/hooks/end_review_nudge_hook.ts","args":[],"fail_closed":false,"severity":"advisory","skip_on_refusal_retry":true},"turn-end-gate":{"script":"src/scripts/hooks/turn_end_gate_hook.ts","args":[],"fail_closed":false,"severity":"blocking"},"edit-shape":{"script":"src/scripts/hooks/edit_shape_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Write"],"needs_payload_bodies":["input"]},"reread-guard":{"script":"src/scripts/hooks/reread_guard_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Read","Edit","Write"],"needs_payload_bodies":["input"]},"session-eol":{"script":"src/scripts/hooks/session_eol_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"run-continuation":{"script":"src/scripts/hooks/run_continuation_hook.ts","args":[],"fail_closed":false,"severity":"blocking"},"interruption-ledger":{"script":"src/scripts/hooks/interruption_ledger_hook.ts","args":[],"fail_closed":false,"severity":"advisory","skip_on_refusal_retry":true},"subagent-ledger":{"script":"src/scripts/hooks/subagent_ledger_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"tool-result-bytes":{"script":"src/scripts/hooks/tool_result_bytes_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"spawn-guard-shadow":{"script":"src/scripts/hooks/spawn_guard_shadow_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Agent","Task"]},"source-first-gate":{"script":"src/scripts/hooks/source_first_gate_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]}},"roles":{"worker":{"drop":["delegation-nudge","skill-route","end-review-nudge","council-availability","team-review-gate","self-repair","session-eol","interruption-ledger"]}},"platforms":{"augment":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress"],"pre_tool_use":["block-no-verify","block-unauthorized-git","evidence-independence","block-kernel-rule-writes","block-config-weakening","rtk-wrap","design-slop","ui-route-nudge","code-graph-nudge","ship-diff-volume","reread-guard"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape"]},"claude":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","team-review-gate","end-review-nudge","turn-end-gate","self-repair","session-register","session-eol","interruption-ledger","roadmap-progress","run-continuation"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","delegation-nudge","skill-route","git-authorization","session-canary","self-repair","session-register"],"pre_tool_use":["block-no-verify","block-unauthorized-git","evidence-independence","block-kernel-rule-writes","block-config-weakening","rtk-wrap","design-slop","ui-route-nudge","code-graph-nudge","ship-diff-volume","reread-guard","spawn-guard-shadow","source-first-gate"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","language-mirror"],"pre_compact":["language-mirror","hot-context"],"subagent_start":["subagent-ledger"],"subagent_stop":["subagent-ledger"]},"cowork":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","git-authorization","session-canary","self-repair","session-register"],"pre_tool_use":["block-no-verify","block-unauthorized-git","evidence-independence","block-kernel-rule-writes","block-config-weakening","rtk-wrap","design-slop","ui-route-nudge","code-graph-nudge","ship-diff-volume","reread-guard","spawn-guard-shadow","source-first-gate"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape"],"subagent_start":["subagent-ledger"],"subagent_stop":["subagent-ledger"]},"cursor":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","git-authorization","session-canary","self-repair","session-register"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape"]},"cline":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","git-authorization","session-canary","self-repair","session-register"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape"]},"windsurf":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","profile-staleness","wrapper-freshness","surface-probe","session-register"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register"],"user_prompt_submit":["chat-history","verify-before-complete","language-mirror","git-authorization","session-canary","self-repair","session-register"]},"gemini":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","git-authorization","session-canary","self-repair","session-register"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape"]},"copilot":{"fallback_only":true}},"native_event_aliases":{"augment":{"SessionStart":"session_start","SessionEnd":"session_end","Stop":"stop","PostToolUse":"post_tool_use","PreToolUse":"pre_tool_use"},"claude":{"SessionStart":"session_start","SessionEnd":"session_end","Stop":"stop","UserPromptSubmit":"user_prompt_submit","PostToolUse":"post_tool_use","PreToolUse":"pre_tool_use","PreCompact":"pre_compact","SubagentStart":"subagent_start","SubagentStop":"subagent_stop"},"cowork":{"SessionStart":"session_start","SessionEnd":"session_end","Stop":"stop","UserPromptSubmit":"user_prompt_submit","PostToolUse":"post_tool_use","PreToolUse":"pre_tool_use","PreCompact":"pre_compact","SubagentStart":"subagent_start","SubagentStop":"subagent_stop"},"cursor":{"sessionStart":"session_start","sessionEnd":"session_end","stop":"stop","beforeSubmitPrompt":"user_prompt_submit","postToolUse":"post_tool_use","preToolUse":"pre_tool_use","preCompact":"pre_compact"},"cline":{"TaskStart":"session_start","TaskResume":"session_start","TaskComplete":"session_end","TaskCancel":"stop","UserPromptSubmit":"user_prompt_submit","PostToolUse":"post_tool_use","PreToolUse":"pre_tool_use","PreCompact":"pre_compact"},"windsurf":{"pre_user_prompt":"user_prompt_submit","post_cascade_response":"stop","post_setup_worktree":"session_start"},"gemini":{"SessionStart":"session_start","SessionEnd":"session_end","BeforeAgent":"user_prompt_submit","AfterAgent":"stop","BeforeTool":"pre_tool_use","AfterTool":"post_tool_use"}}}}
|
|
@@ -80,12 +80,18 @@ concerns:
|
|
|
80
80
|
severity: advisory
|
|
81
81
|
# Phase 5 — Tier-1 hook for the verify-before-complete rule. Records
|
|
82
82
|
# observable evidence of verification commands (tests, quality tools,
|
|
83
|
-
# builds) into agents/state/verify-before-complete
|
|
84
|
-
#
|
|
85
|
-
# `
|
|
86
|
-
#
|
|
87
|
-
#
|
|
88
|
-
#
|
|
83
|
+
# builds) into agents/state/verify-before-complete/<digest>.json — ONE FILE
|
|
84
|
+
# PER SESSION since 2026-08-20, addressed through
|
|
85
|
+
# `before_complete_hook.statePathFor`. Two earlier corrections are worth
|
|
86
|
+
# keeping visible, because this comment was wrong about the path twice: it
|
|
87
|
+
# said `agents/runtime/state/` until round 7 (a directory the code never
|
|
88
|
+
# used), and it named the single `STATE_FILE` until the split, which is the
|
|
89
|
+
# constant `prune_legacy_state_file` now DELETES. The rule body cites that
|
|
90
|
+
# state as the source of truth for "verified this turn?". Since round 7 it
|
|
91
|
+
# also carries `ci_last`, the session-scoped CI-settle negative that
|
|
92
|
+
# `turn-end-gate` reads to refuse a premature completion claim — and
|
|
93
|
+
# "session-scoped" is now a property of the layout rather than of a reset
|
|
94
|
+
# that fired when a foreign id showed up in a shared file.
|
|
89
95
|
verify-before-complete:
|
|
90
96
|
script: src/scripts/before_complete_hook.ts
|
|
91
97
|
args: []
|
|
@@ -423,6 +429,34 @@ concerns:
|
|
|
423
429
|
args: []
|
|
424
430
|
fail_closed: false
|
|
425
431
|
severity: advisory
|
|
432
|
+
# road-to-org-telemetry Phase 2 (step 2.1) — session-end Class-A flush.
|
|
433
|
+
# Checks whether the outbound spool has bytes and, if so, spawns a DETACHED
|
|
434
|
+
# sender and returns. It makes no network call in the session's own process,
|
|
435
|
+
# ever, and that shape is measured rather than preferred: Phase 0's second
|
|
436
|
+
# spike pre-registered "at or below one second at p95" for an inline flush
|
|
437
|
+
# and measured 1002 ms against a blackhole sink (a socket that accepts and
|
|
438
|
+
# never answers — the shape a wedged sink takes), against 20.5 ms for the
|
|
439
|
+
# detached spool. The step's own text defers to that result.
|
|
440
|
+
#
|
|
441
|
+
# DEFAULT-OFF and then some, exactly as telemetry-usage: `active` needs
|
|
442
|
+
# `enabled` AND an endpoint AND an org id AND a salt, none of which this
|
|
443
|
+
# public repository ships a value for, so a clone cannot reach the spawn
|
|
444
|
+
# path. `flush: never` short-circuits before the spool is stat-ed. Inactive
|
|
445
|
+
# ⇒ zero telemetry file operations and zero network calls.
|
|
446
|
+
#
|
|
447
|
+
# Bound on the six platforms that carry `session_end`; windsurf has the slot
|
|
448
|
+
# nowhere in this manifest, so an org running it keeps its records local
|
|
449
|
+
# until a flush slot exists there — a readable absence, not a silent one.
|
|
450
|
+
#
|
|
451
|
+
# Silent on every path and exit 0 always, including a failed spawn: a
|
|
452
|
+
# telemetry concern has nothing to say to the model, least of all at session
|
|
453
|
+
# end where the line would arrive after the last thing the user reads.
|
|
454
|
+
# Carries no hook-token-budget row — it emits nothing. fail_closed: false.
|
|
455
|
+
telemetry-flush:
|
|
456
|
+
script: src/scripts/hooks/telemetry_flush_hook.ts
|
|
457
|
+
args: []
|
|
458
|
+
fail_closed: false
|
|
459
|
+
severity: advisory
|
|
426
460
|
# Self-repair intake (road-to-self-repair Phase 1). Two slots, one queue:
|
|
427
461
|
# user_prompt_submit opens a record when the user states the agent worked
|
|
428
462
|
# wrongly and injects the open-queue line; stop runs the deterministic
|
|
@@ -832,6 +866,35 @@ concerns:
|
|
|
832
866
|
fail_closed: false
|
|
833
867
|
severity: advisory
|
|
834
868
|
tools: [Agent, Task]
|
|
869
|
+
# road-to-source-first-frontend Phase 3 Steps 1-2 — source-first gate, SHADOW
|
|
870
|
+
# ONLY, per docs/contracts/concern-activation-policy.md. On every
|
|
871
|
+
# capture-shaped tool call it appends one `source_first_gate_shadow` line
|
|
872
|
+
# recording what the gate WOULD have warned under four candidate gating
|
|
873
|
+
# rules. It emits nothing to the model and has no code path that can warn or
|
|
874
|
+
# deny.
|
|
875
|
+
#
|
|
876
|
+
# Phase 3 Step 1 was drafted as `exit 2 warn` and Step 2 left the posture an
|
|
877
|
+
# explicit maintainer call; the roadmap's own 2026-08-17 correction records
|
|
878
|
+
# that the activation policy contradicts the drafted default-ON warn. Shadow
|
|
879
|
+
# is the re-argued answer, and it dissolves both of that step's blocking
|
|
880
|
+
# dependencies rather than waiting on them: the verifier-exemption risk is a
|
|
881
|
+
# harm of EMISSION (a concern that emits nothing warns nobody, so the open
|
|
882
|
+
# SLI `agent_id` binding becomes a recorded field instead of a gate), and the
|
|
883
|
+
# unfinished multi-host matcher census becomes the measurement rather than a
|
|
884
|
+
# false-positive generator (`capture_kind` separates page-reaching capture
|
|
885
|
+
# from display capture on every record).
|
|
886
|
+
#
|
|
887
|
+
# No `tools:` filter on purpose: the concern must see ordinary reads to latch
|
|
888
|
+
# whether the handover source was read before the capture. The flip condition
|
|
889
|
+
# to advisory is pre-registered in the hook header.
|
|
890
|
+
#
|
|
891
|
+
# Never blocks, never warns: exit 0 on every path. fail_closed: false.
|
|
892
|
+
source-first-gate:
|
|
893
|
+
script: src/scripts/hooks/source_first_gate_hook.ts
|
|
894
|
+
args: []
|
|
895
|
+
fail_closed: false
|
|
896
|
+
severity: advisory
|
|
897
|
+
needs_payload_bodies: [input]
|
|
835
898
|
|
|
836
899
|
# Role axis (road-to-token-economy-dispatch Phase 2). The dispatcher reads
|
|
837
900
|
# AGENT_CONFIG_SESSION_ROLE (resolved via _lib/session_role.ts — set ONLY by
|
|
@@ -884,17 +947,17 @@ roles:
|
|
|
884
947
|
platforms:
|
|
885
948
|
augment:
|
|
886
949
|
session_start: [chat-history, hot-context, handoff-context, session-canary, council-availability, telemetry-disclosure, first-run-gate, onboarding-gate, verify-before-complete, minimal-safe-diff, profile-staleness, wrapper-freshness, surface-probe, session-register]
|
|
887
|
-
session_end: [chat-history, memory-learn, session-register, roadmap-progress]
|
|
950
|
+
session_end: [chat-history, memory-learn, session-register, roadmap-progress, telemetry-flush]
|
|
888
951
|
stop: [chat-history, hot-context, verify-before-complete, self-repair, session-register, roadmap-progress]
|
|
889
952
|
pre_tool_use: [block-no-verify, block-unauthorized-git, evidence-independence, block-kernel-rule-writes, block-config-weakening, rtk-wrap, design-slop, ui-route-nudge, code-graph-nudge, ship-diff-volume, reread-guard]
|
|
890
953
|
post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder, orchestration-record, telemetry-usage, tool-result-bytes, edit-shape]
|
|
891
954
|
|
|
892
955
|
claude:
|
|
893
956
|
session_start: [chat-history, hot-context, handoff-context, session-canary, council-availability, telemetry-disclosure, first-run-gate, onboarding-gate, verify-before-complete, minimal-safe-diff, profile-staleness, wrapper-freshness, surface-probe, session-register]
|
|
894
|
-
session_end: [chat-history, memory-learn, session-register, roadmap-progress]
|
|
957
|
+
session_end: [chat-history, memory-learn, session-register, roadmap-progress, telemetry-flush]
|
|
895
958
|
stop: [chat-history, hot-context, verify-before-complete, team-review-gate, end-review-nudge, turn-end-gate, self-repair, session-register, session-eol, interruption-ledger, roadmap-progress, run-continuation]
|
|
896
959
|
user_prompt_submit: [chat-history, verify-before-complete, minimal-safe-diff, language-mirror, delegation-nudge, skill-route, git-authorization, session-canary, self-repair, session-register]
|
|
897
|
-
pre_tool_use: [block-no-verify, block-unauthorized-git, evidence-independence, block-kernel-rule-writes, block-config-weakening, rtk-wrap, design-slop, ui-route-nudge, code-graph-nudge, ship-diff-volume, reread-guard, spawn-guard-shadow]
|
|
960
|
+
pre_tool_use: [block-no-verify, block-unauthorized-git, evidence-independence, block-kernel-rule-writes, block-config-weakening, rtk-wrap, design-slop, ui-route-nudge, code-graph-nudge, ship-diff-volume, reread-guard, spawn-guard-shadow, source-first-gate]
|
|
898
961
|
post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder, orchestration-record, telemetry-usage, tool-result-bytes, edit-shape, language-mirror]
|
|
899
962
|
# `language-mirror` — round-5 § 6.1. `pre_compact` sets a pin-lost marker;
|
|
900
963
|
# the `post_tool_use` entry above re-emits the pin exactly once while that
|
|
@@ -935,7 +998,7 @@ platforms:
|
|
|
935
998
|
# agents/settings/contexts/chat-history-platform-hooks.md § Cowork.
|
|
936
999
|
cowork:
|
|
937
1000
|
session_start: [chat-history, hot-context, handoff-context, session-canary, council-availability, telemetry-disclosure, first-run-gate, onboarding-gate, verify-before-complete, minimal-safe-diff, profile-staleness, wrapper-freshness, surface-probe, session-register]
|
|
938
|
-
session_end: [chat-history, memory-learn, session-register, roadmap-progress]
|
|
1001
|
+
session_end: [chat-history, memory-learn, session-register, roadmap-progress, telemetry-flush]
|
|
939
1002
|
# end-review-nudge and delegation-nudge are DELIBERATELY NOT bound on
|
|
940
1003
|
# this platform (F10, review) — cowork-dispatcher.sh's own header states
|
|
941
1004
|
# it "always exit[s] 0" and its dispatch line discards the dispatcher's
|
|
@@ -948,7 +1011,7 @@ platforms:
|
|
|
948
1011
|
# still costs the dispatch, and its entire output is thrown away.
|
|
949
1012
|
stop: [chat-history, hot-context, verify-before-complete, self-repair, session-register, roadmap-progress]
|
|
950
1013
|
user_prompt_submit: [chat-history, verify-before-complete, minimal-safe-diff, language-mirror, git-authorization, session-canary, self-repair, session-register]
|
|
951
|
-
pre_tool_use: [block-no-verify, block-unauthorized-git, evidence-independence, block-kernel-rule-writes, block-config-weakening, rtk-wrap, design-slop, ui-route-nudge, code-graph-nudge, ship-diff-volume, reread-guard, spawn-guard-shadow]
|
|
1014
|
+
pre_tool_use: [block-no-verify, block-unauthorized-git, evidence-independence, block-kernel-rule-writes, block-config-weakening, rtk-wrap, design-slop, ui-route-nudge, code-graph-nudge, ship-diff-volume, reread-guard, spawn-guard-shadow, source-first-gate]
|
|
952
1015
|
post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder, orchestration-record, telemetry-usage, tool-result-bytes, edit-shape]
|
|
953
1016
|
# subagent-ledger IS bound here, unlike the two nudges above, and the
|
|
954
1017
|
# difference is the delivery channel rather than the platform: the nudges
|
|
@@ -969,7 +1032,7 @@ platforms:
|
|
|
969
1032
|
# agents/settings/contexts/chat-history-platform-hooks.md.
|
|
970
1033
|
cursor:
|
|
971
1034
|
session_start: [chat-history, hot-context, handoff-context, session-canary, council-availability, telemetry-disclosure, first-run-gate, onboarding-gate, verify-before-complete, minimal-safe-diff, profile-staleness, wrapper-freshness, surface-probe, session-register]
|
|
972
|
-
session_end: [chat-history, memory-learn, session-register, roadmap-progress]
|
|
1035
|
+
session_end: [chat-history, memory-learn, session-register, roadmap-progress, telemetry-flush]
|
|
973
1036
|
stop: [chat-history, hot-context, verify-before-complete, self-repair, session-register, roadmap-progress]
|
|
974
1037
|
user_prompt_submit: [chat-history, verify-before-complete, minimal-safe-diff, language-mirror, git-authorization, session-canary, self-repair, session-register]
|
|
975
1038
|
post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder, orchestration-record, telemetry-usage, tool-result-bytes, edit-shape]
|
|
@@ -984,7 +1047,7 @@ platforms:
|
|
|
984
1047
|
# session is interrupted with partial state (mirrors Augment Stop).
|
|
985
1048
|
cline:
|
|
986
1049
|
session_start: [chat-history, hot-context, handoff-context, session-canary, council-availability, telemetry-disclosure, first-run-gate, onboarding-gate, verify-before-complete, minimal-safe-diff, profile-staleness, wrapper-freshness, surface-probe, session-register]
|
|
987
|
-
session_end: [chat-history, memory-learn, session-register, roadmap-progress]
|
|
1050
|
+
session_end: [chat-history, memory-learn, session-register, roadmap-progress, telemetry-flush]
|
|
988
1051
|
stop: [chat-history, hot-context, verify-before-complete, self-repair, session-register, roadmap-progress]
|
|
989
1052
|
user_prompt_submit: [chat-history, verify-before-complete, minimal-safe-diff, language-mirror, git-authorization, session-canary, self-repair, session-register]
|
|
990
1053
|
post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder, orchestration-record, telemetry-usage, tool-result-bytes, edit-shape]
|
|
@@ -1020,7 +1083,7 @@ platforms:
|
|
|
1020
1083
|
# — this is our `stop` slot.
|
|
1021
1084
|
gemini:
|
|
1022
1085
|
session_start: [chat-history, hot-context, handoff-context, session-canary, council-availability, telemetry-disclosure, first-run-gate, onboarding-gate, verify-before-complete, minimal-safe-diff, profile-staleness, wrapper-freshness, surface-probe, session-register]
|
|
1023
|
-
session_end: [chat-history, memory-learn, session-register, roadmap-progress]
|
|
1086
|
+
session_end: [chat-history, memory-learn, session-register, roadmap-progress, telemetry-flush]
|
|
1024
1087
|
stop: [chat-history, hot-context, verify-before-complete, self-repair, session-register, roadmap-progress]
|
|
1025
1088
|
user_prompt_submit: [chat-history, verify-before-complete, minimal-safe-diff, language-mirror, git-authorization, session-canary, self-repair, session-register]
|
|
1026
1089
|
post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder, orchestration-record, telemetry-usage, tool-result-bytes, edit-shape]
|
|
@@ -38,7 +38,9 @@ import { substitutionPayloads } from './block_unauthorized_git.js';
|
|
|
38
38
|
|
|
39
39
|
const _HERE = fileURLToPath(import.meta.url);
|
|
40
40
|
|
|
41
|
-
const _SHELL_SEPARATORS: ReadonlySet<string> = new Set(['&&', '||', ';', '|']);
|
|
41
|
+
const _SHELL_SEPARATORS: ReadonlySet<string> = new Set(['&&', '||', ';', '|', '&']);
|
|
42
|
+
/** Characters that begin a shell separator, for `shlexSplit(s, true)`. */
|
|
43
|
+
const _OPERATOR_CHARS = ';|&';
|
|
42
44
|
const _NO_VERIFY_FLAGS: ReadonlySet<string> = new Set(['--no-verify']);
|
|
43
45
|
const _NO_VERIFY_SHORT: ReadonlySet<string> = new Set(['-n']);
|
|
44
46
|
const _HOOKS_PATH_RE = /^core\.hooksPath\s*=/i;
|
|
@@ -78,14 +80,36 @@ type JsonObject = { [k: string]: JsonValue };
|
|
|
78
80
|
* Faithful port of `shlex.split(s, comments=False, posix=True)` for the
|
|
79
81
|
* subset block_no_verify needs: whitespace tokenisation, single + double
|
|
80
82
|
* quotes, backslash escaping (POSIX), and a `ValueError("No closing
|
|
81
|
-
* quotation")` on an unterminated quote.
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
83
|
+
* quotation")` on an unterminated quote.
|
|
84
|
+
*
|
|
85
|
+
* `splitOperators` (default OFF, so the port stays faithful for
|
|
86
|
+
* `rtk_wrap_hook`, its other caller) additionally emits an UNQUOTED shell
|
|
87
|
+
* separator as its own token, maximal-munch for `&&` and `||`.
|
|
88
|
+
*
|
|
89
|
+
* WHY IT EXISTS. Without it, POSIX shlex leaves a separator attached to the
|
|
90
|
+
* preceding word — `git status; sed -n 1,5p f` tokenises as
|
|
91
|
+
* `['git','status;','sed','-n',...]`, one token, no separator. This docstring
|
|
92
|
+
* previously asserted the opposite ("they survive as embedded tokens ... the
|
|
93
|
+
* separator split below matches them as whole tokens"); that holds only when
|
|
94
|
+
* the separator is surrounded by whitespace, and the guard's segmentation is
|
|
95
|
+
* built on it. Measured 2026-08-20, the mistake had TWO faces and the second
|
|
96
|
+
* is the serious one:
|
|
97
|
+
*
|
|
98
|
+
* git status; sed -n 1,5p f → REFUSED (false positive: the `-n`
|
|
99
|
+
* of `sed` is read as git's)
|
|
100
|
+
* echo hi; git commit --no-verify → ALLOWED (BYPASS: the group starts
|
|
101
|
+
* with `echo`, so `_git_base` returns
|
|
102
|
+
* null and the git command is never
|
|
103
|
+
* scanned at all)
|
|
104
|
+
*
|
|
105
|
+
* Quote- and escape-safe by construction: the operator check lives in the
|
|
106
|
+
* unquoted word path only, so `git commit -m "a;b"` and `git commit -m a\;b`
|
|
107
|
+
* keep their semicolon inside one token and cannot be split into a group that
|
|
108
|
+
* no longer starts with `git`.
|
|
85
109
|
*/
|
|
86
110
|
class ShlexError extends Error {}
|
|
87
111
|
|
|
88
|
-
function shlexSplit(s: string): string[] {
|
|
112
|
+
function shlexSplit(s: string, splitOperators = false): string[] {
|
|
89
113
|
const whitespace = ' \t\r\n\f\v';
|
|
90
114
|
const quotes = '\'"';
|
|
91
115
|
const escape = '\\';
|
|
@@ -159,6 +183,25 @@ function shlexSplit(s: string): string[] {
|
|
|
159
183
|
}
|
|
160
184
|
continue;
|
|
161
185
|
}
|
|
186
|
+
if (splitOperators && _OPERATOR_CHARS.includes(c)) {
|
|
187
|
+
// Unquoted separator: close the word in progress, then emit the
|
|
188
|
+
// operator as its own token. Maximal munch so `&&` and `||` stay
|
|
189
|
+
// one token rather than two, matching _SHELL_SEPARATORS.
|
|
190
|
+
if (token !== null) {
|
|
191
|
+
tokens.push(token);
|
|
192
|
+
token = null;
|
|
193
|
+
}
|
|
194
|
+
const nxt = i + 1 < n ? (s[i + 1] as string) : null;
|
|
195
|
+
if (nxt === c && (c === '&' || c === '|')) {
|
|
196
|
+
tokens.push(c + c);
|
|
197
|
+
i += 2;
|
|
198
|
+
} else {
|
|
199
|
+
tokens.push(c);
|
|
200
|
+
i += 1;
|
|
201
|
+
}
|
|
202
|
+
state = 'ws';
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
162
205
|
if (escape.includes(c)) {
|
|
163
206
|
// POSIX escape outside quotes: backslash preserves the next char.
|
|
164
207
|
const nxt = i + 1 < n ? (s[i + 1] as string) : null;
|
|
@@ -293,19 +336,22 @@ function _is_blocked(git_tokens: string[]): [boolean, string] {
|
|
|
293
336
|
while (i < git_tokens.length) {
|
|
294
337
|
const tok = git_tokens[i] as string;
|
|
295
338
|
if (_NO_VERIFY_FLAGS.has(tok)) {
|
|
296
|
-
return [true, `'${tok}' bypasses git hooks (git-history-discipline)
|
|
339
|
+
return [true, `'${tok}' bypasses git hooks (git-history-discipline).`
|
|
340
|
+
+ ' Let the hooks run and fix what they report; that is the only path this guard leaves open.'];
|
|
297
341
|
}
|
|
298
342
|
if (_NO_VERIFY_SHORT.has(tok)) {
|
|
299
343
|
return [
|
|
300
344
|
true,
|
|
301
|
-
`'${tok}' is short for --no-verify and bypasses git hooks (git-history-discipline)
|
|
345
|
+
`'${tok}' is short for --no-verify and bypasses git hooks (git-history-discipline).`
|
|
346
|
+
+ ' Let the hooks run and fix what they report; that is the only path this guard leaves open.',
|
|
302
347
|
];
|
|
303
348
|
}
|
|
304
349
|
// Short flag bundles containing 'n': -nm, -mn, etc.
|
|
305
350
|
if (/^-[a-zA-Z]*n[a-zA-Z]*$/.test(tok) && !tok.startsWith('--')) {
|
|
306
351
|
return [
|
|
307
352
|
true,
|
|
308
|
-
`'${tok}' contains -n (--no-verify) and bypasses git hooks (git-history-discipline)
|
|
353
|
+
`'${tok}' contains -n (--no-verify) and bypasses git hooks (git-history-discipline).`
|
|
354
|
+
+ ' Let the hooks run and fix what they report; that is the only path this guard leaves open.',
|
|
309
355
|
];
|
|
310
356
|
}
|
|
311
357
|
if (tok === '-c') {
|
|
@@ -492,7 +538,12 @@ function _check_command(cmd: string, depth = 0): [boolean, string] {
|
|
|
492
538
|
}
|
|
493
539
|
let tokens: string[];
|
|
494
540
|
try {
|
|
495
|
-
|
|
541
|
+
// splitOperators: an unquoted `;` / `&&` / `||` / `|` / `&` becomes its
|
|
542
|
+
// own token, so _split_subcommands can see it. Without it a separator
|
|
543
|
+
// attached to the preceding word (`status;`) kept the whole line in one
|
|
544
|
+
// group — refusing `git status; sed -n 1,5p f` and, in the other
|
|
545
|
+
// direction, never scanning `echo hi; git commit --no-verify` at all.
|
|
546
|
+
tokens = shlexSplit(stripped, true);
|
|
496
547
|
} catch (e) {
|
|
497
548
|
if (e instanceof ShlexError) {
|
|
498
549
|
// Tested against the string that actually failed to parse. Round 7
|
|
@@ -486,7 +486,7 @@ export function commandOp(command: string): GitOp | null {
|
|
|
486
486
|
}
|
|
487
487
|
|
|
488
488
|
/** A ledger older than this is not "this turn" under any reading. */
|
|
489
|
-
export const LEDGER_MAX_AGE_MS =
|
|
489
|
+
export const LEDGER_MAX_AGE_MS = 6 * 60 * 60 * 1000; // TEMP: PR-drain run, revert after
|
|
490
490
|
|
|
491
491
|
/**
|
|
492
492
|
* Load the ledger, and refuse one that does not belong to THIS session and
|
|
@@ -59,6 +59,7 @@ import { main as codeGraphNudgeMain } from './code_graph_nudge_hook.js';
|
|
|
59
59
|
import { main as uiRouteNudgeMain } from './ui_route_nudge_hook.js';
|
|
60
60
|
import { main as orchestrationRecordMain } from './orchestration_record_hook.js';
|
|
61
61
|
import { main as telemetryUsageMain } from './telemetry_usage_hook.js';
|
|
62
|
+
import { main as telemetryFlushMain } from './telemetry_flush_hook.js';
|
|
62
63
|
import { main as delegationNudgeMain } from './delegation_nudge_hook.js';
|
|
63
64
|
import { main as skillRouteMain } from './skill_route_hook.js';
|
|
64
65
|
import { main as endReviewNudgeMain } from './end_review_nudge_hook.js';
|
|
@@ -69,6 +70,7 @@ import { main as sessionEolMain } from './session_eol_hook.js';
|
|
|
69
70
|
import { main as subagentLedgerMain } from './subagent_ledger_hook.js';
|
|
70
71
|
import { main as toolResultBytesMain } from './tool_result_bytes_hook.js';
|
|
71
72
|
import { main as spawnGuardShadowMain } from './spawn_guard_shadow_hook.js';
|
|
73
|
+
import { main as sourceFirstGateMain } from './source_first_gate_hook.js';
|
|
72
74
|
import { main as interruptionLedgerMain } from './interruption_ledger_hook.js';
|
|
73
75
|
import { main as runContinuationMain } from './run_continuation_hook.js';
|
|
74
76
|
|
|
@@ -112,6 +114,7 @@ export const CONCERN_REGISTRY: Readonly<Record<string, ConcernMain>> = {
|
|
|
112
114
|
'src/scripts/hooks/ui_route_nudge_hook.ts': uiRouteNudgeMain as ConcernMain,
|
|
113
115
|
'src/scripts/hooks/orchestration_record_hook.ts': orchestrationRecordMain as ConcernMain,
|
|
114
116
|
'src/scripts/hooks/telemetry_usage_hook.ts': telemetryUsageMain as ConcernMain,
|
|
117
|
+
'src/scripts/hooks/telemetry_flush_hook.ts': telemetryFlushMain as ConcernMain,
|
|
115
118
|
'src/scripts/hooks/delegation_nudge_hook.ts': delegationNudgeMain as ConcernMain,
|
|
116
119
|
'src/scripts/hooks/skill_route_hook.ts': skillRouteMain as ConcernMain,
|
|
117
120
|
'src/scripts/hooks/end_review_nudge_hook.ts': endReviewNudgeMain as ConcernMain,
|
|
@@ -122,6 +125,7 @@ export const CONCERN_REGISTRY: Readonly<Record<string, ConcernMain>> = {
|
|
|
122
125
|
'src/scripts/hooks/subagent_ledger_hook.ts': subagentLedgerMain as ConcernMain,
|
|
123
126
|
'src/scripts/hooks/tool_result_bytes_hook.ts': toolResultBytesMain as ConcernMain,
|
|
124
127
|
'src/scripts/hooks/spawn_guard_shadow_hook.ts': spawnGuardShadowMain as ConcernMain,
|
|
128
|
+
'src/scripts/hooks/source_first_gate_hook.ts': sourceFirstGateMain as ConcernMain,
|
|
125
129
|
'src/scripts/hooks/interruption_ledger_hook.ts': interruptionLedgerMain as ConcernMain,
|
|
126
130
|
'src/scripts/hooks/run_continuation_hook.ts': runContinuationMain as ConcernMain,
|
|
127
131
|
};
|
|
@@ -155,14 +155,19 @@ export function classify(command: string): Eligibility {
|
|
|
155
155
|
|
|
156
156
|
let tokens: string[];
|
|
157
157
|
try {
|
|
158
|
-
tokens = shlexSplit(cmd);
|
|
158
|
+
tokens = shlexSplit(cmd, true);
|
|
159
159
|
} catch (e) {
|
|
160
160
|
if (e instanceof ShlexError) return { eligible: false, reason_skip: "parse-error" };
|
|
161
161
|
throw e;
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
// Compound / piped → don't wrap (rtk wraps a single command). `_split_subcommands`
|
|
165
|
-
// splits on && || ; | — more than one group means a pipeline/chain.
|
|
165
|
+
// splits on && || ; | & — more than one group means a pipeline/chain.
|
|
166
|
+
// `splitOperators` is REQUIRED here: POSIX shlex leaves a separator attached
|
|
167
|
+
// to the preceding word, so `foo; bar` tokenised to one group and read as a
|
|
168
|
+
// single command. Same construct as the block_no_verify defect measured
|
|
169
|
+
// 2026-08-20; found by the sibling search for that fix, 2 call sites, both
|
|
170
|
+
// in this file.
|
|
166
171
|
const groups = _split_subcommands(tokens);
|
|
167
172
|
if (groups.length !== 1) return { eligible: false, reason_skip: "compound-or-piped" };
|
|
168
173
|
|
|
@@ -256,7 +261,7 @@ export function classifyCap(
|
|
|
256
261
|
if (!cmd) return null;
|
|
257
262
|
let tokens: string[];
|
|
258
263
|
try {
|
|
259
|
-
tokens = shlexSplit(cmd);
|
|
264
|
+
tokens = shlexSplit(cmd, true);
|
|
260
265
|
} catch (e) {
|
|
261
266
|
if (e instanceof ShlexError) return null;
|
|
262
267
|
throw e;
|
|
@@ -72,12 +72,15 @@
|
|
|
72
72
|
* duplicate, whatever the counts say.
|
|
73
73
|
* scope complete (0 open,
|
|
74
74
|
* none blocked) → allow (event: complete; state cleared)
|
|
75
|
-
*
|
|
76
|
-
* (0 open, ≥1
|
|
75
|
+
* remaining work externally
|
|
76
|
+
* impossible (0 open, ≥1
|
|
77
|
+
* blocked) → allow (event: blocked, ONCE per run, guarded by
|
|
77
78
|
* the LEDGER: the state is cleared like `complete`,
|
|
78
|
-
* so no field there outlives the event.
|
|
79
|
-
*
|
|
80
|
-
* `HALT_ACTIONS`, never stamped into `halted
|
|
79
|
+
* so no field there outlives the event. A terminal
|
|
80
|
+
* outcome — not a sixth halt, never in
|
|
81
|
+
* `HALT_ACTIONS`, never stamped into `halted`.
|
|
82
|
+
* ADR-237 narrows what may legally wear a
|
|
83
|
+
* `blocked-by:` marker; semantics unchanged.)
|
|
81
84
|
* iterations ≥ MAX (25) → allow (event: halt-max-iterations)
|
|
82
85
|
* wall clock ≥ cap (4 h) → allow (event: halt-wall-clock)
|
|
83
86
|
* stall (3 engagements, no
|
|
@@ -33,6 +33,7 @@ import path from 'node:path';
|
|
|
33
33
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
34
34
|
|
|
35
35
|
import { readHookStdin } from './hook_stdin.js';
|
|
36
|
+
import { isPayloadStub } from './payload_stub.js';
|
|
36
37
|
import { atomic_write_json } from './state_io.js';
|
|
37
38
|
|
|
38
39
|
export const STATE_FILE = path.join('agents', 'state', 'ship-diff-volume.json');
|
|
@@ -89,31 +90,96 @@ export function correctedVolume(numstat: string): { volume: number; excluded: nu
|
|
|
89
90
|
return { volume, excluded, files };
|
|
90
91
|
}
|
|
91
92
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
/**
|
|
94
|
+
* Tools that carry a shell command. Mirrors `block_unauthorized_git`'s set.
|
|
95
|
+
*
|
|
96
|
+
* `SHIP_PATTERNS` are unanchored, so without this gate a `grep` for the string
|
|
97
|
+
* `git push` spawns two `git` subprocesses on a blocking slot. ALLOW-list: a
|
|
98
|
+
* named tool outside it is declined, so an unlisted host shell goes dark until
|
|
99
|
+
* added — the trade that sibling already makes while BLOCKING. A payload naming
|
|
100
|
+
* no tool still reads; that is the bare-host shape, with nothing to gate on.
|
|
101
|
+
*/
|
|
102
|
+
const COMMAND_TOOLS: ReadonlySet<string> = new Set([
|
|
103
|
+
'launch-process',
|
|
104
|
+
'launch_process',
|
|
105
|
+
'Bash',
|
|
106
|
+
'BashTool',
|
|
107
|
+
'run-process',
|
|
108
|
+
'runProcess',
|
|
109
|
+
'shell',
|
|
110
|
+
'execute_shell',
|
|
111
|
+
'RunShellCommand',
|
|
112
|
+
]);
|
|
113
|
+
|
|
114
|
+
function isObj(v: unknown): v is Record<string, unknown> {
|
|
115
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Descend to the platform payload.
|
|
120
|
+
*
|
|
121
|
+
* The dispatcher nests the host-shaped tool fields under `payload`
|
|
122
|
+
* (`_build_envelope`); a bare host invocation puts them at the top level. This
|
|
123
|
+
* concern shipped reading the top level ONLY, so under the real dispatcher it
|
|
124
|
+
* found nothing and returned `''` every time — it ran, cost a dispatch, and
|
|
125
|
+
* could never fire.
|
|
126
|
+
*
|
|
127
|
+
* Deliberately NOT `envelope.ts`'s shared `unwrap`, which descends only when all
|
|
128
|
+
* four `ENVELOPE_KEYS` are present: a partial envelope would return this concern
|
|
129
|
+
* to its pre-fix dead state with no test noticing. `design-slop` and
|
|
130
|
+
* `ui-route-nudge` each carry their own local descent for the same reason.
|
|
131
|
+
*/
|
|
132
|
+
function payloadOf(root: Record<string, unknown>): Record<string, unknown> {
|
|
133
|
+
const inner = root['payload'];
|
|
134
|
+
return isObj(inner) ? inner : root;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** The ship command, or `''` when this payload does not carry one. */
|
|
138
|
+
function shipCommandFrom(payload: Record<string, unknown>): string {
|
|
139
|
+
const toolRaw = payload['tool_name'] ?? payload['toolName'] ?? payload['tool'];
|
|
140
|
+
if (typeof toolRaw === 'string' && !COMMAND_TOOLS.has(toolRaw)) return '';
|
|
141
|
+
|
|
142
|
+
const ti = payload['tool_input'] ?? payload['toolInput'];
|
|
143
|
+
if (isPayloadStub(ti)) {
|
|
144
|
+
// Body omitted despite `needs_payload_bodies: [input]`. A bare '' here is
|
|
145
|
+
// indistinguishable from "no ship verb" — the silent death this file was
|
|
146
|
+
// fixed to remove — so say so instead of dying quietly again.
|
|
147
|
+
process.stderr.write(
|
|
148
|
+
'ship-diff-volume: tool_input arrived stubbed; the concern declares ' +
|
|
149
|
+
'needs_payload_bodies: [input] and cannot read a command without it.\n',
|
|
150
|
+
);
|
|
151
|
+
return '';
|
|
152
|
+
}
|
|
153
|
+
if (isObj(ti)) {
|
|
154
|
+
const c = ti['command'];
|
|
96
155
|
if (typeof c === 'string') return c;
|
|
97
156
|
}
|
|
98
|
-
const c =
|
|
157
|
+
const c = payload['command'];
|
|
99
158
|
return typeof c === 'string' ? c : '';
|
|
100
159
|
}
|
|
101
160
|
|
|
161
|
+
/**
|
|
162
|
+
* The stdin boundary: raw concern stdin → the ship command. Exported so a
|
|
163
|
+
* regression drives the boundary rather than the extractor. Never throws.
|
|
164
|
+
*/
|
|
165
|
+
export function commandFromStdin(raw: string): string {
|
|
166
|
+
if (!raw.trim()) return '';
|
|
167
|
+
let root: unknown;
|
|
168
|
+
try {
|
|
169
|
+
root = JSON.parse(raw);
|
|
170
|
+
} catch {
|
|
171
|
+
return '';
|
|
172
|
+
}
|
|
173
|
+
if (!isObj(root)) return '';
|
|
174
|
+
return shipCommandFrom(payloadOf(root));
|
|
175
|
+
}
|
|
176
|
+
|
|
102
177
|
export function main(argv?: string[]): number {
|
|
103
178
|
const args = argv ?? process.argv.slice(2);
|
|
104
179
|
const idx = args.indexOf('--command');
|
|
105
180
|
let cmd = idx >= 0 && args[idx + 1] !== undefined ? args[idx + 1]! : '';
|
|
106
181
|
if (!cmd) {
|
|
107
|
-
|
|
108
|
-
let envelope: Record<string, unknown> = {};
|
|
109
|
-
if (raw.trim()) {
|
|
110
|
-
try {
|
|
111
|
-
envelope = JSON.parse(raw) as Record<string, unknown>;
|
|
112
|
-
} catch {
|
|
113
|
-
envelope = {};
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
cmd = extractCommand(envelope);
|
|
182
|
+
cmd = commandFromStdin(readHookStdin());
|
|
117
183
|
}
|
|
118
184
|
if (!isShipCommand(cmd)) return 0;
|
|
119
185
|
|