@event4u/agent-config 14.12.0 → 14.13.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 (466) 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 +234 -0
  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 +109 -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-provenance.md +4 -0
  30. package/dist/agent-src/rules/design-fidelity.md +1 -1
  31. package/dist/agent-src/rules/domain-safety-pii.md +4 -0
  32. package/dist/agent-src/rules/domain-safety-retention.md +4 -0
  33. package/dist/agent-src/rules/engineering-safety-floor.md +2 -0
  34. package/dist/agent-src/rules/external-code-graph-interop.md +14 -12
  35. package/dist/agent-src/rules/improve-before-implement.md +6 -8
  36. package/dist/agent-src/rules/laravel-routing.md +1 -1
  37. package/dist/agent-src/rules/lethal-trifecta-guard.md +4 -0
  38. package/dist/agent-src/rules/secret-vcs-guard.md +2 -0
  39. package/dist/agent-src/rules/security-sensitive-stop.md +2 -0
  40. package/dist/agent-src/rules/source-confidentiality.md +12 -34
  41. package/dist/agent-src/rules/symfony-routing.md +1 -1
  42. package/dist/agent-src/rules/token-efficiency.md +14 -0
  43. package/dist/agent-src/rules/tool-safety.md +4 -0
  44. package/dist/agent-src/rules/untrusted-input-defense.md +4 -0
  45. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +247 -3
  46. package/dist/agent-src/scripts/guarded_baseline.ts +328 -0
  47. package/dist/agent-src/scripts/roadmap_set_step.ts +253 -0
  48. package/dist/agent-src/scripts/stub_queue.ts +82 -0
  49. package/dist/agent-src/scripts/stubs_due.ts +400 -0
  50. package/dist/agent-src/scripts/ticket_bundles.ts +84 -0
  51. package/dist/agent-src/scripts/update_roadmap_progress.ts +8 -4
  52. package/dist/agent-src/skills/brand-asset-generation/SKILL.md +17 -4
  53. package/dist/agent-src/skills/brand-audit/SKILL.md +33 -0
  54. package/dist/agent-src/skills/code-intelligence/SKILL.md +57 -0
  55. package/dist/agent-src/skills/database/SKILL.md +8 -0
  56. package/dist/agent-src/skills/dependency-upgrade/SKILL.md +27 -0
  57. package/dist/agent-src/skills/design-review/SKILL.md +1 -1
  58. package/dist/agent-src/skills/doc-coauthoring/SKILL.md +1 -1
  59. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +17 -1
  60. package/dist/agent-src/skills/feature-planning/SKILL.md +9 -2
  61. package/dist/agent-src/skills/frontend-render-security/SKILL.md +44 -0
  62. package/dist/agent-src/skills/git-workflow/SKILL.md +1 -1
  63. package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.ts +38 -4
  64. package/dist/agent-src/skills/judge-artifact-completeness/rubrics/ticket-quality-score.json +2 -2
  65. package/dist/agent-src/skills/laravel/SKILL.md +35 -0
  66. package/dist/agent-src/skills/laravel-migration/SKILL.md +57 -3
  67. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +26 -0
  68. package/dist/agent-src/skills/playbook-authoring/SKILL.md +28 -1
  69. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +1 -1
  70. package/dist/agent-src/skills/skill-writing/references/procedure.md +5 -5
  71. package/dist/agent-src/skills/sql-writing/SKILL.md +7 -1
  72. package/dist/agent-src/skills/standards-from-config/SKILL.md +27 -4
  73. package/dist/agent-src/skills/supply-chain-intake/SKILL.md +11 -4
  74. package/dist/agent-src/skills/symfony-workflow/SKILL.md +35 -0
  75. package/dist/agent-src/skills/test-case-discovery/SKILL.md +85 -0
  76. package/dist/agent-src/skills/test-driven-development/SKILL.md +33 -9
  77. package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
  78. package/dist/agent-src/skills/testing-anti-patterns/process-anti-patterns.md +37 -0
  79. package/dist/agent-src/skills/ui-component-architect/SKILL.md +45 -2
  80. package/dist/agent-src/skills/upstream-contribute/SKILL.md +38 -1
  81. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +9 -4
  82. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  83. package/dist/agent-src/templates/roadmaps.md +97 -3
  84. package/dist/agent-src/templates/scripts/check_memory.ts +258 -17
  85. package/dist/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
  86. package/dist/agent-src/templates/scripts/memory_lookup.ts +86 -0
  87. package/dist/agent-src/templates/scripts/memory_signal.ts +44 -0
  88. package/dist/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
  89. package/dist/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
  90. package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
  91. package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
  92. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
  93. package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
  94. package/dist/cli/commands/uiAudit.js +124 -5
  95. package/dist/cli/registry.js +2 -0
  96. package/dist/cli-delegate/{chunk-HYWSRNUX.js → chunk-2DK2VJWG.js} +3 -3
  97. package/dist/cli-delegate/{chunk-JCW7ZLHK.js → chunk-4FS4WRXP.js} +5 -0
  98. package/dist/cli-delegate/{chunk-OMIVVCG2.js → chunk-A4QJ6ENT.js} +24 -0
  99. package/dist/cli-delegate/{chunk-JJA2QEWA.js → chunk-AKJGUQNO.js} +466 -285
  100. package/dist/cli-delegate/{chunk-E46KPN6K.js → chunk-BTWUYDGN.js} +424 -363
  101. package/dist/cli-delegate/{chunk-K4FFODTS.js → chunk-ILMUPLGW.js} +1227 -316
  102. package/dist/cli-delegate/{chunk-FF7WAFMR.js → chunk-KPBWFOPZ.js} +5 -1
  103. package/dist/cli-delegate/cmd_adr_effective.js +102 -0
  104. package/dist/cli-delegate/cmd_conformance.js +42 -10
  105. package/dist/cli-delegate/cmd_doctor.js +3 -3
  106. package/dist/cli-delegate/cmd_export.js +3 -2
  107. package/dist/cli-delegate/cmd_fleet.js +2 -2
  108. package/dist/cli-delegate/cmd_handoff.js +1 -1
  109. package/dist/cli-delegate/cmd_preflight.js +2 -2
  110. package/dist/cli-delegate/cmd_prune.js +3 -2
  111. package/dist/cli-delegate/cmd_settings_get.js +1 -1
  112. package/dist/cli-delegate/cmd_settings_migrate.js +3 -2
  113. package/dist/cli-delegate/cmd_settings_set.js +2 -2
  114. package/dist/cli-delegate/cmd_sync.js +3 -2
  115. package/dist/cli-delegate/cmd_uninstall.js +3 -2
  116. package/dist/cli-delegate/cmd_validate.js +3 -2
  117. package/dist/discovery/deprecation-report.md +1 -1
  118. package/dist/discovery/discovery-manifest.json +57 -57
  119. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  120. package/dist/discovery/discovery-manifest.summary.md +1 -1
  121. package/dist/discovery/dormancy-report.md +1 -1
  122. package/dist/discovery/orphan-report.md +1 -1
  123. package/dist/discovery/packs.json +2 -2
  124. package/dist/discovery/trust-report.md +1 -1
  125. package/dist/discovery/workspaces.json +2 -2
  126. package/dist/hooks/dispatch.js +1836 -712
  127. package/dist/install/claudeRuleRewrite.js +254 -0
  128. package/dist/install/detect.js +29 -16
  129. package/dist/install/detect_php_shape.js +159 -0
  130. package/dist/install/install.mjs +634 -428
  131. package/dist/mcp/awesome-mcp-servers.row.md +1 -1
  132. package/dist/mcp/mcp-cloudflare-catalogue.json +1 -1
  133. package/dist/mcp/registry-manifest.json +3 -3
  134. package/dist/mcp/server.json +3 -3
  135. package/dist/mcp/server.mjs +4818 -2645
  136. package/dist/server/schemas/settings.js +3 -0
  137. package/dist/ui/assets/index-D0jaCRPM.js +29 -0
  138. package/dist/ui/index.html +1 -1
  139. package/docs/MIGRATION.md +1 -1
  140. package/docs/THIRD-PARTY-NOTICES.md +25 -0
  141. package/docs/contracts/provider-lifecycle.md +1 -1
  142. package/docs/contracts/settings-classes.md +10 -4
  143. package/docs/guidelines/agent-infra/5w2h-analysis.md +3 -3
  144. package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +1 -0
  145. package/docs/guidelines/agent-infra/artifact-drafting-protocol-mechanics.md +58 -3
  146. package/docs/guidelines/agent-infra/ask-when-uncertain-demos.md +2 -2
  147. package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +3 -3
  148. package/docs/guidelines/agent-infra/break-glass-usage.md +7 -7
  149. package/docs/guidelines/agent-infra/carve-out-predicates.md +3 -3
  150. package/docs/guidelines/agent-infra/comparison-matrix.md +1 -1
  151. package/docs/guidelines/agent-infra/critical-thinking.md +4 -4
  152. package/docs/guidelines/agent-infra/direct-answers-demos.md +2 -2
  153. package/docs/guidelines/agent-infra/domain-eval-anti-pattern.md +1 -1
  154. package/docs/guidelines/agent-infra/engineering-memory-data-format.md +3 -3
  155. package/docs/guidelines/agent-infra/existence-question-verdicts.md +80 -0
  156. package/docs/guidelines/agent-infra/first-principles.md +2 -2
  157. package/docs/guidelines/agent-infra/framework-neutrality-patterns.md +2 -2
  158. package/docs/guidelines/agent-infra/guarded-baseline.md +39 -0
  159. package/docs/guidelines/agent-infra/inversion-thinking.md +5 -5
  160. package/docs/guidelines/agent-infra/language-and-tone-examples.md +1 -1
  161. package/docs/guidelines/agent-infra/layered-settings.md +10 -10
  162. package/docs/guidelines/agent-infra/memory-access.md +1 -1
  163. package/docs/guidelines/agent-infra/mental-models.md +3 -3
  164. package/docs/guidelines/agent-infra/reuse-verdict-mechanics.md +71 -0
  165. package/docs/guidelines/agent-infra/review-routing-data-format.md +7 -7
  166. package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +13 -7
  167. package/docs/guidelines/agent-infra/role-contracts.md +2 -2
  168. package/docs/guidelines/agent-infra/role-mode-router.md +3 -3
  169. package/docs/guidelines/agent-infra/rule-type-governance.md +2 -2
  170. package/docs/guidelines/agent-infra/scqa-framework.md +5 -5
  171. package/docs/guidelines/agent-infra/self-improvement-pipeline.md +6 -6
  172. package/docs/guidelines/agent-infra/simplicity-and-goal-demos.md +2 -2
  173. package/docs/guidelines/agent-infra/six-hats.md +3 -3
  174. package/docs/guidelines/agent-infra/skill-quality-checklist.md +6 -6
  175. package/docs/guidelines/agent-infra/source-confidentiality-mechanics.md +109 -0
  176. package/docs/guidelines/agent-infra/systems-thinking.md +1 -1
  177. package/docs/guidelines/agent-infra/verify-before-complete-demos.md +2 -2
  178. package/docs/guidelines/augment-portability-patterns.md +6 -4
  179. package/docs/guidelines/component-oriented-and-oop-development.md +3 -2
  180. package/docs/guidelines/cross-role-handoff.md +2 -2
  181. package/docs/guidelines/design-fidelity-mechanics.md +1 -1
  182. package/docs/guidelines/docs/readme-size-and-splitting.md +3 -3
  183. package/docs/guidelines/php/database.md +90 -7
  184. package/docs/guidelines/prompt-templates.md +7 -7
  185. package/llms.txt +2 -2
  186. package/package.json +5 -2
  187. package/src/agent-src/scripts/archive_completed_roadmaps.ts +247 -3
  188. package/src/agent-src/scripts/guarded_baseline.ts +328 -0
  189. package/src/agent-src/scripts/roadmap_set_step.ts +253 -0
  190. package/src/agent-src/scripts/stub_queue.ts +82 -0
  191. package/src/agent-src/scripts/stubs_due.ts +400 -0
  192. package/src/agent-src/scripts/ticket_bundles.ts +84 -0
  193. package/src/agent-src/scripts/update_roadmap_progress.ts +8 -4
  194. package/src/agent-src/templates/scripts/check_memory.ts +258 -17
  195. package/src/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
  196. package/src/agent-src/templates/scripts/memory_lookup.ts +86 -0
  197. package/src/agent-src/templates/scripts/memory_signal.ts +44 -0
  198. package/src/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
  199. package/src/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
  200. package/src/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
  201. package/src/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
  202. package/src/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
  203. package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
  204. package/src/config/agent-settings.template.yml +32 -3
  205. package/src/config/assurance-capability-registry.json +21 -9
  206. package/src/config/canonical-terms.yml +119 -0
  207. package/src/config/capability-native-outcome-bars.json +81 -0
  208. package/src/config/ci-local-parity.yml +80 -0
  209. package/src/config/drafting-channels.yml +43 -0
  210. package/src/config/estate-count-budget.json +38 -36
  211. package/src/config/evaluator-budgets.json +14 -14
  212. package/src/config/gate-coverage.yml +579 -63
  213. package/src/config/gate-reachability-exemptions.json +21 -0
  214. package/src/config/gate-violation-baselines.json +37 -19
  215. package/src/config/harness-evolution-budget.json +25 -0
  216. package/src/config/lapsed-beta-baseline.json +96 -0
  217. package/src/config/memory-twin-verdicts.yml +129 -0
  218. package/src/config/metric-registry.yml +124 -0
  219. package/src/config/pack-size-budget.json +16 -15
  220. package/src/config/preamble-payload-budget.json +8 -8
  221. package/src/config/profiles/balanced.ini +27 -0
  222. package/src/config/profiles/full.ini +27 -0
  223. package/src/config/profiles/minimal.ini +27 -0
  224. package/src/config/publish-surface.json +9 -2
  225. package/src/config/routing-coverage-seed.json +16 -2
  226. package/src/config/rule-stub-ceilings.json +126 -112
  227. package/src/config/turnaround-budget.json +66 -0
  228. package/src/install/claudeRuleRewrite.ts +288 -0
  229. package/src/install/detect.ts +60 -17
  230. package/src/install/detect_php_shape.ts +191 -0
  231. package/src/scripts/_cli/cmd_doctor.ts +27 -112
  232. package/src/scripts/_dispatch.bash +27 -0
  233. package/src/scripts/_lib/activation_ladder.ts +211 -0
  234. package/src/scripts/_lib/activation_states.ts +88 -0
  235. package/src/scripts/_lib/adherence_detectors.ts +143 -0
  236. package/src/scripts/_lib/arith_claims.ts +181 -0
  237. package/src/scripts/_lib/arm_ranking.ts +62 -0
  238. package/src/scripts/_lib/asset_delivery_ledger.ts +303 -0
  239. package/src/scripts/_lib/audit_field_provenance.ts +54 -0
  240. package/src/scripts/_lib/auto_dispatch.ts +32 -3
  241. package/src/scripts/_lib/bench_ab_size_claim.ts +98 -4
  242. package/src/scripts/_lib/benchmark_cache_fields.ts +158 -0
  243. package/src/scripts/_lib/candidate_proposer.ts +402 -0
  244. package/src/scripts/_lib/candidate_record.ts +601 -0
  245. package/src/scripts/_lib/capture_rate.ts +319 -0
  246. package/src/scripts/_lib/collector_denominator.ts +771 -0
  247. package/src/scripts/_lib/collector_record.ts +340 -0
  248. package/src/scripts/_lib/collector_store.ts +664 -0
  249. package/src/scripts/_lib/collector_supervision.ts +827 -0
  250. package/src/scripts/_lib/concern_estate.ts +77 -0
  251. package/src/scripts/_lib/config_chain.ts +477 -0
  252. package/src/scripts/_lib/config_cost.ts +209 -0
  253. package/src/scripts/_lib/council_settings_block.ts +6 -0
  254. package/src/scripts/_lib/curator_ops.ts +172 -0
  255. package/src/scripts/_lib/delivery_arm_experiment.ts +266 -0
  256. package/src/scripts/_lib/delivery_criticality.ts +126 -0
  257. package/src/scripts/_lib/doctor_runtime_checks.ts +70 -0
  258. package/src/scripts/_lib/empty_cycles.ts +88 -0
  259. package/src/scripts/_lib/eval_publication.ts +354 -0
  260. package/src/scripts/_lib/evaluation_vector.ts +283 -0
  261. package/src/scripts/_lib/evaluator_promotion.ts +225 -0
  262. package/src/scripts/_lib/evidence_basis.ts +118 -0
  263. package/src/scripts/_lib/exec_evidence.ts +8 -0
  264. package/src/scripts/_lib/experience_card.ts +272 -0
  265. package/src/scripts/_lib/experience_report.ts +151 -0
  266. package/src/scripts/_lib/experiment_freeze.ts +112 -0
  267. package/src/scripts/_lib/generated_by.ts +66 -0
  268. package/src/scripts/_lib/harness_evolution_guards.ts +229 -0
  269. package/src/scripts/_lib/hook_effect_probe.ts +141 -0
  270. package/src/scripts/_lib/host_denominator.ts +687 -0
  271. package/src/scripts/_lib/host_projection_reach.ts +157 -0
  272. package/src/scripts/_lib/ignored_blocker.ts +148 -0
  273. package/src/scripts/_lib/install_reach_checks.ts +495 -0
  274. package/src/scripts/_lib/json_duplicate_keys.ts +150 -0
  275. package/src/scripts/_lib/judge_hygiene.ts +228 -0
  276. package/src/scripts/_lib/legacy_boundary_map.ts +228 -0
  277. package/src/scripts/_lib/loop_guards.ts +299 -0
  278. package/src/scripts/_lib/loss_class.ts +129 -0
  279. package/src/scripts/_lib/machine_wake.ts +51 -0
  280. package/src/scripts/_lib/md_prose_lines.ts +177 -0
  281. package/src/scripts/_lib/minimality_tiebreak.ts +168 -0
  282. package/src/scripts/_lib/one_resolver_invariant.ts +449 -0
  283. package/src/scripts/_lib/orchestration_record.ts +253 -5
  284. package/src/scripts/_lib/outcome_envelope.ts +227 -0
  285. package/src/scripts/_lib/outcome_vocabularies.ts +125 -0
  286. package/src/scripts/_lib/paired_stats.ts +245 -0
  287. package/src/scripts/_lib/paired_verdict.ts +226 -0
  288. package/src/scripts/_lib/prefix_stable_surfaces.ts +123 -0
  289. package/src/scripts/_lib/privacy_class.ts +47 -0
  290. package/src/scripts/_lib/regression_neighbourhood.ts +259 -0
  291. package/src/scripts/_lib/repeated_failure.ts +105 -0
  292. package/src/scripts/_lib/repo_root.ts +111 -0
  293. package/src/scripts/_lib/review_skipped_record.ts +37 -0
  294. package/src/scripts/_lib/role_split.ts +338 -0
  295. package/src/scripts/_lib/runtime_journal.ts +1499 -0
  296. package/src/scripts/_lib/runtime_wiring_checks.ts +430 -0
  297. package/src/scripts/_lib/skill_catalogue.ts +11 -1
  298. package/src/scripts/_lib/source_digest.ts +200 -0
  299. package/src/scripts/_lib/source_redact.ts +260 -0
  300. package/src/scripts/_lib/source_shape.ts +502 -0
  301. package/src/scripts/_lib/source_snapshot_dedup.ts +199 -0
  302. package/src/scripts/_lib/strip_comments.d.mts +8 -0
  303. package/src/scripts/_lib/strip_comments.mjs +65 -0
  304. package/src/scripts/_lib/test_red_state.ts +154 -0
  305. package/src/scripts/_lib/trigger_shift.ts +144 -0
  306. package/src/scripts/_lib/untrusted_content.ts +82 -7
  307. package/src/scripts/adoption_report.ts +1 -1
  308. package/src/scripts/adr/evidence_census.ts +1 -1
  309. package/src/scripts/adr/regenerate_index.ts +26 -2
  310. package/src/scripts/adr_cite_check.ts +164 -1
  311. package/src/scripts/ai_council/blind_review.ts +11 -1
  312. package/src/scripts/ai_council/clients.ts +4 -0
  313. package/src/scripts/ai_council/config.ts +3 -0
  314. package/src/scripts/ai_council/consensus.ts +28 -8
  315. package/src/scripts/ai_council/consensus_round.ts +226 -0
  316. package/src/scripts/ai_council/disagreement_signal.ts +338 -0
  317. package/src/scripts/ai_council/inline_findings.ts +340 -0
  318. package/src/scripts/ai_council/judge_position_bias.ts +197 -0
  319. package/src/scripts/ai_council/orchestrator.ts +16 -203
  320. package/src/scripts/ai_council/orchestrator_results.ts +23 -3
  321. package/src/scripts/ai_council/pricing.ts +106 -0
  322. package/src/scripts/ai_council/prompts.ts +74 -7
  323. package/src/scripts/ai_council/provider_leakage_bench.ts +327 -0
  324. package/src/scripts/ai_council/py_format.ts +14 -3
  325. package/src/scripts/ai_council/recouncil_guard.ts +293 -0
  326. package/src/scripts/ai_council/response_record.ts +50 -0
  327. package/src/scripts/ai_council/topology_bench_manifest.ts +860 -0
  328. package/src/scripts/ai_council/topology_vocabulary.ts +175 -0
  329. package/src/scripts/asset_delivery_ledger.ts +157 -0
  330. package/src/scripts/attest_artifact.ts +193 -0
  331. package/src/scripts/audit_auto_rules.ts +2 -1
  332. package/src/scripts/audit_command_surface.ts +1 -1
  333. package/src/scripts/audit_mcp_tools.ts +2 -2
  334. package/src/scripts/audit_skill_overlap_allowlist.json +6 -1
  335. package/src/scripts/audit_user_type_axis.ts +2 -1
  336. package/src/scripts/bench_ab_clone.ts +215 -10
  337. package/src/scripts/bench_ab_integrity.ts +119 -5
  338. package/src/scripts/bench_ab_v2_stats.ts +40 -213
  339. package/src/scripts/build_archive_index.ts +1 -1
  340. package/src/scripts/build_linear_digest.ts +1 -1
  341. package/src/scripts/build_proof.ts +11 -4
  342. package/src/scripts/build_rule_trigger_matrix.ts +1 -1
  343. package/src/scripts/build_source_digests.ts +157 -0
  344. package/src/scripts/cache_realization_report.ts +103 -0
  345. package/src/scripts/check_adr_frontmatter.ts +126 -0
  346. package/src/scripts/check_benchmark_report_fields.ts +207 -0
  347. package/src/scripts/check_beta_review_markers.ts +235 -6
  348. package/src/scripts/check_bundle_path_leakage.ts +34 -1
  349. package/src/scripts/check_claims.ts +576 -6
  350. package/src/scripts/check_composite_arming.ts +35 -0
  351. package/src/scripts/check_concern_admissions.ts +365 -0
  352. package/src/scripts/check_enforcement_coverage.ts +28 -0
  353. package/src/scripts/check_estate_count.ts +142 -1
  354. package/src/scripts/check_gate_reachability.ts +383 -0
  355. package/src/scripts/check_host_loadability.ts +104 -0
  356. package/src/scripts/check_loss_class_declared.ts +308 -0
  357. package/src/scripts/check_md_language.ts +15 -98
  358. package/src/scripts/check_memory_proposal.ts +18 -11
  359. package/src/scripts/check_no_currency_in_cost_surfaces.ts +225 -0
  360. package/src/scripts/check_no_external_sources.ts +281 -6
  361. package/src/scripts/check_pack_conformance_fixture.ts +11 -1
  362. package/src/scripts/check_pack_size.ts +59 -2
  363. package/src/scripts/check_preamble_payload_budget.ts +114 -3
  364. package/src/scripts/check_prefix_stable_mutation.ts +372 -0
  365. package/src/scripts/check_publish_surface.ts +10 -1
  366. package/src/scripts/check_references.ts +24 -1
  367. package/src/scripts/check_rule_evidence_declaration.ts +316 -0
  368. package/src/scripts/check_rule_projection_integrity.ts +14 -4
  369. package/src/scripts/check_score_contract.ts +26 -3
  370. package/src/scripts/check_static_parity.ts +285 -0
  371. package/src/scripts/check_supervision_claim_atomicity.ts +498 -0
  372. package/src/scripts/check_suppression_hygiene.ts +15 -0
  373. package/src/scripts/ci_settle.ts +39 -2
  374. package/src/scripts/code_graph/build.ts +60 -3
  375. package/src/scripts/code_graph/extract.ts +44 -0
  376. package/src/scripts/code_graph/types.ts +24 -0
  377. package/src/scripts/collector_daemon.ts +714 -0
  378. package/src/scripts/config_cost_report.ts +302 -0
  379. package/src/scripts/consumer_matrix.ts +74 -1
  380. package/src/scripts/cost/budget.mjs +10 -3
  381. package/src/scripts/cost/track.mjs +10 -3
  382. package/src/scripts/council_cli.ts +37 -54
  383. package/src/scripts/dispatch_r2_reviewer.ts +46 -5
  384. package/src/scripts/evolution_lab.ts +980 -0
  385. package/src/scripts/external_sources_denylist.json +5 -18
  386. package/src/scripts/extract_audit_patterns.ts +21 -0
  387. package/src/scripts/fold_intake.ts +12 -1
  388. package/src/scripts/gen_discovery_baseline.ts +1 -1
  389. package/src/scripts/generate_capabilities_index.ts +12 -5
  390. package/src/scripts/generate_capability_matrix.ts +3 -3
  391. package/src/scripts/generate_command_flows.ts +2 -2
  392. package/src/scripts/generate_cookbook.ts +2 -2
  393. package/src/scripts/generate_index.ts +8 -1
  394. package/src/scripts/generate_knowledge_index.ts +2 -1
  395. package/src/scripts/generate_ownership_matrix.ts +2 -1
  396. package/src/scripts/generate_pack_manifests.ts +10 -2
  397. package/src/scripts/generate_role_experiences_catalog.ts +2 -2
  398. package/src/scripts/generate_settings_reference.ts +1 -1
  399. package/src/scripts/git_authorization_hook.ts +22 -1
  400. package/src/scripts/grade_target_readiness.ts +48 -5
  401. package/src/scripts/hook_effect_doctor.ts +261 -0
  402. package/src/scripts/hook_manifest.json +1 -1
  403. package/src/scripts/hook_manifest.yaml +98 -11
  404. package/src/scripts/hooks/block_speaking_inbox_dir.ts +271 -0
  405. package/src/scripts/hooks/block_unauthorized_git.ts +18 -0
  406. package/src/scripts/hooks/concern_registry.ts +4 -0
  407. package/src/scripts/hooks/dispatch_hook.ts +32 -0
  408. package/src/scripts/hooks/journal_record_hook.ts +345 -0
  409. package/src/scripts/hooks/prepush_metadata_sources.sh +110 -0
  410. package/src/scripts/hooks/run_continuation_hook.ts +44 -9
  411. package/src/scripts/hooks/shims/install.sh +61 -0
  412. package/src/scripts/hooks/shims/php +101 -0
  413. package/src/scripts/hooks/suggestion_capture_hook.ts +10 -0
  414. package/src/scripts/hot_context_hook.ts +16 -0
  415. package/src/scripts/install-hooks.sh +20 -5
  416. package/src/scripts/install.ts +17 -35
  417. package/src/scripts/inventory_frontmatter.ts +2 -1
  418. package/src/scripts/lint_adr_sweep_routing.ts +12 -0
  419. package/src/scripts/lint_canonical_terms.ts +604 -0
  420. package/src/scripts/lint_composition_review.ts +619 -0
  421. package/src/scripts/lint_consolidation_lineage.ts +666 -0
  422. package/src/scripts/lint_eval_specs.ts +593 -0
  423. package/src/scripts/lint_hook_manifest.ts +19 -0
  424. package/src/scripts/lint_host_portability.ts +373 -0
  425. package/src/scripts/lint_judge_prompt_expectation.ts +27 -1
  426. package/src/scripts/lint_memory_twin_parity.ts +335 -0
  427. package/src/scripts/lint_metric_consumers.ts +355 -0
  428. package/src/scripts/lint_skill_descriptions.ts +18 -1
  429. package/src/scripts/lint_skill_frontmatter_safety.ts +58 -0
  430. package/src/scripts/lint_skill_link_reach.ts +252 -0
  431. package/src/scripts/lint_skill_trigger_corpus.ts +426 -23
  432. package/src/scripts/lint_ticket_buildable.ts +17 -1
  433. package/src/scripts/mcp_server/consumer_tool_catalog.json +1 -1
  434. package/src/scripts/mcp_server/tool_catalog_source.ts +1 -1
  435. package/src/scripts/measure_docs_dead_links.ts +348 -0
  436. package/src/scripts/measure_host_capture.ts +461 -0
  437. package/src/scripts/migration_status.ts +3 -3
  438. package/src/scripts/model_rule_injection.ts +60 -0
  439. package/src/scripts/orchestration_record.ts +14 -0
  440. package/src/scripts/preamble_byte_census.ts +139 -10
  441. package/src/scripts/prepack-check.mjs +4 -1
  442. package/src/scripts/probe_turnaround.ts +384 -0
  443. package/src/scripts/probe_unblocked_ask.ts +279 -0
  444. package/src/scripts/render_benchmark_md.ts +1 -1
  445. package/src/scripts/rule_activation_census.ts +70 -9
  446. package/src/scripts/rule_backlinks.ts +1 -1
  447. package/src/scripts/run_lifecycle_suite.ts +208 -0
  448. package/src/scripts/run_skill_evals.ts +40 -0
  449. package/src/scripts/schemas/delivery-manifest.schema.json +43 -0
  450. package/src/scripts/schemas/drafting-channels.schema.json +43 -0
  451. package/src/scripts/schemas/evals.schema.json +24 -1
  452. package/src/scripts/schemas/rule.schema.json +52 -1
  453. package/src/scripts/schemas/skill.schema.json +17 -2
  454. package/src/scripts/skill_overlap.ts +7 -1
  455. package/src/scripts/skill_tools/run_block_d_eval.ts +8 -1
  456. package/src/scripts/skill_tools/score_skill_relevance.ts +84 -3
  457. package/src/scripts/skill_tools/suggest_skill_for_task.ts +8 -1
  458. package/src/scripts/skill_usage_report.ts +2 -1
  459. package/src/scripts/stubs_due.ts +211 -0
  460. package/src/scripts/sweep_source_surfaces.ts +678 -0
  461. package/src/scripts/sync_pr_branch.ts +3 -3
  462. package/src/scripts/trigger_eval_grandfather.json +202 -222
  463. package/src/scripts/utilization_report.ts +22 -2
  464. package/src/server/schemas/settings.ts +5 -0
  465. package/src/templates/marketing-copy.yml +1 -1
  466. package/dist/ui/assets/index-Cxgy63kz.js +0 -26
@@ -153,6 +153,24 @@ export function _load_tool_trace(run_dir: string): string[] | null {
153
153
  return raw.map((e) => (typeof e === 'string' ? e : (e.tool ?? ''))).filter((s) => s !== '');
154
154
  }
155
155
 
156
+ /**
157
+ * Load the recorded EVENT trace, or `null` when the run did not record one.
158
+ *
159
+ * Sibling of {@link _load_tool_trace}, and deliberately a separate file rather
160
+ * than a widened tool trace: a tool call is something the agent did, an event
161
+ * is something the harness observed — a gate running, a hook concern firing, a
162
+ * refusal. Conflating them would make "the linter ran" indistinguishable from
163
+ * "the agent invoked the linter", and the interesting failure is precisely the
164
+ * case where a gate was SKIPPED while the agent narrated that it passed.
165
+ */
166
+ export function _load_event_trace(run_dir: string): string[] | null {
167
+ const p = path.join(run_dir, 'event-trace.json');
168
+ if (!_exists(p)) return null;
169
+ const raw = JSON.parse(fs.readFileSync(p, 'utf-8')) as Array<string | { event?: string }>;
170
+ if (!Array.isArray(raw)) return null;
171
+ return raw.map((e) => (typeof e === 'string' ? e : (e.event ?? ''))).filter((s) => s !== '');
172
+ }
173
+
156
174
  /** Count meaningful steps: tool calls net of retries (a call whose name equals
157
175
  * the immediately-preceding call name is a retry, not a new step). */
158
176
  export function _count_meaningful_steps(trace: string[]): number {
@@ -217,6 +235,28 @@ export function _grade_assertions(
217
235
  missing, forbidden, pass: missing.length === 0 && forbidden.length === 0,
218
236
  });
219
237
  }
238
+ } else if (kind === 'event-choice') {
239
+ // The forbidden-event half of the case shape. Same manual-pending
240
+ // rule as tool-choice: no trace is NEVER a silent pass, because a
241
+ // missing trace and a clean run are the two readings this assertion
242
+ // exists to separate.
243
+ const mustEmit = (a['must_emit'] as string[] | undefined) ?? [];
244
+ const mustNotEmit = (a['must_not_emit'] as string[] | undefined) ?? [];
245
+ const trace = _load_event_trace(run_dir);
246
+ if (trace === null) {
247
+ results.push({
248
+ kind, must_emit: mustEmit, must_not_emit: mustNotEmit, pass: null,
249
+ note: 'manual-pending: no event-trace.json in run dir — record a trace or grade manually',
250
+ });
251
+ } else {
252
+ const seen = new Set(trace);
253
+ const missing = mustEmit.filter((e) => !seen.has(e));
254
+ const forbidden = mustNotEmit.filter((e) => seen.has(e));
255
+ results.push({
256
+ kind, must_emit: mustEmit, must_not_emit: mustNotEmit,
257
+ missing, forbidden, pass: missing.length === 0 && forbidden.length === 0,
258
+ });
259
+ }
220
260
  } else if (kind === 'trajectory_budget') {
221
261
  // Meaningful step = one tool call net of retries (a retry is a call whose
222
262
  // tool name repeats the immediately-preceding call). No trace → manual-pending.
@@ -0,0 +1,43 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "delivery-manifest.schema.json",
4
+ "title": "Delivery manifest",
5
+ "description": "Obligations that may travel on a runtime carrier instead of standing context, and what happens to each when that carrier is unavailable. Contract: docs/contracts/resident-process-floors.md § 3. Resolver: src/scripts/_lib/delivery_criticality.ts.",
6
+ "type": "object",
7
+ "required": ["schema_version", "entries"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "schema_version": { "const": 1 },
11
+ "entries": {
12
+ "type": "array",
13
+ "items": { "$ref": "#/definitions/entry" }
14
+ }
15
+ },
16
+ "definitions": {
17
+ "entry": {
18
+ "type": "object",
19
+ "required": ["id", "criticality"],
20
+ "additionalProperties": false,
21
+ "properties": {
22
+ "id": {
23
+ "type": "string",
24
+ "minLength": 1,
25
+ "description": "Logical obligation id — the rule, gate or floor being delivered."
26
+ },
27
+ "criticality": {
28
+ "enum": ["critical-A", "critical-B", "standard"],
29
+ "description": "critical-A never migrates off standing context. critical-B may migrate and is delivered EAGERLY when the carrier is unavailable, never dropped. standard may fail open. Required here even though the resolver defaults an omitted value to critical-B: a manifest is authored, and an author who has not decided should be made to, while a RUNTIME value that is merely absent must still fail closed."
30
+ },
31
+ "carrier": {
32
+ "type": "string",
33
+ "minLength": 1,
34
+ "description": "The runtime carrier that would deliver this obligation."
35
+ },
36
+ "why": {
37
+ "type": "string",
38
+ "description": "Why this class and not the next one down. Required by review, not by schema."
39
+ }
40
+ }
41
+ }
42
+ }
43
+ }
@@ -0,0 +1,43 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://github.com/event4u-app/agent-config/scripts/schemas/drafting-channels.schema.json",
4
+ "x-schemaVersion": "1.0.0",
5
+ "title": "Drafting channel registry (src/config/drafting-channels.yml)",
6
+ "$comment": "road-to-channel-contract-and-profile-drift Phase 1.2. Validated by tests/scripts/drafting_channels_schema.test.ts against the Draft-07 SUBSET exported by src/scripts/validate_frontmatter.ts (type, required, properties, additionalProperties:false, items, minItems, pattern, minLength, enum) — no $ref, no patternProperties, no if-then, because that validator supports none of them and a schema using them would silently not be checked. SCOPE: an output shape for prose this package writes. Deliberately NOT merged into reach-channels.schema.json: a reach channel is an external retrieval backend with an install string, a health probe and a lifecycle, and a drafting channel has none of those and carries a length and a cadence instead; a merged schema would make every field optional for half its rows. The `id` values are FLAG VALUES — what a user types after `--channel=` — which is why the enum is closed: the short form `linkedin` is the plausible typo, and an open enum would accept it silently.",
7
+ "type": "object",
8
+ "additionalProperties": false,
9
+ "required": ["schema_version", "channels"],
10
+ "properties": {
11
+ "schema_version": {
12
+ "type": "string",
13
+ "enum": ["drafting-channels-v1"],
14
+ "description": "Registry format version. Bumped only on a breaking shape change."
15
+ },
16
+ "channels": {
17
+ "type": "array",
18
+ "minItems": 1,
19
+ "description": "The `--channel` enum, one entry per accepted flag value. Order carries no meaning.",
20
+ "items": {
21
+ "type": "object",
22
+ "additionalProperties": false,
23
+ "required": ["id", "length_default", "cadence"],
24
+ "properties": {
25
+ "id": {
26
+ "type": "string",
27
+ "enum": ["tweet", "linkedin-post", "blog", "freeform"],
28
+ "description": "The literal `--channel=` value. Closed enum: adding a drafting channel is a contract change to docs/contracts/write-engine.md and to the three command surfaces, so it may not be done by adding a row here alone."
29
+ },
30
+ "length_default": {
31
+ "type": "integer",
32
+ "description": "Default word count when `--length` is omitted. Mirrors the Length-default column of write-engine.md § Per-channel defaults."
33
+ },
34
+ "cadence": {
35
+ "type": "string",
36
+ "minLength": 10,
37
+ "description": "Paragraph/structure guidance for this channel. Mirrors the Cadence-guidance column of write-engine.md § Per-channel defaults."
38
+ }
39
+ }
40
+ }
41
+ }
42
+ }
43
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "$id": "https://github.com/event4u-app/agent-config/scripts/schemas/evals.schema.json",
4
- "x-schemaVersion": "1.0.0",
4
+ "x-schemaVersion": "1.1.0",
5
5
  "title": "Skill behavioural evals (evals.json)",
6
6
  "$comment": "Behavioural-eval spec consumed by run_skill_evals.ts (scaffold/aggregate/report) and counted by skill_eval_coverage.ts. Distinct from triggers.json (activation/routing axis). Roadmap: road-to-skill-eval-coverage Phase 1. Assertion kinds mirror _grade_assertions() in run_skill_evals.ts exactly \u2014 add a kind there before adding it here.",
7
7
  "type": "object",
@@ -198,6 +198,29 @@
198
198
  "description": "Ceiling on meaningful steps = tool calls net of retries (a call repeating the immediately-preceding call name is a retry, not a step). Counted from <run_dir>/tool-trace.json; no trace → manual-pending. v2, additive."
199
199
  }
200
200
  }
201
+ },
202
+ {
203
+ "type": "object",
204
+ "additionalProperties": false,
205
+ "required": ["kind"],
206
+ "anyOf": [
207
+ { "required": ["kind", "must_emit"] },
208
+ { "required": ["kind", "must_not_emit"] }
209
+ ],
210
+ "properties": {
211
+ "kind": { "const": "event-choice" },
212
+ "must_emit": {
213
+ "type": "array",
214
+ "items": { "type": "string", "minLength": 1 },
215
+ "description": "Harness events the run MUST have emitted, checked against <run_dir>/event-trace.json. v2, additive."
216
+ },
217
+ "must_not_emit": {
218
+ "type": "array",
219
+ "items": { "type": "string", "minLength": 1 },
220
+ "description": "Harness events the run MUST NOT have emitted — a skipped gate or a refused turn becomes checkable rather than narrated. v2, additive."
221
+ }
222
+ },
223
+ "$comment": "Forbidden-event array alongside the expected-event array. An EVENT is something the harness observed (a gate running, a hook concern firing, a refusal); a TOOL call is something the agent did — conflating them makes \"the linter ran\" indistinguishable from \"the agent invoked the linter\", and the interesting failure is a gate that was SKIPPED while the agent narrated a pass. Hence a separate kind and a separate trace file. `anyOf` requires at least one of the two arrays BY CONSTRUCTION: the sibling tool-choice shape requires neither, so {\"kind\": \"tool-choice\"} is schema-valid and enforces nothing — this kind cannot express that. No trace present → pass:null manual-pending, never a silent pass."
201
224
  }
202
225
  ]
203
226
  }
@@ -158,7 +158,43 @@
158
158
  "type": "string",
159
159
  "enum": ["developer", "reviewer", "tester", "po", "incident", "planner"]
160
160
  },
161
- "description": "Subagent role-mode scoping axis (road-to-lean-agent-init Phase 4), parallel to `workspaces`/`packs`. Closed vocabulary — the six RoleMode ids from src/scripts/_lib/subagent_spawn.ts. Absent/empty = untagged, fails safe (ships to every role). Kernel rules (type: always) always ship regardless of this field. Enforced via this schema's `enum` (not a src/config/discovery/*.yml + lint_artefact_frontmatter.ts cross-check like workspaces/packs) because lint_artefact_frontmatter.ts still scans the retired legacy rules tree (0 artefacts post-ADR-051 src/ migration) and is a no-op for src/rules/*.md today; validate_frontmatter.ts (the active src/rules linter) enforces this enum instead."
161
+ "description": "Subagent role-mode scoping axis (road-to-lean-agent-init Phase 4), parallel to `workspaces`/`packs`. Closed vocabulary — the six RoleMode ids from src/scripts/_lib/subagent_spawn.ts. Absent/empty = untagged, fails safe (ships to every role). Kernel rules (type: always) always ship regardless of this field. Enforced via this schema's `enum` (not a src/config/discovery/*.yml + lint_artefact_frontmatter.ts cross-check like workspaces/packs) because lint_artefact_frontmatter.ts still scans the retired legacy rules tree (0 artifacts post-ADR-051 src/ migration) and is a no-op for src/rules/*.md today; validate_frontmatter.ts (the active src/rules linter) enforces this enum instead."
162
+ },
163
+ "evidence": {
164
+ "type": "object",
165
+ "additionalProperties": false,
166
+ "required": ["source_type"],
167
+ "allOf": [
168
+ {
169
+ "$comment": "`normative_level` states how binding the SOURCE is. For `own-analysis` there is no external source, so the field answers a question that does not arise and `informative` is its only coherent value — requiring it there forces a non-answer. `verified_on` is conditional for the same reason and not a second exception: it stamps when an EXTERNAL source pointer was last checked, and where there is no external source the rule\u2019s own git history is its staleness. Both are required for every other source_type, where the questions are real. Surfaced by the delivered-payload ceiling: ten blocks did not fit, and the two fields that did not fit were the two that were not saying anything.",
170
+ "if": { "properties": { "source_type": { "not": { "const": "own-analysis" } } }, "required": ["source_type"] },
171
+ "then": { "required": ["normative_level", "verified_on"] }
172
+ }
173
+ ],
174
+ "description": "Where this rule's NORMATIVE CONTENT came from, and what it was when it left. Optional; road-to-retired-claims-stay-retired Phase 3. Distinct from `decision_impact_evidence`, which points at an observation that the model already complies WITHOUT the rule \u2014 the opposite direction. A rule stating a threshold, a number, or a mechanism taken from outside this repository either cites it here or is recorded as own analysis; `src/rules/code-provenance.md` \u00a7 The knowledge layer states that obligation for prose, and this block is where a rule discharges it structurally. Optional on day one by design: 0 of 120 rules carried any provenance field before this, and a required field would fail the build on all of them at once \u2014 the gate-that-can-only-block shape this repository's own records name as the reason a gate gets suppressed.",
175
+ "properties": {
176
+ "source_type": {
177
+ "type": "string",
178
+ "enum": ["own-analysis", "internal-incident", "external-standard", "external-research", "vendor-doc"],
179
+ "description": "`own-analysis`: derived in this repository, no external source \u2014 a COMPLETE discharge, never a fallback for not having looked. `internal-incident`: a failure observed here. `external-standard`: OWASP, WCAG, an RFC, a regulation. `external-research`: a paper or study. `vendor-doc`: a host or provider's own documentation."
180
+ },
181
+ "source_urls": {
182
+ "type": "array",
183
+ "uniqueItems": true,
184
+ "items": { "type": "string", "minLength": 8 },
185
+ "description": "Optional. Where the source lives. An `ENC1:` token per `src/rules/source-confidentiality.md` where naming the source in the tracked tree is not permitted. Absent is CORRECT for `own-analysis`, and for an `internal-incident` whose record is a commit or an ADR rather than a URL."
186
+ },
187
+ "verified_on": {
188
+ "type": "string",
189
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
190
+ "description": "Dated stamp on the citation, in the same sense as the claims ledger's `https://\u2026 (YYYY-MM-DD)` evidence form: the date this block was last checked against the rule's normative content and the source it names. It is NOT a fetch receipt \u2014 nothing here retrieves a URL, and a block claiming otherwise would be the manufactured verification `src/rules/direct-answers.md` Iron Law 2 forbids. A stamp that never moves while the rule's body changes is the signal a reader should act on."
191
+ },
192
+ "normative_level": {
193
+ "type": "string",
194
+ "enum": ["mandatory", "recommended", "informative"],
195
+ "description": "How binding the SOURCE is \u2014 never how binding this rule is. A rule may impose an Iron Law on top of an `informative` source; stating the source's own level is what stops a house choice being read as an external requirement."
196
+ }
197
+ }
162
198
  },
163
199
  "lifecycle": {
164
200
  "type": "string",
@@ -192,6 +228,21 @@
192
228
  },
193
229
  "description": "ADR-013 trust block. Vocabulary mirrored by scripts/lint_artefact_frontmatter.py."
194
230
  },
231
+ "composition_review": {
232
+ "type": "array",
233
+ "minItems": 1,
234
+ "description": "The authoring-search record (road-to-composition-before-creation Phase 3): which incumbents were searched before this artifact was created, and the declared delta for each. Optional on existing artifacts by design \u2014 nothing is backfilled. Distinct from `collision_ok`, which is keyed by trigger VALUE and fires only on a trigger collision; this is keyed by INCUMBENT and is written at authoring time whether or not any trigger is shared.",
235
+ "items": {
236
+ "type": "object",
237
+ "additionalProperties": false,
238
+ "required": ["candidate", "disposition", "rationale"],
239
+ "properties": {
240
+ "candidate": {"type": "string", "minLength": 1, "description": "The incumbent searched, as `skill:<name>` / `rule:<name>` / `command:<name>` / `guideline:<path>`. The literal `none` records a search that found no credible incumbent \u2014 the value that must exist so an author is never pushed to invent one to satisfy the schema."},
241
+ "disposition": {"type": "string", "enum": ["extend_incumbent", "compose_with_incumbent", "create_separate", "none_found"], "description": "What happened to this candidate. `create_separate` is the value no other disposition vocabulary in this tree can express: an incumbent exists, was evaluated, and a separate artifact was authored anyway."},
242
+ "rationale": {"type": "string", "minLength": 16, "description": "One sentence naming the delta \u2014 what this artifact does that the candidate does not, or why the candidate could not absorb it. A lint checks that this is non-empty and that `candidate` resolves; it cannot check that the search was diligent, and does not pretend to."}
243
+ }
244
+ }
245
+ },
195
246
  "collision_ok": {
196
247
  "type": "object",
197
248
  "additionalProperties": {"type": "string", "minLength": 8},
@@ -26,7 +26,7 @@
26
26
  "type": "string",
27
27
  "minLength": 1,
28
28
  "maxLength": 200,
29
- "description": "Trigger phrase; the ceiling is 200 chars, measured. Lowered from 220 on 2026-08-22 because 220 described no artefact that existed: across all 290 skills the distribution was median 181 / p75 189 / max 200, with ZERO over 200, so the 20 chars above the recommended line were dead headroom a future author could fill with no gate objecting. p75 = 189 is the recorded soft target; 200 is the hard line. Descriptions load eagerly via progressive disclosure, so every char here is standing cost on every spawn."
29
+ "description": "Trigger phrase; the ceiling is 200 chars, measured. Lowered from 220 on 2026-08-22 because 220 described no artifact that existed: across all 290 skills the distribution was median 181 / p75 189 / max 200, with ZERO over 200, so the 20 chars above the recommended line were dead headroom a future author could fill with no gate objecting. p75 = 189 is the recorded soft target; 200 is the hard line. Descriptions load eagerly via progressive disclosure, so every char here is standing cost on every spawn."
30
30
  },
31
31
  "compatibility": {
32
32
  "type": "string",
@@ -374,6 +374,21 @@
374
374
  "default": "active",
375
375
  "description": "ADR-013 lifecycle state."
376
376
  },
377
+ "composition_review": {
378
+ "type": "array",
379
+ "minItems": 1,
380
+ "description": "The authoring-search record (road-to-composition-before-creation Phase 3): which incumbents were searched before this artifact was created, and the declared delta for each. Optional on existing artifacts by design \u2014 nothing is backfilled. Distinct from `collision_ok`, which is keyed by trigger VALUE and fires only on a trigger collision; this is keyed by INCUMBENT and is written at authoring time whether or not any trigger is shared.",
381
+ "items": {
382
+ "type": "object",
383
+ "additionalProperties": false,
384
+ "required": ["candidate", "disposition", "rationale"],
385
+ "properties": {
386
+ "candidate": {"type": "string", "minLength": 1, "description": "The incumbent searched, as `skill:<name>` / `rule:<name>` / `command:<name>` / `guideline:<path>`. The literal `none` records a search that found no credible incumbent \u2014 the value that must exist so an author is never pushed to invent one to satisfy the schema."},
387
+ "disposition": {"type": "string", "enum": ["extend_incumbent", "compose_with_incumbent", "create_separate", "none_found"], "description": "What happened to this candidate. `create_separate` is the value no other disposition vocabulary in this tree can express: an incumbent exists, was evaluated, and a separate artifact was authored anyway."},
388
+ "rationale": {"type": "string", "minLength": 16, "description": "One sentence naming the delta \u2014 what this artifact does that the candidate does not, or why the candidate could not absorb it. A lint checks that this is non-empty and that `candidate` resolves; it cannot check that the search was diligent, and does not pretend to."}
389
+ }
390
+ }
391
+ },
377
392
  "requires_skills": {
378
393
  "type": "array",
379
394
  "minItems": 1,
@@ -382,7 +397,7 @@
382
397
  "type": "string",
383
398
  "pattern": "^[a-z][a-z0-9-]*$"
384
399
  },
385
- "description": "Skill-composition graph (roadmap 3.4): names of sub-skills this skill's body invokes/assumes. Distinct from ADR-015 `requires` (artefact→pack edges). scripts/check_skill_requires.py enforces (a) each target exists and (b) the required skill is co-available wherever this skill ships (same pack, a requires_hint-reachable pack, or always-on)."
400
+ "description": "Skill-composition graph (roadmap 3.4): names of sub-skills this skill's body invokes/assumes. Distinct from ADR-015 `requires` (artifact→pack edges). scripts/check_skill_requires.py enforces (a) each target exists and (b) the required skill is co-available wherever this skill ships (same pack, a requires_hint-reachable pack, or always-on)."
386
401
  },
387
402
  "trust": {
388
403
  "type": "object",
@@ -300,7 +300,13 @@ export function render(pairs: Pair[], total: number): string {
300
300
  const lines: string[] = [
301
301
  '# Skill Structural Overlap (baseline)',
302
302
  '',
303
- '> Generated by `scripts/skill_overlap.py`. Scans',
303
+ // The literal rather than `_lib/generated_by`'s helper, deliberately:
304
+ // `lint_skill_originality`'s harness copies THIS FILE ALONE into a
305
+ // synthetic tree and runs it, so a `./_lib/` import here fails to
306
+ // resolve at runtime. The attribution is a constant, not a
307
+ // computation, and the tree-wide invariant is held by the sweep in
308
+ // tests/scripts/generated_by.test.ts rather than by this import.
309
+ '> Generated by `skill_overlap`. Do not edit. Scans',
304
310
  '> `src/skills/*/SKILL.md` frontmatter (description +',
305
311
  '> trigger metadata) and body symbol references. Reports pairs in two',
306
312
  `> tiers: **strong** ≥ ${pyFloatStr(STRONG_TOKEN)} description-token Jaccard or ≥ ${pyFloatStr(STRONG_SYMBOL)}`,
@@ -28,6 +28,9 @@ import * as path from 'node:path';
28
28
  import { fileURLToPath, pathToFileURL } from 'node:url';
29
29
 
30
30
  import { audit, type PersonaRow } from './audit_persona_coverage.js';
31
+ /** Sentinel for "no catalogue root resolved" — never a readable path. */
32
+ const NO_CATALOGUE = '<no-skills-catalogue>';
33
+
31
34
  import { DEFAULT_SKILLS_DIR, rank } from './score_skill_relevance.js';
32
35
  import { suggest } from './suggest_skill_for_task.js';
33
36
  import { pyRound } from '../_lib/value_ladder.js';
@@ -312,7 +315,11 @@ function _argError(message: string): never {
312
315
 
313
316
  export function parse_args(argv: string[]): Args {
314
317
  const args: Args = {
315
- skills_dir: DEFAULT_SKILLS_DIR,
318
+ // `?? ''` is deliberately NOT used here: an empty string re-creates
319
+ // exactly the silent-empty-catalogue defect that repointing
320
+ // DEFAULT_SKILLS_DIR removed. When no catalogue resolves, this reads
321
+ // as the literal marker below and the caller's own check reports it.
322
+ skills_dir: DEFAULT_SKILLS_DIR ?? NO_CATALOGUE,
316
323
  personas_dir: PERSONAS_DIR,
317
324
  corpus_dir: CORPUS_DIR,
318
325
  json: false,
@@ -50,7 +50,25 @@ const _HERE = fileURLToPath(import.meta.url);
50
50
  // src/scripts/skill_tools/score_skill_relevance.ts → parents[3] of the .py
51
51
  // (skill_tools → scripts → src → repo root) is the package root.
52
52
  export const ROOT = path.resolve(path.dirname(_HERE), '..', '..', '..');
53
- export const DEFAULT_SKILLS_DIR = path.join(ROOT, '.agent-src.uncondensed', 'skills');
53
+ /**
54
+ * The skills root, resolved the way the two real consumers already resolve it.
55
+ *
56
+ * `road-to-inbox-harvest-2026-08-f-skill-selection-evidence` 1.1. This used to be
57
+ * a hardcoded path to a directory that no longer exists, and the failure was
58
+ * SILENT: `--task "review a pull request"` printed `(no relevant skills found)`
59
+ * and exited 0, which is indistinguishable from a task that genuinely matches
60
+ * nothing. A ranker that reports an empty catalogue as an empty result is worse
61
+ * than one that crashes.
62
+ *
63
+ * `resolveSkillsRoot` is the shared resolver the `skill-route` concern and the
64
+ * `suggest_skill_for_task` MCP handler use — deliberately shared, because two
65
+ * resolvers over one catalogue is how a ranker and the tool that exposes it
66
+ * start ranking different trees. `null` when no candidate root exists, and the
67
+ * CLI turns that into a distinct exit code rather than an empty list.
68
+ */
69
+ import { DEFAULT_CATALOGUE_ROOTS, resolveSkillsRoot } from '../_lib/skill_catalogue.js';
70
+
71
+ export const DEFAULT_SKILLS_DIR: string | null = resolveSkillsRoot(ROOT);
54
72
 
55
73
  /** Mirror Python len(str) — count Unicode code points, not UTF-16 units. */
56
74
  function pyLen(s: string): number {
@@ -364,7 +382,8 @@ const PROG = 'score_skill_relevance.py';
364
382
 
365
383
  interface Args {
366
384
  task: string;
367
- skills_dir: string;
385
+ /** `null` when no catalogue root exists — a DIFFERENT answer from an empty ranking. */
386
+ skills_dir: string | null;
368
387
  top: number;
369
388
  json: boolean;
370
389
  sample: boolean;
@@ -433,13 +452,75 @@ export const _SAMPLE = {
433
452
  task: 'build a livewire component for the user dashboard with reactive state',
434
453
  };
435
454
 
455
+ /**
456
+ * Why this catalogue root cannot be ranked, or `null` when it can.
457
+ *
458
+ * `road-to-inbox-harvest-2026-08-f-skill-selection-evidence` 1.2. Three states,
459
+ * and the middle one is the one that actually bit: a root that does not exist, a
460
+ * root that exists and is EMPTY, and a readable root. `.claude/skills` is a
461
+ * gitignored projection, so a fresh worktree has the second — and the ranker
462
+ * reported it as "no relevant skills found", exit 0, on a task that scores 47
463
+ * against `src/skills`.
464
+ *
465
+ * An empty directory is not a missing directory, and neither is an empty result.
466
+ */
467
+ function catalogueDeficit(dir: string | null): string | null {
468
+ if (dir === null) {
469
+ return `no catalogue root resolved — tried ${DEFAULT_CATALOGUE_ROOTS.join(', ')} under ${ROOT}`;
470
+ }
471
+ try {
472
+ if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) {
473
+ return `${dir} is not a directory`;
474
+ }
475
+ if (fs.readdirSync(dir).length === 0) {
476
+ return `${dir} exists and is EMPTY — an empty catalogue, not an empty result`;
477
+ }
478
+ } catch (e) {
479
+ return `${dir} could not be read: ${e instanceof Error ? e.message : String(e)}`;
480
+ }
481
+ return null;
482
+ }
483
+
436
484
  export function main(argv: string[] | null = null): number {
437
485
  const args = parse_args(argv ?? process.argv.slice(2));
438
486
  const task = args.sample ? _SAMPLE.task : args.task;
439
487
  if (!task) {
440
488
  _argError('--task is required (or pass --sample)');
441
489
  }
442
- const rows = rank(task, args.skills_dir);
490
+ // 1.2 — "no matches" and "no catalogue" are DIFFERENT answers and now have
491
+ // different exit codes. `missing-skill-recovery` already draws that line for
492
+ // the MCP tool (`status: no_catalogue`); the CLI did not, and an agent
493
+ // reading `(no relevant skills found)` from an unreachable catalogue
494
+ // concludes "no skill covers this" — the exact wrong conclusion that rule
495
+ // exists to prevent.
496
+ // The check covers an EXPLICIT --skills-dir too, not only the default. An
497
+ // operator who passes a wrong path is in exactly the position the silent
498
+ // failure was about, and answering them with "(no relevant skills found)"
499
+ // is the same wrong answer with a different cause.
500
+ const unreadable = catalogueDeficit(args.skills_dir);
501
+ if (unreadable !== null) {
502
+ if (args.json) {
503
+ process.stdout.write(
504
+ pyJsonDumpsIndent2({
505
+ task,
506
+ status: 'no_catalogue',
507
+ reason: unreadable,
508
+ ...(args.skills_dir === null ? { tried: [...DEFAULT_CATALOGUE_ROOTS] } : { skills_dir: args.skills_dir }),
509
+ }),
510
+ );
511
+ process.stdout.write('\n');
512
+ } else {
513
+ process.stderr.write(
514
+ `(no skills catalogue read — ${unreadable})\n` +
515
+ 'This is NOT "no skill matches": nothing was read, so no conclusion about ' +
516
+ 'skill coverage follows from it.\n',
517
+ );
518
+ }
519
+ return 3;
520
+ }
521
+ // Non-null past the deficit check above, which returns before this line
522
+ // whenever the root cannot be ranked.
523
+ const rows = rank(task, args.skills_dir as string);
443
524
  if (args.json) {
444
525
  const sliced = args.top ? rows.slice(0, args.top) : rows;
445
526
  const payload = sliced.map(([n, s, p]) => ({ name: n, score: s, personas: p }));
@@ -29,6 +29,9 @@ import * as fs from 'node:fs';
29
29
  import { fileURLToPath, pathToFileURL } from 'node:url';
30
30
 
31
31
  import { audit, type PersonaRow } from './audit_persona_coverage.js';
32
+ /** Sentinel for "no catalogue root resolved" — never a readable path. */
33
+ const NO_CATALOGUE = '<no-skills-catalogue>';
34
+
32
35
  import { DEFAULT_SKILLS_DIR, rank } from './score_skill_relevance.js';
33
36
 
34
37
  const _HERE = fileURLToPath(import.meta.url);
@@ -211,7 +214,11 @@ function _parseInt(raw: string): number {
211
214
  export function parse_args(argv: string[]): Args {
212
215
  const args: Args = {
213
216
  task: '',
214
- skills_dir: DEFAULT_SKILLS_DIR,
217
+ // `?? ''` is deliberately NOT used here: an empty string re-creates
218
+ // exactly the silent-empty-catalogue defect that repointing
219
+ // DEFAULT_SKILLS_DIR removed. When no catalogue resolves, this reads
220
+ // as the literal marker below and the caller's own check reports it.
221
+ skills_dir: DEFAULT_SKILLS_DIR ?? NO_CATALOGUE,
215
222
  personas_dir: DEFAULT_PERSONAS,
216
223
  top: 3,
217
224
  json: false,
@@ -24,6 +24,7 @@ import { assertScanned, DeadScopeError } from './_lib/scan_scope.js';
24
24
  // tier-usage re-tier already ships. Imported rather than restated so the sink
25
25
  // section and the re-tier decision cannot drift to two different numbers.
26
26
  import { DEFAULT_TIER_USAGE_RETIER } from '../agent-src/templates/scripts/telemetry/settings.js';
27
+ import { generatedByQuote } from './_lib/generated_by.js';
27
28
 
28
29
  const _HERE = path.dirname(fileURLToPath(import.meta.url));
29
30
  // parent.parent.parent of the .py file (src/scripts/skill_usage_report.py)
@@ -469,7 +470,7 @@ export function render(
469
470
  const lines: string[] = [
470
471
  '# Skill Usage Report (baseline)',
471
472
  '',
472
- '> Generated by `src/scripts/skill_usage_report.ts`. Source:',
473
+ generatedByQuote('skill_usage_report', 'Source:'),
473
474
  '> `agents/runtime/metrics/skill-usage.jsonl` (collector emits per-turn',
474
475
  '> exposure/mention records). See',
475
476
  '> [`step-2-skill-inventory-rationalization.md`](../roadmaps/step-2-skill-inventory-rationalization.md)',