@event4u/agent-config 14.12.0 → 14.14.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 (521) 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 +118 -155
  5. package/CONTRIBUTING.md +38 -0
  6. package/CREDITS.md +135 -0
  7. package/NOTICE +13 -0
  8. package/README.md +8 -6
  9. package/dist/agent-src/commands/analyze/inbox.md +145 -2
  10. package/dist/agent-src/commands/feature/dev.md +7 -2
  11. package/dist/agent-src/commands/ghostwriter/write.md +5 -1
  12. package/dist/agent-src/commands/implement-ticket.md +1 -1
  13. package/dist/agent-src/commands/mission/upgrade.md +1 -1
  14. package/dist/agent-src/commands/orchestrate.md +2 -2
  15. package/dist/agent-src/commands/post-as/me.md +5 -1
  16. package/dist/agent-src/commands/pr/merge.md +19 -6
  17. package/dist/agent-src/commands/roadmap/process-full.md +19 -5
  18. package/dist/agent-src/commands/tdd/red.md +12 -2
  19. package/dist/agent-src/commands/work.md +1 -1
  20. package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +40 -0
  21. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +5 -2
  22. package/dist/agent-src/contexts/execution/autonomy-mechanics.md +21 -0
  23. package/dist/agent-src/contexts/execution/orchestration-telemetry.md +1 -0
  24. package/dist/agent-src/contexts/execution/subagent-response-contract.md +40 -0
  25. package/dist/agent-src/contexts/execution/subagent-steering.md +13 -1
  26. package/dist/agent-src/contexts/execution/terminal-states.md +96 -0
  27. package/dist/agent-src/rules/artifact-drafting-protocol.md +1 -1
  28. package/dist/agent-src/rules/broken-access-control.md +4 -0
  29. package/dist/agent-src/rules/code-comment-discipline.md +6 -0
  30. package/dist/agent-src/rules/code-provenance.md +4 -0
  31. package/dist/agent-src/rules/design-fidelity.md +1 -1
  32. package/dist/agent-src/rules/domain-safety-pii.md +4 -0
  33. package/dist/agent-src/rules/domain-safety-retention.md +4 -0
  34. package/dist/agent-src/rules/engineering-safety-floor.md +2 -0
  35. package/dist/agent-src/rules/external-code-graph-interop.md +14 -12
  36. package/dist/agent-src/rules/improve-before-implement.md +6 -8
  37. package/dist/agent-src/rules/laravel-routing.md +1 -1
  38. package/dist/agent-src/rules/lethal-trifecta-guard.md +4 -0
  39. package/dist/agent-src/rules/secret-vcs-guard.md +2 -0
  40. package/dist/agent-src/rules/security-sensitive-stop.md +2 -0
  41. package/dist/agent-src/rules/source-confidentiality.md +12 -34
  42. package/dist/agent-src/rules/symfony-routing.md +1 -1
  43. package/dist/agent-src/rules/token-efficiency.md +14 -0
  44. package/dist/agent-src/rules/tool-safety.md +4 -0
  45. package/dist/agent-src/rules/untrusted-input-defense.md +4 -0
  46. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +252 -8
  47. package/dist/agent-src/scripts/guarded_baseline.ts +343 -0
  48. package/dist/agent-src/scripts/roadmap_set_step.ts +253 -0
  49. package/dist/agent-src/scripts/stub_queue.ts +82 -0
  50. package/dist/agent-src/scripts/stubs_due.ts +516 -0
  51. package/dist/agent-src/scripts/ticket_bundles.ts +84 -0
  52. package/dist/agent-src/scripts/update_roadmap_progress.ts +16 -12
  53. package/dist/agent-src/skills/brand-asset-generation/SKILL.md +17 -4
  54. package/dist/agent-src/skills/brand-audit/SKILL.md +33 -0
  55. package/dist/agent-src/skills/code-intelligence/SKILL.md +57 -0
  56. package/dist/agent-src/skills/database/SKILL.md +8 -0
  57. package/dist/agent-src/skills/dependency-upgrade/SKILL.md +27 -0
  58. package/dist/agent-src/skills/design-review/SKILL.md +1 -1
  59. package/dist/agent-src/skills/doc-coauthoring/SKILL.md +1 -1
  60. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +17 -1
  61. package/dist/agent-src/skills/feature-planning/SKILL.md +9 -2
  62. package/dist/agent-src/skills/frontend-render-security/SKILL.md +44 -0
  63. package/dist/agent-src/skills/git-workflow/SKILL.md +1 -1
  64. package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.ts +38 -4
  65. package/dist/agent-src/skills/judge-artifact-completeness/rubrics/ticket-quality-score.json +2 -2
  66. package/dist/agent-src/skills/laravel/SKILL.md +35 -0
  67. package/dist/agent-src/skills/laravel-migration/SKILL.md +57 -3
  68. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +26 -0
  69. package/dist/agent-src/skills/playbook-authoring/SKILL.md +28 -1
  70. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +1 -1
  71. package/dist/agent-src/skills/skill-writing/references/procedure.md +5 -5
  72. package/dist/agent-src/skills/sql-writing/SKILL.md +7 -1
  73. package/dist/agent-src/skills/standards-from-config/SKILL.md +27 -4
  74. package/dist/agent-src/skills/supply-chain-intake/SKILL.md +11 -4
  75. package/dist/agent-src/skills/symfony-workflow/SKILL.md +35 -0
  76. package/dist/agent-src/skills/test-case-discovery/SKILL.md +85 -0
  77. package/dist/agent-src/skills/test-driven-development/SKILL.md +33 -9
  78. package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
  79. package/dist/agent-src/skills/testing-anti-patterns/process-anti-patterns.md +37 -0
  80. package/dist/agent-src/skills/ui-component-architect/SKILL.md +45 -2
  81. package/dist/agent-src/skills/upstream-contribute/SKILL.md +38 -1
  82. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +9 -4
  83. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  84. package/dist/agent-src/templates/roadmaps.md +97 -3
  85. package/dist/agent-src/templates/scripts/check_memory.ts +258 -17
  86. package/dist/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
  87. package/dist/agent-src/templates/scripts/memory_lookup.ts +86 -0
  88. package/dist/agent-src/templates/scripts/memory_signal.ts +44 -0
  89. package/dist/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
  90. package/dist/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
  91. package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
  92. package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
  93. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
  94. package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
  95. package/dist/cli/commands/uiAudit.js +124 -5
  96. package/dist/cli/registry.js +2 -0
  97. package/dist/cli-delegate/{chunk-HYWSRNUX.js → chunk-2DK2VJWG.js} +3 -3
  98. package/dist/cli-delegate/{chunk-JCW7ZLHK.js → chunk-4FS4WRXP.js} +5 -0
  99. package/dist/cli-delegate/{chunk-OMIVVCG2.js → chunk-A4QJ6ENT.js} +24 -0
  100. package/dist/cli-delegate/{chunk-JJA2QEWA.js → chunk-AKJGUQNO.js} +466 -285
  101. package/dist/cli-delegate/{chunk-E46KPN6K.js → chunk-BTWUYDGN.js} +424 -363
  102. package/dist/cli-delegate/{chunk-K4FFODTS.js → chunk-ILMUPLGW.js} +1227 -316
  103. package/dist/cli-delegate/{chunk-FF7WAFMR.js → chunk-KPBWFOPZ.js} +5 -1
  104. package/dist/cli-delegate/cmd_adr_effective.js +102 -0
  105. package/dist/cli-delegate/cmd_conformance.js +80 -11
  106. package/dist/cli-delegate/cmd_doctor.js +3 -3
  107. package/dist/cli-delegate/cmd_export.js +3 -2
  108. package/dist/cli-delegate/cmd_fleet.js +2 -2
  109. package/dist/cli-delegate/cmd_handoff.js +1 -1
  110. package/dist/cli-delegate/cmd_preflight.js +2 -2
  111. package/dist/cli-delegate/cmd_prune.js +3 -2
  112. package/dist/cli-delegate/cmd_settings_get.js +1 -1
  113. package/dist/cli-delegate/cmd_settings_migrate.js +3 -2
  114. package/dist/cli-delegate/cmd_settings_set.js +2 -2
  115. package/dist/cli-delegate/cmd_sync.js +3 -2
  116. package/dist/cli-delegate/cmd_uninstall.js +3 -2
  117. package/dist/cli-delegate/cmd_validate.js +3 -2
  118. package/dist/discovery/deprecation-report.md +1 -1
  119. package/dist/discovery/discovery-manifest.json +58 -58
  120. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  121. package/dist/discovery/discovery-manifest.summary.md +1 -1
  122. package/dist/discovery/dormancy-report.md +1 -1
  123. package/dist/discovery/orphan-report.md +1 -1
  124. package/dist/discovery/packs.json +2 -2
  125. package/dist/discovery/trust-report.md +1 -1
  126. package/dist/discovery/workspaces.json +2 -2
  127. package/dist/hooks/dispatch.js +2900 -1049
  128. package/dist/install/claudeRuleRewrite.js +254 -0
  129. package/dist/install/detect.js +29 -16
  130. package/dist/install/detect_php_shape.js +159 -0
  131. package/dist/install/install.mjs +634 -428
  132. package/dist/mcp/awesome-mcp-servers.row.md +1 -1
  133. package/dist/mcp/mcp-cloudflare-catalogue.json +1 -1
  134. package/dist/mcp/registry-manifest.json +3 -3
  135. package/dist/mcp/server.json +3 -3
  136. package/dist/mcp/server.mjs +4895 -2627
  137. package/dist/server/schemas/settings.js +3 -0
  138. package/dist/ui/assets/index-D0jaCRPM.js +29 -0
  139. package/dist/ui/index.html +1 -1
  140. package/docs/MIGRATION.md +1 -1
  141. package/docs/THIRD-PARTY-NOTICES.md +25 -0
  142. package/docs/contracts/provider-lifecycle.md +1 -1
  143. package/docs/contracts/settings-classes.md +10 -4
  144. package/docs/guidelines/agent-infra/5w2h-analysis.md +3 -3
  145. package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +1 -0
  146. package/docs/guidelines/agent-infra/artifact-drafting-protocol-mechanics.md +58 -3
  147. package/docs/guidelines/agent-infra/ask-when-uncertain-demos.md +2 -2
  148. package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +3 -3
  149. package/docs/guidelines/agent-infra/break-glass-usage.md +7 -7
  150. package/docs/guidelines/agent-infra/carve-out-predicates.md +3 -3
  151. package/docs/guidelines/agent-infra/comparison-matrix.md +1 -1
  152. package/docs/guidelines/agent-infra/critical-thinking.md +4 -4
  153. package/docs/guidelines/agent-infra/direct-answers-demos.md +2 -2
  154. package/docs/guidelines/agent-infra/domain-eval-anti-pattern.md +1 -1
  155. package/docs/guidelines/agent-infra/engineering-memory-data-format.md +3 -3
  156. package/docs/guidelines/agent-infra/existence-question-verdicts.md +80 -0
  157. package/docs/guidelines/agent-infra/first-principles.md +2 -2
  158. package/docs/guidelines/agent-infra/framework-neutrality-patterns.md +2 -2
  159. package/docs/guidelines/agent-infra/guarded-baseline.md +39 -0
  160. package/docs/guidelines/agent-infra/inversion-thinking.md +5 -5
  161. package/docs/guidelines/agent-infra/language-and-tone-examples.md +1 -1
  162. package/docs/guidelines/agent-infra/layered-settings.md +10 -10
  163. package/docs/guidelines/agent-infra/memory-access.md +1 -1
  164. package/docs/guidelines/agent-infra/mental-models.md +3 -3
  165. package/docs/guidelines/agent-infra/reuse-verdict-mechanics.md +71 -0
  166. package/docs/guidelines/agent-infra/review-routing-data-format.md +7 -7
  167. package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +13 -7
  168. package/docs/guidelines/agent-infra/role-contracts.md +2 -2
  169. package/docs/guidelines/agent-infra/role-mode-router.md +3 -3
  170. package/docs/guidelines/agent-infra/rule-type-governance.md +2 -2
  171. package/docs/guidelines/agent-infra/scqa-framework.md +5 -5
  172. package/docs/guidelines/agent-infra/self-improvement-pipeline.md +6 -6
  173. package/docs/guidelines/agent-infra/simplicity-and-goal-demos.md +2 -2
  174. package/docs/guidelines/agent-infra/six-hats.md +3 -3
  175. package/docs/guidelines/agent-infra/skill-quality-checklist.md +6 -6
  176. package/docs/guidelines/agent-infra/source-confidentiality-mechanics.md +109 -0
  177. package/docs/guidelines/agent-infra/systems-thinking.md +1 -1
  178. package/docs/guidelines/agent-infra/verify-before-complete-demos.md +2 -2
  179. package/docs/guidelines/augment-portability-patterns.md +6 -4
  180. package/docs/guidelines/code-clarity.md +18 -0
  181. package/docs/guidelines/component-oriented-and-oop-development.md +3 -2
  182. package/docs/guidelines/cross-role-handoff.md +2 -2
  183. package/docs/guidelines/design-fidelity-mechanics.md +1 -1
  184. package/docs/guidelines/docs/readme-size-and-splitting.md +3 -3
  185. package/docs/guidelines/php/database.md +90 -7
  186. package/docs/guidelines/prompt-templates.md +7 -7
  187. package/llms.txt +2 -2
  188. package/package.json +5 -2
  189. package/src/agent-src/scripts/archive_completed_roadmaps.ts +252 -8
  190. package/src/agent-src/scripts/guarded_baseline.ts +343 -0
  191. package/src/agent-src/scripts/roadmap_set_step.ts +253 -0
  192. package/src/agent-src/scripts/stub_queue.ts +82 -0
  193. package/src/agent-src/scripts/stubs_due.ts +516 -0
  194. package/src/agent-src/scripts/ticket_bundles.ts +84 -0
  195. package/src/agent-src/scripts/update_roadmap_progress.ts +16 -12
  196. package/src/agent-src/templates/scripts/check_memory.ts +258 -17
  197. package/src/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
  198. package/src/agent-src/templates/scripts/memory_lookup.ts +86 -0
  199. package/src/agent-src/templates/scripts/memory_signal.ts +44 -0
  200. package/src/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
  201. package/src/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
  202. package/src/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
  203. package/src/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
  204. package/src/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
  205. package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
  206. package/src/config/agent-settings.template.yml +32 -3
  207. package/src/config/assurance-capability-registry.json +21 -9
  208. package/src/config/canonical-terms.yml +119 -0
  209. package/src/config/capability-native-outcome-bars.json +81 -0
  210. package/src/config/ci-local-parity.yml +80 -0
  211. package/src/config/drafting-channels.yml +43 -0
  212. package/src/config/estate-count-budget.json +57 -36
  213. package/src/config/evaluator-budgets.json +14 -14
  214. package/src/config/gate-coverage.yml +729 -63
  215. package/src/config/gate-reachability-exemptions.json +21 -0
  216. package/src/config/gate-violation-baselines.json +42 -19
  217. package/src/config/harness-evolution-budget.json +25 -0
  218. package/src/config/lapsed-beta-baseline.json +96 -0
  219. package/src/config/memory-twin-verdicts.yml +129 -0
  220. package/src/config/metric-registry.yml +124 -0
  221. package/src/config/pack-size-budget.json +16 -15
  222. package/src/config/preamble-payload-budget.json +12 -4
  223. package/src/config/profiles/balanced.ini +27 -0
  224. package/src/config/profiles/full.ini +27 -0
  225. package/src/config/profiles/minimal.ini +27 -0
  226. package/src/config/publish-surface.json +9 -2
  227. package/src/config/routing-coverage-seed.json +16 -2
  228. package/src/config/rule-stub-ceilings.json +133 -112
  229. package/src/config/turnaround-budget.json +66 -0
  230. package/src/install/claudeRuleRewrite.ts +288 -0
  231. package/src/install/detect.ts +60 -17
  232. package/src/install/detect_php_shape.ts +191 -0
  233. package/src/scripts/_cli/cmd_doctor.ts +27 -112
  234. package/src/scripts/_dispatch.bash +23 -0
  235. package/src/scripts/_lib/activation_ladder.ts +255 -0
  236. package/src/scripts/_lib/activation_receipt_producer.ts +341 -0
  237. package/src/scripts/_lib/activation_states.ts +88 -0
  238. package/src/scripts/_lib/adherence_detectors.ts +143 -0
  239. package/src/scripts/_lib/adr_frontmatter.ts +26 -0
  240. package/src/scripts/_lib/arith_claims.ts +181 -0
  241. package/src/scripts/_lib/arm_ranking.ts +62 -0
  242. package/src/scripts/_lib/asset_delivery_ledger.ts +303 -0
  243. package/src/scripts/_lib/audit_field_provenance.ts +54 -0
  244. package/src/scripts/_lib/auto_dispatch.ts +32 -3
  245. package/src/scripts/_lib/bench_ab_size_claim.ts +98 -4
  246. package/src/scripts/_lib/benchmark_cache_fields.ts +158 -0
  247. package/src/scripts/_lib/candidate_pair_delta.ts +349 -0
  248. package/src/scripts/_lib/candidate_proposer.ts +402 -0
  249. package/src/scripts/_lib/candidate_record.ts +601 -0
  250. package/src/scripts/_lib/capture_rate.ts +319 -0
  251. package/src/scripts/_lib/carrier_status.ts +118 -0
  252. package/src/scripts/_lib/cascade_stage_enumeration.ts +92 -0
  253. package/src/scripts/_lib/collector_denominator.ts +771 -0
  254. package/src/scripts/_lib/collector_record.ts +340 -0
  255. package/src/scripts/_lib/collector_store.ts +664 -0
  256. package/src/scripts/_lib/collector_supervision.ts +827 -0
  257. package/src/scripts/_lib/concern_estate.ts +77 -0
  258. package/src/scripts/_lib/config_chain.ts +477 -0
  259. package/src/scripts/_lib/config_cost.ts +209 -0
  260. package/src/scripts/_lib/corpus_manifest.ts +726 -0
  261. package/src/scripts/_lib/council_settings_block.ts +6 -0
  262. package/src/scripts/_lib/curator_ops.ts +172 -0
  263. package/src/scripts/_lib/delivery_arm_experiment.ts +282 -0
  264. package/src/scripts/_lib/delivery_criticality.ts +126 -0
  265. package/src/scripts/_lib/doctor_runtime_checks.ts +70 -0
  266. package/src/scripts/_lib/empty_cycles.ts +88 -0
  267. package/src/scripts/_lib/estate_carrier_cases.ts +72 -0
  268. package/src/scripts/_lib/eval_publication.ts +354 -0
  269. package/src/scripts/_lib/evaluation_cascade.ts +452 -0
  270. package/src/scripts/_lib/evaluation_vector.ts +283 -0
  271. package/src/scripts/_lib/evaluator_promotion.ts +225 -0
  272. package/src/scripts/_lib/evidence_basis.ts +118 -0
  273. package/src/scripts/_lib/evolution_roi.ts +562 -0
  274. package/src/scripts/_lib/exec_evidence.ts +8 -0
  275. package/src/scripts/_lib/experience_card.ts +272 -0
  276. package/src/scripts/_lib/experience_report.ts +151 -0
  277. package/src/scripts/_lib/experiment_freeze.ts +112 -0
  278. package/src/scripts/_lib/generated_by.ts +66 -0
  279. package/src/scripts/_lib/harness_evolution_guards.ts +239 -0
  280. package/src/scripts/_lib/hook_effect_probe.ts +141 -0
  281. package/src/scripts/_lib/host_denominator.ts +687 -0
  282. package/src/scripts/_lib/host_projection_reach.ts +157 -0
  283. package/src/scripts/_lib/ignored_blocker.ts +148 -0
  284. package/src/scripts/_lib/install_reach_checks.ts +495 -0
  285. package/src/scripts/_lib/json_duplicate_keys.ts +150 -0
  286. package/src/scripts/_lib/judge_hygiene.ts +228 -0
  287. package/src/scripts/_lib/legacy_boundary_map.ts +228 -0
  288. package/src/scripts/_lib/lexical_shortlist.ts +215 -0
  289. package/src/scripts/_lib/llm_candidate_proposer.ts +461 -0
  290. package/src/scripts/_lib/llm_proposer_transport.ts +153 -0
  291. package/src/scripts/_lib/loop_guards.ts +299 -0
  292. package/src/scripts/_lib/loss_class.ts +129 -0
  293. package/src/scripts/_lib/machine_wake.ts +51 -0
  294. package/src/scripts/_lib/md_prose_lines.ts +177 -0
  295. package/src/scripts/_lib/minimality_tiebreak.ts +168 -0
  296. package/src/scripts/_lib/one_resolver_invariant.ts +449 -0
  297. package/src/scripts/_lib/orchestration_record.ts +253 -5
  298. package/src/scripts/_lib/outcome_envelope.ts +227 -0
  299. package/src/scripts/_lib/outcome_vocabularies.ts +125 -0
  300. package/src/scripts/_lib/paired_stats.ts +245 -0
  301. package/src/scripts/_lib/paired_verdict.ts +226 -0
  302. package/src/scripts/_lib/pathology_archive.ts +393 -0
  303. package/src/scripts/_lib/prefix_stable_surfaces.ts +123 -0
  304. package/src/scripts/_lib/privacy_class.ts +47 -0
  305. package/src/scripts/_lib/promotion_capability.ts +315 -0
  306. package/src/scripts/_lib/promotion_evidence.ts +414 -0
  307. package/src/scripts/_lib/promotion_review.ts +294 -0
  308. package/src/scripts/_lib/prompt_shape.ts +92 -0
  309. package/src/scripts/_lib/regression_neighbourhood.ts +259 -0
  310. package/src/scripts/_lib/release_highlights.ts +70 -1
  311. package/src/scripts/_lib/release_material.ts +125 -2
  312. package/src/scripts/_lib/repeated_failure.ts +105 -0
  313. package/src/scripts/_lib/repo_root.ts +111 -0
  314. package/src/scripts/_lib/review_skipped_record.ts +37 -0
  315. package/src/scripts/_lib/role_split.ts +338 -0
  316. package/src/scripts/_lib/routing_corpus.ts +307 -0
  317. package/src/scripts/_lib/routing_index_input.ts +104 -0
  318. package/src/scripts/_lib/rule_injection.ts +22 -1
  319. package/src/scripts/_lib/runtime_journal.ts +1499 -0
  320. package/src/scripts/_lib/runtime_wiring_checks.ts +430 -0
  321. package/src/scripts/_lib/semantic_noop.ts +167 -0
  322. package/src/scripts/_lib/skill_catalogue.ts +11 -1
  323. package/src/scripts/_lib/source_digest.ts +200 -0
  324. package/src/scripts/_lib/source_redact.ts +260 -0
  325. package/src/scripts/_lib/source_shape.ts +502 -0
  326. package/src/scripts/_lib/source_snapshot_dedup.ts +199 -0
  327. package/src/scripts/_lib/strip_comments.d.mts +8 -0
  328. package/src/scripts/_lib/strip_comments.mjs +65 -0
  329. package/src/scripts/_lib/test_red_state.ts +154 -0
  330. package/src/scripts/_lib/trigger_shift.ts +144 -0
  331. package/src/scripts/_lib/untrusted_content.ts +82 -7
  332. package/src/scripts/activation_receipt.ts +258 -0
  333. package/src/scripts/adoption_report.ts +1 -1
  334. package/src/scripts/adr/evidence_census.ts +1 -1
  335. package/src/scripts/adr/regenerate_index.ts +26 -2
  336. package/src/scripts/adr_cite_check.ts +164 -1
  337. package/src/scripts/ai_council/blind_review.ts +11 -1
  338. package/src/scripts/ai_council/clients.ts +4 -0
  339. package/src/scripts/ai_council/config.ts +3 -0
  340. package/src/scripts/ai_council/consensus.ts +28 -8
  341. package/src/scripts/ai_council/consensus_round.ts +226 -0
  342. package/src/scripts/ai_council/cross_exam.ts +128 -0
  343. package/src/scripts/ai_council/disagreement_signal.ts +338 -0
  344. package/src/scripts/ai_council/explain_route.ts +157 -0
  345. package/src/scripts/ai_council/information_gain.ts +293 -0
  346. package/src/scripts/ai_council/inline_findings.ts +340 -0
  347. package/src/scripts/ai_council/judge_position_bias.ts +197 -0
  348. package/src/scripts/ai_council/leakage_corpus.ts +385 -0
  349. package/src/scripts/ai_council/leakage_patterns.ts +453 -0
  350. package/src/scripts/ai_council/minority_retention.ts +171 -0
  351. package/src/scripts/ai_council/orchestrator.ts +16 -203
  352. package/src/scripts/ai_council/orchestrator_results.ts +23 -3
  353. package/src/scripts/ai_council/pricing.ts +106 -0
  354. package/src/scripts/ai_council/prompts.ts +74 -7
  355. package/src/scripts/ai_council/provider_leakage_bench.ts +327 -0
  356. package/src/scripts/ai_council/py_format.ts +14 -3
  357. package/src/scripts/ai_council/recouncil_guard.ts +293 -0
  358. package/src/scripts/ai_council/recouncil_savings.ts +299 -0
  359. package/src/scripts/ai_council/replay_route.ts +223 -0
  360. package/src/scripts/ai_council/response_record.ts +50 -0
  361. package/src/scripts/ai_council/reviewer_assignment.ts +279 -0
  362. package/src/scripts/ai_council/routing_training_row.ts +197 -0
  363. package/src/scripts/ai_council/synthesis_strategy.ts +159 -0
  364. package/src/scripts/ai_council/topology_bench_manifest.ts +860 -0
  365. package/src/scripts/ai_council/topology_vocabulary.ts +175 -0
  366. package/src/scripts/asset_delivery_ledger.ts +157 -0
  367. package/src/scripts/attest_artifact.ts +193 -0
  368. package/src/scripts/audit_auto_rules.ts +2 -1
  369. package/src/scripts/audit_command_surface.ts +1 -1
  370. package/src/scripts/audit_mcp_tools.ts +2 -2
  371. package/src/scripts/audit_skill_overlap_allowlist.json +6 -1
  372. package/src/scripts/audit_user_type_axis.ts +2 -1
  373. package/src/scripts/bench_ab_clone.ts +215 -10
  374. package/src/scripts/bench_ab_integrity.ts +119 -5
  375. package/src/scripts/bench_ab_v2_stats.ts +40 -213
  376. package/src/scripts/build_archive_index.ts +1 -1
  377. package/src/scripts/build_linear_digest.ts +1 -1
  378. package/src/scripts/build_proof.ts +11 -4
  379. package/src/scripts/build_rule_trigger_matrix.ts +1 -1
  380. package/src/scripts/build_source_digests.ts +157 -0
  381. package/src/scripts/cache_realization_report.ts +103 -0
  382. package/src/scripts/check_adr_frontmatter.ts +131 -10
  383. package/src/scripts/check_benchmark_report_fields.ts +207 -0
  384. package/src/scripts/check_beta_review_markers.ts +235 -6
  385. package/src/scripts/check_bundle_path_leakage.ts +34 -1
  386. package/src/scripts/check_claims.ts +576 -6
  387. package/src/scripts/check_composite_arming.ts +35 -0
  388. package/src/scripts/check_concern_admissions.ts +365 -0
  389. package/src/scripts/check_enforcement_coverage.ts +28 -0
  390. package/src/scripts/check_estate_count.ts +347 -25
  391. package/src/scripts/check_gate_reachability.ts +383 -0
  392. package/src/scripts/check_host_loadability.ts +104 -0
  393. package/src/scripts/check_loss_class_declared.ts +308 -0
  394. package/src/scripts/check_md_language.ts +15 -98
  395. package/src/scripts/check_memory_proposal.ts +18 -11
  396. package/src/scripts/check_no_currency_in_cost_surfaces.ts +225 -0
  397. package/src/scripts/check_no_external_sources.ts +281 -6
  398. package/src/scripts/check_pack_conformance_fixture.ts +11 -1
  399. package/src/scripts/check_pack_size.ts +59 -2
  400. package/src/scripts/check_preamble_payload_budget.ts +114 -3
  401. package/src/scripts/check_prefix_stable_mutation.ts +372 -0
  402. package/src/scripts/check_publish_surface.ts +10 -1
  403. package/src/scripts/check_references.ts +24 -1
  404. package/src/scripts/check_release_highlights.ts +96 -13
  405. package/src/scripts/check_roadmap_trackable.ts +17 -2
  406. package/src/scripts/check_rule_evidence_declaration.ts +316 -0
  407. package/src/scripts/check_rule_projection_integrity.ts +14 -4
  408. package/src/scripts/check_score_contract.ts +26 -3
  409. package/src/scripts/check_static_parity.ts +285 -0
  410. package/src/scripts/check_supervision_claim_atomicity.ts +498 -0
  411. package/src/scripts/check_suppression_hygiene.ts +15 -0
  412. package/src/scripts/ci_settle.ts +39 -2
  413. package/src/scripts/code_graph/build.ts +60 -3
  414. package/src/scripts/code_graph/extract.ts +44 -0
  415. package/src/scripts/code_graph/types.ts +24 -0
  416. package/src/scripts/collector_daemon.ts +714 -0
  417. package/src/scripts/config_cost_report.ts +302 -0
  418. package/src/scripts/consumer_matrix.ts +74 -1
  419. package/src/scripts/corpus_manifest.ts +235 -0
  420. package/src/scripts/cost/budget.mjs +10 -3
  421. package/src/scripts/cost/track.mjs +10 -3
  422. package/src/scripts/council_cli.ts +37 -54
  423. package/src/scripts/dispatch_r2_reviewer.ts +46 -5
  424. package/src/scripts/evolution_lab.ts +1153 -0
  425. package/src/scripts/external_sources_denylist.json +5 -18
  426. package/src/scripts/extract_audit_patterns.ts +21 -0
  427. package/src/scripts/fold_intake.ts +12 -1
  428. package/src/scripts/gen_discovery_baseline.ts +1 -1
  429. package/src/scripts/generate_capabilities_index.ts +12 -5
  430. package/src/scripts/generate_capability_matrix.ts +3 -3
  431. package/src/scripts/generate_command_flows.ts +2 -2
  432. package/src/scripts/generate_cookbook.ts +2 -2
  433. package/src/scripts/generate_index.ts +8 -1
  434. package/src/scripts/generate_knowledge_index.ts +2 -1
  435. package/src/scripts/generate_ownership_matrix.ts +2 -1
  436. package/src/scripts/generate_pack_manifests.ts +10 -2
  437. package/src/scripts/generate_role_experiences_catalog.ts +2 -2
  438. package/src/scripts/generate_settings_reference.ts +1 -1
  439. package/src/scripts/git_authorization_hook.ts +22 -1
  440. package/src/scripts/grade_target_readiness.ts +48 -5
  441. package/src/scripts/hook_effect_doctor.ts +261 -0
  442. package/src/scripts/hook_manifest.json +1 -1
  443. package/src/scripts/hook_manifest.yaml +125 -16
  444. package/src/scripts/hooks/block_speaking_inbox_dir.ts +271 -0
  445. package/src/scripts/hooks/block_unauthorized_git.ts +18 -0
  446. package/src/scripts/hooks/comment_discipline_hook.ts +146 -0
  447. package/src/scripts/hooks/concern_registry.ts +6 -0
  448. package/src/scripts/hooks/dispatch_hook.ts +32 -0
  449. package/src/scripts/hooks/journal_record_hook.ts +345 -0
  450. package/src/scripts/hooks/prepush_metadata_sources.sh +110 -0
  451. package/src/scripts/hooks/run_continuation_hook.ts +44 -9
  452. package/src/scripts/hooks/shims/install.sh +61 -0
  453. package/src/scripts/hooks/shims/php +101 -0
  454. package/src/scripts/hooks/suggestion_capture_hook.ts +10 -0
  455. package/src/scripts/hooks/turn_end_gate_hook.ts +9 -1
  456. package/src/scripts/hot_context_hook.ts +16 -0
  457. package/src/scripts/install-hooks.sh +20 -5
  458. package/src/scripts/install.ts +17 -35
  459. package/src/scripts/inventory_frontmatter.ts +2 -1
  460. package/src/scripts/language_mirror_hook.ts +14 -2
  461. package/src/scripts/lint_adr_sweep_routing.ts +12 -0
  462. package/src/scripts/lint_canonical_terms.ts +604 -0
  463. package/src/scripts/lint_carrier_integrity.ts +820 -0
  464. package/src/scripts/lint_code_comments.ts +643 -0
  465. package/src/scripts/lint_composition_review.ts +619 -0
  466. package/src/scripts/lint_consolidation_lineage.ts +666 -0
  467. package/src/scripts/lint_eval_specs.ts +593 -0
  468. package/src/scripts/lint_hook_manifest.ts +19 -0
  469. package/src/scripts/lint_host_portability.ts +373 -0
  470. package/src/scripts/lint_judge_prompt_expectation.ts +27 -1
  471. package/src/scripts/lint_memory_twin_parity.ts +335 -0
  472. package/src/scripts/lint_metric_consumers.ts +355 -0
  473. package/src/scripts/lint_plan_risk_register.ts +39 -19
  474. package/src/scripts/lint_promotion_paths.ts +779 -0
  475. package/src/scripts/lint_skill_descriptions.ts +18 -1
  476. package/src/scripts/lint_skill_frontmatter_safety.ts +58 -0
  477. package/src/scripts/lint_skill_link_reach.ts +252 -0
  478. package/src/scripts/lint_skill_trigger_corpus.ts +426 -23
  479. package/src/scripts/lint_ticket_buildable.ts +17 -1
  480. package/src/scripts/llm_propose.ts +256 -0
  481. package/src/scripts/mcp_server/consumer_tool_catalog.json +1 -1
  482. package/src/scripts/mcp_server/tool_catalog_source.ts +1 -1
  483. package/src/scripts/measure_delivery_sets.ts +361 -0
  484. package/src/scripts/measure_docs_dead_links.ts +348 -0
  485. package/src/scripts/measure_host_capture.ts +461 -0
  486. package/src/scripts/measure_routing_signal.ts +307 -0
  487. package/src/scripts/migration_status.ts +3 -3
  488. package/src/scripts/model_rule_injection.ts +76 -0
  489. package/src/scripts/orchestration_record.ts +14 -0
  490. package/src/scripts/preamble_byte_census.ts +139 -10
  491. package/src/scripts/prepack-check.mjs +4 -1
  492. package/src/scripts/probe_council_retention.ts +495 -0
  493. package/src/scripts/probe_turnaround.ts +384 -0
  494. package/src/scripts/probe_unblocked_ask.ts +279 -0
  495. package/src/scripts/release.ts +21 -37
  496. package/src/scripts/release_drill.ts +143 -0
  497. package/src/scripts/release_env.ts +35 -0
  498. package/src/scripts/release_publication.ts +84 -0
  499. package/src/scripts/render_benchmark_md.ts +1 -1
  500. package/src/scripts/rule_activation_census.ts +70 -9
  501. package/src/scripts/rule_backlinks.ts +1 -1
  502. package/src/scripts/run_lifecycle_suite.ts +208 -0
  503. package/src/scripts/run_skill_evals.ts +40 -0
  504. package/src/scripts/schemas/delivery-manifest.schema.json +43 -0
  505. package/src/scripts/schemas/drafting-channels.schema.json +43 -0
  506. package/src/scripts/schemas/evals.schema.json +24 -1
  507. package/src/scripts/schemas/rule.schema.json +52 -1
  508. package/src/scripts/schemas/skill.schema.json +17 -2
  509. package/src/scripts/skill_overlap.ts +7 -1
  510. package/src/scripts/skill_tools/run_block_d_eval.ts +8 -1
  511. package/src/scripts/skill_tools/score_skill_relevance.ts +84 -3
  512. package/src/scripts/skill_tools/suggest_skill_for_task.ts +8 -1
  513. package/src/scripts/skill_usage_report.ts +2 -1
  514. package/src/scripts/stubs_due.ts +211 -0
  515. package/src/scripts/sweep_source_surfaces.ts +678 -0
  516. package/src/scripts/sync_pr_branch.ts +3 -3
  517. package/src/scripts/trigger_eval_grandfather.json +202 -222
  518. package/src/scripts/utilization_report.ts +22 -2
  519. package/src/server/schemas/settings.ts +5 -0
  520. package/src/templates/marketing-copy.yml +1 -1
  521. package/dist/ui/assets/index-Cxgy63kz.js +0 -26
@@ -0,0 +1,430 @@
1
+ /**
2
+ * Runtime-wiring checks for `agent-config doctor`.
3
+ *
4
+ * `road-to-skill-ecosystem-runtime-enforcement` Phase 2, Steps 2-5. The gate
5
+ * estate checks ARTIFACTS — is the rule written, is the projection byte-exact,
6
+ * does the manifest parse. Nothing checked whether the wiring is LIVE: whether
7
+ * the settings resolver returns anything, whether the router artifact parses,
8
+ * whether each registered hook resolves to something executable, and whether an
9
+ * inherited git-discovery variable is silently re-pointing every gate at another
10
+ * repository.
11
+ *
12
+ * All four are REPORTS. `doctor` writes nothing and always exits zero, so a
13
+ * check here returns a verdict and never a refusal — the point is that a
14
+ * disabled or mis-wired estate becomes VISIBLE, not that a diagnostic starts
15
+ * failing builds. A gate that wanted to refuse would belong in the gate estate.
16
+ *
17
+ * Extracted into `_lib/` rather than added to `cmd_doctor.ts` for a stated
18
+ * reason: that file is 3,700 lines and `check_source_size_budget` counts every
19
+ * line above 1,500, so four checks written inline would be charged against a
20
+ * budget while the same code in a new module is free. The seam is also what
21
+ * makes them unit-testable without booting the CLI.
22
+ */
23
+ import { spawnSync } from 'node:child_process';
24
+ import * as fs from 'node:fs';
25
+ import * as path from 'node:path';
26
+ import process from 'node:process';
27
+
28
+ import { parse as parseYaml } from 'yaml';
29
+
30
+ import { inheritedGitOverrides } from './repo_root.js';
31
+
32
+ /** The verdict shape `cmd_doctor` renders. Mirrors its internal `Dict` rows. */
33
+ export interface WiringCheck {
34
+ id: string;
35
+ /**
36
+ * The four the doctor's own report contract publishes. `info` was a fifth
37
+ * here for one commit and is gone: the MCP `doctor_report` tool asserts the
38
+ * published union, so a fifth value that never reached that contract failed
39
+ * the tool's shape test rather than appearing in a report. A vocabulary a
40
+ * consumer cannot receive is not a vocabulary.
41
+ */
42
+ status: 'ok' | 'warn' | 'fail' | 'skipped';
43
+ message: string;
44
+ remedy: string;
45
+ }
46
+
47
+ /**
48
+ * Step 2 — the settings resolver returns something, and WHICH FILE won.
49
+ *
50
+ * The cascade is user-global then project, last write winning. Nearly twenty
51
+ * rules in this suite tell an agent to read `.agent-settings.yml` to learn
52
+ * whether a feature is on, and every one of them is wrong about a key set on
53
+ * another layer. Reporting the winning FILE per key is the part that makes the
54
+ * check worth running — a value alone cannot be argued with.
55
+ */
56
+ export function checkSettingsResolution(
57
+ iterOverrides: () => Iterable<[string, unknown, string]>,
58
+ ): WiringCheck {
59
+ let pairs: [string, unknown, string][];
60
+ try {
61
+ pairs = [...iterOverrides()];
62
+ } catch (e) {
63
+ return {
64
+ id: 'settings-resolution',
65
+ status: 'fail',
66
+ message: `settings cascade did not resolve: ${e instanceof Error ? e.message : String(e)}`,
67
+ remedy: 'check the YAML in every layer `agent-config settings:get <key>` reports',
68
+ };
69
+ }
70
+ if (pairs.length === 0) {
71
+ return {
72
+ id: 'settings-resolution',
73
+ // `skipped`, not `ok`: the cascade RESOLVED and there was nothing
74
+ // in it, which is a check that had nothing to inspect rather than a
75
+ // check that passed. Reporting `ok` here would read as "settings
76
+ // resolved fine" on a tree where no setting exists at all — the
77
+ // same conflation the reach check exists to remove elsewhere.
78
+ status: 'skipped',
79
+ message:
80
+ 'settings cascade resolves, and NO layer sets any key — every read falls to the ' +
81
+ 'template default. That is a valid state, not a failure: a fresh project has no settings.',
82
+ remedy: '',
83
+ };
84
+ }
85
+ // Last writer wins, which is the resolver's own rule — so the winning file
86
+ // is the LAST occurrence of a key, not the first.
87
+ const winner = new Map<string, string>();
88
+ for (const [key, , file] of pairs) winner.set(key, file);
89
+ const byFile = new Map<string, number>();
90
+ for (const file of winner.values()) byFile.set(file, (byFile.get(file) ?? 0) + 1);
91
+ const summary = [...byFile.entries()]
92
+ .sort((a, b) => b[1] - a[1])
93
+ .map(([f, n]) => `${path.basename(f)}=${String(n)}`)
94
+ .join(' · ');
95
+ return {
96
+ id: 'settings-resolution',
97
+ status: 'ok',
98
+ message: `${String(winner.size)} key(s) resolved across ${String(byFile.size)} layer(s) — ${summary}`,
99
+ remedy: '',
100
+ };
101
+ }
102
+
103
+ /**
104
+ * Step 3 — the router artifact exists, PARSES, and reports its rule count.
105
+ *
106
+ * Parsing is the half that matters. A router file that exists but does not parse
107
+ * fails silently at load: the host reads no rules and behaves like a tree with
108
+ * none, which is indistinguishable from a correctly minimal configuration.
109
+ */
110
+ export function checkRouterArtifact(repoRoot: string, rel = 'dist/router.json'): WiringCheck {
111
+ const abs = path.join(repoRoot, rel);
112
+ if (!fs.existsSync(abs)) {
113
+ return {
114
+ id: 'router-artifact',
115
+ status: 'warn',
116
+ message: `${rel} is absent — no rule router is deployed`,
117
+ remedy: 'task generate-tools',
118
+ };
119
+ }
120
+ let doc: unknown;
121
+ try {
122
+ doc = JSON.parse(fs.readFileSync(abs, 'utf8'));
123
+ } catch (e) {
124
+ return {
125
+ id: 'router-artifact',
126
+ status: 'fail',
127
+ message: `${rel} exists but does NOT parse: ${e instanceof Error ? e.message : String(e)}`,
128
+ remedy: 'task generate-tools (a present-but-unparseable router loads as zero rules)',
129
+ };
130
+ }
131
+ const rules = _routerRuleCount(doc);
132
+ if (rules === 0) {
133
+ return {
134
+ id: 'router-artifact',
135
+ status: 'warn',
136
+ message: `${rel} parses and carries ZERO rules — a router with no rules routes nothing`,
137
+ remedy: 'task generate-tools',
138
+ };
139
+ }
140
+ return { id: 'router-artifact', status: 'ok', message: `${rel} parses · ${String(rules)} rule(s)`, remedy: '' };
141
+ }
142
+
143
+ /** Count routed rules across whichever shape the artifact uses. */
144
+ export function _routerRuleCount(doc: unknown): number {
145
+ if (doc === null || typeof doc !== 'object') return 0;
146
+ const d = doc as Record<string, unknown>;
147
+ if (Array.isArray(d['rules'])) return d['rules'].length;
148
+ let n = 0;
149
+ for (const v of Object.values(d)) {
150
+ if (Array.isArray(v)) n += v.length;
151
+ else if (v !== null && typeof v === 'object') n += _routerRuleCount(v);
152
+ }
153
+ return n;
154
+ }
155
+
156
+ export interface HookProbe {
157
+ id: string;
158
+ script: string;
159
+ resolves: boolean;
160
+ ms: number | null;
161
+ }
162
+
163
+ /**
164
+ * Step 4 — every registered hook resolves to a real file, with its cost.
165
+ *
166
+ * Cost is reported PER HOOK rather than as a total, because a latency
167
+ * regression is only actionable where it is incurred: a 300 ms total tells you
168
+ * nothing, while one 280 ms concern names itself.
169
+ *
170
+ * `probe` defaults to a real invocation with `--help`, which every dispatcher
171
+ * entry point accepts and which does no work. Injectable so the unit tests do
172
+ * not spawn 53 processes.
173
+ */
174
+ export function checkHookResolution(
175
+ repoRoot: string,
176
+ manifestRel = 'src/scripts/hook_manifest.yaml',
177
+ probe: ((script: string) => number | null) | null = null,
178
+ ): { check: WiringCheck; probes: HookProbe[] } {
179
+ const abs = path.join(repoRoot, manifestRel);
180
+ if (!fs.existsSync(abs)) {
181
+ return {
182
+ check: {
183
+ id: 'hook-resolution',
184
+ status: 'fail',
185
+ message: `${manifestRel} is absent — the hook estate cannot be enumerated`,
186
+ remedy: 'restore the manifest; every hook is registered from it',
187
+ },
188
+ probes: [],
189
+ };
190
+ }
191
+ let concerns: Record<string, { script?: unknown }>;
192
+ try {
193
+ const doc = parseYaml(fs.readFileSync(abs, 'utf8')) as { concerns?: unknown };
194
+ concerns = (doc.concerns ?? {}) as Record<string, { script?: unknown }>;
195
+ } catch (e) {
196
+ return {
197
+ check: {
198
+ id: 'hook-resolution',
199
+ status: 'fail',
200
+ message: `${manifestRel} does not parse: ${e instanceof Error ? e.message : String(e)}`,
201
+ remedy: 'fix the manifest YAML',
202
+ },
203
+ probes: [],
204
+ };
205
+ }
206
+ const probes: HookProbe[] = [];
207
+ for (const [id, c] of Object.entries(concerns)) {
208
+ const script = typeof c.script === 'string' ? c.script : '';
209
+ const resolves = script !== '' && fs.existsSync(path.join(repoRoot, script));
210
+ probes.push({ id, script, resolves, ms: resolves && probe !== null ? probe(script) : null });
211
+ }
212
+ const broken = probes.filter((p) => !p.resolves);
213
+ if (broken.length > 0) {
214
+ return {
215
+ check: {
216
+ id: 'hook-resolution',
217
+ status: 'fail',
218
+ message:
219
+ `${String(broken.length)} of ${String(probes.length)} registered hook(s) do NOT resolve to a file: ` +
220
+ broken.map((b) => b.id).join(', '),
221
+ remedy: 'a registered hook with no script silently no-ops every session — fix the path or drop the entry',
222
+ },
223
+ probes,
224
+ };
225
+ }
226
+ const timed = probes.filter((p) => p.ms !== null).sort((a, b) => (b.ms ?? 0) - (a.ms ?? 0));
227
+ const slowest = timed.length > 0 ? ` · slowest ${timed[0]!.id} ${String(timed[0]!.ms)}ms` : '';
228
+ return {
229
+ check: {
230
+ id: 'hook-resolution',
231
+ status: 'ok',
232
+ message: `${String(probes.length)} registered hook(s), all resolving${slowest}`,
233
+ remedy: '',
234
+ },
235
+ probes,
236
+ };
237
+ }
238
+
239
+ /** A real `--help` invocation, timed. `null` when it cannot be measured. */
240
+ export function probeHookCost(repoRoot: string, script: string): number | null {
241
+ const started = Date.now();
242
+ const r = spawnSync(process.execPath, [path.join(repoRoot, 'scripts-run'), script, '--help'], {
243
+ cwd: repoRoot,
244
+ encoding: 'utf8',
245
+ timeout: 10_000,
246
+ });
247
+ if (r.error) return null;
248
+ return Date.now() - started;
249
+ }
250
+
251
+ /**
252
+ * Step 5 — an inherited git-discovery variable.
253
+ *
254
+ * The recorded failure: a git hook exports `GIT_DIR` into every child, so a gate
255
+ * run inside one resolves against whatever that points at — inside a worktree,
256
+ * the parent checkout. The gate runs, reads the wrong tree, and PASSES. Nothing
257
+ * about the output says which repository answered.
258
+ *
259
+ * Reported as a warning rather than a failure because the variable is legitimate
260
+ * where git itself set it; what it is not is invisible.
261
+ */
262
+ export function checkInheritedGitEnv(env: NodeJS.ProcessEnv = process.env): WiringCheck {
263
+ const found = inheritedGitOverrides(env);
264
+ if (found.length === 0) {
265
+ return {
266
+ id: 'inherited-git-env',
267
+ status: 'ok',
268
+ message: 'no git discovery override in the environment — git resolves from the working directory',
269
+ remedy: '',
270
+ };
271
+ }
272
+ return {
273
+ id: 'inherited-git-env',
274
+ status: 'warn',
275
+ message:
276
+ `${String(found.length)} git discovery override(s) inherited: ` +
277
+ found.map((f) => `${f.name}=${f.value}`).join(' · ') +
278
+ ' — every git call in this process answers for THAT repository, not the working directory',
279
+ remedy:
280
+ 'unset them before running a gate from inside a git hook (`env -u GIT_DIR -u GIT_WORK_TREE …`), ' +
281
+ 'or resolve the root with _lib/repo_root.ts, which refuses instead of guessing',
282
+ };
283
+ }
284
+
285
+ /**
286
+ * The four runtime-wiring runners, as one table.
287
+ *
288
+ * Returned as a map rather than registered inline at each of `cmd_doctor`'s TWO
289
+ * runner tables: written there it is ~20 lines duplicated, and every line of
290
+ * that file above 1,500 is charged by `check_source_size_budget`. One factory,
291
+ * two spreads.
292
+ */
293
+ /** The four ids, in render order. Spread into `cmd_doctor`'s two id registries. */
294
+ export const WIRING_CHECK_IDS = ['settings-resolution', 'router-artifact', 'hook-resolution', 'inherited-git-env', 'hooks-kill-switch'] as const;
295
+
296
+
297
+ /**
298
+ * The estate kill switch, reported so a DISABLED estate is visible.
299
+ *
300
+ * `road-to-skill-ecosystem-runtime-enforcement` Phase 1 Step 7's second clause,
301
+ * which could not be satisfied until the Phase 2 diagnostic existed. The flag
302
+ * itself has been implemented since Phase 1; what was missing is that a session
303
+ * running with every guard switched off looked exactly like one running with
304
+ * them all armed.
305
+ *
306
+ * ONLY the exact value `1` disarms, and the check mirrors that rather than
307
+ * guessing: a truthy-ish test would report `=0` as disabled, which is the
308
+ * opposite of what it means.
309
+ */
310
+ export function checkHooksDisabled(env: NodeJS.ProcessEnv = process.env): WiringCheck {
311
+ const raw = env['AGENT_CONFIG_DISABLE_HOOKS'];
312
+ if (raw !== '1') {
313
+ return {
314
+ id: 'hooks-kill-switch',
315
+ status: 'ok',
316
+ message:
317
+ raw === undefined || raw === ''
318
+ ? 'AGENT_CONFIG_DISABLE_HOOKS is not set — the hook estate is armed'
319
+ : `AGENT_CONFIG_DISABLE_HOOKS=${raw} — only the exact value "1" disarms, so the estate is armed`,
320
+ remedy: '',
321
+ };
322
+ }
323
+ return {
324
+ id: 'hooks-kill-switch',
325
+ status: 'warn',
326
+ message:
327
+ 'AGENT_CONFIG_DISABLE_HOOKS=1 — EVERY hook and shim in this environment is disabled. ' +
328
+ 'A run under this flag enforces nothing, and without this line it would look identical ' +
329
+ 'to one with the whole estate armed.',
330
+ remedy: 'unset AGENT_CONFIG_DISABLE_HOOKS (it is intended for one command, not a session)',
331
+ };
332
+ }
333
+
334
+ export function wiringRunners(opts: {
335
+ packageRoot: string;
336
+ iterOverrides: () => Iterable<[string, unknown, string]>;
337
+ }): Record<string, () => WiringCheck> {
338
+ return {
339
+ 'settings-resolution': () => checkSettingsResolution(opts.iterOverrides),
340
+ 'router-artifact': () => checkRouterArtifact(opts.packageRoot),
341
+ // Per-hook COST is not probed on the default path: it spawns one process
342
+ // per registered concern (53 today), turning a read-only diagnostic into
343
+ // a multi-second one. `probeHookCost` is exported for a caller that wants it.
344
+ 'hook-resolution': () => checkHookResolution(opts.packageRoot).check,
345
+ 'inherited-git-env': () => checkInheritedGitEnv(),
346
+ 'hooks-kill-switch': () => checkHooksDisabled(),
347
+ };
348
+ }
349
+
350
+ /**
351
+ * Managed hook wiring (single-surface model): the deterministic hook matrix
352
+ * must be registered in ~/.claude/settings.json AND the dispatch target
353
+ * (`agent-config` binary) must resolve on PATH. Both halves are required —
354
+ * hooks without a binary silently no-op every session.
355
+ */
356
+ export interface HookWiringDeps {
357
+ which: (bin: string) => string | null;
358
+ packageRoot: string;
359
+ homeDir: string;
360
+ buildMatrix: (manifestPath: string) => Record<string, unknown>;
361
+ managedSignature: string;
362
+ pluginInstalled: () => boolean;
363
+ }
364
+
365
+ export function checkHookWiring(deps: HookWiringDeps): WiringCheck {
366
+ const claude = deps.which('claude');
367
+ if (claude === null) {
368
+ return {
369
+ id: 'hook-wiring',
370
+ status: 'skipped',
371
+ message: 'Claude Code CLI not on PATH — hook-wiring check not applicable',
372
+ remedy: '',
373
+ };
374
+ }
375
+ const settings_path = path.join(deps.homeDir, '.claude', 'settings.json');
376
+ let missing: string[];
377
+ try {
378
+ const matrix = deps.buildMatrix(path.join(deps.packageRoot, 'src', 'scripts', 'hook_manifest.yaml'));
379
+ const settings = fs.existsSync(settings_path)
380
+ ? (JSON.parse(fs.readFileSync(settings_path, 'utf8')) as Record<string, unknown>)
381
+ : {};
382
+ const hooks = ((settings['hooks'] ?? {}) as Record<string, unknown>) || {};
383
+ missing = Object.keys(matrix).filter((ev) => {
384
+ const groups = hooks[ev];
385
+ if (!Array.isArray(groups)) return true;
386
+ return !JSON.stringify(groups).includes(deps.managedSignature);
387
+ });
388
+ } catch (e) {
389
+ return {
390
+ id: 'hook-wiring',
391
+ status: 'fail',
392
+ message: `cannot evaluate managed hooks: ${String(e)}`,
393
+ remedy: 'fix ~/.claude/settings.json (invalid JSON?), then agent-config refresh --global',
394
+ };
395
+ }
396
+ const binary_ok = deps.which('agent-config') !== null;
397
+ if (missing.length === 0 && binary_ok) {
398
+ return {
399
+ id: 'hook-wiring',
400
+ status: 'ok',
401
+ message: 'managed hooks registered in ~/.claude/settings.json; dispatch binary on PATH',
402
+ remedy: '',
403
+ };
404
+ }
405
+ if (missing.length > 0 && deps.pluginInstalled()) {
406
+ return {
407
+ id: 'hook-wiring',
408
+ status: 'warn',
409
+ message:
410
+ `managed hooks missing for: ${missing.join(', ')} — currently carried by the ` +
411
+ 'installed plugin (deprecated surface)',
412
+ remedy: 'agent-config refresh --global (writes the managed settings.json block)',
413
+ };
414
+ }
415
+ const parts: string[] = [];
416
+ if (missing.length > 0) parts.push(`managed hooks missing for: ${missing.join(', ')}`);
417
+ if (!binary_ok) parts.push('`agent-config` not on PATH (hooks would silently no-op)');
418
+ if (parts.length === 0) {
419
+ // hooks complete, binary missing was the only issue → covered above.
420
+ parts.push('`agent-config` not on PATH');
421
+ }
422
+ return {
423
+ id: 'hook-wiring',
424
+ status: 'fail',
425
+ message: parts.join('; '),
426
+ remedy: binary_ok
427
+ ? 'agent-config refresh --global'
428
+ : 'npm install -g @event4u/agent-config, then agent-config refresh --global',
429
+ };
430
+ }
@@ -0,0 +1,167 @@
1
+ /**
2
+ * The semantic no-op gate — `road-to-harness-promotion-bridge` step 7.4.
3
+ *
4
+ * > *Reject semantic no-ops. A no-op detector plus a minimum
5
+ * > material-improvement threshold. The master kept the cooldown and lineage
6
+ * > from the same attack and dropped both gates.*
7
+ * > verify: **a paraphrase-only candidate is refused before the cascade.**
8
+ *
9
+ * ## "Before the cascade" — what that resolves to in this tree
10
+ *
11
+ * There is no artefact named "cascade" here; the evaluation cascade is the
12
+ * lifecycle spine, `proposed -> diagnostic-evaluated -> selection-evaluated ->
13
+ * …`. So "before the cascade" means: while the candidate is still `proposed`,
14
+ * before the first transition and before anything expensive runs.
15
+ * {@link screenSemanticNoOps} is that stage, and it is SYNCHRONOUS for the same
16
+ * reason `screenNearDuplicates` is — a synchronous function cannot await a
17
+ * network call, so the zero-model-call property follows from the signature
18
+ * rather than from a promise the body has to keep.
19
+ *
20
+ * ## Two gates, because the step asks for two
21
+ *
22
+ * 1. **The no-op detector.** {@link isSemanticNoOp} — a candidate whose text is
23
+ * a paraphrase of what it replaces. Measured with `shingleOverlap`, the same
24
+ * primitive `curator_ops`'s near-duplicate screen and `lint_originality` use.
25
+ * 2. **The minimum material-improvement threshold.** A candidate that is not a
26
+ * paraphrase can still be a rounding error;
27
+ * {@link MIN_MATERIAL_IMPROVEMENT_PERCENT} is the floor its measured delta
28
+ * must clear.
29
+ *
30
+ * Both are needed and neither implies the other: a total rewrite that changes
31
+ * nothing measurable passes (1) and fails (2); a one-word change with a large
32
+ * measured delta passes (2) and fails (1). Shipping one of the two is what the
33
+ * master did.
34
+ */
35
+ import { NEAR_DUPLICATE_THRESHOLD } from './curator_ops.js';
36
+ import { shingleOverlap } from './shingle_similarity.js';
37
+
38
+ /**
39
+ * Containment-overlap percent at which a candidate is a paraphrase of what it
40
+ * replaces.
41
+ *
42
+ * **Measured bound, stated rather than left for a reader to discover.**
43
+ * `shingleOverlap` uses 8-word shingles, so ONE substitution breaks eight
44
+ * shingles. On a one-sentence candidate (~10 shingles) that is already a
45
+ * 45-point drop and no paraphrase can reach 70 %; on rule-body-sized text
46
+ * (~60 words, 56 shingles) the same edit measures 85.7 %. The detector is
47
+ * therefore meaningful for the corpus it will see — rule and skill bodies — and
48
+ * weak for one-liners. `revisit-if` candidates turn out to be short.
49
+ *
50
+ * Pinned EQUAL to {@link NEAR_DUPLICATE_THRESHOLD} rather than given its own
51
+ * number, and the equality is the argument: both questions are "is this text
52
+ * substantially the text we already have", measured on the same primitive, and
53
+ * two independently-tuned constants for one question is how they drift. If one
54
+ * moves, the reason has to cover both.
55
+ */
56
+ export const PARAPHRASE_OVERLAP_THRESHOLD = NEAR_DUPLICATE_THRESHOLD;
57
+
58
+ /**
59
+ * The smallest measured improvement that counts as material, in percentage
60
+ * points.
61
+ *
62
+ * A STATED default, not a measured optimum — the honest label this repository
63
+ * uses for a number nobody has derived. `revisit-if` a real promotion is refused
64
+ * for a delta a human calls material, or admitted for one a human calls noise.
65
+ * It is deliberately small: the gate exists to reject ZERO, not to set a bar for
66
+ * ambition.
67
+ */
68
+ export const MIN_MATERIAL_IMPROVEMENT_PERCENT = 1;
69
+
70
+ export interface NoOpVerdict {
71
+ readonly isNoOp: boolean;
72
+ /** Why, in one clause. Empty when it is not a no-op. */
73
+ readonly reason: string;
74
+ readonly overlapPercent: number;
75
+ /** Literal 0. This stage is deterministic; a model call here would be a defect. */
76
+ readonly modelCalls: 0;
77
+ }
78
+
79
+ /**
80
+ * Is this candidate a semantic no-op against the text it replaces?
81
+ *
82
+ * Two ways to be one, and the second is the one a paraphrase detector alone
83
+ * misses: the text barely moved, or the text moved and the measured effect did
84
+ * not.
85
+ */
86
+ export function isSemanticNoOp(
87
+ baselineText: string,
88
+ candidateText: string,
89
+ deltaPercent: number,
90
+ overlapThreshold: number = PARAPHRASE_OVERLAP_THRESHOLD,
91
+ minDelta: number = MIN_MATERIAL_IMPROVEMENT_PERCENT,
92
+ ): NoOpVerdict {
93
+ const overlapPercent = shingleOverlap(baselineText, candidateText);
94
+ if (overlapPercent >= overlapThreshold) {
95
+ return {
96
+ isNoOp: true,
97
+ reason:
98
+ `paraphrase-only: ${String(overlapPercent)}% shingle overlap with the text it replaces ` +
99
+ `(threshold ${String(overlapThreshold)}%)`,
100
+ overlapPercent,
101
+ modelCalls: 0,
102
+ };
103
+ }
104
+ if (deltaPercent < minDelta) {
105
+ return {
106
+ isNoOp: true,
107
+ reason:
108
+ `no material improvement: measured delta ${String(deltaPercent)} pp is below the ` +
109
+ `${String(minDelta)} pp floor`,
110
+ overlapPercent,
111
+ modelCalls: 0,
112
+ };
113
+ }
114
+ return { isNoOp: false, reason: '', overlapPercent, modelCalls: 0 };
115
+ }
116
+
117
+ export class SemanticNoOpError extends Error {
118
+ readonly candidateId: string;
119
+ constructor(candidateId: string, reason: string) {
120
+ super(
121
+ `candidate '${candidateId}' is a semantic no-op and is refused before the cascade: ${reason}. ` +
122
+ 'Evaluating it would spend trials to measure nothing, and promoting it would grow the ' +
123
+ 'estate by an artefact that says what the estate already says.',
124
+ );
125
+ this.name = 'SemanticNoOpError';
126
+ this.candidateId = candidateId;
127
+ }
128
+ }
129
+
130
+ /** @throws {SemanticNoOpError} when the candidate is a no-op. */
131
+ export function assertNotSemanticNoOp(candidateId: string, verdict: NoOpVerdict): void {
132
+ if (verdict.isNoOp) {
133
+ throw new SemanticNoOpError(candidateId, verdict.reason);
134
+ }
135
+ }
136
+
137
+ export interface NoOpScreenInput {
138
+ readonly id: string;
139
+ readonly baselineText: string;
140
+ readonly candidateText: string;
141
+ readonly deltaPercent: number;
142
+ }
143
+
144
+ export interface NoOpScreenResult {
145
+ readonly admitted: readonly string[];
146
+ readonly refused: readonly { readonly id: string; readonly reason: string }[];
147
+ /** Literal 0 — the whole point of a pre-stage is that it is cheaper than what follows. */
148
+ readonly modelCalls: 0;
149
+ }
150
+
151
+ /**
152
+ * The pre-stage: refuse no-ops while every candidate is still `proposed`.
153
+ *
154
+ * Synchronous, and it takes TEXT rather than records on purpose — it must be
155
+ * callable before a candidate has any evaluation results attached, which is the
156
+ * whole meaning of "before the cascade".
157
+ */
158
+ export function screenSemanticNoOps(candidates: readonly NoOpScreenInput[]): NoOpScreenResult {
159
+ const admitted: string[] = [];
160
+ const refused: { id: string; reason: string }[] = [];
161
+ for (const c of candidates) {
162
+ const verdict = isSemanticNoOp(c.baselineText, c.candidateText, c.deltaPercent);
163
+ if (verdict.isNoOp) refused.push({ id: c.id, reason: verdict.reason });
164
+ else admitted.push(c.id);
165
+ }
166
+ return { admitted, refused, modelCalls: 0 };
167
+ }
@@ -93,7 +93,17 @@ export function resolveSkillsRoot(workspaceRoot: string): string | null {
93
93
  for (const candidate of DEFAULT_CATALOGUE_ROOTS) {
94
94
  const abs = path.join(workspaceRoot, candidate);
95
95
  try {
96
- if (fs.existsSync(abs) && fs.statSync(abs).isDirectory()) return abs;
96
+ if (!fs.existsSync(abs) || !fs.statSync(abs).isDirectory()) continue;
97
+ // NON-EMPTY, and that qualifier is the whole fix. `.claude/skills`
98
+ // is a gitignored projection, so in a fresh worktree it EXISTS and
99
+ // holds nothing — and an empty root resolved as a match makes the
100
+ // ranker report an empty catalogue as an empty RESULT, which is the
101
+ // silent failure `road-to-inbox-harvest-2026-08-f-skill-selection-evidence`
102
+ // is about, arriving through a second door. Measured in that run: a
103
+ // worktree that had never run `generate-tools` ranked zero skills
104
+ // and exited 0 on a task that scores 47 against `src/skills`.
105
+ if (fs.readdirSync(abs).length === 0) continue;
106
+ return abs;
97
107
  } catch {
98
108
  // Unreadable candidate is not a match; try the next.
99
109
  }