@event4u/agent-config 14.10.0 → 14.12.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 (667) 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 +161 -208
  5. package/README.md +1 -1
  6. package/dist/agent-src/commands/design.md +88 -0
  7. package/dist/agent-src/commands/project/analyze.md +47 -0
  8. package/dist/agent-src/commands/review/changes.md +67 -6
  9. package/dist/agent-src/commands/roadmap/create.md +49 -0
  10. package/dist/agent-src/commands/roadmap/next.md +27 -11
  11. package/dist/agent-src/commands/roadmap/process-full.md +14 -0
  12. package/dist/agent-src/commands/video/from-script.md +60 -3
  13. package/dist/agent-src/commands/video/stitch.md +14 -0
  14. package/dist/agent-src/contexts/communication/rules-auto/guidelines-mechanics.md +1 -0
  15. package/dist/agent-src/contexts/execution/evidence-discipline.md +26 -0
  16. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +154 -2
  17. package/dist/agent-src/rules/active-remediation.md +3 -3
  18. package/dist/agent-src/rules/code-provenance.md +2 -2
  19. package/dist/agent-src/rules/context-hygiene.md +13 -33
  20. package/dist/agent-src/rules/council-availability.md +2 -2
  21. package/dist/agent-src/rules/decision-revisit-gate.md +3 -1
  22. package/dist/agent-src/rules/design-fidelity.md +18 -0
  23. package/dist/agent-src/rules/design-review-after-ui-write.md +2 -2
  24. package/dist/agent-src/rules/evaluator-independence.md +56 -44
  25. package/dist/agent-src/rules/fix-what-you-see.md +9 -1
  26. package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +1 -1
  27. package/dist/agent-src/rules/minimal-safe-diff.md +14 -20
  28. package/dist/agent-src/rules/missing-skill-recovery.md +13 -1
  29. package/dist/agent-src/rules/playbook-precedence.md +105 -0
  30. package/dist/agent-src/rules/recurring-criticism.md +3 -1
  31. package/dist/agent-src/rules/roadmap-progress-sync.md +14 -13
  32. package/dist/agent-src/rules/scale-discipline.md +24 -0
  33. package/dist/agent-src/rules/security-sensitive-stop.md +2 -2
  34. package/dist/agent-src/rules/settings-ask-protocol.md +2 -2
  35. package/dist/agent-src/rules/ui-audit-gate.md +27 -15
  36. package/dist/agent-src/rules/untrusted-input-defense.md +2 -2
  37. package/dist/agent-src/skills/accessibility-auditor/SKILL.md +19 -0
  38. package/dist/agent-src/skills/adr-create/SKILL.md +7 -0
  39. package/dist/agent-src/skills/agents-md-thin-root/SKILL.md +33 -0
  40. package/dist/agent-src/skills/ai-council/references/advanced-modes.md +17 -3
  41. package/dist/agent-src/skills/ai-council/references/output-and-synthesis.md +31 -0
  42. package/dist/agent-src/skills/ai-council/references/procedure.md +19 -0
  43. package/dist/agent-src/skills/alerting-doctrine/SKILL.md +225 -0
  44. package/dist/agent-src/skills/authz-review/SKILL.md +0 -1
  45. package/dist/agent-src/skills/blast-radius-analyzer/SKILL.md +32 -0
  46. package/dist/agent-src/skills/brand/SKILL.md +3 -0
  47. package/dist/agent-src/skills/brand-asset-generation/SKILL.md +3 -0
  48. package/dist/agent-src/skills/brand-audit/SKILL.md +3 -0
  49. package/dist/agent-src/skills/brand-identity/SKILL.md +3 -0
  50. package/dist/agent-src/skills/brand-strategy/SKILL.md +3 -0
  51. package/dist/agent-src/skills/brand-to-tokens/SKILL.md +3 -0
  52. package/dist/agent-src/skills/check-refs/SKILL.md +3 -0
  53. package/dist/agent-src/skills/code-refactoring/SKILL.md +45 -1
  54. package/dist/agent-src/skills/code-review/SKILL.md +75 -5
  55. package/dist/agent-src/skills/command-routing/SKILL.md +6 -0
  56. package/dist/agent-src/skills/command-writing/SKILL.md +35 -0
  57. package/dist/agent-src/skills/condense-memory/SKILL.md +3 -0
  58. package/dist/agent-src/skills/context-authoring/SKILL.md +1 -1
  59. package/dist/agent-src/skills/conventional-commits-writing/SKILL.md +3 -0
  60. package/dist/agent-src/skills/copilot-agents-optimization/SKILL.md +10 -0
  61. package/dist/agent-src/skills/corpus-grounding/SKILL.md +3 -0
  62. package/dist/agent-src/skills/design-intelligence/SKILL.md +3 -0
  63. package/dist/agent-src/skills/design-intelligence/data/landing.csv +36 -35
  64. package/dist/agent-src/skills/design-intelligence/data/stacks/threejs.csv +1 -0
  65. package/dist/agent-src/skills/design-review/SKILL.md +79 -1
  66. package/dist/agent-src/skills/design-review/references/verification-automation.md +41 -0
  67. package/dist/agent-src/skills/design-system-capture/SKILL.md +35 -40
  68. package/dist/agent-src/skills/design-system-capture/references/import-procedure.md +50 -0
  69. package/dist/agent-src/skills/design-tokens/SKILL.md +3 -0
  70. package/dist/agent-src/skills/design-variations/SKILL.md +3 -0
  71. package/dist/agent-src/skills/developer-like-execution/SKILL.md +3 -0
  72. package/dist/agent-src/skills/estimate-ticket/SKILL.md +3 -0
  73. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +28 -4
  74. package/dist/agent-src/skills/fe-design/SKILL.md +74 -41
  75. package/dist/agent-src/skills/fe-design/references/craft-floor.md +52 -0
  76. package/dist/agent-src/skills/fe-design/references/source-led-port.md +36 -0
  77. package/dist/agent-src/skills/file-editor/SKILL.md +5 -0
  78. package/dist/agent-src/skills/finishing-a-development-branch/SKILL.md +2 -2
  79. package/dist/agent-src/skills/git-workflow/SKILL.md +3 -0
  80. package/dist/agent-src/skills/html-deck/SKILL.md +3 -0
  81. package/dist/agent-src/skills/iconography/SKILL.md +3 -0
  82. package/dist/agent-src/skills/image-editing/SKILL.md +3 -0
  83. package/dist/agent-src/skills/image-generation/SKILL.md +3 -0
  84. package/dist/agent-src/skills/image-provider-routing/SKILL.md +3 -0
  85. package/dist/agent-src/skills/incident-commander/SKILL.md +10 -0
  86. package/dist/agent-src/skills/js-library-packaging/SKILL.md +173 -0
  87. package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.ts +270 -0
  88. package/dist/agent-src/skills/laravel-migration/SKILL.md +3 -0
  89. package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +3 -0
  90. package/dist/agent-src/skills/lint-skills/SKILL.md +3 -0
  91. package/dist/agent-src/skills/llm-provider-knowledge/SKILL.md +3 -0
  92. package/dist/agent-src/skills/logging-monitoring/SKILL.md +234 -51
  93. package/dist/agent-src/skills/logo-generation/SKILL.md +3 -0
  94. package/dist/agent-src/skills/md-language-check/SKILL.md +3 -0
  95. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +149 -0
  96. package/dist/agent-src/skills/motion-choreographer/SKILL.md +6 -0
  97. package/dist/agent-src/skills/multi-tenancy/SKILL.md +4 -0
  98. package/dist/agent-src/skills/operational-readiness/SKILL.md +184 -0
  99. package/dist/agent-src/skills/override-management/SKILL.md +3 -0
  100. package/dist/agent-src/skills/persona-improvement/SKILL.md +3 -0
  101. package/dist/agent-src/skills/pest-testing/SKILL.md +3 -0
  102. package/dist/agent-src/skills/playbook-authoring/SKILL.md +162 -0
  103. package/dist/agent-src/skills/playwright-testing/SKILL.md +3 -0
  104. package/dist/agent-src/skills/privacy-review/SKILL.md +3 -0
  105. package/dist/agent-src/skills/project-analysis-core/SKILL.md +23 -0
  106. package/dist/agent-src/skills/prompt-engineering-image/SKILL.md +3 -0
  107. package/dist/agent-src/skills/quality-tools/SKILL.md +5 -0
  108. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +81 -33
  109. package/dist/agent-src/skills/readme-reviewer/SKILL.md +3 -0
  110. package/dist/agent-src/skills/readme-writing/SKILL.md +3 -0
  111. package/dist/agent-src/skills/readme-writing-package/SKILL.md +3 -0
  112. package/dist/agent-src/skills/receiving-code-review/SKILL.md +2 -2
  113. package/dist/agent-src/skills/refine-prompt/SKILL.md +3 -0
  114. package/dist/agent-src/skills/refine-ticket/SKILL.md +3 -0
  115. package/dist/agent-src/skills/requesting-code-review/SKILL.md +2 -2
  116. package/dist/agent-src/skills/review-routing/SKILL.md +2 -2
  117. package/dist/agent-src/skills/roadmap-writing/SKILL.md +23 -41
  118. package/dist/agent-src/skills/roadmap-writing/references/follow-up-roadmap-shape.md +47 -0
  119. package/dist/agent-src/skills/rtk-output-filtering/SKILL.md +22 -6
  120. package/dist/agent-src/skills/runway-cognition/SKILL.md +3 -0
  121. package/dist/agent-src/skills/scene-expander/scene-blueprint.schema.yaml +26 -0
  122. package/dist/agent-src/skills/secrets-management/SKILL.md +4 -0
  123. package/dist/agent-src/skills/server-hardening/SKILL.md +159 -0
  124. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +3 -0
  125. package/dist/agent-src/skills/skill-management/SKILL.md +3 -0
  126. package/dist/agent-src/skills/skill-reviewer/SKILL.md +3 -0
  127. package/dist/agent-src/skills/skill-writing/SKILL.md +6 -0
  128. package/dist/agent-src/skills/skill-writing/references/procedure.md +24 -2
  129. package/dist/agent-src/skills/spreadsheet-authoring/SKILL.md +3 -0
  130. package/dist/agent-src/skills/storybook-workshop/SKILL.md +203 -0
  131. package/dist/agent-src/skills/storybook-workshop/scripts/story_contrast_floor.ts +134 -0
  132. package/dist/agent-src/skills/subagent-orchestration/SKILL.md +1 -1
  133. package/dist/agent-src/skills/subagent-orchestration/prompts/README.md +25 -0
  134. package/dist/agent-src/skills/supply-chain-intake/SKILL.md +12 -0
  135. package/dist/agent-src/skills/systematic-debugging/SKILL.md +1 -1
  136. package/dist/agent-src/skills/terraform/SKILL.md +3 -0
  137. package/dist/agent-src/skills/test-driven-development/SKILL.md +1 -1
  138. package/dist/agent-src/skills/threat-modeling/SKILL.md +0 -3
  139. package/dist/agent-src/skills/token-optimizer/SKILL.md +3 -0
  140. package/dist/agent-src/skills/typography-system/SKILL.md +3 -0
  141. package/dist/agent-src/skills/ui-component-architect/SKILL.md +17 -1
  142. package/dist/agent-src/skills/upstream-contribute/SKILL.md +3 -0
  143. package/dist/agent-src/skills/validate-feature-fit/SKILL.md +3 -0
  144. package/dist/agent-src/skills/verify-completion-evidence/SKILL.md +2 -2
  145. package/dist/agent-src/skills/wireframe/SKILL.md +3 -0
  146. package/dist/agent-src/skills/wireframe/references/story-beat-ledger.schema.json +115 -0
  147. package/dist/agent-src/skills/workspace-link/SKILL.md +131 -0
  148. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  149. package/dist/agent-src/templates/playbook.md +75 -0
  150. package/dist/agent-src/templates/roadmaps.md +37 -0
  151. package/dist/agent-src/templates/scripts/check_playbook_invokes.ts +231 -0
  152. package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +24 -0
  153. package/dist/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +2 -0
  154. package/dist/agent-src/templates/scripts/work_engine/directives/ui/review.ts +216 -0
  155. package/dist/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +159 -0
  156. package/dist/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +73 -4
  157. package/dist/agent-src/templates/scripts/work_engine/stack/detect.ts +325 -40
  158. package/dist/cli/commands/uiAudit.js +221 -0
  159. package/dist/cli/commands/uiRender.js +206 -0
  160. package/dist/cli/main.js +22 -1
  161. package/dist/cli/mcp/content.js +64 -1
  162. package/dist/cli/mcp/dispatch.js +175 -10
  163. package/dist/cli/registry.js +3 -0
  164. package/dist/cli-delegate/{chunk-G23AT6GD.js → chunk-DMSZHXZS.js} +57 -1
  165. package/dist/cli-delegate/{chunk-77GR3VD4.js → chunk-FF7WAFMR.js} +58 -3
  166. package/dist/cli-delegate/{chunk-YM4GZDJG.js → chunk-JCW7ZLHK.js} +10 -0
  167. package/dist/cli-delegate/{chunk-H4VIVD4C.js → chunk-JJA2QEWA.js} +413 -391
  168. package/dist/cli-delegate/{chunk-PLSG6UL5.js → chunk-K4FFODTS.js} +341 -204
  169. package/dist/cli-delegate/{chunk-B2ERU2VA.js → chunk-WOKWX5PL.js} +1 -1
  170. package/dist/cli-delegate/cmd_brand_status.js +8 -6
  171. package/dist/cli-delegate/cmd_conformance.js +3 -3
  172. package/dist/cli-delegate/cmd_doctor.js +3 -3
  173. package/dist/cli-delegate/cmd_export.js +4 -4
  174. package/dist/cli-delegate/cmd_handoff.js +1 -1
  175. package/dist/cli-delegate/cmd_preflight.js +2 -2
  176. package/dist/cli-delegate/cmd_prune.js +4 -4
  177. package/dist/cli-delegate/cmd_session_recycle.js +70 -9
  178. package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
  179. package/dist/cli-delegate/cmd_settings_set.js +1 -1
  180. package/dist/cli-delegate/cmd_sync.js +4 -4
  181. package/dist/cli-delegate/cmd_uninstall.js +4 -4
  182. package/dist/cli-delegate/cmd_validate.js +4 -4
  183. package/dist/discovery/deprecation-report.md +1 -1
  184. package/dist/discovery/discovery-manifest.json +362 -127
  185. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  186. package/dist/discovery/discovery-manifest.summary.md +4 -4
  187. package/dist/discovery/dormancy-report.md +1 -1
  188. package/dist/discovery/orphan-report.md +1 -1
  189. package/dist/discovery/packs.json +18 -8
  190. package/dist/discovery/trust-report.md +3 -3
  191. package/dist/discovery/workspaces.json +16 -6
  192. package/dist/hooks/dispatch.js +2575 -1472
  193. package/dist/install/install.mjs +800 -708
  194. package/dist/mcp/registry-manifest.json +3 -3
  195. package/dist/mcp/server.json +2 -2
  196. package/dist/mcp/server.mjs +1685 -1250
  197. package/dist/router.json +1 -1
  198. package/dist/scripts/_lib/lean_projection_mode.js +40 -0
  199. package/dist/scripts/_lib/scoped_projection.js +84 -0
  200. package/dist/scripts/_lib/ui_surface.js +89 -0
  201. package/dist/scripts/condense.js +6 -10
  202. package/dist/scripts/project_thin_rules.js +40 -2
  203. package/dist/server/schemas/settings.js +6 -0
  204. package/dist/shared/skillRanking.js +159 -0
  205. package/docs/contracts/provider-lifecycle.md +47 -18
  206. package/docs/contracts/settings-classes.md +35 -5
  207. package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +49 -0
  208. package/docs/guidelines/agent-infra/downstream-changes-mechanics.md +91 -0
  209. package/docs/guidelines/agent-infra/evaluator-independence-mechanics.md +92 -0
  210. package/docs/guidelines/agent-infra/minimal-safe-diff-mechanics.md +45 -1
  211. package/docs/guidelines/agent-infra/roadmap-deferred-resolution-provenance.md +54 -0
  212. package/docs/guidelines/code-clarity.md +21 -0
  213. package/docs/guidelines/design-antipatterns.md +4 -2
  214. package/docs/guidelines/design-asset-discipline.md +38 -0
  215. package/docs/guidelines/design-fidelity-mechanics.md +45 -29
  216. package/docs/guidelines/design-handover-extraction.md +35 -5
  217. package/docs/guidelines/design-modes.md +41 -1
  218. package/docs/guidelines/monorepo-antipatterns.md +141 -0
  219. package/docs/guidelines/redundancy-taxonomy.md +180 -0
  220. package/llms.txt +50 -39
  221. package/package.json +6 -2
  222. package/src/agent-src/templates/scripts/check_playbook_invokes.ts +231 -0
  223. package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +24 -0
  224. package/src/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +2 -0
  225. package/src/agent-src/templates/scripts/work_engine/directives/ui/review.ts +216 -0
  226. package/src/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +159 -0
  227. package/src/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +73 -4
  228. package/src/agent-src/templates/scripts/work_engine/stack/detect.ts +325 -40
  229. package/src/config/agent-settings.template.yml +44 -0
  230. package/src/config/assurance-capability-registry.json +223 -0
  231. package/src/config/assurance-threshold-budget.json +65 -0
  232. package/src/config/budgets.yml +19 -0
  233. package/src/config/ci-local-parity.yml +29 -0
  234. package/src/config/discovery/prompt-patterns.yml +56 -0
  235. package/src/config/discovery/unassigned-artefacts.yml +2 -0
  236. package/src/config/dispatch-economy-metrics.json +4 -2
  237. package/src/config/estate-count-budget.json +8 -3
  238. package/src/config/evaluator-budgets.json +14 -14
  239. package/src/config/gate-coverage.yml +392 -8
  240. package/src/config/gate-violation-baselines.json +76 -72
  241. package/src/config/hook-latency-budget.json +1 -0
  242. package/src/config/hook-token-budget.json +137 -125
  243. package/src/config/pack-size-budget.json +39 -10
  244. package/src/config/preamble-payload-budget.json +97 -71
  245. package/src/config/quorum-attendance-budget.json +12 -4
  246. package/src/config/routing-coverage-seed.json +29 -0
  247. package/src/config/rule-activation-census.json +7 -3
  248. package/src/config/rule-enforcement-baseline.json +0 -1
  249. package/src/config/rule-stub-ceilings.json +112 -91
  250. package/src/config/suggestion-capture.json +28 -0
  251. package/src/config/surface-matrix.yml +21 -2
  252. package/src/config/web-launch-readiness.json +188 -0
  253. package/src/scripts/_cli/cmd_doctor.ts +15 -16
  254. package/src/scripts/_cli/doctor_install_mode.ts +49 -0
  255. package/src/scripts/_cli/doctor_overrides.ts +154 -0
  256. package/src/scripts/_dispatch.bash +17 -0
  257. package/src/scripts/_lib/as_of.ts +412 -0
  258. package/src/scripts/_lib/exec_evidence.ts +7 -0
  259. package/src/scripts/_lib/gate_baseline.ts +150 -1
  260. package/src/scripts/_lib/hook_settings.ts +33 -0
  261. package/src/scripts/_lib/host_listing_model.ts +192 -0
  262. package/src/scripts/_lib/lean_projection_mode.ts +44 -0
  263. package/src/scripts/_lib/mcp_bridge.ts +199 -0
  264. package/src/scripts/_lib/review_independence.ts +62 -10
  265. package/src/scripts/_lib/rule_injection.ts +239 -0
  266. package/src/scripts/_lib/run_checkpoint.ts +54 -1
  267. package/src/scripts/_lib/scoped_projection.ts +96 -0
  268. package/src/scripts/_lib/session_register.ts +44 -2
  269. package/src/scripts/_lib/skill_catalogue.ts +38 -2
  270. package/src/scripts/_lib/skill_estate.ts +115 -0
  271. package/src/scripts/_lib/transcript_reads.ts +207 -0
  272. package/src/scripts/_lib/ui_authority.ts +343 -0
  273. package/src/scripts/ai-video/adapters/fal.sh +8 -3
  274. package/src/scripts/ai-video/adapters/gemini-veo.sh +10 -0
  275. package/src/scripts/ai-video/adapters/higgsfield.sh +10 -2
  276. package/src/scripts/ai-video/adapters/kling.sh +10 -0
  277. package/src/scripts/ai-video/adapters/sora.sh +10 -0
  278. package/src/scripts/ai-video/lib/calibrate-cost.sh +145 -0
  279. package/src/scripts/ai-video/lib/model-capabilities/README.md +53 -7
  280. package/src/scripts/ai-video/lib/model-capabilities/comfyui.json +15 -3
  281. package/src/scripts/ai-video/lib/model-capabilities/fal.json +36 -6
  282. package/src/scripts/ai-video/lib/model-capabilities/gemini-veo.json +23 -0
  283. package/src/scripts/ai-video/lib/model-capabilities/higgsfield.json +23 -0
  284. package/src/scripts/ai-video/lib/model-capabilities/kling.json +23 -0
  285. package/src/scripts/ai-video/lib/model-capabilities/musetalk.json +8 -2
  286. package/src/scripts/ai-video/lib/model-capabilities/replicate.json +36 -6
  287. package/src/scripts/ai-video/lib/model-capabilities/sora.json +45 -0
  288. package/src/scripts/ai-video/lib/model-capabilities/syncso.json +8 -2
  289. package/src/scripts/ai-video/lib/parse-blueprint.sh +52 -5
  290. package/src/scripts/ai-video/lib/resume-scan.sh +92 -3
  291. package/src/scripts/ai-video/lib/seam-plan.sh +212 -0
  292. package/src/scripts/ai-video/smoke-trace.sh +450 -2
  293. package/src/scripts/ai-video/stitch.sh +191 -10
  294. package/src/scripts/ai-video/test-pipeline.sh +84 -6
  295. package/src/scripts/ai_council/argument_exhaustion.ts +130 -0
  296. package/src/scripts/ai_council/cli_agency_bounds.ts +139 -0
  297. package/src/scripts/ai_council/cli_least_agency_canary.ts +347 -0
  298. package/src/scripts/ai_council/clients.ts +3 -2
  299. package/src/scripts/ai_council/consensus.ts +63 -6
  300. package/src/scripts/ai_council/events_log.ts +46 -1
  301. package/src/scripts/ai_council/orchestrator.ts +103 -108
  302. package/src/scripts/ai_council/orchestrator_results.ts +166 -0
  303. package/src/scripts/ai_council/prompts.ts +12 -5
  304. package/src/scripts/ai_council/quorum.ts +82 -1
  305. package/src/scripts/ai_council/quorum_wiring.ts +82 -5
  306. package/src/scripts/ai_council/stance_tally.ts +22 -0
  307. package/src/scripts/bench_hook_latency.ts +62 -0
  308. package/src/scripts/build_proof.ts +12 -1
  309. package/src/scripts/capture_skill_catalogue.ts +21 -0
  310. package/src/scripts/check_always_budget.ts +2 -1
  311. package/src/scripts/check_augmentignore.ts +2 -1
  312. package/src/scripts/check_beta_review_markers.ts +2 -1
  313. package/src/scripts/check_bundle_path_leakage.ts +162 -7
  314. package/src/scripts/check_command_examples.ts +557 -0
  315. package/src/scripts/check_composite_arming.ts +364 -0
  316. package/src/scripts/check_corpus_staleness.ts +2 -1
  317. package/src/scripts/check_council_pin_staleness.ts +3 -1
  318. package/src/scripts/check_enforcement_coverage.ts +116 -3
  319. package/src/scripts/check_enforcement_denominator.ts +365 -0
  320. package/src/scripts/check_estate_count.ts +122 -3
  321. package/src/scripts/check_gate_coverage.ts +2 -1
  322. package/src/scripts/check_hook_bundle_freshness.ts +13 -1
  323. package/src/scripts/check_knowledge_cards.ts +2 -1
  324. package/src/scripts/check_knowledge_pages.ts +3 -2
  325. package/src/scripts/check_memory.ts +2 -1
  326. package/src/scripts/check_no_automerge_key.ts +287 -0
  327. package/src/scripts/check_pack_conformance_fixture.ts +565 -0
  328. package/src/scripts/check_preamble_payload_budget.ts +30 -3
  329. package/src/scripts/check_proposal.ts +2 -1
  330. package/src/scripts/check_reach_staleness.ts +2 -1
  331. package/src/scripts/check_release_adjacent_health.ts +2 -1
  332. package/src/scripts/check_release_pr_shape.ts +5 -0
  333. package/src/scripts/check_review_schema.ts +34 -1
  334. package/src/scripts/check_roadmap_trackable.ts +48 -3
  335. package/src/scripts/check_routing_coverage.ts +352 -0
  336. package/src/scripts/check_score_contract.ts +505 -0
  337. package/src/scripts/check_skill_admissions.ts +514 -0
  338. package/src/scripts/check_source_size_budget.ts +2 -1
  339. package/src/scripts/check_standing_payload_delta.ts +505 -0
  340. package/src/scripts/check_trigger_evals.ts +2 -1
  341. package/src/scripts/check_web_launch_readiness.ts +705 -0
  342. package/src/scripts/classify_change_risk.ts +281 -0
  343. package/src/scripts/compute_skill_tiers.ts +186 -0
  344. package/src/scripts/condense.ts +8 -13
  345. package/src/scripts/council_attendance_metrics.ts +183 -0
  346. package/src/scripts/council_cli.ts +10 -8
  347. package/src/scripts/council_parse_rate.ts +116 -0
  348. package/src/scripts/derive_playbooks.ts +406 -0
  349. package/src/scripts/description_route_check.ts +494 -0
  350. package/src/scripts/design_slop_rules.ts +56 -2
  351. package/src/scripts/dispatch_r2_reviewer.ts +16 -0
  352. package/src/scripts/frontend_corpus_hash.ts +116 -0
  353. package/src/scripts/grade_target_readiness.ts +478 -0
  354. package/src/scripts/hook_manifest.json +1 -1
  355. package/src/scripts/hook_manifest.yaml +124 -16
  356. package/src/scripts/hooks/concern_registry.ts +6 -0
  357. package/src/scripts/hooks/design_pass_hook.ts +356 -0
  358. package/src/scripts/hooks/rtk_wrap_hook.ts +30 -7
  359. package/src/scripts/hooks/rule_inject_hook.ts +318 -0
  360. package/src/scripts/hooks/suggestion_capture_hook.ts +368 -0
  361. package/src/scripts/hot_context_hook.ts +74 -7
  362. package/src/scripts/install.ts +40 -89
  363. package/src/scripts/lint_adapter_tier.ts +663 -0
  364. package/src/scripts/lint_archived_skills.ts +93 -0
  365. package/src/scripts/lint_budget_ownership.ts +56 -5
  366. package/src/scripts/lint_deterministic_time.ts +470 -0
  367. package/src/scripts/lint_framework_leakage.ts +5 -0
  368. package/src/scripts/lint_handoffs.ts +525 -1
  369. package/src/scripts/lint_judge_prompt_expectation.ts +155 -0
  370. package/src/scripts/lint_marketplace.ts +88 -0
  371. package/src/scripts/lint_media_policy_linkage.ts +140 -1
  372. package/src/scripts/lint_one_off_age.ts +6 -1
  373. package/src/scripts/lint_override_kernel_guard.ts +87 -5
  374. package/src/scripts/lint_roadmap_complexity.ts +56 -0
  375. package/src/scripts/lint_rule_enforcement_declaration.ts +24 -7
  376. package/src/scripts/lint_rule_norm_pin.ts +321 -0
  377. package/src/scripts/lint_skill_trigger_corpus.ts +349 -0
  378. package/src/scripts/lint_spawn_payload.ts +42 -5
  379. package/src/scripts/lint_symptom_intake.ts +2 -1
  380. package/src/scripts/mcp_parity_smoke.ts +30 -4
  381. package/src/scripts/mcp_render.ts +66 -1
  382. package/src/scripts/mcp_tool_fingerprint.ts +241 -0
  383. package/src/scripts/measure_risk_class_drift.ts +140 -0
  384. package/src/scripts/measure_skill_ranker_baseline.ts +212 -0
  385. package/src/scripts/media/lib/adapter-common.sh +211 -1
  386. package/src/scripts/media/lib/adapter-contract.md +74 -6
  387. package/src/scripts/model_rule_injection.ts +907 -0
  388. package/src/scripts/pack_install_smoke.ts +363 -0
  389. package/src/scripts/pr_conflict_census.ts +187 -0
  390. package/src/scripts/project_thin_rules.ts +45 -2
  391. package/src/scripts/release.ts +66 -860
  392. package/src/scripts/release_drill.ts +59 -3
  393. package/src/scripts/release_env.ts +298 -0
  394. package/src/scripts/release_publication.ts +720 -0
  395. package/src/scripts/report_pack_delta.ts +204 -0
  396. package/src/scripts/roadmap_context.ts +778 -0
  397. package/src/scripts/schemas/fidelity-measurement-sheet.schema.json +169 -0
  398. package/src/scripts/schemas/rule.schema.json +24 -2
  399. package/src/scripts/schemas/skill.schema.json +39 -0
  400. package/src/scripts/schemas/ui-authority.schema.json +114 -0
  401. package/src/scripts/select_analysis_mode.ts +112 -0
  402. package/src/scripts/session_register_hook.ts +29 -3
  403. package/src/scripts/sessions_cli.ts +67 -3
  404. package/src/scripts/skill_tools/score_skill_relevance.ts +36 -53
  405. package/src/scripts/sync_pr_branch.ts +40 -1
  406. package/src/scripts/token_sink_report.ts +239 -0
  407. package/src/scripts/trigger_coverage.ts +122 -3
  408. package/src/scripts/update_counts.ts +7 -3
  409. package/src/scripts/validate_frontmatter.ts +66 -0
  410. package/src/server/schemas/settings.ts +10 -0
  411. package/src/shared/skillRanking.ts +183 -0
  412. package/dist/agent-src/skills/accessibility-auditor/evals/evals.json +0 -15
  413. package/dist/agent-src/skills/agent-security-review/evals/triggers.json +0 -52
  414. package/dist/agent-src/skills/ai-code-blindspots/evals/triggers.json +0 -52
  415. package/dist/agent-src/skills/analysis-skill-router/evals/evals.json +0 -13
  416. package/dist/agent-src/skills/brand/evals/triggers.json +0 -17
  417. package/dist/agent-src/skills/brand-asset-generation/evals/triggers.json +0 -17
  418. package/dist/agent-src/skills/brand-audit/evals/triggers.json +0 -17
  419. package/dist/agent-src/skills/brand-identity/evals/triggers.json +0 -17
  420. package/dist/agent-src/skills/brand-strategy/evals/triggers.json +0 -17
  421. package/dist/agent-src/skills/brand-to-tokens/evals/triggers.json +0 -17
  422. package/dist/agent-src/skills/bug-analyzer/evals/evals.json +0 -13
  423. package/dist/agent-src/skills/canvas-design/evals/triggers.json +0 -17
  424. package/dist/agent-src/skills/character-consistency/evals/evals.json +0 -16
  425. package/dist/agent-src/skills/code-intelligence/evals/triggers.json +0 -52
  426. package/dist/agent-src/skills/code-review/evals/evals.json +0 -100
  427. package/dist/agent-src/skills/command-routing/evals/evals.json +0 -14
  428. package/dist/agent-src/skills/complexity-first-planning/evals/triggers.json +0 -17
  429. package/dist/agent-src/skills/contract-review/evals/triggers.json +0 -17
  430. package/dist/agent-src/skills/conventional-commits-writing/evals/evals.json +0 -15
  431. package/dist/agent-src/skills/corpus-grounding/evals/triggers.json +0 -17
  432. package/dist/agent-src/skills/dashboard-design/evals/evals.json +0 -16
  433. package/dist/agent-src/skills/dcf-modeling/evals/domain-truth.json +0 -29
  434. package/dist/agent-src/skills/dcf-modeling/evals/evals.json +0 -20
  435. package/dist/agent-src/skills/decision-record/evals/evals.json +0 -20
  436. package/dist/agent-src/skills/decision-record/evals/triggers.json +0 -87
  437. package/dist/agent-src/skills/design-intelligence/evals/evals.json +0 -14
  438. package/dist/agent-src/skills/design-intelligence/evals/triggers.json +0 -17
  439. package/dist/agent-src/skills/design-system-capture/evals/evals.json +0 -15
  440. package/dist/agent-src/skills/design-tokens/evals/triggers.json +0 -17
  441. package/dist/agent-src/skills/design-variations/evals/triggers.json +0 -17
  442. package/dist/agent-src/skills/developer-like-execution/evals/evals.json +0 -16
  443. package/dist/agent-src/skills/doc-coauthoring/evals/evals.json +0 -16
  444. package/dist/agent-src/skills/doc-coauthoring/evals/triggers.json +0 -17
  445. package/dist/agent-src/skills/docx-authoring/evals/triggers.json +0 -52
  446. package/dist/agent-src/skills/dpa-review/evals/triggers.json +0 -17
  447. package/dist/agent-src/skills/editorial-calendar/evals/domain-truth.json +0 -16
  448. package/dist/agent-src/skills/editorial-calendar/evals/evals.json +0 -16
  449. package/dist/agent-src/skills/eloquent/evals/triggers.json +0 -17
  450. package/dist/agent-src/skills/estimate-ticket/evals/evals.json +0 -16
  451. package/dist/agent-src/skills/estimate-ticket/evals/output-schema.yml +0 -20
  452. package/dist/agent-src/skills/estimate-ticket/evals/triggers.json +0 -19
  453. package/dist/agent-src/skills/evaluate-llm-feature/evals/triggers.json +0 -52
  454. package/dist/agent-src/skills/existing-ui-audit/evals/triggers.json +0 -47
  455. package/dist/agent-src/skills/experiment-loop/evals/output-schema.yml +0 -27
  456. package/dist/agent-src/skills/experiment-loop/evals/triggers.json +0 -17
  457. package/dist/agent-src/skills/fe-design/evals/triggers.json +0 -55
  458. package/dist/agent-src/skills/forecasting/evals/domain-truth.json +0 -29
  459. package/dist/agent-src/skills/forecasting/evals/evals.json +0 -20
  460. package/dist/agent-src/skills/forensics-report/evals/triggers.json +0 -17
  461. package/dist/agent-src/skills/frontend-render-security/evals/triggers.json +0 -52
  462. package/dist/agent-src/skills/fundraising-narrative/evals/domain-truth.json +0 -16
  463. package/dist/agent-src/skills/fundraising-narrative/evals/evals.json +0 -16
  464. package/dist/agent-src/skills/gated-reach/evals/triggers.json +0 -72
  465. package/dist/agent-src/skills/github-ci/evals/evals.json +0 -25
  466. package/dist/agent-src/skills/history-design/evals/triggers.json +0 -17
  467. package/dist/agent-src/skills/html-deck/evals/triggers.json +0 -17
  468. package/dist/agent-src/skills/humanizer/evals/strip_fixtures.json +0 -57
  469. package/dist/agent-src/skills/humanizer/evals/triggers.json +0 -17
  470. package/dist/agent-src/skills/iconography/evals/triggers.json +0 -17
  471. package/dist/agent-src/skills/image-analyser/evals/triggers.json +0 -17
  472. package/dist/agent-src/skills/image-creator/evals/triggers.json +0 -17
  473. package/dist/agent-src/skills/image-editing/evals/triggers.json +0 -17
  474. package/dist/agent-src/skills/image-generation/evals/triggers.json +0 -17
  475. package/dist/agent-src/skills/image-provider-routing/evals/triggers.json +0 -17
  476. package/dist/agent-src/skills/incident-commander/evals/domain-truth.json +0 -16
  477. package/dist/agent-src/skills/incident-commander/evals/evals.json +0 -20
  478. package/dist/agent-src/skills/judge-artifact-completeness/evals/triggers.json +0 -17
  479. package/dist/agent-src/skills/judge-injection-defense/evals/triggers.json +0 -17
  480. package/dist/agent-src/skills/judge-synthesis/evals/triggers.json +0 -17
  481. package/dist/agent-src/skills/launch-readiness/evals/evals.json +0 -21
  482. package/dist/agent-src/skills/learning-tutor/evals/triggers.json +0 -52
  483. package/dist/agent-src/skills/legal-intake-triage/evals/triggers.json +0 -17
  484. package/dist/agent-src/skills/legal-practice-profile/evals/triggers.json +0 -17
  485. package/dist/agent-src/skills/license-compliance-audit/evals/triggers.json +0 -52
  486. package/dist/agent-src/skills/license-compliance-borrow-check/evals/triggers.json +0 -52
  487. package/dist/agent-src/skills/license-compliance-credits/evals/triggers.json +0 -52
  488. package/dist/agent-src/skills/llm-provider-knowledge/evals/triggers.json +0 -20
  489. package/dist/agent-src/skills/logging-monitoring/evals/evals.json +0 -16
  490. package/dist/agent-src/skills/logo-generation/evals/triggers.json +0 -17
  491. package/dist/agent-src/skills/messaging-architecture/evals/domain-truth.json +0 -16
  492. package/dist/agent-src/skills/messaging-architecture/evals/evals.json +0 -16
  493. package/dist/agent-src/skills/nda-triage/evals/triggers.json +0 -17
  494. package/dist/agent-src/skills/pdf-tools/evals/triggers.json +0 -52
  495. package/dist/agent-src/skills/perf-feedback-craft/evals/evals.json +0 -16
  496. package/dist/agent-src/skills/persona-improvement/evals/triggers.json +0 -52
  497. package/dist/agent-src/skills/php-coder/evals/triggers.json +0 -17
  498. package/dist/agent-src/skills/prediction-pool-optimizer/evals/triggers.json +0 -21
  499. package/dist/agent-src/skills/prompt-engineering-image/evals/triggers.json +0 -17
  500. package/dist/agent-src/skills/prompt-engineering-patterns/evals/evals.json +0 -16
  501. package/dist/agent-src/skills/prompt-validator/evals/triggers.json +0 -17
  502. package/dist/agent-src/skills/quality-tools/evals/evals.json +0 -15
  503. package/dist/agent-src/skills/reasoning-orchestrator/evals/triggers.json +0 -17
  504. package/dist/agent-src/skills/refine-prompt/evals/evals.json +0 -16
  505. package/dist/agent-src/skills/refine-ticket/evals/evals.json +0 -16
  506. package/dist/agent-src/skills/refine-ticket/evals/output-schema.yml +0 -16
  507. package/dist/agent-src/skills/refine-ticket/evals/triggers.json +0 -17
  508. package/dist/agent-src/skills/release-comms/evals/evals.json +0 -16
  509. package/dist/agent-src/skills/rice-prioritization/evals/evals.json +0 -20
  510. package/dist/agent-src/skills/runway-cognition/evals/domain-truth.json +0 -29
  511. package/dist/agent-src/skills/runway-cognition/evals/evals.json +0 -20
  512. package/dist/agent-src/skills/scenario-modeling/evals/domain-truth.json +0 -29
  513. package/dist/agent-src/skills/scenario-modeling/evals/evals.json +0 -20
  514. package/dist/agent-src/skills/schema-review/evals/triggers.json +0 -17
  515. package/dist/agent-src/skills/screenshot-hygiene/evals/triggers.json +0 -52
  516. package/dist/agent-src/skills/security-maturity-assessment/evals/triggers.json +0 -52
  517. package/dist/agent-src/skills/skill-writing/evals/triggers.json +0 -17
  518. package/dist/agent-src/skills/spreadsheet-authoring/evals/triggers.json +0 -47
  519. package/dist/agent-src/skills/subagent-orchestration/evals/evals.json +0 -60
  520. package/dist/agent-src/skills/supply-chain-intake/evals/triggers.json +0 -52
  521. package/dist/agent-src/skills/systematic-debugging/evals/evals.json +0 -20
  522. package/dist/agent-src/skills/test-case-discovery/evals/triggers.json +0 -52
  523. package/dist/agent-src/skills/test-driven-development/evals/evals.json +0 -16
  524. package/dist/agent-src/skills/threat-modeling/evals/evals.json +0 -21
  525. package/dist/agent-src/skills/typography-system/evals/evals.json +0 -14
  526. package/dist/agent-src/skills/typography-system/evals/triggers.json +0 -17
  527. package/dist/agent-src/skills/unit-economics-modeling/evals/domain-truth.json +0 -40
  528. package/dist/agent-src/skills/unit-economics-modeling/evals/evals.json +0 -24
  529. package/dist/agent-src/skills/verify-completion-evidence/evals/evals.json +0 -16
  530. package/dist/agent-src/skills/verify-repair-loop/evals/output-schema.yml +0 -20
  531. package/dist/agent-src/skills/verify-repair-loop/evals/triggers.json +0 -17
  532. package/dist/agent-src/skills/vision-articulation/evals/evals.json +0 -16
  533. package/dist/agent-src/skills/voice-and-tone-design/evals/evals.json +0 -16
  534. package/dist/agent-src/skills/wireframe/evals/triggers.json +0 -17
  535. package/dist/agent-src/skills/worktree-lifecycle/evals/evals.json +0 -38
  536. package/dist/agent-src/skills/worktree-lifecycle/evals/triggers.json +0 -52
  537. package/dist/cli/agent-config.js.map +0 -1
  538. package/dist/cli/bash/runBash.js.map +0 -1
  539. package/dist/cli/commands/commands.js.map +0 -1
  540. package/dist/cli/commands/config.js.map +0 -1
  541. package/dist/cli/commands/doctorShell.js.map +0 -1
  542. package/dist/cli/commands/mcpServer.js.map +0 -1
  543. package/dist/cli/commands/packs.js.map +0 -1
  544. package/dist/cli/commands/profiles.js.map +0 -1
  545. package/dist/cli/commands/recordTriggerEval.js.map +0 -1
  546. package/dist/cli/commands/rtkDetect.js.map +0 -1
  547. package/dist/cli/commands/settings.js.map +0 -1
  548. package/dist/cli/commands/uiServe.js.map +0 -1
  549. package/dist/cli/commands/versions.js.map +0 -1
  550. package/dist/cli/commands/workspaces.js.map +0 -1
  551. package/dist/cli/configRoot.js.map +0 -1
  552. package/dist/cli/discovery/loadManifest.js.map +0 -1
  553. package/dist/cli/firstRunNotice.js.map +0 -1
  554. package/dist/cli/help.js.map +0 -1
  555. package/dist/cli/initRouting.js.map +0 -1
  556. package/dist/cli/log/logger.js.map +0 -1
  557. package/dist/cli/main.js.map +0 -1
  558. package/dist/cli/mcp/content.js.map +0 -1
  559. package/dist/cli/mcp/dispatch.js.map +0 -1
  560. package/dist/cli/mcp/stdio.js.map +0 -1
  561. package/dist/cli/paths.js.map +0 -1
  562. package/dist/cli/python/knowledge_ingest.js.map +0 -1
  563. package/dist/cli/python/workspace_analytics.js.map +0 -1
  564. package/dist/cli/python/workspace_crypto.js.map +0 -1
  565. package/dist/cli/python/workspace_documents.js.map +0 -1
  566. package/dist/cli/python/workspace_drive.js.map +0 -1
  567. package/dist/cli/python/workspace_drive_health.js.map +0 -1
  568. package/dist/cli/python/workspace_explain.js.map +0 -1
  569. package/dist/cli/python/workspace_hosts.js.map +0 -1
  570. package/dist/cli/python/workspace_inbox.js.map +0 -1
  571. package/dist/cli/python/workspace_render.js.map +0 -1
  572. package/dist/cli/python/workspace_roles.js.map +0 -1
  573. package/dist/cli/python/workspace_secrets.js.map +0 -1
  574. package/dist/cli/python/workspace_sessions.js.map +0 -1
  575. package/dist/cli/python/workspace_skills.js.map +0 -1
  576. package/dist/cli/registry.js.map +0 -1
  577. package/dist/install/agentSwitchDetection.js.map +0 -1
  578. package/dist/install/agentSwitchProfile.js.map +0 -1
  579. package/dist/install/atomic.js.map +0 -1
  580. package/dist/install/claudePathsPlan.js.map +0 -1
  581. package/dist/install/conflict.js.map +0 -1
  582. package/dist/install/detect.js.map +0 -1
  583. package/dist/install/emit_host_rules_cli.js.map +0 -1
  584. package/dist/install/globalRuleLayers.js.map +0 -1
  585. package/dist/install/hostLayerFingerprint.js.map +0 -1
  586. package/dist/install/partitionEligibility.js.map +0 -1
  587. package/dist/install/paths.js.map +0 -1
  588. package/dist/install/plan.js.map +0 -1
  589. package/dist/install/preflight.js.map +0 -1
  590. package/dist/install/rtkDetection.js.map +0 -1
  591. package/dist/install/ruleInScope.js.map +0 -1
  592. package/dist/install/ruleLayerPartition.js.map +0 -1
  593. package/dist/install/rule_scope.js.map +0 -1
  594. package/dist/install/rule_scope_cli.js.map +0 -1
  595. package/dist/install/selectedTools.js.map +0 -1
  596. package/dist/install/toolDetection.js.map +0 -1
  597. package/dist/install/txlog.js.map +0 -1
  598. package/dist/install/types.js.map +0 -1
  599. package/dist/install/wizard-plan.js.map +0 -1
  600. package/dist/install/wizardDismissals.js.map +0 -1
  601. package/dist/scripts/_lib/agent_settings.js.map +0 -1
  602. package/dist/scripts/_lib/agent_src.js.map +0 -1
  603. package/dist/scripts/_lib/claude_builtin_names.js.map +0 -1
  604. package/dist/scripts/_lib/claude_plugin.js.map +0 -1
  605. package/dist/scripts/_lib/claude_settings_hooks.js.map +0 -1
  606. package/dist/scripts/_lib/compile_time_toggles.js.map +0 -1
  607. package/dist/scripts/_lib/environment_detector.js.map +0 -1
  608. package/dist/scripts/_lib/host_launch.js.map +0 -1
  609. package/dist/scripts/_lib/install_layout.js.map +0 -1
  610. package/dist/scripts/_lib/installed_lock.js.map +0 -1
  611. package/dist/scripts/_lib/model_tier.js.map +0 -1
  612. package/dist/scripts/_lib/prune_empty_dirs.js.map +0 -1
  613. package/dist/scripts/_lib/scoped_projection.js.map +0 -1
  614. package/dist/scripts/_lib/script_output.js.map +0 -1
  615. package/dist/scripts/_lib/spawn_env.js.map +0 -1
  616. package/dist/scripts/_lib/surface_tiers.js.map +0 -1
  617. package/dist/scripts/_lib/token_count.js.map +0 -1
  618. package/dist/scripts/_lib/trigger_eval_floors.js.map +0 -1
  619. package/dist/scripts/_lib/user_global_paths.js.map +0 -1
  620. package/dist/scripts/ai_council/modes.js.map +0 -1
  621. package/dist/scripts/ai_council/transport_resolver.js.map +0 -1
  622. package/dist/scripts/condense.js.map +0 -1
  623. package/dist/scripts/project_thin_rules.js.map +0 -1
  624. package/dist/server/app.js.map +0 -1
  625. package/dist/server/io/atomicMultiWrite.js.map +0 -1
  626. package/dist/server/io/atomicWrite.js.map +0 -1
  627. package/dist/server/io/sharedWriteCheck.js.map +0 -1
  628. package/dist/server/io/substituteTemplate.js.map +0 -1
  629. package/dist/server/io/yamlIO.js.map +0 -1
  630. package/dist/server/nicknameResolver.js.map +0 -1
  631. package/dist/server/port.js.map +0 -1
  632. package/dist/server/routes/discovery.js.map +0 -1
  633. package/dist/server/routes/install.js.map +0 -1
  634. package/dist/server/routes/ping.js.map +0 -1
  635. package/dist/server/routes/schema.js.map +0 -1
  636. package/dist/server/routes/settings.js.map +0 -1
  637. package/dist/server/routes/settingsChanges.js.map +0 -1
  638. package/dist/server/routes/userMd.js.map +0 -1
  639. package/dist/server/routes/wizard.js.map +0 -1
  640. package/dist/server/routes/workspace.js.map +0 -1
  641. package/dist/server/schemas/settings.js.map +0 -1
  642. package/dist/server/serverInfo.js.map +0 -1
  643. package/dist/server/token.js.map +0 -1
  644. package/dist/server/writeRoot.js.map +0 -1
  645. package/dist/shared/capabilities.js.map +0 -1
  646. package/dist/shared/interactiveContext.js.map +0 -1
  647. package/dist/shared/nicknamePrefill.js.map +0 -1
  648. package/dist/shared/settingsAsks.js.map +0 -1
  649. package/dist/shared/settingsCarveOut.js.map +0 -1
  650. package/dist/shared/settingsClasses.js.map +0 -1
  651. package/dist/shared/settingsConsent.js.map +0 -1
  652. package/dist/shared/settingsSurface.js.map +0 -1
  653. package/dist/shared/userMd/formAdapter.js.map +0 -1
  654. package/dist/shared/userMd/schema.js.map +0 -1
  655. package/dist/shared/userMd/utils.js.map +0 -1
  656. package/dist/ui/assets/index-Cxgy63kz.js.map +0 -1
  657. package/src/scripts/_lib/adr_frontmatter.test.ts +0 -365
  658. package/src/scripts/_lib/adversarial_council_gate.test.ts +0 -112
  659. package/src/scripts/_lib/adversarial_reconcile.test.ts +0 -197
  660. package/src/scripts/_lib/auto_dispatch.corpus.test.ts +0 -150
  661. package/src/scripts/_lib/secret_detector.test.ts +0 -108
  662. package/src/scripts/_lib/secret_detector_adversarial.test.ts +0 -116
  663. package/src/scripts/_lib/untrusted_content.test.ts +0 -175
  664. package/src/scripts/check_secret_leak.test.ts +0 -90
  665. package/src/scripts/design_slop_rules.test.ts +0 -239
  666. package/src/scripts/self_review_gate.test.ts +0 -296
  667. package/src/shared/capabilities.test.ts +0 -43
@@ -0,0 +1,318 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * Rule-inject — the delivery twin of `skill-route`, with the opposite payload
4
+ * policy (`road-to-trigger-delivered-rule-bodies` Phase 1).
5
+ *
6
+ * BODIES, NEVER POINTERS — and the difference from its twin is deliberate
7
+ * rather than incidental. `skill_route_hook.ts:14` ships "POINTERS, NEVER
8
+ * BODIES" on this same slot, and it is right to: a skill is a thing the agent
9
+ * *invokes*, so naming it is enough. A rule is a thing the agent must already
10
+ * be *under*, and the only datum anyone has on pointer-shaped rule delivery is
11
+ * the 36.2 %-against-48 % run at `docs/CLAIMS.md:188-189`. Whatever that
12
+ * instrument's flaws — and ADR-202 closed it — it points one way.
13
+ *
14
+ * DEFAULT OFF, AND OFF MEANS ZERO BYTES. The concern registers on two slots but
15
+ * returns before reading the router unless `lean_projection.mode: delivery` is
16
+ * set. Under every shipped default it emits nothing, costs no injection budget,
17
+ * and leaves the standing corpus exactly as it is today. That is why its
18
+ * `hook-token-budget.json` row is registered against the per-prompt cap rather
19
+ * than a measured emission: there is no measured emission to register yet.
20
+ *
21
+ * ONE MATCHER, SHARED WITH THE OFFLINE MODEL. Everything about selection,
22
+ * ordering, capping and body loading comes from `_lib/rule_injection.ts`, which
23
+ * `model_rule_injection.ts` also imports. Step 0.5 states the reason in as many
24
+ * words: an experiment whose offline pricing and runtime delivery use different
25
+ * matchers measures nothing.
26
+ *
27
+ * ONCE PER SESSION PER RULE, RE-ARMED ON COMPACTION. A rule's body is injected
28
+ * the first time one of its triggers fires and not again, because the model
29
+ * already has it. Compaction is exactly the event that makes that false, so
30
+ * `pre_compact` clears the seen-set — the same pin-lost shape `language-mirror`
31
+ * uses. State lives under `agents/runtime/state/`, the class
32
+ * `context-hygiene.json` already occupies; no new state convention is created.
33
+ *
34
+ * NEVER BLOCKS. Every failure path returns 0: unreadable stdin, malformed JSON,
35
+ * missing router, unreadable body, unwritable state. The one non-zero exit is
36
+ * the host's advisory context channel (exit 2 + `decision: "warn"`), the same
37
+ * channel `ui-route-nudge` and `code-graph-nudge` already use on `pre_tool_use`
38
+ * with `severity: advisory` — a warn there is an injection, not a deny.
39
+ *
40
+ * HOST BOUNDARY, STATED RATHER THAN IMPLIED. `user_prompt_submit` and
41
+ * `pre_tool_use` are bound on a subset of hosts, and only `claude` honours a
42
+ * deny at all. On a host where neither slot is bound this concern cannot run,
43
+ * which is the whole reason the flip step 2.4 gates on is Claude-only. Run
44
+ * `agent-config hooks:status` for the host you are actually on.
45
+ *
46
+ * SUBAGENTS ARE OUT OF REACH, MEASURED. Neither slot fires inside a spawned
47
+ * child session and the `subagent_start` payload carries no prompt field — see
48
+ * `agents/evidence/investigations/subagent-start-payload-probe.md` (2026-08-23,
49
+ * claude 2.1.241, three verdicts). Delivery is therefore orchestrator-only, and
50
+ * no third binding is added.
51
+ */
52
+ import * as fs from 'node:fs';
53
+ import * as path from 'node:path';
54
+ import process from 'node:process';
55
+ import { fileURLToPath, pathToFileURL } from 'node:url';
56
+
57
+ import { hookSectionEnabled, leanProjectionModeRaw } from '../_lib/hook_settings.js';
58
+ import { deliversBodies, normalizeLeanProjectionMode } from '../_lib/lean_projection_mode.js';
59
+ import {
60
+ loadRuleBody,
61
+ loadRouter,
62
+ matchTierRules,
63
+ selectForInjection,
64
+ } from '../_lib/rule_injection.js';
65
+ import { readHookStdin } from './hook_stdin.js';
66
+
67
+ const EXIT_ALLOW = 0;
68
+ const EXIT_WARN = 2;
69
+
70
+ /**
71
+ * Per-prompt injection ceiling, in UTF-8 BYTES.
72
+ *
73
+ * DERIVED, NOT PICKED: `model_rule_injection --corpus tests/eval/routing-matrix`
74
+ * measured the matched-body-token distribution over the frozen labelled corpus
75
+ * at p50 1,728 / p90 4,804 / p99 8,248 / max 12,957 exact-BPE tokens, and step
76
+ * 1.1 specifies "the p90 from 0.4, rounded to 500" — 4,804 rounds up to 5,000.
77
+ *
78
+ * BYTES rather than tokens, and the unit change is the point rather than a
79
+ * detail. `_lib/token_count.ts` resolves `js-tiktoken` at module load, so a
80
+ * token-capped concern drags a tokenizer into EVERY hook dispatch on every
81
+ * slot, for a concern that is default-OFF and emits nothing. Measured: 202 ms
82
+ * -> 196 ms on the `pre_tool_use` p95 when the concern is unbound entirely, and
83
+ * the CI latency gate went red on the branch that introduced it while passing
84
+ * on main. So the runtime cap is the same bound in the unit
85
+ * `hook-token-budget.json` already enforces — 5,000 tok at the ~4 bytes/token
86
+ * this corpus measures is 20,480 B, which is exactly this concern's registered
87
+ * row. Cap and budget row are now one number instead of two units.
88
+ *
89
+ * Re-run that command if the corpus or the bodies move; a cap copied from a
90
+ * stale measurement is worse than no cap, because it looks derived.
91
+ */
92
+ export const CAP_BYTES = 20480;
93
+
94
+ /** Tools whose input names a file this concern can match path triggers against. */
95
+ export const FILE_TOOLS = new Set(['Write', 'Edit', 'NotebookEdit', 'Read', 'MultiEdit']);
96
+
97
+ type JsonObject = Record<string, unknown>;
98
+
99
+ function isObject(v: unknown): v is JsonObject {
100
+ return typeof v === 'object' && v !== null && !Array.isArray(v);
101
+ }
102
+
103
+ function str(o: JsonObject, ...keys: string[]): string | null {
104
+ for (const k of keys) {
105
+ const v = o[k];
106
+ if (typeof v === 'string' && v !== '') return v;
107
+ }
108
+ return null;
109
+ }
110
+
111
+ /** Workspace root the envelope points at, falling back to the process cwd. */
112
+ export function workspaceRoot(env: JsonObject): string {
113
+ return str(env, 'workspace', 'cwd', 'project_dir') ?? process.cwd();
114
+ }
115
+
116
+ // ── seen-set state ───────────────────────────────────────────────────────
117
+
118
+ export interface SeenState {
119
+ rules: string[];
120
+ }
121
+
122
+ export function statePath(root: string, session: string): string {
123
+ const safe = session.replace(/[^A-Za-z0-9_-]/g, '_').slice(0, 80) || 'unknown';
124
+ return path.join(root, 'agents', 'runtime', 'state', 'rule-inject', `${safe}.json`);
125
+ }
126
+
127
+ export function readSeen(root: string, session: string): Set<string> {
128
+ try {
129
+ const raw = fs.readFileSync(statePath(root, session), 'utf-8');
130
+ const parsed = JSON.parse(raw) as SeenState;
131
+ return new Set(Array.isArray(parsed.rules) ? parsed.rules.map(String) : []);
132
+ } catch {
133
+ return new Set(); // fresh session, or a file nothing can parse
134
+ }
135
+ }
136
+
137
+ export function writeSeen(root: string, session: string, seen: Set<string>): void {
138
+ const p = statePath(root, session);
139
+ try {
140
+ fs.mkdirSync(path.dirname(p), { recursive: true });
141
+ const payload: SeenState = { rules: [...seen].sort() };
142
+ fs.writeFileSync(`${p}.tmp`, `${JSON.stringify(payload)}\n`, 'utf-8');
143
+ fs.renameSync(`${p}.tmp`, p);
144
+ } catch {
145
+ /* unwritable state must never fail a turn — worst case a re-injection */
146
+ }
147
+ }
148
+
149
+ export function clearSeen(root: string, session: string): void {
150
+ try {
151
+ fs.rmSync(statePath(root, session), { force: true });
152
+ } catch {
153
+ /* ignore */
154
+ }
155
+ }
156
+
157
+ // ── payload extraction ───────────────────────────────────────────────────
158
+
159
+ /** The user's prompt, across the shapes the hosts use. */
160
+ export function extractPrompt(payload: JsonObject): string {
161
+ return str(payload, 'prompt', 'user_prompt', 'userPrompt', 'message', 'text') ?? '';
162
+ }
163
+
164
+ /** The file path a file-touching tool call names, or `null`. */
165
+ export function extractFilePath(payload: JsonObject): string | null {
166
+ const ti = payload['tool_input'] ?? payload['toolInput'] ?? payload['input'];
167
+ if (!isObject(ti)) return null;
168
+ return str(ti, 'file_path', 'path', 'filePath', 'notebook_path');
169
+ }
170
+
171
+ // ── decision ─────────────────────────────────────────────────────────────
172
+
173
+ export interface Injection {
174
+ rules: string[];
175
+ bytes: number;
176
+ body: string;
177
+ }
178
+
179
+ /**
180
+ * Build the injection for one event, or `null` for silence.
181
+ *
182
+ * `prompt` drives keyword / phrase / command triggers; `openFiles` drives
183
+ * `path_prefix` / `file_pattern`. On the tool slot the prompt is deliberately
184
+ * empty, so a file event can only ever fire a path trigger — a tool call is not
185
+ * a restatement of the user's request and must not re-fire keyword rules.
186
+ */
187
+ export function buildInjection(
188
+ root: string,
189
+ prompt: string,
190
+ openFiles: string[] | null,
191
+ command: string | null,
192
+ seen: Set<string>,
193
+ ): Injection | null {
194
+ let router;
195
+ try {
196
+ router = loadRouter(root);
197
+ } catch {
198
+ return null; // no router — nothing to deliver, and never a failure
199
+ }
200
+ const matches = matchTierRules(router, prompt, openFiles, command).filter(
201
+ (m) => !seen.has(m.id),
202
+ );
203
+ if (matches.length === 0) return null;
204
+ const sel = selectForInjection(root, matches, CAP_BYTES);
205
+ const parts: string[] = [];
206
+ const ids: string[] = [];
207
+ for (const m of sel.selected) {
208
+ const body = loadRuleBody(root, m.id);
209
+ if (body === null) continue;
210
+ ids.push(m.id);
211
+ parts.push(`<rule id="${m.id}" tier="${m.tier}">\n${body.trim()}\n</rule>`);
212
+ }
213
+ if (ids.length === 0) return null;
214
+ return { rules: ids, bytes: sel.bytes, body: parts.join('\n\n') };
215
+ }
216
+
217
+ // ── main ─────────────────────────────────────────────────────────────────
218
+
219
+ /**
220
+ * Whether the settings gate applies.
221
+ *
222
+ * Through the dispatcher the gate is absolute: no `lean_projection.mode:
223
+ * delivery`, no bytes. A DIRECT CLI invocation is a probe by definition — an
224
+ * operator piping an envelope into this file is asking to see what it would
225
+ * deliver — so there the mode defaults to on. `AGENT_CONFIG_REPLAY` re-imposes
226
+ * the gate, which is what keeps `bench_hook_injection` measuring the shipped
227
+ * default (zero bytes) rather than the probe.
228
+ */
229
+ export function gateOpen(root: string, cliEntry: boolean): boolean {
230
+ if (deliversBodies(normalizeLeanProjectionMode(leanProjectionModeRaw(root)))) return true;
231
+ if (hookSectionEnabled(root, 'rule_inject')) return true;
232
+ return cliEntry && process.env['AGENT_CONFIG_REPLAY'] !== '1';
233
+ }
234
+
235
+ export function main(argv: readonly string[] = process.argv.slice(2)): number {
236
+ let eventOverride: string | null = null;
237
+ for (let i = 0; i < argv.length; i += 1) {
238
+ if (argv[i] === '--event') {
239
+ i += 1;
240
+ eventOverride = argv[i] ?? null;
241
+ }
242
+ }
243
+
244
+ let env: JsonObject = {};
245
+ try {
246
+ const raw = readHookStdin();
247
+ const parsed = raw.trim() ? (JSON.parse(raw) as unknown) : {};
248
+ env = isObject(parsed) ? parsed : {};
249
+ } catch {
250
+ return EXIT_ALLOW; // malformed envelope — never block
251
+ }
252
+
253
+ const root = workspaceRoot(env);
254
+ const payload = isObject(env['payload']) ? (env['payload'] as JsonObject) : env;
255
+ const slot = eventOverride ?? str(env, 'event') ?? 'user_prompt_submit';
256
+ const session = str(env, 'session_id', 'sessionId') ?? str(payload, 'session_id', 'sessionId') ?? 'unknown';
257
+
258
+ if (slot === 'pre_compact') {
259
+ clearSeen(root, session);
260
+ return EXIT_ALLOW; // re-arm is silent; the next turn re-injects
261
+ }
262
+ if (slot !== 'user_prompt_submit' && slot !== 'pre_tool_use') return EXIT_ALLOW;
263
+ if (!gateOpen(root, _isCliEntry())) return EXIT_ALLOW;
264
+
265
+ let prompt = '';
266
+ let openFiles: string[] | null = null;
267
+ let command: string | null = null;
268
+ if (slot === 'user_prompt_submit') {
269
+ prompt = extractPrompt(payload);
270
+ if (prompt === '') return EXIT_ALLOW;
271
+ const m = /^\s*(\/[A-Za-z0-9:_-]+)/.exec(prompt);
272
+ command = m ? (m[1] as string) : null;
273
+ } else {
274
+ const tool = str(payload, 'tool_name', 'toolName', 'tool');
275
+ if (tool === null || !FILE_TOOLS.has(tool)) return EXIT_ALLOW;
276
+ const fp = extractFilePath(payload);
277
+ if (fp === null) return EXIT_ALLOW;
278
+ openFiles = [fp];
279
+ }
280
+
281
+ const seen = readSeen(root, session);
282
+ const injection = buildInjection(root, prompt, openFiles, command, seen);
283
+ if (injection === null) return EXIT_ALLOW; // silence is the default
284
+
285
+ for (const id of injection.rules) seen.add(id);
286
+ writeSeen(root, session, seen);
287
+
288
+ process.stdout.write(
289
+ `${JSON.stringify({
290
+ decision: 'warn',
291
+ reason: `rule-inject: ${injection.rules.length} rule body/bodies on ${slot} (${injection.bytes} B)`,
292
+ additional_context: injection.body,
293
+ })}\n`,
294
+ );
295
+ return EXIT_WARN;
296
+ }
297
+
298
+ // Bundle-safety: never auto-run when inlined into an esbuild bundle, where
299
+ // every module shares the bundle's `import.meta.url`.
300
+ declare const __AGENT_CONFIG_BUNDLE__: boolean | undefined;
301
+ function _isCliEntry(): boolean {
302
+ if (typeof __AGENT_CONFIG_BUNDLE__ !== 'undefined' && __AGENT_CONFIG_BUNDLE__) return false;
303
+ if (process.argv[1] === undefined) return false;
304
+ const argvUrl = pathToFileURL(path.resolve(process.argv[1])).href;
305
+ if (import.meta.url === argvUrl) return true;
306
+ try {
307
+ return (
308
+ fs.realpathSync(fileURLToPath(import.meta.url)) ===
309
+ fs.realpathSync(path.resolve(process.argv[1]))
310
+ );
311
+ } catch {
312
+ return false;
313
+ }
314
+ }
315
+
316
+ if (_isCliEntry()) {
317
+ process.exit(main());
318
+ }
@@ -0,0 +1,368 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * Suggestion-block capture — a two-slot latch, counts only.
4
+ *
5
+ * ## What it measures and why it exists
6
+ *
7
+ * `command_suggester/render.ts` emits a numbered-options block with exactly one
8
+ * `Recommendation: N — …` line and the as-is option always last. Nothing records
9
+ * whether those blocks are ever *answered*, so no roadmap can cite a selection
10
+ * rate — and the model-carried alternative is measured and dead:
11
+ * `orchestration_record` captured 1 of 369 dispatches. This instrument exists so
12
+ * that figure is not repeated by construction.
13
+ *
14
+ * ## Two slots, not one — and the probe is why
15
+ *
16
+ * `road-to-suggestion-block-capture` planned a single `user_prompt_submit` hook
17
+ * reading the transcript tail. A live probe
18
+ * (`agents/evidence/analysis/suggestion-capture-probe.md`) found something
19
+ * cheaper: **`stop` carries `last_assistant_message` in the payload**, so the
20
+ * "was a block emitted" half needs no file read at all, and the turn-1 blind
21
+ * spot (`transcript_path` present but the file not yet written) does not arise.
22
+ *
23
+ * stop → detect the signature in `last_assistant_message`,
24
+ * write a latch keyed by `prompt_id`
25
+ * user_prompt_submit → CONSUME the latch, classify `prompt`, append one line
26
+ *
27
+ * ## The misclassification guard, which is the whole correctness argument
28
+ *
29
+ * A bare `1` three turns later must never read as a pick. So the latch is
30
+ * **consumed exactly once**: `user_prompt_submit` deletes it after reading, and
31
+ * a prompt arriving with no latch is `other`, never `option_n`. A latch older
32
+ * than `LATCH_TTL_MS` is `stale_block`. An unparseable latch is `stale_block`
33
+ * too — never a guess.
34
+ *
35
+ * ## Privacy is a property of the schema, not of a scrubber
36
+ *
37
+ * `src/config/suggestion-capture.json` registers five fields and **none can hold
38
+ * free text**: a timestamp, a boolean, an options COUNT, and two closed enums.
39
+ * `option_n` records THAT a numbered option was chosen and out of how many —
40
+ * deliberately not WHICH, because the block's option order is content and the
41
+ * capture-rate question does not need it. A type with no field able to carry a
42
+ * prompt cannot leak one; a scrubber can fail.
43
+ *
44
+ * Default-OFF (`hooks.suggestion_capture.enabled: true`). `fail_closed: false`,
45
+ * always exit 0: an instrument must never break a turn it is only observing.
46
+ */
47
+ import fs from 'node:fs';
48
+ import path from 'node:path';
49
+ import { fileURLToPath, pathToFileURL } from 'node:url';
50
+
51
+ import { unwrap } from './envelope.js';
52
+ import { readHookStdin } from './hook_stdin.js';
53
+
54
+ const EXIT_ALLOW = 0;
55
+ const SETTINGS_FILE = '.agent-settings.yml';
56
+ const SINK_REL = path.join('agents', 'runtime', 'state', 'audit', 'suggestion-capture.jsonl');
57
+ const LATCH_REL = path.join('agents', 'runtime', 'state', 'suggestion-latch.json');
58
+ /** A block older than this cannot be what the current prompt is answering. */
59
+ export const LATCH_TTL_MS = 15 * 60 * 1000;
60
+
61
+ export type Classification = 'option_n' | 'as_is' | 'other' | 'stale_block';
62
+ export type EvidenceClass = 'render-signature' | 'latch-consumed' | 'latch-stale' | 'no-latch';
63
+
64
+ type JsonValue = string | number | boolean | null | JsonValue[] | { [k: string]: JsonValue };
65
+ type JsonObject = { [k: string]: JsonValue };
66
+
67
+ const isObject = (v: unknown): v is JsonObject =>
68
+ typeof v === 'object' && v !== null && !Array.isArray(v);
69
+
70
+ const str = (v: JsonValue | undefined): string => (typeof v === 'string' ? v : '');
71
+
72
+ /* ── the render signature ──────────────────────────────────────────────────── */
73
+
74
+ /**
75
+ * Exactly one `Recommendation:`/`Empfehlung:` line, plus at least two numbered
76
+ * options. Both halves are required: a numbered list alone is ordinary prose,
77
+ * and a `Recommendation:` line alone is a sentence.
78
+ *
79
+ * The label is matched in both languages because `user-interaction`'s Iron Law 1
80
+ * makes a wrong-language label a rule violation, not a variant — so a German
81
+ * session's block carries `Empfehlung:` and a single-language matcher would
82
+ * under-count exactly the sessions the mirror rule produces.
83
+ */
84
+ export function detectBlock(text: string): { emitted: boolean; optionsCount: number } {
85
+ if (text === '') return { emitted: false, optionsCount: 0 };
86
+ const lines = text.split('\n');
87
+ const recommendation = lines.filter((l) => /^\s*(?:\*\*)?(?:Recommendation|Empfehlung)\s*:/i.test(l)).length;
88
+ const numbered = new Set<string>();
89
+ for (const l of lines) {
90
+ const m = /^\s*(\d{1,2})[.)]\s+\S/.exec(l);
91
+ if (m?.[1] !== undefined) numbered.add(m[1]);
92
+ }
93
+ const emitted = recommendation === 1 && numbered.size >= 2;
94
+ return { emitted, optionsCount: emitted ? numbered.size : 0 };
95
+ }
96
+
97
+ /* ── classification ────────────────────────────────────────────────────────── */
98
+
99
+ /**
100
+ * The as-is escape hatch, matched by intent rather than by an exact string:
101
+ * `command-suggestion-policy` requires it present and last but fixes no wording,
102
+ * so a literal matcher would silently classify every as-is pick as `other`.
103
+ */
104
+ const AS_IS_RE = /\b(as[- ]is|as is|unver(?:ä|ae)ndert|so lassen|wie es ist|keep it|leave it|no change)\b/i;
105
+
106
+ export function classify(prompt: string, optionsCount: number): Classification {
107
+ const t = prompt.trim();
108
+ if (t === '') return 'other';
109
+ if (AS_IS_RE.test(t)) return 'as_is';
110
+ // A bare number, or a number with trailing punctuation — the shape a pick
111
+ // actually takes. `1. do the thing` is NOT a pick: it is an instruction that
112
+ // happens to start with a digit, and counting it would inflate the rate.
113
+ const bare = /^(\d{1,2})\s*[.)]?\s*$/.exec(t);
114
+ if (bare?.[1] !== undefined) {
115
+ const n = Number(bare[1]);
116
+ // Out-of-range is `other`: a "7" against a 3-option block is answering
117
+ // something else, and recording it as a pick would corrupt the metric
118
+ // the whole instrument exists to produce.
119
+ if (n >= 1 && (optionsCount === 0 || n <= optionsCount)) return 'option_n';
120
+ }
121
+ return 'other';
122
+ }
123
+
124
+ /* ── settings, latch, sink ─────────────────────────────────────────────────── */
125
+
126
+ /** `hooks.suggestion_capture.enabled: true` — the same mini-parse siblings use. */
127
+ export function enabled(root: string): boolean {
128
+ let raw: string;
129
+ try {
130
+ raw = fs.readFileSync(path.join(root, SETTINGS_FILE), 'utf8');
131
+ } catch {
132
+ return false;
133
+ }
134
+ let inHooks = false;
135
+ let inSection = false;
136
+ for (const line of raw.split('\n')) {
137
+ if (/^hooks:\s*$/.test(line)) {
138
+ inHooks = true;
139
+ inSection = false;
140
+ continue;
141
+ }
142
+ if (/^\S/.test(line)) {
143
+ inHooks = false;
144
+ inSection = false;
145
+ continue;
146
+ }
147
+ if (!inHooks) continue;
148
+ if (/^\s{2}suggestion_capture:\s*$/.test(line)) {
149
+ inSection = true;
150
+ continue;
151
+ }
152
+ if (/^\s{2}\S/.test(line)) {
153
+ inSection = false;
154
+ continue;
155
+ }
156
+ if (inSection && /^\s{4}enabled:\s*true\s*$/.test(line)) return true;
157
+ }
158
+ return false;
159
+ }
160
+
161
+ export interface Latch {
162
+ readonly prompt_id: string;
163
+ readonly options_count: number;
164
+ readonly at: number;
165
+ }
166
+
167
+ export function writeLatch(root: string, latch: Latch): void {
168
+ const p = path.join(root, LATCH_REL);
169
+ fs.mkdirSync(path.dirname(p), { recursive: true });
170
+ fs.writeFileSync(p, `${JSON.stringify(latch)}\n`, 'utf8');
171
+ }
172
+
173
+ /** Read AND delete. Consume-once is the misclassification guard, not a detail. */
174
+ export function consumeLatch(root: string): Latch | null {
175
+ const p = path.join(root, LATCH_REL);
176
+ let raw: string;
177
+ try {
178
+ raw = fs.readFileSync(p, 'utf8');
179
+ } catch {
180
+ return null;
181
+ }
182
+ try {
183
+ fs.rmSync(p, { force: true });
184
+ } catch {
185
+ /* a latch we cannot delete is still consumed for this turn */
186
+ }
187
+ try {
188
+ const v = JSON.parse(raw) as unknown;
189
+ if (!isObject(v)) return null;
190
+ const at = v['at'];
191
+ const oc = v['options_count'];
192
+ const pid = v['prompt_id'];
193
+ if (typeof at !== 'number' || typeof oc !== 'number' || typeof pid !== 'string') return null;
194
+ return { prompt_id: pid, options_count: oc, at };
195
+ } catch {
196
+ return null; // unparseable → stale_block, never a guess
197
+ }
198
+ }
199
+
200
+ export interface Record_ {
201
+ readonly ts: string;
202
+ readonly block_emitted: boolean;
203
+ readonly options_count: number;
204
+ readonly evidence_class: EvidenceClass;
205
+ readonly turn_classification: Classification;
206
+ }
207
+
208
+ /** The exact key set `src/config/suggestion-capture.json` registers. */
209
+ export const RECORD_KEYS: readonly string[] = [
210
+ 'ts',
211
+ 'block_emitted',
212
+ 'options_count',
213
+ 'evidence_class',
214
+ 'turn_classification',
215
+ ];
216
+
217
+ export function appendRecord(root: string, rec: Record_, now: Date): void {
218
+ const p = path.join(root, SINK_REL);
219
+ fs.mkdirSync(path.dirname(p), { recursive: true });
220
+ const line = {
221
+ ts: now.toISOString().replace(/\.\d{3}Z$/, 'Z'),
222
+ block_emitted: rec.block_emitted,
223
+ options_count: rec.options_count,
224
+ evidence_class: rec.evidence_class,
225
+ turn_classification: rec.turn_classification,
226
+ };
227
+ fs.appendFileSync(p, `${JSON.stringify(line)}\n`, 'utf8');
228
+ }
229
+
230
+ /* ── the two slots ─────────────────────────────────────────────────────────── */
231
+
232
+ /** Decide what a prompt turn should record. Pure, so the tests drive it directly. */
233
+ export function classifyTurn(
234
+ prompt: string,
235
+ latch: Latch | null,
236
+ nowMs: number,
237
+ ): { record: boolean; evidence_class: EvidenceClass; turn_classification: Classification; options_count: number } {
238
+ if (latch === null) {
239
+ // No block preceded this turn. Recording every ordinary turn would make
240
+ // the sink a prompt log with the volume of one, so nothing is written.
241
+ return { record: false, evidence_class: 'no-latch', turn_classification: 'other', options_count: 0 };
242
+ }
243
+ if (nowMs - latch.at > LATCH_TTL_MS) {
244
+ return {
245
+ record: true,
246
+ evidence_class: 'latch-stale',
247
+ turn_classification: 'stale_block',
248
+ options_count: latch.options_count,
249
+ };
250
+ }
251
+ return {
252
+ record: true,
253
+ evidence_class: 'latch-consumed',
254
+ turn_classification: classify(prompt, latch.options_count),
255
+ options_count: latch.options_count,
256
+ };
257
+ }
258
+
259
+ /**
260
+ * Canonical event name, from either invocation shape.
261
+ *
262
+ * The dispatcher supplies `envelope.event` (`stop`, `user_prompt_submit`); a
263
+ * direct/legacy invocation carries only the host's own `hook_event_name`
264
+ * (`Stop`, `UserPromptSubmit`). Reading just the second one is how the first
265
+ * version of this concern became a silent no-op under the dispatcher: it ran,
266
+ * matched nothing, and exited 0 — indistinguishable from a disabled hook.
267
+ */
268
+ export function eventOf(envelope: JsonObject, payload: JsonObject): string {
269
+ const canonical = str(envelope['event'] as JsonValue | undefined);
270
+ const native = str(
271
+ (envelope['native_event'] ?? payload['hook_event_name']) as JsonValue | undefined,
272
+ );
273
+ const raw = (canonical !== '' ? canonical : native).toLowerCase();
274
+ if (raw === 'stop') return 'stop';
275
+ if (raw === 'userpromptsubmit' || raw === 'user_prompt_submit') return 'user_prompt_submit';
276
+ return raw;
277
+ }
278
+
279
+ /**
280
+ * The dispatcher calls every in-process concern as `main(argv)` — see
281
+ * `_run_concern_inproc` in `hooks/dispatch_hook.ts`, and the `ConcernMain`
282
+ * signature in `hooks/concern_registry.ts`.
283
+ *
284
+ * This used to be `main(now: Date = new Date())`, and the mismatch made the
285
+ * concern a SILENT NO-OP on every live dispatch: argv arrived where a Date was
286
+ * expected, `now.getTime()` threw `TypeError: now.getTime is not a function`,
287
+ * and the outer catch — "an instrument never breaks the turn it observes" —
288
+ * swallowed it and returned EXIT_ALLOW. The dispatcher recorded exit 0 and no
289
+ * output, which is indistinguishable from a disabled hook. Three earlier
290
+ * isolation attempts read that silence as a `--project-dir` problem; it was
291
+ * this.
292
+ *
293
+ * The clock stays injectable because the TTL and the timestamp need to be
294
+ * driven from a test, but it is now the SECOND parameter, where the dispatcher
295
+ * cannot land on it.
296
+ */
297
+ export function main(_argv: readonly string[] = [], now: Date = new Date()): number {
298
+ let envelope: JsonObject;
299
+ let payload: JsonObject;
300
+ try {
301
+ [envelope, payload] = unwrap(readHookStdin(), 'claude');
302
+ } catch {
303
+ return EXIT_ALLOW;
304
+ }
305
+
306
+ // `workspace_root` is the dispatcher's; `cwd` is the host payload's. Both
307
+ // are read because the concern must work under either invocation.
308
+ const root =
309
+ str(envelope['workspace_root'] as JsonValue | undefined) ||
310
+ str(payload['cwd'] as JsonValue | undefined) ||
311
+ str(envelope['project_root'] as JsonValue | undefined) ||
312
+ '.';
313
+ if (!enabled(root)) return EXIT_ALLOW;
314
+
315
+ const event = eventOf(envelope, payload);
316
+ try {
317
+ if (event === 'stop') {
318
+ const { emitted, optionsCount } = detectBlock(
319
+ str(payload['last_assistant_message'] as JsonValue | undefined),
320
+ );
321
+ if (emitted) {
322
+ writeLatch(root, {
323
+ prompt_id: str(payload['prompt_id'] as JsonValue | undefined),
324
+ options_count: optionsCount,
325
+ at: now.getTime(),
326
+ });
327
+ }
328
+ return EXIT_ALLOW;
329
+ }
330
+ if (event === 'user_prompt_submit') {
331
+ const latch = consumeLatch(root);
332
+ const v = classifyTurn(str(payload['prompt'] as JsonValue | undefined), latch, now.getTime());
333
+ if (v.record) {
334
+ appendRecord(
335
+ root,
336
+ {
337
+ ts: '',
338
+ block_emitted: true,
339
+ options_count: v.options_count,
340
+ evidence_class: v.evidence_class,
341
+ turn_classification: v.turn_classification,
342
+ },
343
+ now,
344
+ );
345
+ }
346
+ return EXIT_ALLOW;
347
+ }
348
+ } catch {
349
+ return EXIT_ALLOW; // an instrument never breaks the turn it observes
350
+ }
351
+ return EXIT_ALLOW;
352
+ }
353
+
354
+ declare const __AGENT_CONFIG_BUNDLE__: boolean | undefined;
355
+ function isCliEntry(): boolean {
356
+ if (typeof __AGENT_CONFIG_BUNDLE__ !== 'undefined' && __AGENT_CONFIG_BUNDLE__) return false;
357
+ if (process.argv[1] === undefined) return false;
358
+ const argvUrl = pathToFileURL(path.resolve(process.argv[1])).href;
359
+ if (import.meta.url === argvUrl) return true;
360
+ try {
361
+ return fs.realpathSync(fileURLToPath(import.meta.url)) === fs.realpathSync(path.resolve(process.argv[1]));
362
+ } catch {
363
+ return false;
364
+ }
365
+ }
366
+ if (isCliEntry()) process.exit(main());
367
+
368
+ export { SINK_REL, LATCH_REL };