@event4u/agent-config 14.18.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.
Files changed (146) hide show
  1. package/.augment-plugin/marketplace.json +3 -3
  2. package/.augment-plugin/plugin.json +1 -1
  3. package/.claude-plugin/marketplace.json +1 -1
  4. package/CHANGELOG.md +169 -130
  5. package/README.md +71 -149
  6. package/dist/agent-src/README.md +1 -1
  7. package/dist/agent-src/commands/agent-handoff.md +2 -2
  8. package/dist/agent-src/commands/review/changes.md +19 -19
  9. package/dist/agent-src/commands/review.md +2 -2
  10. package/dist/agent-src/contexts/execution/host-capability-manifest.md +30 -3
  11. package/dist/agent-src/rules/autonomous-execution.md +1 -1
  12. package/dist/agent-src/rules/git-history-discipline.md +2 -2
  13. package/dist/agent-src/rules/guidelines.md +1 -1
  14. package/dist/agent-src/rules/session-canary.md +2 -2
  15. package/dist/agent-src/rules/token-efficiency.md +1 -1
  16. package/dist/agent-src/skills/adversarial-review/SKILL.md +0 -8
  17. package/dist/agent-src/skills/canvas-design/SKILL.md +1 -1
  18. package/dist/agent-src/skills/design-intelligence/SKILL.md +1 -1
  19. package/dist/agent-src/skills/design-intelligence/data/app-interface.csv +1 -1
  20. package/dist/agent-src/skills/design-intelligence/data/motion.csv +17 -17
  21. package/dist/agent-src/skills/design-intelligence/data/ux-guidelines.csv +2 -2
  22. package/dist/agent-src/skills/design-intelligence/references/context-and-registers.md +17 -0
  23. package/dist/agent-src/skills/design-intelligence/references/design-rules-checklist.md +4 -4
  24. package/dist/agent-src/skills/design-review/SKILL.md +1 -1
  25. package/dist/agent-src/skills/design-variations/SKILL.md +1 -1
  26. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +1 -1
  27. package/dist/agent-src/skills/fe-design/SKILL.md +32 -5
  28. package/dist/agent-src/skills/fe-design/references/craft-floor.md +7 -0
  29. package/dist/agent-src/skills/fe-design/references/design-patterns.md +47 -2
  30. package/dist/agent-src/skills/laravel-scheduling/SKILL.md +3 -1
  31. package/dist/agent-src/skills/project-analyzer/SKILL.md +0 -6
  32. package/dist/agent-src/skills/react-native-setup/SKILL.md +3 -3
  33. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +1 -1
  34. package/dist/agent-src/skills/sequential-thinking/SKILL.md +18 -8
  35. package/dist/agent-src/skills/tailwind-engineer/SKILL.md +1 -1
  36. package/dist/agent-src/skills/ui-apply-generic/SKILL.md +1 -1
  37. package/dist/agent-src/skills/ui-component-architect/SKILL.md +1 -1
  38. package/dist/agent-src/skills/using-git-worktrees/SKILL.md +17 -2
  39. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  40. package/dist/cli/commands/recordTriggerEval.js +2 -2
  41. package/dist/cli/main.js +1 -1
  42. package/dist/cli-delegate/{chunk-AKJGUQNO.js → chunk-GZTMRYCN.js} +405 -341
  43. package/dist/cli-delegate/{chunk-7RXIKF62.js → chunk-IDHUQIXP.js} +283 -132
  44. package/dist/cli-delegate/cmd_adr_effective.js +318 -81
  45. package/dist/cli-delegate/cmd_conformance.js +420 -16
  46. package/dist/cli-delegate/cmd_doctor.js +1 -1
  47. package/dist/cli-delegate/cmd_export.js +1 -1
  48. package/dist/cli-delegate/cmd_handoff.js +1 -1
  49. package/dist/cli-delegate/cmd_prune.js +1 -1
  50. package/dist/cli-delegate/cmd_route_audit.js +1 -1
  51. package/dist/cli-delegate/cmd_settings_migrate.js +1 -1
  52. package/dist/cli-delegate/cmd_sync.js +1 -1
  53. package/dist/cli-delegate/cmd_uninstall.js +1 -1
  54. package/dist/cli-delegate/cmd_validate.js +1 -1
  55. package/dist/discovery/deprecation-report.md +1 -1
  56. package/dist/discovery/discovery-manifest.json +28 -27
  57. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  58. package/dist/discovery/discovery-manifest.summary.md +1 -1
  59. package/dist/discovery/dormancy-report.md +1 -1
  60. package/dist/discovery/orphan-report.md +1 -1
  61. package/dist/discovery/packs.json +2 -2
  62. package/dist/discovery/trust-report.md +1 -1
  63. package/dist/discovery/workspaces.json +2 -2
  64. package/dist/hooks/dispatch.js +2132 -1462
  65. package/dist/install/install.mjs +588 -527
  66. package/dist/mcp/registry-manifest.json +1 -1
  67. package/dist/mcp/server.json +2 -2
  68. package/dist/mcp/server.mjs +1619 -1045
  69. package/dist/scripts/_lib/model_tier.js +1 -1
  70. package/docs/guidelines/agent-infra/evaluator-independence-mechanics.md +1 -1
  71. package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
  72. package/docs/guidelines/design-antipatterns.md +87 -64
  73. package/package.json +1 -1
  74. package/src/agent-src/README.md +1 -1
  75. package/src/config/ci-local-parity.yml +6 -0
  76. package/src/config/gate-coverage.yml +170 -0
  77. package/src/config/gate-violation-baselines.json +3 -3
  78. package/src/config/release-gate-locality.yml +12 -0
  79. package/src/scripts/_cli/cmd_doctor.ts +2 -2
  80. package/src/scripts/_cli/cmd_handoff.ts +1 -1
  81. package/src/scripts/_cli/cmd_update.ts +1 -1
  82. package/src/scripts/_cli/cmd_versions.ts +1 -1
  83. package/src/scripts/_lib/adr_frontmatter.ts +44 -0
  84. package/src/scripts/_lib/consequence_objects.ts +152 -0
  85. package/src/scripts/_lib/exec_evidence.ts +7 -0
  86. package/src/scripts/_lib/global_deploy_inventory.ts +2 -2
  87. package/src/scripts/_lib/host_permission_checks.ts +251 -0
  88. package/src/scripts/_lib/model_tier.ts +1 -1
  89. package/src/scripts/_lib/obligation_frequency.ts +2 -2
  90. package/src/scripts/_lib/release_highlights.ts +93 -0
  91. package/src/scripts/_lib/release_material.ts +64 -1
  92. package/src/scripts/_lib/runtime_journal.ts +26 -3
  93. package/src/scripts/_lib/runtime_wiring_checks.ts +12 -1
  94. package/src/scripts/_lib/session_register.ts +11 -6
  95. package/src/scripts/_lib/sqlite_schema.ts +22 -0
  96. package/src/scripts/_lib/surface.ts +86 -0
  97. package/src/scripts/_lib/ui_authority.ts +116 -0
  98. package/src/scripts/adr/regenerate_index.ts +54 -1
  99. package/src/scripts/adr_cite_check.ts +71 -15
  100. package/src/scripts/ai_council/clients.ts +1 -1
  101. package/src/scripts/autonomy_friction_corpus.ts +229 -0
  102. package/src/scripts/build_proof.ts +15 -2
  103. package/src/scripts/check_beta_review_markers.ts +141 -17
  104. package/src/scripts/check_enforcement_coverage.ts +1 -1
  105. package/src/scripts/check_enforcement_denominator.ts +121 -11
  106. package/src/scripts/check_finding_dispositions.ts +66 -9
  107. package/src/scripts/check_gate_coverage.ts +96 -0
  108. package/src/scripts/check_release_highlights.ts +74 -1
  109. package/src/scripts/check_skill_activation_claim.ts +179 -0
  110. package/src/scripts/check_trigger_evals.ts +1 -1
  111. package/src/scripts/conformance_scan.ts +44 -3
  112. package/src/scripts/explain_run.ts +1 -1
  113. package/src/scripts/generate_capability_matrix.ts +1 -1
  114. package/src/scripts/git_authorization_hook.ts +75 -1
  115. package/src/scripts/hook_manifest.json +1 -1
  116. package/src/scripts/hook_manifest.yaml +14 -11
  117. package/src/scripts/hooks/augment-dispatcher.sh +1 -1
  118. package/src/scripts/hooks/category_a.ts +291 -0
  119. package/src/scripts/hooks/cline-dispatcher.sh +1 -1
  120. package/src/scripts/hooks/cursor-dispatcher.sh +11 -5
  121. package/src/scripts/hooks/dispatch_hook.ts +17 -22
  122. package/src/scripts/hooks/git_command_classifier.ts +156 -1
  123. package/src/scripts/hooks/host_lowering.ts +215 -0
  124. package/src/scripts/hooks/host_lowering.yaml +185 -0
  125. package/src/scripts/hooks/host_semantics.ts +105 -37
  126. package/src/scripts/hooks/journal_record_hook.ts +10 -0
  127. package/src/scripts/hooks/permission_gate.ts +117 -0
  128. package/src/scripts/hooks_status.ts +12 -10
  129. package/src/scripts/install.ts +53 -82
  130. package/src/scripts/install_anthropic_key.sh +2 -2
  131. package/src/scripts/lint_design_antipattern_parity.ts +80 -0
  132. package/src/scripts/lint_evidence_artifacts.ts +45 -1
  133. package/src/scripts/lint_hook_manifest.ts +87 -3
  134. package/src/scripts/lint_motion_authority_drift.ts +731 -0
  135. package/src/scripts/lint_readme_size.ts +158 -12
  136. package/src/scripts/lint_reasoning_fixtures.ts +216 -0
  137. package/src/scripts/lint_skill_trigger_contradiction.ts +161 -0
  138. package/src/scripts/measure_sibling_naming.ts +150 -0
  139. package/src/scripts/redact_hook_capture.ts +1 -1
  140. package/src/scripts/report_skill_activation.ts +319 -7
  141. package/src/scripts/schemas/review-findings.schema.json +5 -0
  142. package/src/scripts/schemas/skill.schema.json +2 -2
  143. package/src/scripts/session_canary_hook.ts +1 -1
  144. package/src/scripts/session_register_hook.ts +4 -3
  145. package/src/scripts/trigger_eval_grandfather.json +5 -1
  146. package/src/scripts/validate_agent_settings.ts +1 -1
@@ -1 +1 @@
1
- {"fingerprint":"40918412:83446","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-speaking-inbox-dir":{"script":"src/scripts/hooks/block_speaking_inbox_dir.ts","args":[],"fail_closed":false,"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"]},"design-pass":{"script":"src/scripts/hooks/design_pass_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"design-pass-stop":{"script":"src/scripts/hooks/design_pass_hook.ts","args":["--slot","stop"],"fail_closed":false,"severity":"advisory"},"ui-route-nudge":{"script":"src/scripts/hooks/ui_route_nudge_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"suggestion-capture":{"script":"src/scripts/hooks/suggestion_capture_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"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"]},"push-settle":{"script":"src/scripts/hooks/push_settle_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"},"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},"rule-inject":{"script":"src/scripts/hooks/rule_inject_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"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"},"comment-discipline":{"script":"src/scripts/hooks/comment_discipline_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Write","Edit"],"needs_payload_bodies":["input"]},"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"]},"journal-record":{"script":"src/scripts/hooks/journal_record_hook.ts","args":[],"fail_closed":false,"severity":"advisory"}},"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","design-pass-stop"],"pre_tool_use":["block-no-verify","evidence-independence","block-kernel-rule-writes","block-config-weakening","block-speaking-inbox-dir","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","push-settle","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","comment-discipline","design-pass"]},"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","journal-record"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress","telemetry-flush","journal-record"],"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","design-pass-stop","suggestion-capture","journal-record","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","rule-inject","suggestion-capture","journal-record"],"pre_tool_use":["block-no-verify","evidence-independence","block-kernel-rule-writes","block-config-weakening","block-speaking-inbox-dir","rtk-wrap","design-slop","ui-route-nudge","code-graph-nudge","ship-diff-volume","reread-guard","spawn-guard-shadow","source-first-gate","rule-inject"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","push-settle","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","comment-discipline","language-mirror","design-pass","journal-record"],"pre_compact":["language-mirror","hot-context","rule-inject","journal-record"],"subagent_start":["subagent-ledger","journal-record"],"subagent_stop":["subagent-ledger","journal-record"]},"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","design-pass-stop"],"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","evidence-independence","block-kernel-rule-writes","block-config-weakening","block-speaking-inbox-dir","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","push-settle","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","comment-discipline","design-pass"],"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","design-pass-stop"],"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","push-settle","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","comment-discipline","design-pass"]},"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","design-pass-stop"],"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","push-settle","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","comment-discipline","design-pass"]},"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","design-pass-stop"],"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","design-pass-stop"],"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","push-settle","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","comment-discipline","design-pass"]},"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":"8ca65564:83643","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-speaking-inbox-dir":{"script":"src/scripts/hooks/block_speaking_inbox_dir.ts","args":[],"fail_closed":false,"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"]},"design-pass":{"script":"src/scripts/hooks/design_pass_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"design-pass-stop":{"script":"src/scripts/hooks/design_pass_hook.ts","args":["--slot","stop"],"fail_closed":false,"severity":"advisory"},"ui-route-nudge":{"script":"src/scripts/hooks/ui_route_nudge_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"suggestion-capture":{"script":"src/scripts/hooks/suggestion_capture_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"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"]},"push-settle":{"script":"src/scripts/hooks/push_settle_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"},"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},"rule-inject":{"script":"src/scripts/hooks/rule_inject_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"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"},"comment-discipline":{"script":"src/scripts/hooks/comment_discipline_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Write","Edit"],"needs_payload_bodies":["input"]},"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"]},"journal-record":{"script":"src/scripts/hooks/journal_record_hook.ts","args":[],"fail_closed":false,"severity":"advisory"}},"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","design-pass-stop"],"pre_tool_use":["block-no-verify","evidence-independence","block-kernel-rule-writes","block-config-weakening","block-speaking-inbox-dir","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","push-settle","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","comment-discipline","design-pass"]},"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","journal-record"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress","telemetry-flush","journal-record"],"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","design-pass-stop","suggestion-capture","journal-record","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","rule-inject","suggestion-capture","journal-record"],"pre_tool_use":["block-no-verify","evidence-independence","block-kernel-rule-writes","block-config-weakening","block-speaking-inbox-dir","rtk-wrap","design-slop","ui-route-nudge","code-graph-nudge","ship-diff-volume","reread-guard","spawn-guard-shadow","source-first-gate","rule-inject"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","push-settle","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","comment-discipline","language-mirror","design-pass","journal-record"],"pre_compact":["language-mirror","hot-context","rule-inject","journal-record"],"subagent_start":["subagent-ledger","journal-record"],"subagent_stop":["subagent-ledger","journal-record"]},"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","design-pass-stop"],"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","evidence-independence","block-kernel-rule-writes","block-config-weakening","block-speaking-inbox-dir","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","push-settle","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","comment-discipline","design-pass"],"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","design-pass-stop"],"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","push-settle","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","comment-discipline","design-pass"]},"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","design-pass-stop"],"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","push-settle","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","comment-discipline","design-pass"]},"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","design-pass-stop"],"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","design-pass-stop"],"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","push-settle","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","comment-discipline","design-pass"]},"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,8 +1,8 @@
1
1
  # Hook manifest — single source of truth for which concerns fire on which
2
2
  # (platform, event) tuples. Consumed by:
3
- # - scripts/hooks/dispatch_hook.py (runtime resolver)
4
- # - scripts/lint_hook_manifest.py (CI gate; Phase 7.10)
5
- # - scripts/install.py (per-platform config writer)
3
+ # - src/scripts/hooks/dispatch_hook.ts (runtime resolver)
4
+ # - src/scripts/lint_hook_manifest.ts (CI gate; Phase 7.10)
5
+ # - src/scripts/install.ts (per-platform config writer)
6
6
  #
7
7
  # Schema and event vocabulary: docs/contracts/hook-architecture-v1.md.
8
8
  # Per-platform event-name mapping: agents/settings/contexts/chat-history-platform-hooks.md.
@@ -626,8 +626,9 @@ concerns:
626
626
  #
627
627
  # Correctness rests on heartbeat + TTL alone; deregistration only frees a claim
628
628
  # sooner. So Windsurf's missing session_end costs latency, not correctness.
629
- # Declared non-carriers: copilot (no hook surface), cursor CLI (per-turn slots
630
- # are IDE-only), cowork (slots wired, lifecycle events inert) — a session there
629
+ # Declared non-carriers: copilot (this package binds nothing there and has
630
+ # measured nothing there), cursor (per-turn reachability unestablished), cowork
631
+ # (slots wired, lifecycle events inert) — a session there
631
632
  # registers but expires by TTL rather than heartbeating, and the concern says so
632
633
  # on stderr rather than letting the coverage join read green.
633
634
  # Never blocks. fail_closed: false.
@@ -1256,11 +1257,12 @@ platforms:
1256
1257
 
1257
1258
  # Phase 7.5 — Cursor. `.cursor/hooks.json` (project) is read by the
1258
1259
  # IDE and CLI; `~/.cursor/hooks.json` (user) is opt-in via
1259
- # `install.py --cursor-user-hooks` and uses scripts/hooks/cursor-dispatcher.sh
1260
+ # `agent-config install --cursor-user-hooks` and uses scripts/hooks/cursor-dispatcher.sh
1260
1261
  # to route into the active workspace. UserPromptSubmit maps to
1261
- # `beforeSubmitPrompt` (Cursor third-party-hooks table). Stop is
1262
- # IDE-only — CLI-only users fall back to /checkpoint per
1263
- # agents/settings/contexts/chat-history-platform-hooks.md.
1262
+ # `beforeSubmitPrompt` (Cursor third-party-hooks table). Whether the CLI
1263
+ # surface fires `stop` is not established here; the /checkpoint fallback
1264
+ # covers a session where it does not. See
1265
+ # agents/settings/contexts/chat-history-platform-hooks.md § Cursor.
1264
1266
  cursor:
1265
1267
  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]
1266
1268
  session_end: [chat-history, memory-learn, session-register, roadmap-progress, telemetry-flush]
@@ -1319,8 +1321,9 @@ platforms:
1319
1321
  user_prompt_submit: [chat-history, verify-before-complete, minimal-safe-diff, language-mirror, git-authorization, session-canary, self-repair, session-register]
1320
1322
  post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder, push-settle, orchestration-record, telemetry-usage, tool-result-bytes, edit-shape, comment-discipline, design-pass]
1321
1323
 
1322
- # Phase 7.9 — Copilot has no hook surface. Concerns route through
1323
- # rule-only fallback; the dispatcher silently no-ops on --platform copilot.
1324
+ # Phase 7.9 — this package binds no hook on Copilot and has measured none
1325
+ # there. Concerns route through rule-only fallback; the dispatcher silently
1326
+ # no-ops on --platform copilot.
1324
1327
  copilot:
1325
1328
  fallback_only: true
1326
1329
 
@@ -4,7 +4,7 @@
4
4
  # Replaces the four per-concern trampolines (augment-chat-history.sh,
5
5
  # augment-roadmap-progress.sh, augment-onboarding-gate.sh,
6
6
  # augment-context-hygiene.sh). One script, dispatched per (platform, event)
7
- # tuple via scripts/hooks/dispatch_hook.py reading scripts/hook_manifest.yaml.
7
+ # tuple via src/scripts/hooks/dispatch_hook.ts reading src/scripts/hook_manifest.yaml.
8
8
  #
9
9
  # Augment requires hook scripts to use the .sh extension and live at user
10
10
  # scope (~/.augment/hooks/) — same constraint as the legacy trampolines.
@@ -0,0 +1,291 @@
1
+ /**
2
+ * category_a — which `pre_tool_use` calls this package is willing to hand the
3
+ * host an explicit `permissionDecision: allow` for.
4
+ *
5
+ * WHY THIS EXISTS. `host_semantics` built exactly one envelope shape, so a
6
+ * call this package does not gate at all still cost the user a host
7
+ * confirmation. `permissionDecision` is offered by the host contract and was
8
+ * never emitted, so the prompt is ours to remove — but only for calls where
9
+ * "we do not gate this" is a fact about the call rather than about our
10
+ * coverage. That is what category A names: reads, navigation, build, test and
11
+ * lint inside the working tree with no consequence operation attached.
12
+ *
13
+ * THE CLASSIFIER IS AN ALLOWLIST AND MUST STAY ONE. A denylist answers "is
14
+ * this one of the bad shapes I thought of", so every shape nobody thought of
15
+ * would be auto-allowed. Everything below answers the opposite question, and an
16
+ * unrecognised call is not category A. The failure direction of a bug here is
17
+ * then a prompt that did not go away, never a confirmation that was skipped.
18
+ *
19
+ * WHAT AN ALLOW DOES NOT DO. It never overrides a verdict from this package:
20
+ * composition lives in `host_semantics.composePermissionDecision`, where one
21
+ * `ask` or `deny` beats every `allow`, and the dispatcher reaches the allow
22
+ * path only when the reduced severity is already `allow`. It is also not a
23
+ * grant — the host's own strings record `permissionDecision=allow ignored: a
24
+ * confined session takes grants only from its command line`.
25
+ */
26
+ import * as path from "node:path";
27
+
28
+ /** A JSON-ish tool input as it arrives in the dispatcher envelope. */
29
+ export type ToolInput = Record<string, unknown>;
30
+
31
+ /**
32
+ * Tools whose every documented effect is a read. `WebFetch` and `WebSearch`
33
+ * are deliberately absent — they reach the network, which is the egress leg of
34
+ * the lethal trifecta and not something to auto-allow.
35
+ */
36
+ const READ_ONLY_TOOLS: ReadonlySet<string> = new Set([
37
+ "Read",
38
+ "Glob",
39
+ "Grep",
40
+ "NotebookRead",
41
+ "LS",
42
+ "TodoRead",
43
+ ]);
44
+
45
+ /** Per-tool input keys that carry a filesystem path needing confinement. */
46
+ const PATH_KEYS: readonly string[] = [
47
+ "file_path",
48
+ "notebook_path",
49
+ "path",
50
+ "directory",
51
+ ];
52
+
53
+ /**
54
+ * Any of these in a Bash command string disqualifies it before the argv is
55
+ * looked at. Chaining, substitution, redirection and backgrounding all let a
56
+ * safe head token carry an arbitrary second command, and a classifier that
57
+ * tries to parse past them is a shell parser with a security boundary attached.
58
+ * Refusing the whole shape is both smaller and correct.
59
+ */
60
+ const SHELL_METACHARACTERS = /[;&|`$><\n\r(){}\\]/;
61
+
62
+ /**
63
+ * Words naming a consequence operation, matched as whole tokens anywhere in
64
+ * the command. Defence in depth: the metacharacter rule already prevents a
65
+ * second command, so a hit here means the FIRST command is consequential.
66
+ */
67
+ const CONSEQUENCE_WORDS: ReadonlySet<string> = new Set([
68
+ "push", "publish", "deploy", "release", "merge", "rebase", "reset",
69
+ "revert", "restore", "checkout", "commit", "tag", "fetch", "pull", "clone",
70
+ "rm", "rmdir", "unlink", "mv", "cp", "chmod", "chown", "kill", "sudo",
71
+ "curl", "wget", "ssh", "scp", "rsync", "nc", "telnet",
72
+ "drop", "truncate", "delete", "insert", "migrate", "seed", "restore-db",
73
+ "install", "uninstall", "upgrade", "prune", "clean", "apply", "destroy",
74
+ "terraform", "kubectl", "helm", "aws", "gcloud", "az", "docker", "podman",
75
+ "systemctl", "launchctl", "crontab", "mail", "sendmail",
76
+ ]);
77
+
78
+ /** Read-only `git` subcommands; every consequential one is absent by design. */
79
+ const GIT_READ_SUBCOMMANDS: ReadonlySet<string> = new Set([
80
+ "status", "log", "diff", "show", "branch", "blame", "describe",
81
+ "shortlog", "rev-parse", "ls-files", "ls-tree", "cat-file", "whatchanged",
82
+ ]);
83
+
84
+ /**
85
+ * Head tokens that cannot write outside their arguments and whose named
86
+ * operation is a read, a navigation, a build, a test or a lint.
87
+ *
88
+ * `node`, `python`, `ruby`, `php` and `sh` are deliberately absent: their named
89
+ * operation is "run this program", which establishes nothing about what the
90
+ * program does. A test runner is admitted by name because the name IS the
91
+ * operation.
92
+ */
93
+ const SAFE_HEADS: ReadonlySet<string> = new Set([
94
+ "ls", "pwd", "cat", "head", "tail", "wc", "file", "stat", "find",
95
+ "grep", "rg", "tree", "du", "df", "which", "basename", "dirname",
96
+ "realpath", "sort", "uniq", "cut", "diff", "cmp", "date", "echo",
97
+ "tsc", "eslint", "prettier", "biome", "stylelint",
98
+ "vitest", "jest", "mocha", "pytest", "mypy", "ruff", "flake8", "black",
99
+ "phpstan", "phpunit", "psalm", "pest", "rspec", "rubocop",
100
+ "golangci-lint", "shellcheck", "markdownlint", "hadolint",
101
+ ]);
102
+
103
+ /**
104
+ * Multi-purpose runners: the head token decides nothing, so the subcommand
105
+ * must be declared. `npm run <script>` executes whatever the manifest says,
106
+ * which is why the script name is checked separately below.
107
+ */
108
+ const RUNNER_SUBCOMMANDS: Readonly<Record<string, ReadonlySet<string>>> = {
109
+ npm: new Set(["test", "run", "ls", "list", "why", "outdated", "view"]),
110
+ pnpm: new Set(["test", "run", "ls", "list", "why", "outdated"]),
111
+ yarn: new Set(["test", "run", "list", "why", "info"]),
112
+ npx: new Set(["tsc", "eslint", "prettier", "vitest", "jest"]),
113
+ composer: new Set(["test", "run-script", "show", "validate", "diagnose"]),
114
+ cargo: new Set(["test", "build", "check", "clippy", "fmt", "tree"]),
115
+ go: new Set(["test", "build", "vet", "list", "version"]),
116
+ make: new Set(["test", "build", "lint", "check", "typecheck"]),
117
+ task: new Set(["test", "build", "lint", "check", "typecheck", "--list"]),
118
+ just: new Set(["test", "build", "lint", "check"]),
119
+ bundle: new Set(["exec"]),
120
+ dotnet: new Set(["test", "build"]),
121
+ mvn: new Set(["test", "compile", "verify"]),
122
+ gradle: new Set(["test", "build", "check"]),
123
+ };
124
+
125
+ /** Script names a `run`-style subcommand may name and stay category A. */
126
+ const SAFE_SCRIPT_NAMES: ReadonlySet<string> = new Set([
127
+ "test", "tests", "lint", "typecheck", "types", "build", "check",
128
+ "format", "fmt", "unit", "e2e", "coverage", "compile",
129
+ ]);
130
+
131
+ /** Subcommands that take a script name rather than acting themselves. */
132
+ const SCRIPT_TAKING_SUBCOMMANDS: ReadonlySet<string> = new Set([
133
+ "run", "run-script", "exec",
134
+ ]);
135
+
136
+ /**
137
+ * Is `candidate` inside `root`?
138
+ *
139
+ * Pure `path` arithmetic, no `fs`: the classifier must be decidable from the
140
+ * envelope alone, and a stat call would make it depend on what happens to
141
+ * exist on the machine that runs the hook.
142
+ */
143
+ export function isInsideWorkingTree(candidate: string, root: string): boolean {
144
+ if (!candidate.trim() || !root.trim()) return false;
145
+ const abs = path.resolve(root, candidate);
146
+ const rel = path.relative(path.resolve(root), abs);
147
+ if (rel === "") return true;
148
+ return !rel.startsWith("..") && !path.isAbsolute(rel);
149
+ }
150
+
151
+ /** Split a command on whitespace; the caller has already refused metacharacters. */
152
+ function _argv(command: string): string[] {
153
+ return command.trim().split(/\s+/).filter((t) => t.length > 0);
154
+ }
155
+
156
+ /** Strip a leading `-`/`--` so a flag is never mistaken for a subcommand. */
157
+ function _isFlag(token: string): boolean {
158
+ return token.startsWith("-");
159
+ }
160
+
161
+ /** First non-flag token after the head, or `""`. */
162
+ function _firstSubcommand(argv: readonly string[]): string {
163
+ for (const token of argv.slice(1)) {
164
+ if (!_isFlag(token)) return token;
165
+ }
166
+ return "";
167
+ }
168
+
169
+ /**
170
+ * `git` global options that consume the NEXT token as their value.
171
+ *
172
+ * Without this, `git -C sub status` resolves its subcommand to `sub` and the
173
+ * whole directory-flag form — the shape the canon now teaches in place of
174
+ * `cd X && …` — falls out of category A. That defect was found by the friction
175
+ * corpus on its first run, which is the reason the corpus counts confirmations
176
+ * rather than gates: a gate count would have looked identical.
177
+ *
178
+ * The `--flag=value` spelling consumes no extra token and needs no entry.
179
+ */
180
+ const GIT_VALUE_FLAGS: ReadonlySet<string> = new Set([
181
+ "-C", "-c", "--git-dir", "--work-tree", "--namespace", "--exec-path",
182
+ ]);
183
+
184
+ /**
185
+ * The `git` subcommand, with global options skipped.
186
+ *
187
+ * Returns `""` when a global option's VALUE escapes the working tree — an
188
+ * absolute path or a `..` traversal. The check is textual rather than resolved
189
+ * against a root because this function is pure and receives no root; what it
190
+ * can decide is exactly the property that matters, and a relative path with no
191
+ * `..` cannot escape.
192
+ */
193
+ function _gitSubcommand(argv: readonly string[]): string {
194
+ for (let i = 1; i < argv.length; i++) {
195
+ const token = argv[i] as string;
196
+ if (!_isFlag(token)) return token;
197
+ const [flag, inlineValue] = token.includes("=")
198
+ ? [token.slice(0, token.indexOf("=")), token.slice(token.indexOf("=") + 1)]
199
+ : [token, null];
200
+ const value = inlineValue ?? (GIT_VALUE_FLAGS.has(flag) ? argv[++i] : undefined);
201
+ if (value !== undefined && (path.isAbsolute(value) || value.split("/").includes(".."))) {
202
+ return "";
203
+ }
204
+ }
205
+ return "";
206
+ }
207
+
208
+ /** Non-flag token after the subcommand, or `""`. */
209
+ function _secondSubcommand(argv: readonly string[]): string {
210
+ const nonFlags = argv.slice(1).filter((t) => !_isFlag(t));
211
+ return nonFlags[1] ?? "";
212
+ }
213
+
214
+ /**
215
+ * Does any token in the command name a consequence operation?
216
+ *
217
+ * Tokenised rather than substring-matched: a substring test would refuse
218
+ * `git log --format=…` for containing `mat`, and a classifier that refuses
219
+ * everything is indistinguishable from one that was never wired.
220
+ */
221
+ export function namesConsequenceOperation(command: string): boolean {
222
+ for (const raw of _argv(command)) {
223
+ const token = raw.replace(/^-+/, "").toLowerCase();
224
+ if (CONSEQUENCE_WORDS.has(token)) return true;
225
+ // `npm:publish`, `db:seed`, `deploy:prod` — a namespaced script name
226
+ // hides the consequential half behind a separator.
227
+ for (const part of token.split(/[:/=,]/)) {
228
+ if (part && CONSEQUENCE_WORDS.has(part)) return true;
229
+ }
230
+ }
231
+ return false;
232
+ }
233
+
234
+ /** Is this Bash command string category A? */
235
+ export function isCategoryABashCommand(command: string): boolean {
236
+ if (typeof command !== "string" || !command.trim()) return false;
237
+ if (SHELL_METACHARACTERS.test(command)) return false;
238
+ if (namesConsequenceOperation(command)) return false;
239
+
240
+ const argv = _argv(command);
241
+ const head = (argv[0] ?? "").toLowerCase();
242
+ if (!head) return false;
243
+
244
+ if (SAFE_HEADS.has(head)) return true;
245
+
246
+ if (head === "git") {
247
+ return GIT_READ_SUBCOMMANDS.has(_gitSubcommand(argv));
248
+ }
249
+
250
+ const allowed = RUNNER_SUBCOMMANDS[head];
251
+ if (!allowed) return false;
252
+ const sub = _firstSubcommand(argv);
253
+ if (!sub || !allowed.has(sub)) return false;
254
+ if (SCRIPT_TAKING_SUBCOMMANDS.has(sub)) {
255
+ const script = _secondSubcommand(argv);
256
+ return script !== "" && SAFE_SCRIPT_NAMES.has(script.toLowerCase());
257
+ }
258
+ return true;
259
+ }
260
+
261
+ /**
262
+ * Is this tool call category A?
263
+ *
264
+ * `workingTree` is the root every path argument must resolve inside. An empty
265
+ * root means the dispatcher could not establish one, and an unestablished
266
+ * boundary is not a boundary — the call is not category A.
267
+ */
268
+ export function isCategoryA(
269
+ toolName: string,
270
+ toolInput: ToolInput,
271
+ workingTree: string,
272
+ ): boolean {
273
+ if (!workingTree.trim()) return false;
274
+ if (typeof toolName !== "string" || !toolName) return false;
275
+
276
+ if (READ_ONLY_TOOLS.has(toolName)) {
277
+ for (const key of PATH_KEYS) {
278
+ const value = toolInput?.[key];
279
+ if (typeof value !== "string") continue;
280
+ if (!isInsideWorkingTree(value, workingTree)) return false;
281
+ }
282
+ return true;
283
+ }
284
+
285
+ if (toolName === "Bash") {
286
+ const command = toolInput?.["command"];
287
+ return typeof command === "string" && isCategoryABashCommand(command);
288
+ }
289
+
290
+ return false;
291
+ }
@@ -4,7 +4,7 @@
4
4
  # Routes user-scope `~/Documents/Cline/Hooks/<HookName>` events into
5
5
  # the active workspace's `./agent-config dispatch:hook`. Project-scope
6
6
  # `.clinerules/hooks/<HookName>` does NOT need this trampoline —
7
- # install.py `ensure_cline_bridge()` writes per-event scripts there
7
+ # the installer's `ensure_cline_bridge()` writes per-event scripts there
8
8
  # that dispatch directly because Cline fires project hooks with the
9
9
  # workspace as cwd.
10
10
  #
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # Routes user-scope `~/.cursor/hooks.json` events into the active
5
5
  # workspace's `./agent-config dispatch:hook`. Project-scope
6
- # `.cursor/hooks.json` does NOT need this trampoline — install.py
6
+ # `.cursor/hooks.json` does NOT need this trampoline — the installer
7
7
  # `ensure_cursor_bridge()` writes direct dispatch:hook commands there
8
8
  # because the project hooks fire with the workspace as cwd.
9
9
  #
@@ -20,10 +20,16 @@
20
20
  # - Re-pipe the original JSON into
21
21
  # ./agent-config dispatch:hook --platform cursor \
22
22
  # --event $1 --native-event $2
23
- # - Always exit 0 — Cursor's pre-hooks can block via exit code, but
24
- # none of our concerns block; chat-history / roadmap-progress /
25
- # context-hygiene are observe-only and onboarding-gate writes
26
- # state without denying sessionStart.
23
+ # - Always exit 0 — Cursor's pre-hooks can block via exit code. The
24
+ # manifest declares 7 concerns at `severity: blocking`, and this host
25
+ # binds none of them: cursor's platform row carries session_start,
26
+ # session_end, stop, user_prompt_submit and post_tool_use, and every
27
+ # blocking concern sits in a slot or platform row outside that set.
28
+ # The count is a YAML parse of the concerns map, never `grep -c
29
+ # 'severity: blocking'`, which returns 8 by also counting the prose
30
+ # line that quotes the key. What IS bound here — chat-history /
31
+ # roadmap-progress / context-hygiene — is observe-only, and
32
+ # onboarding-gate writes state without denying sessionStart.
27
33
 
28
34
  set -u
29
35
 
@@ -9,12 +9,10 @@
9
9
  * stdout/stderr split, and exit codes. Helper names keep snake_case for
10
10
  * fidelity (concern authors rely on the documented surface).
11
11
  *
12
- * Per `docs/contracts/hook-architecture-v1.md`. Reads the manifest at
13
- * `scripts/hook_manifest.yaml`, resolves which concerns fire on the given
14
- * (platform, event) tuple, and runs each concern sequentially with the
15
- * stdin envelope contract. Reduces concern exit codes per the spec
16
- * (0=allow, 1=block, 2=warn, ≥3=error → fail-open unless concern is
17
- * fail_closed).
12
+ * Per `docs/contracts/hook-architecture-v1.md`. Reads `src/scripts/hook_manifest.yaml`,
13
+ * resolves which concerns fire on the given (platform, event) tuple, and runs each
14
+ * sequentially with the stdin envelope contract. Reduces concern exit codes per the
15
+ * spec (0=allow, 1=block, 2=warn, ≥3=error → fail-open unless concern is fail_closed).
18
16
  *
19
17
  * Invocation:
20
18
  *
@@ -50,13 +48,16 @@ import {
50
48
  setHookStdinOverride,
51
49
  clearHookStdinOverride,
52
50
  } from "./hook_stdin.js";
53
- import { emitFor, type Severity } from "./host_semantics.js";
51
+ import { emitFor, type PermissionDecision, type Severity } from "./host_semantics.js";
52
+ import { _concern_permission_verdict, _payload_tool_name, _permission_for } from "./permission_gate.js";
53
+ export { _concern_permission_verdict, _payload_tool_input, _payload_tool_name, _permission_for, _working_tree_root } from "./permission_gate.js";
54
54
  import { _concern_body_classes, planPayloadShapes } from "./payload_stub.js";
55
55
  import { resolveSessionRole, type SessionRole } from "../_lib/session_role.js";
56
56
  import { stdinReadFailure, denyOnStdinFailure } from './stdin_failure_policy.js';
57
57
  export { stdinReadFailure, denyOnStdinFailure, _is_fail_closed_blocking } from './stdin_failure_policy.js';
58
58
  import { _py_json_dumps } from './py_json_dumps.js';
59
59
  import { _fallback_yaml } from './fallback_yaml.js';
60
+ import { detectSurface } from '../_lib/surface.js';
60
61
  import { recordCapture, recordOpportunity } from "../_lib/collector_denominator.js";
61
62
  export { _fallback_yaml } from './fallback_yaml.js';
62
63
 
@@ -255,20 +256,6 @@ interface ConcernDef extends JsonObject {
255
256
  name: string;
256
257
  }
257
258
 
258
- /**
259
- * The tool name the host reported for this event, or `""`.
260
- *
261
- * Only tool events carry one. Read defensively: the payload is host-shaped and
262
- * a missing / non-string field must degrade to "unknown tool", never throw.
263
- */
264
- export function _payload_tool_name(envelope: JsonObject): string {
265
- const payload = envelope["payload"];
266
- if (!_isObject(payload)) {
267
- return "";
268
- }
269
- const raw = payload["tool_name"];
270
- return typeof raw === "string" ? raw : "";
271
- }
272
259
 
273
260
  /**
274
261
  * Per-concern tool filter — the `tools:` key.
@@ -290,7 +277,7 @@ export function _payload_tool_name(envelope: JsonObject): string {
290
277
  * - A host matcher would only help the two hosts that support one (Claude,
291
278
  * Gemini). The in-process skip helps all eight platforms in the manifest.
292
279
  *
293
- * ## What this does NOT claim
280
+ * What this does NOT claim:
294
281
  *
295
282
  * It does not claim a latency win. The measured hook cost that was fixed was
296
283
  * the *invocation path* (~370 of ~450–500 ms was eager CLI imports); nothing in
@@ -509,6 +496,7 @@ export function _build_envelope(args: Args, payload_text: string): JsonObject {
509
496
  process.env["AGENT_SESSION_ID"] ||
510
497
  "",
511
498
  workspace_root: process.cwd(),
499
+ surface: detectSurface(payloadObj),
512
500
  payload: payloadObj,
513
501
  settings: {},
514
502
  };
@@ -1280,6 +1268,11 @@ export function main(argv?: string[]): number {
1280
1268
  // fixed-field schema (PII-exclusion-by-construction), and a concern's raw
1281
1269
  // stderr is free-form content. This array is in-memory only.
1282
1270
  const concern_messages: ConcernMessage[] = [];
1271
+ // Per-concern permission verdicts for the host's `permissionDecision` field.
1272
+ // Separate from `rcs` because the two ladders are not the same: an advisory
1273
+ // concern can ask for a confirmation without blocking, and a reduced `allow`
1274
+ // must not become a grant when one of them did.
1275
+ const permission_verdicts: PermissionDecision[] = [];
1283
1276
  // Per-concern `tools:` filter (see _concern_matches_tool). Applied here so it
1284
1277
  // is one place, after the envelope exists and before any concern is spawned.
1285
1278
  const tool_name = _payload_tool_name(envelope);
@@ -1339,6 +1332,7 @@ export function main(argv?: string[]): number {
1339
1332
  }
1340
1333
  rcs.push(rc);
1341
1334
  const reply = _parse_concern_stdout(stdout_text);
1335
+ permission_verdicts.push(_concern_permission_verdict(rc, reply));
1342
1336
  // A concern states its reason either as JSON {"reason": …} on stdout
1343
1337
  // (advisory concerns) or as a formatted stderr line (the block guards, e.g.
1344
1338
  // `block-no-verify: BLOCKED — …`). Both are captured here so the emission
@@ -1423,6 +1417,7 @@ export function main(argv?: string[]): number {
1423
1417
  _severity_for(final_rc) as Severity,
1424
1418
  decidingReasons,
1425
1419
  final_rc,
1420
+ _permission_for(args.event, envelope, final_rc, permission_verdicts),
1426
1421
  );
1427
1422
  if (emission.stdout) {
1428
1423
  process.stdout.write(emission.stdout);