@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
@@ -217,6 +217,7 @@ interface ParsedArgs {
217
217
  intake_id: string | null;
218
218
  proposal: string | null;
219
219
  format: 'text' | 'json';
220
+ quiet: boolean;
220
221
  }
221
222
 
222
223
  function _argparse_error(message: string): never {
@@ -228,6 +229,7 @@ function parse_args(argv: readonly string[]): ParsedArgs {
228
229
  let intake_id: string | null = null;
229
230
  let proposal: string | null = null;
230
231
  let format: 'text' | 'json' = 'text';
232
+ let quiet = false;
231
233
  // argparse reports a mutually-exclusive conflict against the SECOND-seen
232
234
  // arg at the point it is parsed (order-sensitive), so check inline rather
233
235
  // than after the loop.
@@ -248,10 +250,12 @@ function parse_args(argv: readonly string[]): ParsedArgs {
248
250
  format = _checkFormat(v);
249
251
  } else if (arg.startsWith('--format=')) {
250
252
  format = _checkFormat(arg.slice('--format='.length));
253
+ } else if (arg === '--quiet') {
254
+ quiet = true;
251
255
  } else if (arg === '-h' || arg === '--help') {
252
256
  process.stdout.write(
253
257
  'usage: check_memory_proposal [-h] (--intake-id INTAKE_ID | --proposal PROPOSAL)\n' +
254
- ' [--format {text,json}]\n',
258
+ ' [--format {text,json}] [--quiet]\n',
255
259
  );
256
260
  process.exit(0);
257
261
  } else {
@@ -261,7 +265,7 @@ function parse_args(argv: readonly string[]): ParsedArgs {
261
265
  if (intake_id === null && proposal === null) {
262
266
  _argparse_error('one of the arguments --intake-id --proposal is required');
263
267
  }
264
- return { intake_id, proposal, format };
268
+ return { intake_id, proposal, format, quiet };
265
269
  }
266
270
 
267
271
  function _need(argv: readonly string[], i: number, flag: string): string {
@@ -322,7 +326,9 @@ function main(argv?: readonly string[]): number {
322
326
  process.stdout.write(` 🔴 ${f}\n`);
323
327
  }
324
328
  } else {
325
- process.stdout.write(`✅ ${source} — gate passed\n`);
329
+ if (!args.quiet) {
330
+ process.stdout.write(`✅ ${source} — gate passed\n`);
331
+ }
326
332
  }
327
333
  }
328
334
  return failures.length > 0 ? 1 : 0;
@@ -246,6 +246,74 @@ function _pad2(v: string): string {
246
246
  * (`agents/memory/<type>.yml` or `<type>/entries.yml` with an `entries:`
247
247
  * list), so consumers can adopt either.
248
248
  */
249
+ const _CURATED_STATUS_EXCLUDE: ReadonlySet<string> = new Set(['deprecated', 'archived', 'superseded']);
250
+
251
+ /** Mirror Python `entry.get("status") in _CURATED_STATUS_EXCLUDE`. */
252
+ function _statusExcluded(entry: Record<string, unknown>): boolean {
253
+ const status = entry['status'];
254
+ return typeof status === 'string' && _CURATED_STATUS_EXCLUDE.has(status);
255
+ }
256
+
257
+
258
+ /*
259
+ * Staleness, ported from `src/scripts/memory_lookup.ts` on 2026-08-26
260
+ * (`road-to-memory-twin-reconciliation` 2.2, verdict `dev-side-correct`).
261
+ *
262
+ * The template previously had NO staleness handling at all — `grep -c stale`
263
+ * returned 0 — so a consumer retrieved curated entries whose own
264
+ * `review_after_days` window had expired, with nothing saying so. `check_memory`
265
+ * required both fields on every entry the whole time; only retrieval ignored
266
+ * them.
267
+ *
268
+ * Portable by construction: Date math and a regex, no `_lib` import.
269
+ */
270
+ function _today(): Date {
271
+ const now = new Date();
272
+ return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));
273
+ }
274
+
275
+ function _parseIsoDate(s: string): Date | null {
276
+ const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(s);
277
+ if (!m) {
278
+ return null;
279
+ }
280
+ const y = Number(m[1]);
281
+ const mo = Number(m[2]);
282
+ const d = Number(m[3]);
283
+ if (mo < 1 || mo > 12 || d < 1 || d > 31) {
284
+ return null;
285
+ }
286
+ const date = new Date(Date.UTC(y, mo - 1, d));
287
+ // Reject overflow (e.g. 2026-02-31 → March), matching fromisoformat's strictness.
288
+ if (date.getUTCFullYear() !== y || date.getUTCMonth() !== mo - 1 || date.getUTCDate() !== d) {
289
+ return null;
290
+ }
291
+ return date;
292
+ }
293
+
294
+ function _pyStrDateLike(lv: unknown): string {
295
+ if (lv instanceof PyTimestamp) {
296
+ return lv.pyStr;
297
+ }
298
+ return _pyStr(lv);
299
+ }
300
+
301
+ function _isStale(entry: Record<string, unknown>, today: Date): boolean {
302
+ const lv = entry['last_validated'];
303
+ const rad = entry['review_after_days'];
304
+ // Python: `not lv or not isinstance(rad, int)`. PyYAML ints land as JS
305
+ // numbers; booleans are int in Python but excluded here as the common path.
306
+ if (!lv || typeof rad !== 'number' || !Number.isInteger(rad)) {
307
+ return false;
308
+ }
309
+ const validated = _parseIsoDate(_pyStrDateLike(lv));
310
+ if (validated === null) {
311
+ return false;
312
+ }
313
+ const days = Math.round((today.getTime() - validated.getTime()) / 86_400_000);
314
+ return days > rad;
315
+ }
316
+
249
317
  function* _iter_curated_entries(mtype: string): Generator<[string, Record<string, unknown>]> {
250
318
  const type_dir = path.join(MEMORY_ROOT, mtype);
251
319
  const single_file = path.join(MEMORY_ROOT, `${mtype}.yml`);
@@ -254,6 +322,9 @@ function* _iter_curated_entries(mtype: string): Generator<[string, Record<string
254
322
  const entries = _isPlainObject(data) ? data['entries'] : null;
255
323
  for (const e of Array.isArray(entries) ? entries : []) {
256
324
  if (_isPlainObject(e)) {
325
+ if (_statusExcluded(e)) {
326
+ continue;
327
+ }
257
328
  yield [single_file, e];
258
329
  }
259
330
  }
@@ -266,11 +337,17 @@ function* _iter_curated_entries(mtype: string): Generator<[string, Record<string
266
337
  if (Array.isArray(entries)) {
267
338
  for (const e of entries) {
268
339
  if (_isPlainObject(e)) {
340
+ if (_statusExcluded(e)) {
341
+ continue;
342
+ }
269
343
  yield [yml, e];
270
344
  }
271
345
  }
272
346
  } else if (_isPlainObject(data) && data['id']) {
273
347
  // Flat, one-entry-per-file layout (content-addressed).
348
+ if (_statusExcluded(data)) {
349
+ continue;
350
+ }
274
351
  yield [yml, data];
275
352
  }
276
353
  }
@@ -454,6 +531,7 @@ function _cross_repo_hits(keys: string[], limit: number): Hit[] {
454
531
  */
455
532
  export function retrieve(types: string[], keys: string[], limit = 5): Hit[] {
456
533
  const repo_hits: Hit[] = [];
534
+ const today = _today();
457
535
  for (const mtype of types) {
458
536
  if (mtype === KNOWLEDGE_TYPE) {
459
537
  for (const [p, entry] of _iter_knowledge_entries()) {
@@ -488,6 +566,14 @@ export function retrieve(types: string[], keys: string[], limit = 5): Hit[] {
488
566
  continue;
489
567
  }
490
568
  for (const [p, entry] of _iter_curated_entries(mtype)) {
569
+ // A curated entry past its own `review_after_days` window is not
570
+ // retrieved. The dev side additionally reports it under `skipped`;
571
+ // this copy has no `retrieve_with_meta`, so it filters silently —
572
+ // the exclusion is the behaviour that matters, the report is the
573
+ // richer surface.
574
+ if (_isStale(entry, today)) {
575
+ continue;
576
+ }
491
577
  repo_hits.push(new Hit(String(entry['id'] ?? ''), mtype, 'curated', String(p), _score(entry, keys), entry));
492
578
  }
493
579
  for (const [p, entry] of _iter_intake_entries(mtype)) {
@@ -29,6 +29,7 @@
29
29
 
30
30
  import * as crypto from 'node:crypto';
31
31
  import * as fs from 'node:fs';
32
+ import * as os from 'node:os';
32
33
  import * as path from 'node:path';
33
34
  import process from 'node:process';
34
35
  import { fileURLToPath, pathToFileURL } from 'node:url';
@@ -217,6 +218,45 @@ export interface SignalRecord {
217
218
  * The file path is the single source of truth: there is no external backend
218
219
  * to route to, so merge-safety holds in every mode.
219
220
  */
221
+ export class ProvenanceRefusedError extends Error {}
222
+
223
+ // lint-store-boundary: ignore — the provenance gate must RECOGNISE the global root to refuse it
224
+ const _GLOBAL_STORE_MARKER = `.event4u${path.sep}agent-config`;
225
+
226
+ export function _origin_is_global(origin: string): boolean {
227
+ if (!origin.includes('/') && !origin.includes(path.sep) && !origin.startsWith('~')) {
228
+ return false; // symbolic origins ('agent', 'claude', 'cursor', …) are not paths
229
+ }
230
+ const expanded = origin.startsWith('~')
231
+ ? path.join(os.homedir(), origin.slice(1)) // lint-store-boundary: ignore — the gate itself must recognise the global root
232
+ : origin;
233
+ let resolved: string;
234
+ try {
235
+ resolved = path.resolve(expanded);
236
+ } catch {
237
+ return false;
238
+ }
239
+ return resolved.includes(_GLOBAL_STORE_MARKER) || /(^|[\\/])\.event4u([\\/]|$)/.test(origin);
240
+ }
241
+
242
+ export function _assert_project_writable(record: { origin: string; subject?: unknown }): void {
243
+ if (record.subject === 'user') {
244
+ throw new ProvenanceRefusedError(
245
+ 'provenance gate: subject: user records live global-only and may ' +
246
+ 'never be written into a tracked project artifact (ADR-130).',
247
+ );
248
+ }
249
+ if (_origin_is_global(record.origin)) {
250
+ throw new ProvenanceRefusedError(
251
+ `provenance gate: origin resolves into the user-global store ` +
252
+ `(${record.origin}) — refused entry into tracked project intake (ADR-130).`,
253
+ );
254
+ }
255
+ }
256
+
257
+ /**
258
+ * Append a signal entry. Returns the written record, or null when skipped.
259
+ */
220
260
  export function emit(
221
261
  entry_type: string,
222
262
  p: string,
@@ -255,6 +295,10 @@ export function emit(
255
295
  }
256
296
  }
257
297
  }
298
+ if (!('subject' in record)) {
299
+ record.subject = 'project'; // additive default (ADR-130)
300
+ }
301
+ _assert_project_writable(record as { origin: string; subject?: unknown });
258
302
  fs.mkdirSync(INTAKE_ROOT, { recursive: true });
259
303
  const target = _monthly_file();
260
304
  fs.appendFileSync(target, `${_jsonDumpsUnicode(record)}\n`, 'utf-8');
@@ -16,6 +16,9 @@
16
16
  * Flow:
17
17
  *
18
18
  * - `plan` outcome is not `success` → BLOCKED on precondition.
19
+ * - no RED evidence on `state.tests` → BLOCKED with
20
+ * `@agent-directive: observe-red` so the agent writes and observes the
21
+ * failing test for the next single behaviour BEFORE any production edit.
19
22
  * - `state.changes` empty → BLOCKED with `@agent-directive:
20
23
  * apply-plan` so the agent applies the plan.
21
24
  * - `state.changes` populated but malformed (entries missing
@@ -26,6 +29,26 @@
26
29
  * `docs/contracts/implement-ticket-flow.md#deliverystate-the-only-shared-object`
27
30
  * — each entry is a dict with at least a `path`; optional
28
31
  * `lines` / `purpose` feed the delivery report.
32
+ *
33
+ * RED evidence lives at `state.tests.red` and is the engine-side carrier for
34
+ * the test-first default in `rules/think-before-action.md`. Two accepted
35
+ * shapes, and nothing else counts:
36
+ *
37
+ * - one observation, or a list of them, each a dict with a non-empty
38
+ * `behaviour` and a `failure_class` from `_RED_FAILURE_CLASSES` — the three
39
+ * valid RED classes the `test-driven-development` skill admits (a failing
40
+ * assertion, a missing target, a contract failure). A broken fixture, a
41
+ * syntax error in the test, a missing unrelated dependency and a runner
42
+ * fault are NOT RED and are rejected by that same contract, not here.
43
+ * - `{exempt: "<reason>"}` — the recorded override for work the skill's
44
+ * *Do NOT use when* list already excludes (scaffolding, generated files,
45
+ * documentation). Recorded, never silent: an absent key is not an exemption.
46
+ *
47
+ * The gate is per behaviour, not per run: it names the behaviour it is waiting
48
+ * on and re-fires for the next one. It does NOT detect a batch — an agent that
49
+ * front-loads every test for the feature satisfies it, and the eval that fails
50
+ * a one-test-phase-then-one-code-phase plan is the control for that, not this
51
+ * step.
29
52
  */
30
53
 
31
54
  import type { DeliveryState} from '../../delivery_state.js';
@@ -39,6 +62,13 @@ export const AMBIGUITIES: ReadonlyArray<Record<string, string>> = [
39
62
  trigger: '`plan` outcome is not `success`',
40
63
  resolution: 're-run `/implement-ticket` from the start',
41
64
  },
65
+ {
66
+ code: 'no_red_evidence',
67
+ trigger: '`state.tests.red` carries neither an observed failing test for a ' +
68
+ 'behaviour nor a recorded exemption',
69
+ resolution: 'agent directive `observe-red` → write the failing test for the ' +
70
+ 'next single behaviour, observe it fail, record it',
71
+ },
42
72
  {
43
73
  code: 'empty_changes_delegate',
44
74
  trigger: '`state.changes` empty — plan not applied yet',
@@ -68,6 +98,13 @@ export function run(state: DeliveryState): StepResult {
68
98
  return _blocked_on_precondition(state);
69
99
  }
70
100
 
101
+ // Test-first, enforced where the engine can see it: no production work is
102
+ // emitted for a behaviour whose failing test has not been observed.
103
+ const redIssue = _diagnose_red(state.tests);
104
+ if (redIssue !== null) {
105
+ return _blocked_on_missing_red(state, redIssue);
106
+ }
107
+
71
108
  if (!_pyTruthy(state.changes)) {
72
109
  return _delegate_to_apply_plan(state);
73
110
  }
@@ -98,6 +135,59 @@ function _diagnose_changes(changes: Any[]): string[] {
98
135
  return issues;
99
136
  }
100
137
 
138
+ /** The three RED classes the `test-driven-development` mode contract admits. */
139
+ const _RED_FAILURE_CLASSES = ['assertion', 'missing_target', 'contract'] as const;
140
+
141
+ /**
142
+ * `null` when `state.tests` carries usable RED evidence, else the complaint.
143
+ *
144
+ * Absent is a complaint, not an exemption — the whole point of the gate.
145
+ */
146
+ function _diagnose_red(tests: Any): string | null {
147
+ if (!_isPlainObject(tests)) {
148
+ return 'no `state.tests.red` recorded';
149
+ }
150
+ const red = (tests as Record<string, unknown>).red;
151
+ if (!_pyTruthy(red)) {
152
+ return 'no `state.tests.red` recorded';
153
+ }
154
+ if (_isPlainObject(red) && _pyTruthy((red as Record<string, unknown>).exempt)) {
155
+ return null;
156
+ }
157
+ const observations = Array.isArray(red) ? red : [red];
158
+ for (const obs of observations) {
159
+ if (!_isPlainObject(obs)) {
160
+ return 'a `red` observation is not a dict';
161
+ }
162
+ const o = obs as Record<string, unknown>;
163
+ if (typeof o.behaviour !== 'string' || _pyStrip(o.behaviour).length === 0) {
164
+ return 'a `red` observation names no `behaviour`';
165
+ }
166
+ if (!_RED_FAILURE_CLASSES.includes(o.failure_class as (typeof _RED_FAILURE_CLASSES)[number])) {
167
+ return (
168
+ `\`red\` observation for \`${_pyStrip(o.behaviour)}\` has ` +
169
+ `\`failure_class\` outside ${_RED_FAILURE_CLASSES.join(', ')}`
170
+ );
171
+ }
172
+ }
173
+ return null;
174
+ }
175
+
176
+ function _blocked_on_missing_red(state: DeliveryState, issue: string): StepResult {
177
+ const ticketId = _ticketId(state);
178
+ return new StepResult({
179
+ outcome: Outcome.BLOCKED,
180
+ questions: [
181
+ agent_directive('observe-red', { ticket: ticketId }),
182
+ `> Ticket ${ticketId} — implement gate refused: ${issue}. Write the ` +
183
+ 'failing test for the next single behaviour and observe it fail first.',
184
+ '> 1. Continue — write and run that one failing test',
185
+ '> 2. Record an exemption — `state.tests.red = {exempt: "<reason>"}`',
186
+ ],
187
+ message: `Ticket ${ticketId} needs an observed failing test before production work: ${issue}.`,
188
+ });
189
+ }
190
+
101
191
  function _delegate_to_apply_plan(state: DeliveryState): StepResult {
102
192
  const ticketId = _ticketId(state);
103
193
  return new StepResult({
@@ -45,6 +45,17 @@ export const SUPPORTED_KINDS: ReadonlyArray<string> = ['ticket', 'prompt'];
45
45
  // test, verify, report). The leaf name is the dispatcher slot key; in Python
46
46
  // it is derived via `step.__name__.rsplit(".", 1)[-1]` — hardcoded here since
47
47
  // the modules are imported statically.
48
+ //
49
+ // `implement` stays BEFORE `test`, deliberately, and the order is not the
50
+ // test-after instruction it looks like. The tuple is linear and runs once per
51
+ // flow, so moving `test` in front of `implement` would buy exactly one test
52
+ // phase followed by one code phase — batch-TDD, which is the second
53
+ // anti-pattern rather than a fix for the first. Test-first is enforced INSIDE
54
+ // `implement` instead: `./implement.ts` refuses to emit production work for a
55
+ // behaviour whose failing test has not been observed (`state.tests.red`), so
56
+ // the discipline is per behaviour while the tuple stays per flow. The `test`
57
+ // slot here is the whole-suite verdict that gates `verify`, never the first
58
+ // time a test is written.
48
59
  const _STEPS: ReadonlyArray<[string, { run: Step; AMBIGUITIES: ReadonlyArray<Record<string, string>> }]> = [
49
60
  ['refine', refine],
50
61
  ['memory', memory],
@@ -25,6 +25,13 @@
25
25
  * be silently skipped, and the loop cannot report one as success.
26
26
  * - Optional keys (`targeted`, `full`, `duration_ms`,
27
27
  * `followups`) feed the delivery report.
28
+ * - `red` is NOT a verdict. It is the per-behaviour RED evidence
29
+ * `./implement.ts` gates on, written before any production edit, and it
30
+ * says nothing about the suite. A `state.tests` carrying `red` and no
31
+ * `verdict` therefore means the runner has not been invoked for the suite
32
+ * yet → delegate, exactly as an empty `state.tests` does. A `verdict` that
33
+ * is present and unrecognised still blocks on shape; this is a
34
+ * not-yet-run case, never a relaxed verdict check.
28
35
  */
29
36
 
30
37
  import type { DeliveryState} from '../../delivery_state.js';
@@ -86,7 +93,7 @@ export function run(state: DeliveryState): StepResult {
86
93
  }
87
94
 
88
95
  const tests = state.tests;
89
- if (!_pyTruthy(tests)) {
96
+ if (!_pyTruthy(tests) || _isRedOnly(tests)) {
90
97
  return _delegate_to_run_tests(state, policy.widen_tests);
91
98
  }
92
99
 
@@ -104,6 +111,21 @@ export function run(state: DeliveryState): StepResult {
104
111
  return new StepResult({ outcome: Outcome.SUCCESS });
105
112
  }
106
113
 
114
+ /**
115
+ * True when `state.tests` carries only the pre-implement RED record.
116
+ *
117
+ * `red` is written by the `implement` gate's `observe-red` directive; it is
118
+ * evidence about one behaviour's first failing run, not a suite verdict. Only
119
+ * a MISSING `verdict` routes here — a present-but-wrong one still blocks.
120
+ */
121
+ function _isRedOnly(tests: Any): boolean {
122
+ if (!_isPlainObject(tests)) {
123
+ return false;
124
+ }
125
+ const d = tests as Record<string, unknown>;
126
+ return !('verdict' in d) && _pyTruthy(d.red);
127
+ }
128
+
107
129
  function _diagnose_tests(tests: Any): string[] {
108
130
  if (!_isPlainObject(tests)) {
109
131
  return [`state.tests must be a dict, got ${_pyTypeName(tests)}`];
@@ -33,7 +33,16 @@ import { type Any, Outcome, StepResult, agent_directive } from '../../delivery_s
33
33
  import { resolve_policy } from '../../persona_policy.js';
34
34
  import { decide, partial_exit, record_attempt, retry_halt, unmet_dod, verdict_signature } from './_self_fix.js';
35
35
 
36
- const _ALLOWED_VERDICTS = ['success', 'blocked', 'partial'] as const;
36
+ /**
37
+ * DERIVED, never re-declared. `delivery_state.ts` is the step vocabulary's
38
+ * declaration for the template tree (templates are self-contained by contract
39
+ * and may not import from `src/scripts/`, so the registry mirrors it rather
40
+ * than the other way round). Spelling the three values again here made this the
41
+ * THIRD copy, and a third copy is how one vocabulary becomes two truths --
42
+ * which is the defect the outcome-vocabulary reconciliation was opened to fix.
43
+ * Found by the widened duplicate detector, 2026-08-30.
44
+ */
45
+ const _ALLOWED_VERDICTS = Object.values(Outcome) as ReadonlyArray<Outcome>;
37
46
 
38
47
  /** Declared ambiguity surfaces. Advisory personas skip this step entirely. */
39
48
  export const AMBIGUITIES: ReadonlyArray<Record<string, string>> = [
@@ -20,7 +20,11 @@ import {
20
20
  /** Agent directive that drives end-to-end smoke scenarios. */
21
21
  export const INTEGRATION_TEST_DIRECTIVE = 'integration-test';
22
22
 
23
- const _ALLOWED_VERDICTS: ReadonlyArray<string> = ['success', 'blocked', 'partial'];
23
+ /**
24
+ * DERIVED, never re-declared — see the note in `directives/backend/verify.ts`.
25
+ * This was the fourth copy of the step vocabulary.
26
+ */
27
+ const _ALLOWED_VERDICTS: ReadonlyArray<string> = Object.values(Outcome);
24
28
 
25
29
  export const AMBIGUITIES: ReadonlyArray<Record<string, string>> = [
26
30
  {
@@ -236,7 +236,7 @@ export function resolve_toolchain(
236
236
  quality.push(..._php_quality(project_root, composer, wrappers));
237
237
  }
238
238
  if (has_package) {
239
- runners.push(..._js_runners(pkg, wrappers));
239
+ runners.push(..._js_runners(pkg, wrappers, _package_manager(project_root, pkg)));
240
240
  quality.push(..._js_quality(pkg, wrappers));
241
241
  }
242
242
  if (has_python) {
@@ -347,7 +347,7 @@ function _php_runners(root: string, composer: Manifest, wrappers: Wrappers): Run
347
347
  ];
348
348
  }
349
349
 
350
- function _js_runners(pkg: Manifest, wrappers: Wrappers): RunnerResult[] {
350
+ function _js_runners(pkg: Manifest, wrappers: Wrappers, manager: string): RunnerResult[] {
351
351
  const deps = _all_dependencies(
352
352
  pkg,
353
353
  'dependencies',
@@ -383,17 +383,17 @@ function _js_runners(pkg: Manifest, wrappers: Wrappers): RunnerResult[] {
383
383
 
384
384
  // e2e runner — separate bucket, excluded unless --include-e2e.
385
385
  if ('@playwright/test' in deps || 'playwright' in deps) {
386
- const cmd = _script_command(scripts, ['test:e2e', 'e2e', 'playwright']) || 'npx playwright test';
386
+ const cmd = _script_command(scripts, ['test:e2e', 'e2e', 'playwright'], manager) || 'npx playwright test';
387
387
  out.push(
388
388
  new RunnerResult('js', 'playwright', cmd, SPEED_E2E, HIGH, '@playwright/test in package deps'),
389
389
  );
390
390
  } else if ('cypress' in deps) {
391
- const cmd = _script_command(scripts, ['test:e2e', 'e2e', 'cypress']) || 'npx cypress run';
391
+ const cmd = _script_command(scripts, ['test:e2e', 'e2e', 'cypress'], manager) || 'npx cypress run';
392
392
  out.push(new RunnerResult('js', 'cypress', cmd, SPEED_E2E, HIGH, 'cypress in package deps'));
393
393
  }
394
394
 
395
395
  // slow bucket — an explicit slow/integration script.
396
- const slow_cmd = _script_command(scripts, ['test:slow', 'test:integration']);
396
+ const slow_cmd = _script_command(scripts, ['test:slow', 'test:integration'], manager);
397
397
  if (slow_cmd) {
398
398
  out.push(
399
399
  new RunnerResult(
@@ -487,19 +487,100 @@ function _task_runner_wrappers(root: string, pkg: Manifest): Wrappers {
487
487
  }
488
488
  const scripts: Manifest = _isDict(pkg.scripts) ? pkg.scripts : {};
489
489
  if (_isDict(scripts) && 'test' in scripts) {
490
- out['js-test'] = `${_package_manager(root)} test`;
490
+ out['js-test'] = `${_package_manager(root, pkg)} test`;
491
491
  }
492
492
  return out;
493
493
  }
494
494
 
495
- function _package_manager(root: string): string {
496
- if (_is_file(path.join(root, 'pnpm-lock.yaml'))) {
497
- return 'pnpm';
495
+ /**
496
+ * Lockfile → manager, in the order `monorepo-workspace/SKILL.md` § 1 states.
497
+ * Kept as data rather than a chain of ifs so `PACKAGE_MANAGER_BRANCHES` below
498
+ * can assert the count against the documented one.
499
+ */
500
+ const LOCKFILE_MANAGERS: ReadonlyArray<readonly [string, string]> = [
501
+ ['pnpm-lock.yaml', 'pnpm'],
502
+ ['yarn.lock', 'yarn'],
503
+ ['bun.lock', 'bun'],
504
+ ['bun.lockb', 'bun'],
505
+ ['package-lock.json', 'npm'],
506
+ ];
507
+
508
+ /**
509
+ * The five branches `monorepo-workspace/SKILL.md` § 1 specifies, named so a
510
+ * test can assert none went missing. The skill is the contract and it was
511
+ * already correct; this list exists because the code implemented three of the
512
+ * five and nothing noticed.
513
+ */
514
+ export const PACKAGE_MANAGER_BRANCHES: readonly string[] = [
515
+ 'packageManager',
516
+ 'pnpm',
517
+ 'yarn',
518
+ 'bun',
519
+ 'npm',
520
+ ] as const;
521
+
522
+ export interface PackageManagerResolution {
523
+ /** The resolved manager, or `null` when the cascade deliberately refuses. */
524
+ manager: string | null;
525
+ /** Which branch answered — one of `PACKAGE_MANAGER_BRANCHES`, or `'ambiguous'`. */
526
+ via: string;
527
+ /** Non-empty when the cascade refuses: the reported finding. */
528
+ finding: string;
529
+ }
530
+
531
+ /**
532
+ * Resolve the package manager per `monorepo-workspace/SKILL.md` § 1.
533
+ *
534
+ * Two behaviours the previous three-branch version did not have, and both are
535
+ * in the skill rather than invented here:
536
+ *
537
+ * - `packageManager` in the root `package.json` is the DECLARATION and wins
538
+ * when present, because it is what Corepack enforces. A lockfile is an
539
+ * inference; a declaration is not.
540
+ * - **Two lockfiles is a finding, not a tie to break.** The old code returned
541
+ * `pnpm` for a repository carrying both `pnpm-lock.yaml` and `yarn.lock`,
542
+ * silently picking the first branch it tested. That is a guess presented as
543
+ * an answer, and the skill says to report both and stop.
544
+ */
545
+ export function _resolve_package_manager(
546
+ root: string,
547
+ pkg?: Manifest,
548
+ ): PackageManagerResolution {
549
+ const declared = pkg === undefined ? undefined : pkg['packageManager'];
550
+ if (typeof declared === 'string' && declared.trim() !== '') {
551
+ // `pnpm@9.1.0` → `pnpm`. Corepack's own format.
552
+ const name = declared.trim().split('@')[0] as string;
553
+ if (name !== '') {
554
+ return { manager: name, via: 'packageManager', finding: '' };
555
+ }
556
+ }
557
+ const present = LOCKFILE_MANAGERS.filter(([file]) => _is_file(path.join(root, file)));
558
+ const distinct = [...new Set(present.map(([, mgr]) => mgr))];
559
+ if (distinct.length > 1) {
560
+ return {
561
+ manager: null,
562
+ via: 'ambiguous',
563
+ finding:
564
+ `two package-manager lockfiles present (${present.map(([f]) => f).join(', ')}) ` +
565
+ 'and no `packageManager` declaration — report both and stop, per ' +
566
+ 'monorepo-workspace SKILL.md § 1',
567
+ };
498
568
  }
499
- if (_is_file(path.join(root, 'yarn.lock'))) {
500
- return 'yarn';
569
+ if (distinct.length === 1) {
570
+ const mgr = distinct[0] as string;
571
+ return { manager: mgr, via: mgr, finding: '' };
501
572
  }
502
- return 'npm';
573
+ return { manager: 'npm', via: 'npm', finding: '' };
574
+ }
575
+
576
+ /**
577
+ * The resolved manager as a bare string for command construction. Falls back to
578
+ * `npm` on the ambiguous case so a caller building a command string still gets
579
+ * one — the FINDING is what carries the ambiguity, and a caller that needs it
580
+ * calls `_resolve_package_manager` directly.
581
+ */
582
+ function _package_manager(root: string, pkg?: Manifest): string {
583
+ return _resolve_package_manager(root, pkg).manager ?? 'npm';
503
584
  }
504
585
 
505
586
  // --------------------------------------------------------------------------
@@ -580,10 +661,17 @@ function _script_uses(scripts: Manifest, name: string, tool: string): boolean {
580
661
  return typeof value === 'string' && value.includes(tool);
581
662
  }
582
663
 
583
- function _script_command(scripts: Manifest, names: string[]): string {
664
+ /**
665
+ * Build a `<manager> run <script>` command for the first matching script name.
666
+ *
667
+ * `manager` used to be hardcoded `npm`. Every command the work engine hands an
668
+ * agent for verification inherited that, so a pnpm or yarn repository was told
669
+ * to run a command its lockfile contradicts.
670
+ */
671
+ function _script_command(scripts: Manifest, names: string[], manager: string): string {
584
672
  for (const name of names) {
585
673
  if (typeof scripts[name] === 'string') {
586
- return `npm run ${name}`;
674
+ return `${manager} run ${name}`;
587
675
  }
588
676
  }
589
677
  return '';