@event4u/agent-config 16.1.0 → 16.3.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 (467) 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 +98 -257
  5. package/README.md +14 -12
  6. package/dist/agent-src/commands/analyze/inbox.md +1 -1
  7. package/dist/agent-src/commands/analyze/roadmap-repos.md +1 -1
  8. package/dist/agent-src/commands/bug/fix.md +17 -2
  9. package/dist/agent-src/commands/feature/plan.md +1 -1
  10. package/dist/agent-src/commands/feature/roadmap.md +1 -1
  11. package/dist/agent-src/commands/fix/ci.md +1 -1
  12. package/dist/agent-src/commands/implement-ticket.md +1 -1
  13. package/dist/agent-src/commands/jira-ticket.md +1 -1
  14. package/dist/agent-src/commands/roadmap/create.md +1 -1
  15. package/dist/agent-src/commands/roadmap/materialize.md +1 -1
  16. package/dist/agent-src/commands/roadmap/process-full.md +5 -5
  17. package/dist/agent-src/commands/roadmap/resolve-blockers.md +361 -0
  18. package/dist/agent-src/commands/roadmap/triage-parked.md +325 -0
  19. package/dist/agent-src/commands/roadmap.md +18 -4
  20. package/dist/agent-src/commands/tests/create.md +17 -3
  21. package/dist/agent-src/commands/tests/execute.md +22 -5
  22. package/dist/agent-src/commands/work.md +4 -0
  23. package/dist/agent-src/contexts/authority/decision-revisit-gate-enforcement.md +43 -0
  24. package/dist/agent-src/contexts/communication/rules-auto/design-fidelity-enforcement.md +24 -0
  25. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +6 -6
  26. package/dist/agent-src/contexts/execution/autonomy-mechanics.md +4 -8
  27. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +32 -2
  28. package/dist/agent-src/contexts/execution/session-canary-enforcement-history.md +67 -0
  29. package/dist/agent-src/contexts/execution/toolchain-resolver.md +101 -7
  30. package/dist/agent-src/rules/active-remediation.md +1 -1
  31. package/dist/agent-src/rules/autonomous-execution.md +1 -0
  32. package/dist/agent-src/rules/broken-access-control.md +1 -0
  33. package/dist/agent-src/rules/command-suggestion-policy.md +1 -0
  34. package/dist/agent-src/rules/context-hygiene.md +1 -1
  35. package/dist/agent-src/rules/decision-revisit-gate.md +16 -33
  36. package/dist/agent-src/rules/design-fidelity.md +13 -16
  37. package/dist/agent-src/rules/doc-screenshot-hygiene.md +1 -0
  38. package/dist/agent-src/rules/domain-safety-disclaimer.md +1 -0
  39. package/dist/agent-src/rules/domain-safety-pii.md +1 -0
  40. package/dist/agent-src/rules/domain-safety-retention.md +1 -0
  41. package/dist/agent-src/rules/engineering-safety-floor.md +1 -0
  42. package/dist/agent-src/rules/evaluator-independence.md +3 -2
  43. package/dist/agent-src/rules/fast-path-marker-visibility.md +1 -0
  44. package/dist/agent-src/rules/finance-safety-floor.md +1 -0
  45. package/dist/agent-src/rules/git-history-discipline.md +1 -0
  46. package/dist/agent-src/rules/image-likeness-and-rights.md +1 -0
  47. package/dist/agent-src/rules/legal-safety-floor.md +3 -2
  48. package/dist/agent-src/rules/lethal-trifecta-guard.md +1 -0
  49. package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +1 -0
  50. package/dist/agent-src/rules/media-governance-routing.md +14 -17
  51. package/dist/agent-src/rules/persona-governance.md +2 -2
  52. package/dist/agent-src/rules/provider-lifecycle-discipline.md +1 -1
  53. package/dist/agent-src/rules/question-not-instruction.md +1 -0
  54. package/dist/agent-src/rules/roadmap-progress-sync.md +1 -1
  55. package/dist/agent-src/rules/runtime-safety.md +1 -0
  56. package/dist/agent-src/rules/secret-vcs-guard.md +1 -0
  57. package/dist/agent-src/rules/security-sensitive-stop.md +3 -2
  58. package/dist/agent-src/rules/session-canary.md +8 -62
  59. package/dist/agent-src/rules/settings-ask-protocol.md +1 -0
  60. package/dist/agent-src/rules/source-confidentiality.md +1 -0
  61. package/dist/agent-src/rules/strategy-safety-floor.md +1 -0
  62. package/dist/agent-src/rules/tool-safety.md +1 -0
  63. package/dist/agent-src/rules/ui-audit-gate.md +1 -2
  64. package/dist/agent-src/rules/untrusted-input-defense.md +1 -0
  65. package/dist/agent-src/rules/user-interrupt-priority.md +1 -0
  66. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +115 -20
  67. package/dist/agent-src/scripts/deferral_carry.ts +339 -0
  68. package/dist/agent-src/scripts/update_roadmap_progress.ts +4 -1
  69. package/dist/agent-src/skills/accessibility-auditor/data/aria-patterns.csv +1 -1
  70. package/dist/agent-src/skills/accessibility-auditor/data/manifest.json +2 -2
  71. package/dist/agent-src/skills/api-design/data/manifest.json +2 -2
  72. package/dist/agent-src/skills/api-testing/SKILL.md +17 -0
  73. package/dist/agent-src/skills/code-intelligence/SKILL.md +14 -2
  74. package/dist/agent-src/skills/design-review/SKILL.md +30 -4
  75. package/dist/agent-src/skills/design-review/references/verification-automation.md +32 -0
  76. package/dist/agent-src/skills/design-system-capture/references/import-procedure.md +1 -1
  77. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +18 -3
  78. package/dist/agent-src/skills/existing-ui-audit/references/component-taxonomy-detection.md +56 -0
  79. package/dist/agent-src/skills/fe-design/SKILL.md +1 -1
  80. package/dist/agent-src/skills/iconography/SKILL.md +1 -1
  81. package/dist/agent-src/skills/js-library-packaging/SKILL.md +2 -2
  82. package/dist/agent-src/skills/markitdown/SKILL.md +4 -0
  83. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +1 -1
  84. package/dist/agent-src/skills/playwright-testing/SKILL.md +30 -6
  85. package/dist/agent-src/skills/quality-tools/SKILL.md +11 -1
  86. package/dist/agent-src/skills/quality-tools/references/go-tools.md +76 -0
  87. package/dist/agent-src/skills/quality-tools/references/python-tools.md +104 -0
  88. package/dist/agent-src/skills/review-routing/SKILL.md +2 -2
  89. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +1 -1
  90. package/dist/agent-src/skills/storybook-workshop/SKILL.md +3 -3
  91. package/dist/agent-src/skills/tailwind-engineer/SKILL.md +1 -1
  92. package/dist/agent-src/skills/test-case-discovery/SKILL.md +7 -0
  93. package/dist/agent-src/skills/test-driven-development/SKILL.md +17 -0
  94. package/dist/agent-src/skills/test-performance/SKILL.md +19 -1
  95. package/dist/agent-src/skills/ui-component-architect/SKILL.md +25 -2
  96. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  97. package/dist/agent-src/templates/roadmaps.md +30 -0
  98. package/dist/agent-src/templates/scripts/work_engine/directives/ui/app_spec.ts +10 -4
  99. package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +302 -21
  100. package/dist/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +22 -3
  101. package/dist/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +6 -1
  102. package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
  103. package/dist/agent-src/templates/scripts/work_engine/state.ts +57 -7
  104. package/dist/agent-src/templates/scripts/work_engine/taxonomy/detect.ts +500 -0
  105. package/dist/agent-src/templates/scripts/work_engine/taxonomy/place.ts +183 -0
  106. package/dist/cli/python/knowledge_ingest.js +1 -1
  107. package/dist/cli/python/workspace_drive.js +1 -1
  108. package/dist/cli/registry.js +1 -1
  109. package/dist/cli-delegate/archive_completed_roadmaps.js +92 -12
  110. package/dist/cli-delegate/check_update_banner.js +12 -1
  111. package/dist/cli-delegate/chunk-523HCFYO.js +90 -0
  112. package/dist/cli-delegate/{chunk-M2DPGFZ4.js → chunk-6V6TA25H.js} +22 -152
  113. package/dist/cli-delegate/chunk-7IQE3D5S.js +191 -0
  114. package/dist/cli-delegate/{chunk-6KFEC3G7.js → chunk-CQWX336L.js} +1 -1
  115. package/dist/cli-delegate/chunk-DEIV7XP7.js +108 -0
  116. package/dist/cli-delegate/chunk-EEHDXSYD.js +2040 -0
  117. package/dist/cli-delegate/{chunk-P6ZHP5W2.js → chunk-GKE7ZVFA.js} +4 -4
  118. package/dist/cli-delegate/chunk-JQOM7TTM.js +1201 -0
  119. package/dist/cli-delegate/{chunk-UNCRJBT3.js → chunk-JQVYKIZA.js} +41 -0
  120. package/dist/cli-delegate/{chunk-FC75PGJE.js → chunk-JY2I2DXV.js} +12 -1
  121. package/dist/cli-delegate/chunk-KB5FZ655.js +208 -0
  122. package/dist/cli-delegate/{chunk-YUM5KURG.js → chunk-KR6EM23A.js} +235 -1455
  123. package/dist/cli-delegate/{chunk-LTYVIY76.js → chunk-LIYTLH6O.js} +1 -1
  124. package/dist/cli-delegate/chunk-NQ7WT43P.js +2729 -0
  125. package/dist/cli-delegate/chunk-NXEILF2K.js +2160 -0
  126. package/dist/cli-delegate/{chunk-5R7HOLAF.js → chunk-NYX3L2PZ.js} +1 -1
  127. package/dist/cli-delegate/{chunk-4E2W63DA.js → chunk-OKJUIAPS.js} +62 -1
  128. package/dist/cli-delegate/{chunk-QAJS5YWY.js → chunk-PHD7OOLE.js} +2 -1
  129. package/dist/cli-delegate/{chunk-RGNIWTEA.js → chunk-QLDHIPWR.js} +1 -1
  130. package/dist/cli-delegate/{chunk-HDVVGPQW.js → chunk-RQNNW7IF.js} +1405 -567
  131. package/dist/cli-delegate/{chunk-S3VFXMTM.js → chunk-S4UMZNES.js} +1 -1
  132. package/dist/cli-delegate/{chunk-6KM6ORRY.js → chunk-S4YWNRKO.js} +24 -8
  133. package/dist/cli-delegate/{chunk-GJCBB2UG.js → chunk-TRI6DQZ6.js} +3054 -325
  134. package/dist/cli-delegate/chunk-ULQRUR23.js +208 -0
  135. package/dist/cli-delegate/{chunk-NUHLI2RX.js → chunk-YCU3TIXH.js} +2 -0
  136. package/dist/cli-delegate/chunk-ZBZV2G5R.js +210 -0
  137. package/dist/cli-delegate/{chunk-WGXTVKCQ.js → chunk-ZUZKZYCN.js} +5 -3
  138. package/dist/cli-delegate/cmd_analyze_session.js +1 -1
  139. package/dist/cli-delegate/cmd_brand_status.js +1 -1
  140. package/dist/cli-delegate/cmd_conformance.js +1862 -809
  141. package/dist/cli-delegate/cmd_doctor.js +13 -6
  142. package/dist/cli-delegate/cmd_doctor_neighbours.js +23 -0
  143. package/dist/cli-delegate/cmd_explain.js +5 -5
  144. package/dist/cli-delegate/cmd_export.js +11 -8
  145. package/dist/cli-delegate/cmd_fleet.js +3 -3
  146. package/dist/cli-delegate/cmd_handoff.js +10 -7
  147. package/dist/cli-delegate/cmd_mcp_available.js +1 -1
  148. package/dist/cli-delegate/cmd_memory_get.js +3 -1
  149. package/dist/cli-delegate/cmd_migrate.js +2 -2
  150. package/dist/cli-delegate/cmd_packs_active.js +3 -3
  151. package/dist/cli-delegate/cmd_preflight.js +6 -6
  152. package/dist/cli-delegate/cmd_prune.js +11 -8
  153. package/dist/cli-delegate/cmd_refresh.js +2 -1
  154. package/dist/cli-delegate/cmd_route_audit.js +8 -6
  155. package/dist/cli-delegate/cmd_route_explain.js +4 -4
  156. package/dist/cli-delegate/cmd_session_recycle.js +4 -3
  157. package/dist/cli-delegate/cmd_settings_get.js +1 -1
  158. package/dist/cli-delegate/cmd_settings_migrate.js +11 -8
  159. package/dist/cli-delegate/cmd_settings_set.js +4 -4
  160. package/dist/cli-delegate/cmd_sync.js +11 -8
  161. package/dist/cli-delegate/cmd_uninstall.js +11 -8
  162. package/dist/cli-delegate/cmd_update.js +1 -1
  163. package/dist/cli-delegate/cmd_upgrade.js +3 -2
  164. package/dist/cli-delegate/cmd_validate.js +11 -8
  165. package/dist/cli-delegate/cmd_versions.js +1 -1
  166. package/dist/cli-delegate/deferral_carry.js +16 -0
  167. package/dist/cli-delegate/gate_execute.js +2 -2
  168. package/dist/cli-delegate/roadmap_gates.js +5 -5
  169. package/dist/cli-delegate/update_roadmap_progress.js +1 -1
  170. package/dist/discovery/deprecation-report.md +1 -1
  171. package/dist/discovery/discovery-manifest.json +132 -80
  172. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  173. package/dist/discovery/discovery-manifest.summary.md +3 -3
  174. package/dist/discovery/dormancy-report.md +1 -1
  175. package/dist/discovery/orphan-report.md +1 -1
  176. package/dist/discovery/packs.json +7 -5
  177. package/dist/discovery/trust-report.md +2 -2
  178. package/dist/discovery/workspaces.json +6 -4
  179. package/dist/hooks/dispatch.js +7972 -5186
  180. package/dist/hooks/dispatch.sha256 +1 -0
  181. package/dist/install/claudePathsPlan.js +47 -6
  182. package/dist/install/claudeRuleRewrite.js +7 -0
  183. package/dist/install/emit_host_rules_cli.js +39 -36
  184. package/dist/install/globalRuleScope.js +87 -0
  185. package/dist/install/host_rule_ownership.js +160 -0
  186. package/dist/install/install.mjs +2226 -1055
  187. package/dist/install/installThinLayer.js +261 -0
  188. package/dist/install/installedRuleLinks.js +176 -0
  189. package/dist/install/wizard-plan.js +24 -0
  190. package/dist/mcp/registry-manifest.json +3 -3
  191. package/dist/mcp/server.json +2 -2
  192. package/dist/mcp/server.mjs +40913 -34865
  193. package/dist/scripts/_lib/agent_settings.js +11 -0
  194. package/dist/scripts/_lib/claude_settings_hooks.js +10 -8
  195. package/dist/scripts/_lib/installed_layer.js +378 -0
  196. package/dist/scripts/_lib/lean_projection_mode.js +218 -15
  197. package/dist/scripts/_lib/rule_consequence_class.js +45 -0
  198. package/dist/scripts/_lib/rule_injection.js +67 -10
  199. package/dist/scripts/_lib/rule_law_section.js +122 -0
  200. package/dist/scripts/_lib/thin_rules.js +458 -0
  201. package/dist/scripts/_lib/windsurf_render.js +60 -0
  202. package/dist/scripts/condense.js +14 -26
  203. package/dist/scripts/project_thin_rules.js +14 -294
  204. package/dist/server/schemas/settings.js +29 -0
  205. package/dist/shared/skillRanking.js +74 -13
  206. package/dist/ui/assets/index-Cwq4d0hX.js +23 -0
  207. package/dist/ui/assets/index-Cyjy8bWO.css +1 -0
  208. package/dist/ui/index.html +2 -2
  209. package/docs/contracts/settings-classes.md +10 -6
  210. package/package.json +4 -4
  211. package/src/agent-src/scripts/archive_completed_roadmaps.ts +115 -20
  212. package/src/agent-src/scripts/deferral_carry.ts +339 -0
  213. package/src/agent-src/scripts/update_roadmap_progress.ts +4 -1
  214. package/src/agent-src/templates/scripts/work_engine/directives/ui/app_spec.ts +10 -4
  215. package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +302 -21
  216. package/src/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +22 -3
  217. package/src/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +6 -1
  218. package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
  219. package/src/agent-src/templates/scripts/work_engine/state.ts +57 -7
  220. package/src/agent-src/templates/scripts/work_engine/taxonomy/detect.ts +500 -0
  221. package/src/agent-src/templates/scripts/work_engine/taxonomy/place.ts +183 -0
  222. package/src/config/agent-settings.template.yml +91 -22
  223. package/src/config/ci-local-parity.yml +18 -0
  224. package/src/config/continuity-surface.json +9 -2
  225. package/src/config/evaluator-budgets.json +4 -4
  226. package/src/config/gate-coverage.yml +327 -3
  227. package/src/config/gate-violation-baselines.json +21 -9
  228. package/src/config/hook-bundle-budget.json +25 -0
  229. package/src/config/hook-latency-budget.json +21 -0
  230. package/src/config/hook-token-budget.json +8 -3
  231. package/src/config/host-instruction-limits.json +33 -0
  232. package/src/config/metric-registry.yml +114 -0
  233. package/src/config/placeholder-drift-budget.json +10 -0
  234. package/src/config/routing-coverage-seed.json +38 -3
  235. package/src/config/rule-activation-census.json +7 -3
  236. package/src/config/rule-consequence-class.json +161 -0
  237. package/src/config/rule-law-ceilings.json +99 -0
  238. package/src/install/claudePathsPlan.ts +46 -4
  239. package/src/install/claudeRuleRewrite.ts +10 -1
  240. package/src/install/emit_host_rules_cli.ts +43 -34
  241. package/src/install/globalRuleScope.ts +109 -0
  242. package/src/install/host_rule_ownership.ts +170 -0
  243. package/src/install/installThinLayer.ts +312 -0
  244. package/src/install/installedRuleLinks.ts +220 -0
  245. package/src/install/wizard-plan.ts +24 -0
  246. package/src/scripts/_cli/cmd_doctor.ts +28 -90
  247. package/src/scripts/_cli/cmd_doctor_neighbours.ts +293 -0
  248. package/src/scripts/_cli/doctor_execution.ts +100 -17
  249. package/src/scripts/_cli/doctor_network_posture.ts +226 -0
  250. package/src/scripts/_dispatch.bash +16 -2
  251. package/src/scripts/_lib/agent_settings.ts +11 -0
  252. package/src/scripts/_lib/body_portable.ts +102 -0
  253. package/src/scripts/_lib/cc_transcript.ts +132 -1
  254. package/src/scripts/_lib/claude_settings_hooks.ts +10 -8
  255. package/src/scripts/_lib/concern_sla_window.ts +200 -0
  256. package/src/scripts/_lib/estate_offsets.ts +241 -0
  257. package/src/scripts/_lib/exemption_shape.ts +143 -0
  258. package/src/scripts/_lib/fnv.ts +23 -0
  259. package/src/scripts/_lib/foreign_scan.ts +106 -0
  260. package/src/scripts/_lib/forge_protection.ts +114 -0
  261. package/src/scripts/_lib/forge_reader.ts +558 -0
  262. package/src/scripts/_lib/gitignore_block.ts +314 -0
  263. package/src/scripts/_lib/global_deploy_inventory.ts +32 -0
  264. package/src/scripts/_lib/graph_feeder_record.ts +214 -0
  265. package/src/scripts/_lib/hook_settings.ts +73 -0
  266. package/src/scripts/_lib/host_capability.ts +40 -19
  267. package/src/scripts/_lib/host_env_write.ts +111 -0
  268. package/src/scripts/_lib/host_hook_merge.ts +165 -0
  269. package/src/scripts/_lib/installed_layer.ts +538 -0
  270. package/src/scripts/_lib/json_merge.ts +82 -0
  271. package/src/scripts/_lib/json_pointers.ts +93 -11
  272. package/src/scripts/_lib/lean_projection_mode.ts +275 -15
  273. package/src/scripts/_lib/llm_proposer_transport.ts +14 -4
  274. package/src/scripts/_lib/machine_wake.ts +16 -3
  275. package/src/scripts/_lib/neighbour_census.ts +760 -0
  276. package/src/scripts/_lib/neighbour_scan.ts +122 -0
  277. package/src/scripts/_lib/neighbour_tool_use.ts +189 -0
  278. package/src/scripts/_lib/obligations.ts +119 -8
  279. package/src/scripts/_lib/probe_inputs.ts +271 -0
  280. package/src/scripts/_lib/prompt_shape.ts +46 -0
  281. package/src/scripts/_lib/read_surface_scan.ts +322 -0
  282. package/src/scripts/_lib/release_highlights.ts +2 -1
  283. package/src/scripts/_lib/release_migration_gate.ts +19 -3
  284. package/src/scripts/_lib/reserved_name_sweep.ts +73 -0
  285. package/src/scripts/_lib/retrieval_sanitize.ts +77 -16
  286. package/src/scripts/_lib/review_coverage.ts +134 -0
  287. package/src/scripts/_lib/rule_consequence_class.ts +71 -0
  288. package/src/scripts/_lib/rule_injection.ts +130 -10
  289. package/src/scripts/_lib/rule_law_section.ts +147 -0
  290. package/src/scripts/_lib/rule_layer_overlap.ts +58 -0
  291. package/src/scripts/_lib/shell_write_shapes.ts +108 -0
  292. package/src/scripts/_lib/skill_origin.ts +254 -0
  293. package/src/scripts/_lib/structural_hiding.ts +622 -0
  294. package/src/scripts/_lib/structured_ask.ts +64 -21
  295. package/src/scripts/_lib/thin_rules.ts +540 -0
  296. package/src/scripts/_lib/touched_file_quality.ts +434 -0
  297. package/src/scripts/_lib/turn_end_refusals.ts +600 -4
  298. package/src/scripts/_lib/turn_end_transcript.ts +216 -0
  299. package/src/scripts/_lib/verification_command.ts +324 -0
  300. package/src/scripts/_lib/verification_evidence.ts +647 -0
  301. package/src/scripts/_lib/verify_clause.ts +280 -0
  302. package/src/scripts/_lib/windsurf_render.ts +63 -0
  303. package/src/scripts/ai_council/cli_call_budget.ts +13 -5
  304. package/src/scripts/ai_council/clients.ts +26 -57
  305. package/src/scripts/ai_council/config.ts +1 -1
  306. package/src/scripts/ai_council/vendor_defaults.ts +45 -0
  307. package/src/scripts/ai_team/team_dispatch.ts +4 -0
  308. package/src/scripts/audit_skill_overlap.ts +261 -0
  309. package/src/scripts/before_complete_hook.ts +573 -25
  310. package/src/scripts/bench_hook_latency.ts +412 -5
  311. package/src/scripts/bench_touched_file_quality.ts +238 -0
  312. package/src/scripts/cache_realization_report.ts +61 -1
  313. package/src/scripts/check_argument_hint.ts +287 -0
  314. package/src/scripts/check_claims.ts +125 -1
  315. package/src/scripts/check_enforcement_coverage.ts +38 -9
  316. package/src/scripts/check_enforcement_matrix.ts +621 -22
  317. package/src/scripts/check_estate_count.ts +130 -153
  318. package/src/scripts/check_finding_dispositions.ts +138 -7
  319. package/src/scripts/check_generator_sync.ts +71 -0
  320. package/src/scripts/check_hook_bundle_composition.ts +370 -0
  321. package/src/scripts/check_host_docs_digest.ts +786 -0
  322. package/src/scripts/check_host_format_column.ts +559 -0
  323. package/src/scripts/check_input_references.ts +228 -0
  324. package/src/scripts/check_inputs_parity.ts +235 -0
  325. package/src/scripts/check_kernel_edit_ratified.ts +89 -9
  326. package/src/scripts/check_kill_switch_table.ts +294 -0
  327. package/src/scripts/check_memory.ts +7 -1
  328. package/src/scripts/check_placeholder_drift.ts +221 -0
  329. package/src/scripts/check_read_surface_coverage.ts +515 -0
  330. package/src/scripts/check_release_highlights.ts +10 -0
  331. package/src/scripts/check_release_holds.ts +2 -1
  332. package/src/scripts/check_release_pr_shape.ts +38 -15
  333. package/src/scripts/check_routing_coverage.ts +378 -11
  334. package/src/scripts/check_standing_rule_delivery.ts +33 -13
  335. package/src/scripts/check_static_parity.ts +17 -0
  336. package/src/scripts/check_verify_expectation_delta.ts +521 -0
  337. package/src/scripts/ci_settle.ts +145 -19
  338. package/src/scripts/closure_scan.ts +115 -1
  339. package/src/scripts/code_graph/detect.ts +127 -7
  340. package/src/scripts/code_graph/foreign.ts +194 -0
  341. package/src/scripts/code_graph/query.ts +217 -4
  342. package/src/scripts/code_graph/types.ts +26 -2
  343. package/src/scripts/code_graph/validate.ts +3 -1
  344. package/src/scripts/code_graph/verbs.ts +103 -0
  345. package/src/scripts/compile_hook_manifest.ts +90 -14
  346. package/src/scripts/condense.ts +14 -27
  347. package/src/scripts/estate_exemption_shape.ts +202 -0
  348. package/src/scripts/external_sources_denylist.json +29 -4
  349. package/src/scripts/generate_host_cost_table.ts +1 -1
  350. package/src/scripts/hook_manifest.json +1 -1
  351. package/src/scripts/hook_manifest.yaml +192 -14
  352. package/src/scripts/hooks/block_config_weakening.ts +294 -4
  353. package/src/scripts/hooks/block_kernel_rule_writes.ts +9 -78
  354. package/src/scripts/hooks/block_plumbing_writes.ts +342 -0
  355. package/src/scripts/hooks/bundle_integrity.ts +291 -0
  356. package/src/scripts/hooks/chain_nudge_hook.ts +1 -2
  357. package/src/scripts/hooks/code_graph_context_hook.ts +253 -25
  358. package/src/scripts/hooks/comment_discipline_hook.ts +1 -3
  359. package/src/scripts/hooks/concern_failure_policy.ts +280 -0
  360. package/src/scripts/hooks/concern_registry.ts +2 -0
  361. package/src/scripts/hooks/concern_timings.ts +94 -0
  362. package/src/scripts/hooks/delegation_nudge_hook.ts +1 -2
  363. package/src/scripts/hooks/design_pass_hook.ts +100 -9
  364. package/src/scripts/hooks/design_slop_hook.ts +1 -2
  365. package/src/scripts/hooks/dispatch_hook.ts +77 -71
  366. package/src/scripts/hooks/edit_shape_hook.ts +1 -2
  367. package/src/scripts/hooks/end_review_nudge_hook.ts +1 -1
  368. package/src/scripts/hooks/evidence_independence.ts +1 -2
  369. package/src/scripts/hooks/exit_codes.ts +129 -0
  370. package/src/scripts/hooks/host_lowering.json +1 -0
  371. package/src/scripts/hooks/host_lowering.ts +146 -3
  372. package/src/scripts/hooks/host_lowering.yaml +262 -46
  373. package/src/scripts/hooks/host_semantics.ts +30 -2
  374. package/src/scripts/hooks/injection_budget.ts +9 -2
  375. package/src/scripts/hooks/interruption_ledger_hook.ts +1 -2
  376. package/src/scripts/hooks/journal_record_hook.ts +1 -2
  377. package/src/scripts/hooks/memory_recall_hook.ts +1 -2
  378. package/src/scripts/hooks/obligation_settle_hook.ts +151 -5
  379. package/src/scripts/hooks/one_question_per_ask_hook.ts +43 -6
  380. package/src/scripts/hooks/orchestration_record_hook.ts +1 -2
  381. package/src/scripts/hooks/payload_stub.ts +10 -1
  382. package/src/scripts/hooks/permission_gate.ts +1 -2
  383. package/src/scripts/hooks/push_settle_hook.ts +1 -3
  384. package/src/scripts/hooks/replay_hook.ts +2 -1
  385. package/src/scripts/hooks/reread_guard_hook.ts +1 -2
  386. package/src/scripts/hooks/review_baseline_hook.ts +1 -2
  387. package/src/scripts/hooks/rtk_wrap_hook.ts +1 -2
  388. package/src/scripts/hooks/rule_inject_hook.ts +765 -68
  389. package/src/scripts/hooks/run_continuation_hook.ts +13 -15
  390. package/src/scripts/hooks/skill_route_hook.ts +1 -2
  391. package/src/scripts/hooks/source_first_gate_hook.ts +1 -2
  392. package/src/scripts/hooks/spawn_guard_shadow_hook.ts +1 -2
  393. package/src/scripts/hooks/subagent_ledger_hook.ts +1 -2
  394. package/src/scripts/hooks/suggestion_capture_hook.ts +1 -1
  395. package/src/scripts/hooks/table_fingerprint.ts +70 -0
  396. package/src/scripts/hooks/telemetry_flush_hook.ts +1 -2
  397. package/src/scripts/hooks/telemetry_usage_hook.ts +65 -10
  398. package/src/scripts/hooks/tool_result_bytes_hook.ts +93 -9
  399. package/src/scripts/hooks/turn_end_gate_hook.ts +421 -324
  400. package/src/scripts/hooks/ui_route_nudge_hook.ts +1 -2
  401. package/src/scripts/hooks_status.ts +112 -0
  402. package/src/scripts/injection_scan_hook.ts +7 -0
  403. package/src/scripts/install.ts +75 -189
  404. package/src/scripts/installed_layer_report.ts +103 -0
  405. package/src/scripts/language_mirror_hook.ts +15 -6
  406. package/src/scripts/learning_sidecar.ts +119 -8
  407. package/src/scripts/lint_deny_text.ts +419 -0
  408. package/src/scripts/lint_exit_codes.ts +262 -0
  409. package/src/scripts/lint_hook_manifest.ts +108 -0
  410. package/src/scripts/lint_major_migration_sections.ts +156 -26
  411. package/src/scripts/lint_pack_boundaries.ts +63 -5
  412. package/src/scripts/lint_roadmap_blockers.ts +78 -12
  413. package/src/scripts/lint_rule_law_section.ts +517 -0
  414. package/src/scripts/lint_skill_descriptions.ts +1 -1
  415. package/src/scripts/lint_skill_scripts_readonly.ts +1 -1
  416. package/src/scripts/lint_workflow_security.ts +161 -5
  417. package/src/scripts/mcp_server/consumer_tool_catalog.json +53 -0
  418. package/src/scripts/mcp_server/graph_tools.ts +72 -3
  419. package/src/scripts/mcp_server/prompts.ts +142 -1
  420. package/src/scripts/measure_routing_signal.ts +54 -16
  421. package/src/scripts/measure_skill_ranker_baseline.ts +515 -53
  422. package/src/scripts/measure_turn_end_gate.ts +193 -0
  423. package/src/scripts/memory_learn_hook.ts +91 -6
  424. package/src/scripts/memory_lookup.ts +1 -1
  425. package/src/scripts/model_rule_injection.ts +52 -5
  426. package/src/scripts/prepack-check.mjs +53 -0
  427. package/src/scripts/project_thin_rules.ts +34 -327
  428. package/src/scripts/release_publication.ts +13 -1
  429. package/src/scripts/report_evidence_temperature.ts +657 -0
  430. package/src/scripts/report_installed_rule_links.ts +157 -0
  431. package/src/scripts/report_invocation_surface.ts +383 -0
  432. package/src/scripts/report_label_agreement.ts +233 -0
  433. package/src/scripts/report_obligation_carriers.ts +699 -0
  434. package/src/scripts/report_obligation_mechanism.ts +230 -0
  435. package/src/scripts/report_obligation_writer_split.ts +236 -0
  436. package/src/scripts/report_single_token_triggers.ts +277 -0
  437. package/src/scripts/report_skill_menu_census.ts +208 -0
  438. package/src/scripts/report_skill_ranker_confusion.ts +442 -0
  439. package/src/scripts/report_standing_payload_by_host.ts +188 -15
  440. package/src/scripts/report_verification_record_coverage.ts +306 -0
  441. package/src/scripts/roadmap_verify_share.ts +213 -0
  442. package/src/scripts/rule_activation_census.ts +5 -2
  443. package/src/scripts/rule_trigger_eval.ts +9 -9
  444. package/src/scripts/schemas/command.schema.json +44 -0
  445. package/src/scripts/schemas/review-findings.schema.json +7 -2
  446. package/src/scripts/schemas/rule.schema.json +5 -0
  447. package/src/scripts/schemas/skill.schema.json +44 -0
  448. package/src/scripts/self_review_gate.ts +421 -17
  449. package/src/scripts/semantic_parity_census.ts +314 -0
  450. package/src/scripts/session_eol_report.ts +54 -1
  451. package/src/scripts/skill_tools/score_skill_relevance.ts +290 -25
  452. package/src/scripts/sweep_dead_scan_roots.ts +1 -1
  453. package/src/scripts/sweep_skill_ranker_signals.ts +129 -0
  454. package/src/scripts/sync_gitignore.ts +29 -235
  455. package/src/scripts/trigger_eval_grandfather.json +0 -7
  456. package/src/scripts/trigger_eval_rotation.ts +122 -27
  457. package/src/scripts/ui_conformance_probe.ts +156 -4
  458. package/src/scripts/update_prices.ts +85 -3
  459. package/src/scripts/write_bundle_digest.mjs +74 -0
  460. package/src/server/schemas/settings.ts +41 -0
  461. package/src/shared/skillRanking.ts +117 -11
  462. package/src/templates/consumer-settings/ONBOARDING.md +1 -0
  463. package/dist/cli-delegate/chunk-FXYUYU4N.js +0 -4416
  464. package/dist/cli-delegate/chunk-QJWAUMJW.js +0 -1072
  465. package/dist/cli-delegate/chunk-YDPILCOL.js +0 -152
  466. package/dist/ui/assets/index-DH1xc62v.js +0 -29
  467. package/dist/ui/assets/index-jSfMW8_t.css +0 -1
@@ -48,9 +48,8 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
48
48
  import { hookSectionEnabled } from '../_lib/hook_settings.js';
49
49
  import { isUiPath, isUiTreePath } from '../_lib/ui_surface.js';
50
50
  import { readHookStdin } from './hook_stdin.js';
51
+ import { EXIT_ALLOW, EXIT_WARN } from './exit_codes.js';
51
52
 
52
- const EXIT_ALLOW = 0;
53
- const EXIT_WARN = 2;
54
53
  /** Nudges per session before the valve goes silent. */
55
54
  export const MAX_NUDGES = 2;
56
55
 
@@ -23,11 +23,14 @@ import fs from "node:fs";
23
23
  import path from "node:path";
24
24
  import { fileURLToPath, pathToFileURL } from "node:url";
25
25
 
26
+ import { enforcementFor } from "./check_enforcement_matrix.js";
26
27
  import {
27
28
  type JsonObject,
28
29
  type JsonValue,
29
30
  _load_yaml,
30
31
  } from "./hooks/dispatch_hook.js";
32
+ import { loadHostLowering } from "./hooks/host_lowering.js";
33
+ import { type SlotReading, readSlots } from "./report_enforcement_drift.js";
31
34
 
32
35
  // src/scripts/hooks_status.ts → parents[1] is the repo root (.../parents[2]
33
36
  // in the Python which lives one level deeper relative computation).
@@ -90,6 +93,18 @@ export interface PlatformRow {
90
93
  */
91
94
  ask: AskShape;
92
95
  bindings: Record<string, string[]>;
96
+ /**
97
+ * For each slot that binds at least one `blocking` concern, what that host's
98
+ * slot can actually carry — `refusal`, `warning-only`, `unverified` or
99
+ * `proof-expired` (road-to-blocking-severities 1.2).
100
+ *
101
+ * Slots with no blocking concern are ABSENT rather than present with a
102
+ * value, so a reader cannot mistake "nothing here claims to refuse" for a
103
+ * capability reading. Derived from `host_lowering.yaml`, never from the
104
+ * manifest: the manifest declares intent and only the lowering table records
105
+ * whether a refusal can land.
106
+ */
107
+ blocking_enforcement: Record<string, string>;
93
108
  hint: string | null;
94
109
  }
95
110
 
@@ -123,10 +138,79 @@ function _bridge_status(project_root: string, rel_path: string): string {
123
138
  return stat && stat.isFile() ? "installed" : "missing";
124
139
  }
125
140
 
141
+ /**
142
+ * `severity` per concern, read off the manifest this report already loaded.
143
+ *
144
+ * `(undeclared)` is folded into "not blocking": this report publishes the
145
+ * enforcement of concerns that CLAIM to refuse, and a concern that claims
146
+ * nothing has nothing to reconcile. `lint_hook_manifest` is what refuses an
147
+ * undeclared severity; duplicating that judgement here would put two answers
148
+ * in the tree.
149
+ */
150
+ function _severities(manifest: JsonObject): Map<string, string> {
151
+ const out = new Map<string, string>();
152
+ const concerns = manifest["concerns"];
153
+ if (!_isObject(concerns)) {
154
+ return out;
155
+ }
156
+ for (const [name, spec] of Object.entries(concerns)) {
157
+ const sev = _isObject(spec) ? spec["severity"] : undefined;
158
+ if (typeof sev === "string") {
159
+ out.set(name, sev);
160
+ }
161
+ }
162
+ return out;
163
+ }
164
+
165
+ /**
166
+ * What each slot carrying a `blocking` concern can actually do on this host.
167
+ *
168
+ * road-to-blocking-severities 1.2, the third surface. The decision and the
169
+ * vocabulary live in `check_enforcement_matrix`; this reads them rather than
170
+ * restating them, so the published document and this report cannot drift into
171
+ * two different answers to one question.
172
+ *
173
+ * Failure is SILENT and the field is simply absent. This is a read-only status
174
+ * report that the post-install smoke probe runs, and a malformed or missing
175
+ * lowering table must degrade it, never abort it — the gate is where a broken
176
+ * lowering table is supposed to fail.
177
+ */
178
+ function _blocking_enforcement(
179
+ platform: string,
180
+ bindings: Record<string, string[]>,
181
+ severities: Map<string, string>,
182
+ ): Record<string, string> {
183
+ const out: Record<string, string> = {};
184
+ let slots: SlotReading[];
185
+ try {
186
+ slots = readSlots(loadHostLowering(), platform).slots;
187
+ } catch {
188
+ return out;
189
+ }
190
+ const bySlot = new Map(slots.map((s) => [s.slot, s]));
191
+ for (const [event, concerns] of Object.entries(bindings)) {
192
+ if (!concerns.some((c) => severities.get(c) === "blocking")) {
193
+ continue;
194
+ }
195
+ const row = bySlot.get(event);
196
+ out[event] = enforcementFor(
197
+ row === undefined
198
+ ? "unlowerable"
199
+ : row.literal === null
200
+ ? "null-block"
201
+ : row.effective === null
202
+ ? "stale-proof"
203
+ : null,
204
+ );
205
+ }
206
+ return out;
207
+ }
208
+
126
209
  /** Build the runtime matrix as a plain object — JSON-serialisable. */
127
210
  export function collect(project_root: string, manifest: JsonObject): StatusMatrix {
128
211
  const platformsRaw = manifest["platforms"];
129
212
  const platforms = _isObject(platformsRaw) ? platformsRaw : {};
213
+ const severities = _severities(manifest);
130
214
  const rows: PlatformRow[] = [];
131
215
  for (const platform of Object.keys(PLATFORM_BRIDGES)) {
132
216
  const [rel, hint] = PLATFORM_BRIDGES[platform] as [string, string];
@@ -148,6 +232,7 @@ export function collect(project_root: string, manifest: JsonObject): StatusMatri
148
232
  rows.push({
149
233
  platform,
150
234
  status,
235
+ blocking_enforcement: _blocking_enforcement(platform, bindings, severities),
151
236
  bridge_path: rel || null,
152
237
  fallback_only,
153
238
  ask,
@@ -160,6 +245,23 @@ export function collect(project_root: string, manifest: JsonObject): StatusMatri
160
245
  return { schema_version: 1, platforms: rows };
161
246
  }
162
247
 
248
+ /**
249
+ * One short line per enforcement value, for the table.
250
+ *
251
+ * `unverified` says what is MISSING, never what the host cannot do — the same
252
+ * wording discipline `docs/enforcement-by-host.md` carries, and the reason this
253
+ * report distinguishes the two values at all.
254
+ */
255
+ const _ENFORCEMENT_NOTE: Record<string, string> = {
256
+ refusal: "the slot denies, so a blocking verdict stops the call",
257
+ "proof-expired":
258
+ "the slot can deny; this package's `verified` citation has lapsed",
259
+ "warning-only":
260
+ "`block_exit` is null here — they run and warn, they cannot refuse",
261
+ unverified:
262
+ "no lowering row for this slot — nothing bound natively, nothing established",
263
+ };
264
+
163
265
  const _STATUS_MARKER: Record<string, string> = {
164
266
  installed: "✅ ",
165
267
  missing: "❌ ",
@@ -199,6 +301,16 @@ export function _render_table(matrix: StatusMatrix): string {
199
301
  for (const event of Object.keys(row.bindings).sort()) {
200
302
  const concerns = row.bindings[event]?.join(", ") || "—";
201
303
  lines.push(` ${event.padEnd(22)} → ${concerns}`);
304
+ // road-to-blocking-severities 1.2 — printed only where a concern on this
305
+ // slot DECLARES `blocking`, and worded so `unverified` never reads as a
306
+ // claim about the host.
307
+ const enforcement = row.blocking_enforcement[event];
308
+ if (enforcement !== undefined) {
309
+ lines.push(
310
+ ` ${" ".repeat(22)} blocking concerns here: ${enforcement} — ` +
311
+ `${_ENFORCEMENT_NOTE[enforcement] ?? "see docs/enforcement-by-host.md"}`,
312
+ );
313
+ }
202
314
  }
203
315
  if (row.hint) {
204
316
  lines.push(` hint: ${row.hint}`);
@@ -214,6 +214,13 @@ export const OUTPUT_KEYS: readonly string[] = [
214
214
  "toolResponse",
215
215
  "tool_result",
216
216
  "toolUseResult",
217
+ // The failure event's result body. A FAILING command on claude carries its
218
+ // stdout and stderr here and carries no `tool_response` at all, so without
219
+ // this line a failed `curl` of a hostile page would reach the model with
220
+ // nothing scanned — the one direction where the output is most likely to be
221
+ // attacker-shaped. Caught by this concern's own coverage test, which pins
222
+ // OUTPUT_KEYS as a superset of what the dispatcher serves.
223
+ "error",
217
224
  // Generic spellings accepted since this concern shipped.
218
225
  "output",
219
226
  "result",
@@ -76,6 +76,10 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
76
76
  import type * as YamlModule from 'yaml';
77
77
 
78
78
  import { build_merge_entries } from './_lib/json_pointers.js';
79
+ import { deepMerge as deep_merge, isPlainObject as _isPlainObject, jsonEqual } from './_lib/json_merge.js';
80
+ import { mergeHostConfig, HOOK_SIGNATURES } from './_lib/host_hook_merge.js';
81
+ import { sweepReservedNames } from './_lib/reserved_name_sweep.js';
82
+ import { withHostEnv } from './_lib/host_env_write.js';
79
83
  import { jsonDumpsCompact, jsonDumpsIndent } from './_lib/json_python_parity.js';
80
84
  import { is_claude_builtin_name } from './_lib/claude_builtin_names.js';
81
85
  import * as installed_lock from './_lib/installed_lock.js';
@@ -92,6 +96,7 @@ import * as rule_layer_overlap from './_lib/rule_layer_overlap.js';
92
96
  import * as installed_tools from './_lib/installed_tools.js';
93
97
  import { collect_drift, format_drift_report } from './_lib/install_drift.js';
94
98
  import * as user_global_paths from './_lib/user_global_paths.js';
99
+ import * as gitignore_block from './_lib/gitignore_block.js';
95
100
  // The LIBRARY half, deliberately not `capture_skill_catalogue.js`: that module
96
101
  // is a CLI entry with a top-level `process.exit()`, and esbuild would bundle
97
102
  // that exit into the installer a consumer loads (`check_installer_import_purity`
@@ -102,15 +107,17 @@ import * as claude_desktop_bundler from './_lib/claude_desktop_bundler.js';
102
107
  import * as claude_settings_hooks from './_lib/claude_settings_hooks.js';
103
108
  import { hostBindings } from './hooks/host_lowering.js';
104
109
  import { find_project_root_with_anchor, load_agent_settings } from './_lib/agent_settings.js';
105
- import {
106
- LEGACY_ALL,
107
- ruleFileArrives,
108
- ruleScopeFromSettings,
109
- type RuleScope,
110
- } from '../install/rule_scope.js';
110
+ import { ruleFileArrives, type RuleScope } from '../install/rule_scope.js';
111
111
  import { isExclusivelyPackageOnly, stampHostLayerFingerprint } from '../install/partitionEligibility.js'; // ADR-236
112
112
  import * as claude_rule_rewrite from '../install/claudeRuleRewrite.js';
113
- import { RULE_SOURCE_REL } from '../install/wizard-plan.js';
113
+ import {
114
+ describeThinInstalledLayer,
115
+ installReceiptBudgetLines,
116
+ thinInstalledRuleLayer,
117
+ } from '../install/installThinLayer.js';
118
+ import { resolveGlobalRuleScope } from '../install/globalRuleScope.js';
119
+ import { installerThinsHost } from './_lib/lean_projection_mode.js';
120
+ import { GLOBAL_DEPLOY_SOURCES, RULE_SOURCE_REL } from '../install/wizard-plan.js';
114
121
  import { flattenSurface, computeSurfaceDelta, type SettingsSurface } from '../shared/settingsSurface.js';
115
122
  import { settingsSchema } from '../server/schemas/settings.js';
116
123
  import { zodToJsonSchema } from 'zod-to-json-schema';
@@ -480,63 +487,6 @@ function write_json_file(p: string, data: unknown): void {
480
487
  write_file(p, content);
481
488
  }
482
489
 
483
- function _isPlainObject(v: unknown): v is Record<string, unknown> {
484
- return typeof v === 'object' && v !== null && !Array.isArray(v);
485
- }
486
-
487
- /** `copy.deepcopy` for JSON-shaped values. */
488
- function deepcopy<T>(v: T): T {
489
- if (v === null || typeof v !== 'object') return v;
490
- if (Array.isArray(v)) return v.map((x) => deepcopy(x)) as unknown as T;
491
- const out: Record<string, unknown> = {};
492
- for (const k of Object.keys(v as Record<string, unknown>)) {
493
- out[k] = deepcopy((v as Record<string, unknown>)[k]);
494
- }
495
- return out as unknown as T;
496
- }
497
-
498
- function deep_merge(
499
- base: Record<string, unknown>,
500
- overlay: Record<string, unknown>,
501
- ): Record<string, unknown> {
502
- const result = deepcopy(base);
503
- for (const key of Object.keys(overlay)) {
504
- const value = overlay[key];
505
- if (
506
- Object.prototype.hasOwnProperty.call(result, key) &&
507
- _isPlainObject(result[key]) &&
508
- _isPlainObject(value)
509
- ) {
510
- result[key] = deep_merge(
511
- result[key] as Record<string, unknown>,
512
- value as Record<string, unknown>,
513
- );
514
- } else {
515
- result[key] = deepcopy(value);
516
- }
517
- }
518
- return result;
519
- }
520
-
521
- /** Deep structural equality for JSON-shaped values (Python dict `==`). */
522
- function jsonEqual(a: unknown, b: unknown): boolean {
523
- if (a === b) return true;
524
- if (typeof a !== typeof b) return false;
525
- if (Array.isArray(a) || Array.isArray(b)) {
526
- if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;
527
- return a.every((v, i) => jsonEqual(v, b[i]));
528
- }
529
- if (_isPlainObject(a) && _isPlainObject(b)) {
530
- const ka = Object.keys(a);
531
- const kb = Object.keys(b);
532
- if (ka.length !== kb.length) return false;
533
- return ka.every(
534
- (k) => Object.prototype.hasOwnProperty.call(b, k) && jsonEqual(a[k], (b as Record<string, unknown>)[k]),
535
- );
536
- }
537
- return false;
538
- }
539
-
540
490
  function merge_json_file(
541
491
  p: string,
542
492
  new_data: Record<string, unknown>,
@@ -556,7 +506,9 @@ function merge_json_file(
556
506
  }
557
507
 
558
508
  const existing = read_json_file(p);
559
- const merged = deep_merge(existing, new_data);
509
+ // Hook arrays are shared with whatever else the consumer installed, so the
510
+ // `hooks` key merges per event by signature instead of being replaced.
511
+ const merged = mergeHostConfig(existing, new_data, HOOK_SIGNATURES[label] ?? '', deep_merge);
560
512
 
561
513
  if (jsonEqual(merged, existing)) {
562
514
  skip(`${label} already configured`);
@@ -996,10 +948,8 @@ function _heal_legacy_claude_plugin_ids(p: string): string[] {
996
948
  function ensure_claude_bridge(project_root: string, force: boolean): Record<string, unknown>[] {
997
949
  const target = path.join(project_root, '.claude', 'settings.json');
998
950
  const healed = _heal_legacy_claude_plugin_ids(target);
999
- for (const pid of healed) {
1000
- success(`.claude/settings.json: removed stale plugin id \`${pid}\``);
1001
- }
1002
- const bridge = { enabledPlugins: { [CLAUDE_PLUGIN_ID]: true } };
951
+ for (const pid of healed) success(`.claude/settings.json: removed stale plugin id \`${pid}\``);
952
+ const bridge = withHostEnv({ enabledPlugins: { [CLAUDE_PLUGIN_ID]: true } }, project_root, success);
1003
953
  return merge_json_file(target, bridge, force || healed.length > 0, '.claude/settings.json');
1004
954
  }
1005
955
 
@@ -1804,48 +1754,20 @@ export const PROJECT_BRIDGE_MARKERS: Record<string, string> = {
1804
1754
  kiro: '.kiro/steering/agent-config.md',
1805
1755
  };
1806
1756
 
1807
- const _CLAUDE_SKILL_BUNDLE: ReadonlyArray<readonly [string, string]> = [
1808
- ['dist/agent-src/rules', 'rules'],
1809
- ['dist/agent-src/skills', 'skills'],
1810
- ['dist/agent-src/commands', 'commands'],
1811
- ['dist/agent-src/personas', 'personas'],
1812
- ];
1813
-
1814
- export const GLOBAL_DEPLOY_SOURCES: Record<string, ReadonlyArray<readonly [string, string]>> = {
1815
- 'claude-code': _CLAUDE_SKILL_BUNDLE,
1816
- augment: [
1817
- ['dist/agent-src/rules', 'rules'],
1818
- ['dist/agent-src/skills', 'skills'],
1819
- ['dist/agent-src/commands', 'commands'],
1820
- ['dist/agent-src/contexts', 'contexts'],
1821
- ['dist/agent-src/personas', 'personas'],
1822
- ['dist/agent-src/templates', 'templates'],
1823
- ],
1824
- cursor: [
1825
- ['dist/agent-src/rules', 'rules'],
1826
- ['dist/agent-src/commands', 'commands'],
1827
- ['dist/agent-src/personas', 'personas'],
1828
- ],
1829
- windsurf: [['dist/agent-src/rules', 'rules']],
1830
- cline: [['dist/agent-src/rules', '']],
1831
- 'gemini-cli': _CLAUDE_SKILL_BUNDLE,
1832
- codex: _CLAUDE_SKILL_BUNDLE,
1833
- continue: _CLAUDE_SKILL_BUNDLE,
1834
- roocode: _CLAUDE_SKILL_BUNDLE,
1835
- kilocode: _CLAUDE_SKILL_BUNDLE,
1836
- qoder: _CLAUDE_SKILL_BUNDLE,
1837
- opencode: _CLAUDE_SKILL_BUNDLE,
1838
- trae: _CLAUDE_SKILL_BUNDLE,
1839
- antigravity: _CLAUDE_SKILL_BUNDLE,
1840
- codebuddy: _CLAUDE_SKILL_BUNDLE,
1841
- droid: _CLAUDE_SKILL_BUNDLE,
1842
- warp: _CLAUDE_SKILL_BUNDLE,
1843
- kiro: [
1844
- ['dist/agent-src/rules', 'rules'],
1845
- ['dist/agent-src/skills', 'steering'],
1846
- ['dist/agent-src/personas', 'personas'],
1847
- ],
1848
- };
1757
+ /**
1758
+ * Re-exported from `wizard-plan.ts`, which is now the ONLY definition.
1759
+ *
1760
+ * It was defined here too, and the two copies were byte-identical in every
1761
+ * one of their 18 host rows — a duplicate of the same truth, and the kind
1762
+ * that stays correct right up until somebody edits one of them. Step 1.2 of
1763
+ * `road-to-rule-triggers-and-links-that-hold` did exactly that: it added two
1764
+ * directories here and the wizard kept installing without them.
1765
+ *
1766
+ * Re-exported rather than moved-and-left-broken so every caller of
1767
+ * `install.ts::GLOBAL_DEPLOY_SOURCES` keeps working unchanged. Imported as
1768
+ * well as re-exported because this file's own call sites read the binding.
1769
+ */
1770
+ export { GLOBAL_DEPLOY_SOURCES };
1849
1771
 
1850
1772
  const _CLAUDE_DESKTOP_MARKER_TEMPLATE_HEAD = `# agent-config — Claude Desktop marker
1851
1773
 
@@ -2109,8 +2031,9 @@ export function _gate_rule_layer_overlap(
2109
2031
  layer: string | null,
2110
2032
  dry_run: boolean,
2111
2033
  ): boolean {
2112
- const global_dir = path.join(os.homedir(), '.claude', 'rules');
2113
- const project_dir = path.join(project_root, '.claude', 'rules');
2034
+ // ONE source of truth for which directories the host loads, shared with the
2035
+ // delivery carrier's scope filter (`rule_layer_overlap.hostRuleLayerDirs`).
2036
+ const [global_dir, project_dir] = rule_layer_overlap.hostRuleLayerDirs(project_root);
2114
2037
  const g = rule_layer_overlap.readRuleLayer(global_dir);
2115
2038
  const p = rule_layer_overlap.readRuleLayer(project_dir);
2116
2039
  if (g === null || p === null) return true; // only one layer exists — nothing to double
@@ -2958,26 +2881,12 @@ export function _apply_claude_flat_command_wrappers(
2958
2881
  anchor: string,
2959
2882
  package_root: string,
2960
2883
  current_files: Set<string>,
2961
- ): { wrapped: string[]; collisions: string[]; reserved: string[] } {
2884
+ recorded_files: ReadonlySet<string> = new Set<string>(),
2885
+ ): { wrapped: string[]; collisions: string[]; reserved: string[]; foreign: string[] } {
2962
2886
  const wrapped: string[] = [];
2963
2887
  const collisions: string[] = [];
2964
- const reserved: string[] = [];
2965
- // Reserved-name sweep over ALL flat command files (any tier): a name
2966
- // shadowing a Claude Code built-in never ships on the claude-code anchor.
2967
2888
  const commands_dir = path.join(anchor, 'commands');
2968
- let flat_entries: string[] = [];
2969
- try {
2970
- flat_entries = fs.readdirSync(commands_dir).filter((f) => f.endsWith('.md'));
2971
- } catch {
2972
- // No commands dir → nothing to sweep.
2973
- }
2974
- for (const fname of flat_entries.sort()) {
2975
- const slug = fname.slice(0, -'.md'.length);
2976
- if (!is_claude_builtin_name(slug)) continue;
2977
- fs.rmSync(path.join(commands_dir, fname), { force: true });
2978
- current_files.delete(`commands/${fname}`);
2979
- reserved.push(slug);
2980
- }
2889
+ const { reserved, foreign } = sweepReservedNames(commands_dir, current_files, is_claude_builtin_name, recorded_files);
2981
2890
  // Visible command slugs from the locked discovery manifest. `visibility`
2982
2891
  // is the source of truth (ADR-090/092); the integer `tier` stays only as
2983
2892
  // the fallback for a manifest published before `visibility` was emitted,
@@ -3024,7 +2933,7 @@ export function _apply_claude_flat_command_wrappers(
3024
2933
  current_files.add(`skills/${slug}/SKILL.md`);
3025
2934
  wrapped.push(slug);
3026
2935
  }
3027
- return { wrapped, collisions, reserved };
2936
+ return { wrapped, collisions, reserved, foreign };
3028
2937
  }
3029
2938
 
3030
2939
  function _deploy_global_content(
@@ -3097,15 +3006,33 @@ function _deploy_global_content(
3097
3006
  if (tool_id === 'claude-code') {
3098
3007
  // Rules land verbatim from the copy above; see the module. It also
3099
3008
  // renders the flat-command wrapper report, unchanged.
3100
- const res = _apply_claude_flat_command_wrappers(anchor, package_root, current_files);
3009
+ const res = _apply_claude_flat_command_wrappers(anchor, package_root, current_files, global_deploy_inventory.recorded_rel_files(tool_id, anchor));
3010
+ const preserved_now = new Set(
3011
+ tracker.conflictState.preserved.map((p) => path.resolve(p)),
3012
+ );
3101
3013
  claude_rule_rewrite.rewriteAndReport(
3102
3014
  path.join(anchor, 'rules'),
3103
3015
  state.QUIET,
3104
3016
  info,
3105
3017
  warn,
3106
3018
  res,
3107
- new Set(tracker.conflictState.preserved.map((p) => path.resolve(p))),
3019
+ preserved_now,
3108
3020
  );
3021
+ // Steps 1.1 and 1.4 of road-to-an-installed-layer-that-is-thinned;
3022
+ // both modules' headers carry the reasoning.
3023
+ if (installerThinsHost(tool_id, { packageRoot: package_root })) {
3024
+ try {
3025
+ const thin = thinInstalledRuleLayer({
3026
+ rulesDir: path.join(anchor, 'rules'),
3027
+ packageRoot: package_root,
3028
+ preserved: preserved_now,
3029
+ });
3030
+ if (!state.QUIET) for (const l of describeThinInstalledLayer(thin)) info(l);
3031
+ } catch (e) {
3032
+ warn(`claude-code: thinned rule layer not written — ${String(e)}`);
3033
+ }
3034
+ }
3035
+ if (!state.QUIET) for (const l of installReceiptBudgetLines(package_root)) info(l);
3109
3036
  }
3110
3037
 
3111
3038
  const missing_targets = _verify_deploy_targets(anchor, plan);
@@ -3340,65 +3267,21 @@ function _resolve_scoped_projection(
3340
3267
  }
3341
3268
 
3342
3269
  /**
3343
- * Resolve the rule scope governing THIS global deploy — the same way the wizard
3344
- * does (`src/server/routes/install.ts::_resolveRuleScope`), so the two global
3345
- * paths cannot ship different rule sets for the same settings.
3270
+ * Resolve the rule scope governing THIS global deploy.
3346
3271
  *
3347
- * Settings resolution mirrors `_resolve_scoped_projection` above: an existing
3348
- * global settings doc is authoritative, and only a genuinely fresh machine falls
3349
- * through to the packaged template. Any read or parse failure resolves to
3350
- * `LEGACY_ALL` — over-shipping is the safe direction, and the compat exclusion
3351
- * (`source-of-truth.md`) still applies even then.
3272
+ * Thin wrapper: the body moved to `src/install/globalRuleScope.ts` (see that
3273
+ * module's header for why). Name, signature and behaviour are unchanged, so the
3274
+ * re-export below and every caller and test keep what they had.
3352
3275
  */
3353
3276
  function _resolve_global_rule_scope(package_root: string): RuleScope {
3354
- const settings_path = _resolve_global_settings_path();
3355
-
3356
- // No global settings artefact at all — a genuinely fresh machine. Fall
3357
- // through to the packaged template silently: there is no user decision to
3358
- // contradict, and this is the documented upgrade-compat path.
3359
- if (settings_path === null) {
3360
- try {
3361
- return ruleScopeFromSettings(_load_default_settings(package_root), package_root);
3362
- } catch {
3363
- return LEGACY_ALL;
3364
- }
3365
- }
3366
-
3367
- // A doc EXISTS, so the user has expressed a configuration. Failing to read
3368
- // it is not the same as not having one: falling back to legacy-all here
3369
- // ships the maintainer-only rules the user may have deliberately scoped out,
3370
- // and `_load_yaml_doc` would report that as an indistinguishable `{}`. So
3371
- // parse it explicitly and be LOUD when it does not parse — over-shipping
3372
- // stays the safe direction, but it must not be a silent one.
3373
- let text: string;
3374
- try {
3375
- text = readText(settings_path);
3376
- } catch (e) {
3377
- warn(
3378
- `could not read ${settings_path} (${String(e)}) — rule scoping falls back ` +
3379
- 'to legacy-all, so ALL rules including maintainer-only ones will be ' +
3380
- 'installed. Fix the file to restore scoping.',
3381
- );
3382
- return LEGACY_ALL;
3383
- }
3384
- const parsed = yamlSafeLoad(text);
3385
- if (!_isPlainObject(parsed)) {
3386
- warn(
3387
- `${settings_path} is not a YAML mapping — rule scoping falls back to ` +
3388
- 'legacy-all, so ALL rules including maintainer-only ones will be ' +
3389
- 'installed. Fix the file to restore scoping.',
3390
- );
3391
- return LEGACY_ALL;
3392
- }
3393
- try {
3394
- return ruleScopeFromSettings(parsed as Record<string, unknown>, package_root);
3395
- } catch (e) {
3396
- warn(
3397
- `could not derive rule scope from ${settings_path} (${String(e)}) — ` +
3398
- 'falling back to legacy-all; ALL rules will be installed.',
3399
- );
3400
- return LEGACY_ALL;
3401
- }
3277
+ return resolveGlobalRuleScope({
3278
+ settingsPath: _resolve_global_settings_path(),
3279
+ packageRoot: package_root,
3280
+ readText,
3281
+ parseYaml: yamlSafeLoad,
3282
+ loadDefaults: () => _load_default_settings(package_root),
3283
+ warn,
3284
+ });
3402
3285
  }
3403
3286
 
3404
3287
  /**
@@ -5137,6 +5020,9 @@ function _main_project_install(
5137
5020
  if (will_launch) {
5138
5021
  return _wizard_spawn(project_root);
5139
5022
  }
5023
+ // No wizard, so nothing else installs the managed ignore block.
5024
+ const ign = gitignore_block.write_managed_block(project_root, opts.dry_run);
5025
+ if (ign > 0) success(`.gitignore: ${opts.dry_run ? 'would add ' : '+'}${ign} managed entries`);
5140
5026
  return 0;
5141
5027
  }
5142
5028
 
@@ -0,0 +1,103 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * Report what a host actually loads, per host rule directory (step 0.1).
4
+ *
5
+ * REPORT-ONLY, AND THE NAME SAYS SO. Phase 0 of
6
+ * `road-to-a-rule-carrier-that-works-outside-the-repo` makes no behavior
7
+ * change, so this never fails on a number: exit 0 whenever it could read, 2 on
8
+ * usage. It is also deliberately NOT named `check_*` or `lint_*` —
9
+ * `_lib/gate_population.ts` enters any script with those prefixes into the gate
10
+ * population and the ledger then owes it a per-target accounting, which is the
11
+ * wrong contract for an instrument. A later ceiling over this measurement is a
12
+ * different script with a `check_` name.
13
+ *
14
+ * `--home` and `--project` exist so this can be pointed at a temporary `HOME`,
15
+ * which is the step's own framing and the thing that refutes
16
+ * `check_standing_rule_delivery`'s "no CI workflow performs a user-scope
17
+ * install": the installer reads `HOME` from the environment, so a runner can
18
+ * stage one and measure it. The library behind this takes the same two as
19
+ * parameters, which is what keeps CI, `doctor` and the upgrade receipt from
20
+ * each growing their own reader.
21
+ */
22
+
23
+ import * as os from 'node:os';
24
+ import * as path from 'node:path';
25
+ import process from 'node:process';
26
+
27
+ import { hostVersion } from './cache_realization_report.js';
28
+ import { manifest_path } from './_lib/installed_tools.js';
29
+ import {
30
+ buildInstalledLayerReport,
31
+ renderInstalledLayerReport,
32
+ type InstalledLayerReport,
33
+ } from './_lib/installed_layer.js';
34
+
35
+ const PROG = 'installed_layer_report';
36
+
37
+ interface Args {
38
+ home: string;
39
+ project: string;
40
+ json: boolean;
41
+ }
42
+
43
+ export function parseArgs(argv: readonly string[]): Args | null {
44
+ let home = process.env['HOME'] ?? os.homedir();
45
+ let project = process.cwd();
46
+ let json = false;
47
+ for (let i = 0; i < argv.length; i += 1) {
48
+ const a = argv[i];
49
+ if (a === '--json') {
50
+ json = true;
51
+ } else if (a === '--home') {
52
+ i += 1;
53
+ const v = argv[i];
54
+ if (v === undefined) return null;
55
+ home = v;
56
+ } else if (a === '--project') {
57
+ i += 1;
58
+ const v = argv[i];
59
+ if (v === undefined) return null;
60
+ project = v;
61
+ } else if (a === '--quiet') {
62
+ // Accepted and ignored: this prints one block either way, and a flag
63
+ // that silences a report leaves nothing to have run it for.
64
+ } else {
65
+ return null;
66
+ }
67
+ }
68
+ return { home, project, json };
69
+ }
70
+
71
+ /** Build the report for one machine, resolving the manifest from the project root. */
72
+ export function reportFor(args: Args): InstalledLayerReport {
73
+ return buildInstalledLayerReport({
74
+ home: args.home,
75
+ projectRoot: args.project,
76
+ manifestPath: manifest_path(args.project),
77
+ hostVersion: hostVersion(),
78
+ });
79
+ }
80
+
81
+ export function main(argv: readonly string[] = process.argv.slice(2)): number {
82
+ const args = parseArgs(argv);
83
+ if (args === null) {
84
+ process.stderr.write(`usage: ${PROG} [--home <dir>] [--project <dir>] [--json]\n`);
85
+ return 2;
86
+ }
87
+ const report = reportFor(args);
88
+ if (args.json) {
89
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
90
+ } else {
91
+ process.stdout.write(`${renderInstalledLayerReport(report).join('\n')}\n`);
92
+ }
93
+ // One machine-readable line, in the shape every reporting script here uses.
94
+ // It counts FILES across every layer read, which is the denominator the
95
+ // character total is over — a reader comparing two runs needs both.
96
+ process.stdout.write(`scanned: ${String(report.totals.files)}\n`);
97
+ return 0;
98
+ }
99
+
100
+ const _entry = process.argv[1];
101
+ if (_entry !== undefined && path.resolve(_entry) === path.resolve(new URL(import.meta.url).pathname)) {
102
+ process.exit(main());
103
+ }