@event4u/agent-config 14.12.0 → 14.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (521) hide show
  1. package/.augment-plugin/marketplace.json +3 -3
  2. package/.augment-plugin/plugin.json +1 -1
  3. package/.claude-plugin/marketplace.json +1 -1
  4. package/CHANGELOG.md +118 -155
  5. package/CONTRIBUTING.md +38 -0
  6. package/CREDITS.md +135 -0
  7. package/NOTICE +13 -0
  8. package/README.md +8 -6
  9. package/dist/agent-src/commands/analyze/inbox.md +145 -2
  10. package/dist/agent-src/commands/feature/dev.md +7 -2
  11. package/dist/agent-src/commands/ghostwriter/write.md +5 -1
  12. package/dist/agent-src/commands/implement-ticket.md +1 -1
  13. package/dist/agent-src/commands/mission/upgrade.md +1 -1
  14. package/dist/agent-src/commands/orchestrate.md +2 -2
  15. package/dist/agent-src/commands/post-as/me.md +5 -1
  16. package/dist/agent-src/commands/pr/merge.md +19 -6
  17. package/dist/agent-src/commands/roadmap/process-full.md +19 -5
  18. package/dist/agent-src/commands/tdd/red.md +12 -2
  19. package/dist/agent-src/commands/work.md +1 -1
  20. package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +40 -0
  21. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +5 -2
  22. package/dist/agent-src/contexts/execution/autonomy-mechanics.md +21 -0
  23. package/dist/agent-src/contexts/execution/orchestration-telemetry.md +1 -0
  24. package/dist/agent-src/contexts/execution/subagent-response-contract.md +40 -0
  25. package/dist/agent-src/contexts/execution/subagent-steering.md +13 -1
  26. package/dist/agent-src/contexts/execution/terminal-states.md +96 -0
  27. package/dist/agent-src/rules/artifact-drafting-protocol.md +1 -1
  28. package/dist/agent-src/rules/broken-access-control.md +4 -0
  29. package/dist/agent-src/rules/code-comment-discipline.md +6 -0
  30. package/dist/agent-src/rules/code-provenance.md +4 -0
  31. package/dist/agent-src/rules/design-fidelity.md +1 -1
  32. package/dist/agent-src/rules/domain-safety-pii.md +4 -0
  33. package/dist/agent-src/rules/domain-safety-retention.md +4 -0
  34. package/dist/agent-src/rules/engineering-safety-floor.md +2 -0
  35. package/dist/agent-src/rules/external-code-graph-interop.md +14 -12
  36. package/dist/agent-src/rules/improve-before-implement.md +6 -8
  37. package/dist/agent-src/rules/laravel-routing.md +1 -1
  38. package/dist/agent-src/rules/lethal-trifecta-guard.md +4 -0
  39. package/dist/agent-src/rules/secret-vcs-guard.md +2 -0
  40. package/dist/agent-src/rules/security-sensitive-stop.md +2 -0
  41. package/dist/agent-src/rules/source-confidentiality.md +12 -34
  42. package/dist/agent-src/rules/symfony-routing.md +1 -1
  43. package/dist/agent-src/rules/token-efficiency.md +14 -0
  44. package/dist/agent-src/rules/tool-safety.md +4 -0
  45. package/dist/agent-src/rules/untrusted-input-defense.md +4 -0
  46. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +252 -8
  47. package/dist/agent-src/scripts/guarded_baseline.ts +343 -0
  48. package/dist/agent-src/scripts/roadmap_set_step.ts +253 -0
  49. package/dist/agent-src/scripts/stub_queue.ts +82 -0
  50. package/dist/agent-src/scripts/stubs_due.ts +516 -0
  51. package/dist/agent-src/scripts/ticket_bundles.ts +84 -0
  52. package/dist/agent-src/scripts/update_roadmap_progress.ts +16 -12
  53. package/dist/agent-src/skills/brand-asset-generation/SKILL.md +17 -4
  54. package/dist/agent-src/skills/brand-audit/SKILL.md +33 -0
  55. package/dist/agent-src/skills/code-intelligence/SKILL.md +57 -0
  56. package/dist/agent-src/skills/database/SKILL.md +8 -0
  57. package/dist/agent-src/skills/dependency-upgrade/SKILL.md +27 -0
  58. package/dist/agent-src/skills/design-review/SKILL.md +1 -1
  59. package/dist/agent-src/skills/doc-coauthoring/SKILL.md +1 -1
  60. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +17 -1
  61. package/dist/agent-src/skills/feature-planning/SKILL.md +9 -2
  62. package/dist/agent-src/skills/frontend-render-security/SKILL.md +44 -0
  63. package/dist/agent-src/skills/git-workflow/SKILL.md +1 -1
  64. package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.ts +38 -4
  65. package/dist/agent-src/skills/judge-artifact-completeness/rubrics/ticket-quality-score.json +2 -2
  66. package/dist/agent-src/skills/laravel/SKILL.md +35 -0
  67. package/dist/agent-src/skills/laravel-migration/SKILL.md +57 -3
  68. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +26 -0
  69. package/dist/agent-src/skills/playbook-authoring/SKILL.md +28 -1
  70. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +1 -1
  71. package/dist/agent-src/skills/skill-writing/references/procedure.md +5 -5
  72. package/dist/agent-src/skills/sql-writing/SKILL.md +7 -1
  73. package/dist/agent-src/skills/standards-from-config/SKILL.md +27 -4
  74. package/dist/agent-src/skills/supply-chain-intake/SKILL.md +11 -4
  75. package/dist/agent-src/skills/symfony-workflow/SKILL.md +35 -0
  76. package/dist/agent-src/skills/test-case-discovery/SKILL.md +85 -0
  77. package/dist/agent-src/skills/test-driven-development/SKILL.md +33 -9
  78. package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
  79. package/dist/agent-src/skills/testing-anti-patterns/process-anti-patterns.md +37 -0
  80. package/dist/agent-src/skills/ui-component-architect/SKILL.md +45 -2
  81. package/dist/agent-src/skills/upstream-contribute/SKILL.md +38 -1
  82. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +9 -4
  83. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  84. package/dist/agent-src/templates/roadmaps.md +97 -3
  85. package/dist/agent-src/templates/scripts/check_memory.ts +258 -17
  86. package/dist/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
  87. package/dist/agent-src/templates/scripts/memory_lookup.ts +86 -0
  88. package/dist/agent-src/templates/scripts/memory_signal.ts +44 -0
  89. package/dist/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
  90. package/dist/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
  91. package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
  92. package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
  93. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
  94. package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
  95. package/dist/cli/commands/uiAudit.js +124 -5
  96. package/dist/cli/registry.js +2 -0
  97. package/dist/cli-delegate/{chunk-HYWSRNUX.js → chunk-2DK2VJWG.js} +3 -3
  98. package/dist/cli-delegate/{chunk-JCW7ZLHK.js → chunk-4FS4WRXP.js} +5 -0
  99. package/dist/cli-delegate/{chunk-OMIVVCG2.js → chunk-A4QJ6ENT.js} +24 -0
  100. package/dist/cli-delegate/{chunk-JJA2QEWA.js → chunk-AKJGUQNO.js} +466 -285
  101. package/dist/cli-delegate/{chunk-E46KPN6K.js → chunk-BTWUYDGN.js} +424 -363
  102. package/dist/cli-delegate/{chunk-K4FFODTS.js → chunk-ILMUPLGW.js} +1227 -316
  103. package/dist/cli-delegate/{chunk-FF7WAFMR.js → chunk-KPBWFOPZ.js} +5 -1
  104. package/dist/cli-delegate/cmd_adr_effective.js +102 -0
  105. package/dist/cli-delegate/cmd_conformance.js +80 -11
  106. package/dist/cli-delegate/cmd_doctor.js +3 -3
  107. package/dist/cli-delegate/cmd_export.js +3 -2
  108. package/dist/cli-delegate/cmd_fleet.js +2 -2
  109. package/dist/cli-delegate/cmd_handoff.js +1 -1
  110. package/dist/cli-delegate/cmd_preflight.js +2 -2
  111. package/dist/cli-delegate/cmd_prune.js +3 -2
  112. package/dist/cli-delegate/cmd_settings_get.js +1 -1
  113. package/dist/cli-delegate/cmd_settings_migrate.js +3 -2
  114. package/dist/cli-delegate/cmd_settings_set.js +2 -2
  115. package/dist/cli-delegate/cmd_sync.js +3 -2
  116. package/dist/cli-delegate/cmd_uninstall.js +3 -2
  117. package/dist/cli-delegate/cmd_validate.js +3 -2
  118. package/dist/discovery/deprecation-report.md +1 -1
  119. package/dist/discovery/discovery-manifest.json +58 -58
  120. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  121. package/dist/discovery/discovery-manifest.summary.md +1 -1
  122. package/dist/discovery/dormancy-report.md +1 -1
  123. package/dist/discovery/orphan-report.md +1 -1
  124. package/dist/discovery/packs.json +2 -2
  125. package/dist/discovery/trust-report.md +1 -1
  126. package/dist/discovery/workspaces.json +2 -2
  127. package/dist/hooks/dispatch.js +2900 -1049
  128. package/dist/install/claudeRuleRewrite.js +254 -0
  129. package/dist/install/detect.js +29 -16
  130. package/dist/install/detect_php_shape.js +159 -0
  131. package/dist/install/install.mjs +634 -428
  132. package/dist/mcp/awesome-mcp-servers.row.md +1 -1
  133. package/dist/mcp/mcp-cloudflare-catalogue.json +1 -1
  134. package/dist/mcp/registry-manifest.json +3 -3
  135. package/dist/mcp/server.json +3 -3
  136. package/dist/mcp/server.mjs +4895 -2627
  137. package/dist/server/schemas/settings.js +3 -0
  138. package/dist/ui/assets/index-D0jaCRPM.js +29 -0
  139. package/dist/ui/index.html +1 -1
  140. package/docs/MIGRATION.md +1 -1
  141. package/docs/THIRD-PARTY-NOTICES.md +25 -0
  142. package/docs/contracts/provider-lifecycle.md +1 -1
  143. package/docs/contracts/settings-classes.md +10 -4
  144. package/docs/guidelines/agent-infra/5w2h-analysis.md +3 -3
  145. package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +1 -0
  146. package/docs/guidelines/agent-infra/artifact-drafting-protocol-mechanics.md +58 -3
  147. package/docs/guidelines/agent-infra/ask-when-uncertain-demos.md +2 -2
  148. package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +3 -3
  149. package/docs/guidelines/agent-infra/break-glass-usage.md +7 -7
  150. package/docs/guidelines/agent-infra/carve-out-predicates.md +3 -3
  151. package/docs/guidelines/agent-infra/comparison-matrix.md +1 -1
  152. package/docs/guidelines/agent-infra/critical-thinking.md +4 -4
  153. package/docs/guidelines/agent-infra/direct-answers-demos.md +2 -2
  154. package/docs/guidelines/agent-infra/domain-eval-anti-pattern.md +1 -1
  155. package/docs/guidelines/agent-infra/engineering-memory-data-format.md +3 -3
  156. package/docs/guidelines/agent-infra/existence-question-verdicts.md +80 -0
  157. package/docs/guidelines/agent-infra/first-principles.md +2 -2
  158. package/docs/guidelines/agent-infra/framework-neutrality-patterns.md +2 -2
  159. package/docs/guidelines/agent-infra/guarded-baseline.md +39 -0
  160. package/docs/guidelines/agent-infra/inversion-thinking.md +5 -5
  161. package/docs/guidelines/agent-infra/language-and-tone-examples.md +1 -1
  162. package/docs/guidelines/agent-infra/layered-settings.md +10 -10
  163. package/docs/guidelines/agent-infra/memory-access.md +1 -1
  164. package/docs/guidelines/agent-infra/mental-models.md +3 -3
  165. package/docs/guidelines/agent-infra/reuse-verdict-mechanics.md +71 -0
  166. package/docs/guidelines/agent-infra/review-routing-data-format.md +7 -7
  167. package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +13 -7
  168. package/docs/guidelines/agent-infra/role-contracts.md +2 -2
  169. package/docs/guidelines/agent-infra/role-mode-router.md +3 -3
  170. package/docs/guidelines/agent-infra/rule-type-governance.md +2 -2
  171. package/docs/guidelines/agent-infra/scqa-framework.md +5 -5
  172. package/docs/guidelines/agent-infra/self-improvement-pipeline.md +6 -6
  173. package/docs/guidelines/agent-infra/simplicity-and-goal-demos.md +2 -2
  174. package/docs/guidelines/agent-infra/six-hats.md +3 -3
  175. package/docs/guidelines/agent-infra/skill-quality-checklist.md +6 -6
  176. package/docs/guidelines/agent-infra/source-confidentiality-mechanics.md +109 -0
  177. package/docs/guidelines/agent-infra/systems-thinking.md +1 -1
  178. package/docs/guidelines/agent-infra/verify-before-complete-demos.md +2 -2
  179. package/docs/guidelines/augment-portability-patterns.md +6 -4
  180. package/docs/guidelines/code-clarity.md +18 -0
  181. package/docs/guidelines/component-oriented-and-oop-development.md +3 -2
  182. package/docs/guidelines/cross-role-handoff.md +2 -2
  183. package/docs/guidelines/design-fidelity-mechanics.md +1 -1
  184. package/docs/guidelines/docs/readme-size-and-splitting.md +3 -3
  185. package/docs/guidelines/php/database.md +90 -7
  186. package/docs/guidelines/prompt-templates.md +7 -7
  187. package/llms.txt +2 -2
  188. package/package.json +5 -2
  189. package/src/agent-src/scripts/archive_completed_roadmaps.ts +252 -8
  190. package/src/agent-src/scripts/guarded_baseline.ts +343 -0
  191. package/src/agent-src/scripts/roadmap_set_step.ts +253 -0
  192. package/src/agent-src/scripts/stub_queue.ts +82 -0
  193. package/src/agent-src/scripts/stubs_due.ts +516 -0
  194. package/src/agent-src/scripts/ticket_bundles.ts +84 -0
  195. package/src/agent-src/scripts/update_roadmap_progress.ts +16 -12
  196. package/src/agent-src/templates/scripts/check_memory.ts +258 -17
  197. package/src/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
  198. package/src/agent-src/templates/scripts/memory_lookup.ts +86 -0
  199. package/src/agent-src/templates/scripts/memory_signal.ts +44 -0
  200. package/src/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
  201. package/src/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
  202. package/src/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
  203. package/src/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
  204. package/src/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
  205. package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
  206. package/src/config/agent-settings.template.yml +32 -3
  207. package/src/config/assurance-capability-registry.json +21 -9
  208. package/src/config/canonical-terms.yml +119 -0
  209. package/src/config/capability-native-outcome-bars.json +81 -0
  210. package/src/config/ci-local-parity.yml +80 -0
  211. package/src/config/drafting-channels.yml +43 -0
  212. package/src/config/estate-count-budget.json +57 -36
  213. package/src/config/evaluator-budgets.json +14 -14
  214. package/src/config/gate-coverage.yml +729 -63
  215. package/src/config/gate-reachability-exemptions.json +21 -0
  216. package/src/config/gate-violation-baselines.json +42 -19
  217. package/src/config/harness-evolution-budget.json +25 -0
  218. package/src/config/lapsed-beta-baseline.json +96 -0
  219. package/src/config/memory-twin-verdicts.yml +129 -0
  220. package/src/config/metric-registry.yml +124 -0
  221. package/src/config/pack-size-budget.json +16 -15
  222. package/src/config/preamble-payload-budget.json +12 -4
  223. package/src/config/profiles/balanced.ini +27 -0
  224. package/src/config/profiles/full.ini +27 -0
  225. package/src/config/profiles/minimal.ini +27 -0
  226. package/src/config/publish-surface.json +9 -2
  227. package/src/config/routing-coverage-seed.json +16 -2
  228. package/src/config/rule-stub-ceilings.json +133 -112
  229. package/src/config/turnaround-budget.json +66 -0
  230. package/src/install/claudeRuleRewrite.ts +288 -0
  231. package/src/install/detect.ts +60 -17
  232. package/src/install/detect_php_shape.ts +191 -0
  233. package/src/scripts/_cli/cmd_doctor.ts +27 -112
  234. package/src/scripts/_dispatch.bash +23 -0
  235. package/src/scripts/_lib/activation_ladder.ts +255 -0
  236. package/src/scripts/_lib/activation_receipt_producer.ts +341 -0
  237. package/src/scripts/_lib/activation_states.ts +88 -0
  238. package/src/scripts/_lib/adherence_detectors.ts +143 -0
  239. package/src/scripts/_lib/adr_frontmatter.ts +26 -0
  240. package/src/scripts/_lib/arith_claims.ts +181 -0
  241. package/src/scripts/_lib/arm_ranking.ts +62 -0
  242. package/src/scripts/_lib/asset_delivery_ledger.ts +303 -0
  243. package/src/scripts/_lib/audit_field_provenance.ts +54 -0
  244. package/src/scripts/_lib/auto_dispatch.ts +32 -3
  245. package/src/scripts/_lib/bench_ab_size_claim.ts +98 -4
  246. package/src/scripts/_lib/benchmark_cache_fields.ts +158 -0
  247. package/src/scripts/_lib/candidate_pair_delta.ts +349 -0
  248. package/src/scripts/_lib/candidate_proposer.ts +402 -0
  249. package/src/scripts/_lib/candidate_record.ts +601 -0
  250. package/src/scripts/_lib/capture_rate.ts +319 -0
  251. package/src/scripts/_lib/carrier_status.ts +118 -0
  252. package/src/scripts/_lib/cascade_stage_enumeration.ts +92 -0
  253. package/src/scripts/_lib/collector_denominator.ts +771 -0
  254. package/src/scripts/_lib/collector_record.ts +340 -0
  255. package/src/scripts/_lib/collector_store.ts +664 -0
  256. package/src/scripts/_lib/collector_supervision.ts +827 -0
  257. package/src/scripts/_lib/concern_estate.ts +77 -0
  258. package/src/scripts/_lib/config_chain.ts +477 -0
  259. package/src/scripts/_lib/config_cost.ts +209 -0
  260. package/src/scripts/_lib/corpus_manifest.ts +726 -0
  261. package/src/scripts/_lib/council_settings_block.ts +6 -0
  262. package/src/scripts/_lib/curator_ops.ts +172 -0
  263. package/src/scripts/_lib/delivery_arm_experiment.ts +282 -0
  264. package/src/scripts/_lib/delivery_criticality.ts +126 -0
  265. package/src/scripts/_lib/doctor_runtime_checks.ts +70 -0
  266. package/src/scripts/_lib/empty_cycles.ts +88 -0
  267. package/src/scripts/_lib/estate_carrier_cases.ts +72 -0
  268. package/src/scripts/_lib/eval_publication.ts +354 -0
  269. package/src/scripts/_lib/evaluation_cascade.ts +452 -0
  270. package/src/scripts/_lib/evaluation_vector.ts +283 -0
  271. package/src/scripts/_lib/evaluator_promotion.ts +225 -0
  272. package/src/scripts/_lib/evidence_basis.ts +118 -0
  273. package/src/scripts/_lib/evolution_roi.ts +562 -0
  274. package/src/scripts/_lib/exec_evidence.ts +8 -0
  275. package/src/scripts/_lib/experience_card.ts +272 -0
  276. package/src/scripts/_lib/experience_report.ts +151 -0
  277. package/src/scripts/_lib/experiment_freeze.ts +112 -0
  278. package/src/scripts/_lib/generated_by.ts +66 -0
  279. package/src/scripts/_lib/harness_evolution_guards.ts +239 -0
  280. package/src/scripts/_lib/hook_effect_probe.ts +141 -0
  281. package/src/scripts/_lib/host_denominator.ts +687 -0
  282. package/src/scripts/_lib/host_projection_reach.ts +157 -0
  283. package/src/scripts/_lib/ignored_blocker.ts +148 -0
  284. package/src/scripts/_lib/install_reach_checks.ts +495 -0
  285. package/src/scripts/_lib/json_duplicate_keys.ts +150 -0
  286. package/src/scripts/_lib/judge_hygiene.ts +228 -0
  287. package/src/scripts/_lib/legacy_boundary_map.ts +228 -0
  288. package/src/scripts/_lib/lexical_shortlist.ts +215 -0
  289. package/src/scripts/_lib/llm_candidate_proposer.ts +461 -0
  290. package/src/scripts/_lib/llm_proposer_transport.ts +153 -0
  291. package/src/scripts/_lib/loop_guards.ts +299 -0
  292. package/src/scripts/_lib/loss_class.ts +129 -0
  293. package/src/scripts/_lib/machine_wake.ts +51 -0
  294. package/src/scripts/_lib/md_prose_lines.ts +177 -0
  295. package/src/scripts/_lib/minimality_tiebreak.ts +168 -0
  296. package/src/scripts/_lib/one_resolver_invariant.ts +449 -0
  297. package/src/scripts/_lib/orchestration_record.ts +253 -5
  298. package/src/scripts/_lib/outcome_envelope.ts +227 -0
  299. package/src/scripts/_lib/outcome_vocabularies.ts +125 -0
  300. package/src/scripts/_lib/paired_stats.ts +245 -0
  301. package/src/scripts/_lib/paired_verdict.ts +226 -0
  302. package/src/scripts/_lib/pathology_archive.ts +393 -0
  303. package/src/scripts/_lib/prefix_stable_surfaces.ts +123 -0
  304. package/src/scripts/_lib/privacy_class.ts +47 -0
  305. package/src/scripts/_lib/promotion_capability.ts +315 -0
  306. package/src/scripts/_lib/promotion_evidence.ts +414 -0
  307. package/src/scripts/_lib/promotion_review.ts +294 -0
  308. package/src/scripts/_lib/prompt_shape.ts +92 -0
  309. package/src/scripts/_lib/regression_neighbourhood.ts +259 -0
  310. package/src/scripts/_lib/release_highlights.ts +70 -1
  311. package/src/scripts/_lib/release_material.ts +125 -2
  312. package/src/scripts/_lib/repeated_failure.ts +105 -0
  313. package/src/scripts/_lib/repo_root.ts +111 -0
  314. package/src/scripts/_lib/review_skipped_record.ts +37 -0
  315. package/src/scripts/_lib/role_split.ts +338 -0
  316. package/src/scripts/_lib/routing_corpus.ts +307 -0
  317. package/src/scripts/_lib/routing_index_input.ts +104 -0
  318. package/src/scripts/_lib/rule_injection.ts +22 -1
  319. package/src/scripts/_lib/runtime_journal.ts +1499 -0
  320. package/src/scripts/_lib/runtime_wiring_checks.ts +430 -0
  321. package/src/scripts/_lib/semantic_noop.ts +167 -0
  322. package/src/scripts/_lib/skill_catalogue.ts +11 -1
  323. package/src/scripts/_lib/source_digest.ts +200 -0
  324. package/src/scripts/_lib/source_redact.ts +260 -0
  325. package/src/scripts/_lib/source_shape.ts +502 -0
  326. package/src/scripts/_lib/source_snapshot_dedup.ts +199 -0
  327. package/src/scripts/_lib/strip_comments.d.mts +8 -0
  328. package/src/scripts/_lib/strip_comments.mjs +65 -0
  329. package/src/scripts/_lib/test_red_state.ts +154 -0
  330. package/src/scripts/_lib/trigger_shift.ts +144 -0
  331. package/src/scripts/_lib/untrusted_content.ts +82 -7
  332. package/src/scripts/activation_receipt.ts +258 -0
  333. package/src/scripts/adoption_report.ts +1 -1
  334. package/src/scripts/adr/evidence_census.ts +1 -1
  335. package/src/scripts/adr/regenerate_index.ts +26 -2
  336. package/src/scripts/adr_cite_check.ts +164 -1
  337. package/src/scripts/ai_council/blind_review.ts +11 -1
  338. package/src/scripts/ai_council/clients.ts +4 -0
  339. package/src/scripts/ai_council/config.ts +3 -0
  340. package/src/scripts/ai_council/consensus.ts +28 -8
  341. package/src/scripts/ai_council/consensus_round.ts +226 -0
  342. package/src/scripts/ai_council/cross_exam.ts +128 -0
  343. package/src/scripts/ai_council/disagreement_signal.ts +338 -0
  344. package/src/scripts/ai_council/explain_route.ts +157 -0
  345. package/src/scripts/ai_council/information_gain.ts +293 -0
  346. package/src/scripts/ai_council/inline_findings.ts +340 -0
  347. package/src/scripts/ai_council/judge_position_bias.ts +197 -0
  348. package/src/scripts/ai_council/leakage_corpus.ts +385 -0
  349. package/src/scripts/ai_council/leakage_patterns.ts +453 -0
  350. package/src/scripts/ai_council/minority_retention.ts +171 -0
  351. package/src/scripts/ai_council/orchestrator.ts +16 -203
  352. package/src/scripts/ai_council/orchestrator_results.ts +23 -3
  353. package/src/scripts/ai_council/pricing.ts +106 -0
  354. package/src/scripts/ai_council/prompts.ts +74 -7
  355. package/src/scripts/ai_council/provider_leakage_bench.ts +327 -0
  356. package/src/scripts/ai_council/py_format.ts +14 -3
  357. package/src/scripts/ai_council/recouncil_guard.ts +293 -0
  358. package/src/scripts/ai_council/recouncil_savings.ts +299 -0
  359. package/src/scripts/ai_council/replay_route.ts +223 -0
  360. package/src/scripts/ai_council/response_record.ts +50 -0
  361. package/src/scripts/ai_council/reviewer_assignment.ts +279 -0
  362. package/src/scripts/ai_council/routing_training_row.ts +197 -0
  363. package/src/scripts/ai_council/synthesis_strategy.ts +159 -0
  364. package/src/scripts/ai_council/topology_bench_manifest.ts +860 -0
  365. package/src/scripts/ai_council/topology_vocabulary.ts +175 -0
  366. package/src/scripts/asset_delivery_ledger.ts +157 -0
  367. package/src/scripts/attest_artifact.ts +193 -0
  368. package/src/scripts/audit_auto_rules.ts +2 -1
  369. package/src/scripts/audit_command_surface.ts +1 -1
  370. package/src/scripts/audit_mcp_tools.ts +2 -2
  371. package/src/scripts/audit_skill_overlap_allowlist.json +6 -1
  372. package/src/scripts/audit_user_type_axis.ts +2 -1
  373. package/src/scripts/bench_ab_clone.ts +215 -10
  374. package/src/scripts/bench_ab_integrity.ts +119 -5
  375. package/src/scripts/bench_ab_v2_stats.ts +40 -213
  376. package/src/scripts/build_archive_index.ts +1 -1
  377. package/src/scripts/build_linear_digest.ts +1 -1
  378. package/src/scripts/build_proof.ts +11 -4
  379. package/src/scripts/build_rule_trigger_matrix.ts +1 -1
  380. package/src/scripts/build_source_digests.ts +157 -0
  381. package/src/scripts/cache_realization_report.ts +103 -0
  382. package/src/scripts/check_adr_frontmatter.ts +131 -10
  383. package/src/scripts/check_benchmark_report_fields.ts +207 -0
  384. package/src/scripts/check_beta_review_markers.ts +235 -6
  385. package/src/scripts/check_bundle_path_leakage.ts +34 -1
  386. package/src/scripts/check_claims.ts +576 -6
  387. package/src/scripts/check_composite_arming.ts +35 -0
  388. package/src/scripts/check_concern_admissions.ts +365 -0
  389. package/src/scripts/check_enforcement_coverage.ts +28 -0
  390. package/src/scripts/check_estate_count.ts +347 -25
  391. package/src/scripts/check_gate_reachability.ts +383 -0
  392. package/src/scripts/check_host_loadability.ts +104 -0
  393. package/src/scripts/check_loss_class_declared.ts +308 -0
  394. package/src/scripts/check_md_language.ts +15 -98
  395. package/src/scripts/check_memory_proposal.ts +18 -11
  396. package/src/scripts/check_no_currency_in_cost_surfaces.ts +225 -0
  397. package/src/scripts/check_no_external_sources.ts +281 -6
  398. package/src/scripts/check_pack_conformance_fixture.ts +11 -1
  399. package/src/scripts/check_pack_size.ts +59 -2
  400. package/src/scripts/check_preamble_payload_budget.ts +114 -3
  401. package/src/scripts/check_prefix_stable_mutation.ts +372 -0
  402. package/src/scripts/check_publish_surface.ts +10 -1
  403. package/src/scripts/check_references.ts +24 -1
  404. package/src/scripts/check_release_highlights.ts +96 -13
  405. package/src/scripts/check_roadmap_trackable.ts +17 -2
  406. package/src/scripts/check_rule_evidence_declaration.ts +316 -0
  407. package/src/scripts/check_rule_projection_integrity.ts +14 -4
  408. package/src/scripts/check_score_contract.ts +26 -3
  409. package/src/scripts/check_static_parity.ts +285 -0
  410. package/src/scripts/check_supervision_claim_atomicity.ts +498 -0
  411. package/src/scripts/check_suppression_hygiene.ts +15 -0
  412. package/src/scripts/ci_settle.ts +39 -2
  413. package/src/scripts/code_graph/build.ts +60 -3
  414. package/src/scripts/code_graph/extract.ts +44 -0
  415. package/src/scripts/code_graph/types.ts +24 -0
  416. package/src/scripts/collector_daemon.ts +714 -0
  417. package/src/scripts/config_cost_report.ts +302 -0
  418. package/src/scripts/consumer_matrix.ts +74 -1
  419. package/src/scripts/corpus_manifest.ts +235 -0
  420. package/src/scripts/cost/budget.mjs +10 -3
  421. package/src/scripts/cost/track.mjs +10 -3
  422. package/src/scripts/council_cli.ts +37 -54
  423. package/src/scripts/dispatch_r2_reviewer.ts +46 -5
  424. package/src/scripts/evolution_lab.ts +1153 -0
  425. package/src/scripts/external_sources_denylist.json +5 -18
  426. package/src/scripts/extract_audit_patterns.ts +21 -0
  427. package/src/scripts/fold_intake.ts +12 -1
  428. package/src/scripts/gen_discovery_baseline.ts +1 -1
  429. package/src/scripts/generate_capabilities_index.ts +12 -5
  430. package/src/scripts/generate_capability_matrix.ts +3 -3
  431. package/src/scripts/generate_command_flows.ts +2 -2
  432. package/src/scripts/generate_cookbook.ts +2 -2
  433. package/src/scripts/generate_index.ts +8 -1
  434. package/src/scripts/generate_knowledge_index.ts +2 -1
  435. package/src/scripts/generate_ownership_matrix.ts +2 -1
  436. package/src/scripts/generate_pack_manifests.ts +10 -2
  437. package/src/scripts/generate_role_experiences_catalog.ts +2 -2
  438. package/src/scripts/generate_settings_reference.ts +1 -1
  439. package/src/scripts/git_authorization_hook.ts +22 -1
  440. package/src/scripts/grade_target_readiness.ts +48 -5
  441. package/src/scripts/hook_effect_doctor.ts +261 -0
  442. package/src/scripts/hook_manifest.json +1 -1
  443. package/src/scripts/hook_manifest.yaml +125 -16
  444. package/src/scripts/hooks/block_speaking_inbox_dir.ts +271 -0
  445. package/src/scripts/hooks/block_unauthorized_git.ts +18 -0
  446. package/src/scripts/hooks/comment_discipline_hook.ts +146 -0
  447. package/src/scripts/hooks/concern_registry.ts +6 -0
  448. package/src/scripts/hooks/dispatch_hook.ts +32 -0
  449. package/src/scripts/hooks/journal_record_hook.ts +345 -0
  450. package/src/scripts/hooks/prepush_metadata_sources.sh +110 -0
  451. package/src/scripts/hooks/run_continuation_hook.ts +44 -9
  452. package/src/scripts/hooks/shims/install.sh +61 -0
  453. package/src/scripts/hooks/shims/php +101 -0
  454. package/src/scripts/hooks/suggestion_capture_hook.ts +10 -0
  455. package/src/scripts/hooks/turn_end_gate_hook.ts +9 -1
  456. package/src/scripts/hot_context_hook.ts +16 -0
  457. package/src/scripts/install-hooks.sh +20 -5
  458. package/src/scripts/install.ts +17 -35
  459. package/src/scripts/inventory_frontmatter.ts +2 -1
  460. package/src/scripts/language_mirror_hook.ts +14 -2
  461. package/src/scripts/lint_adr_sweep_routing.ts +12 -0
  462. package/src/scripts/lint_canonical_terms.ts +604 -0
  463. package/src/scripts/lint_carrier_integrity.ts +820 -0
  464. package/src/scripts/lint_code_comments.ts +643 -0
  465. package/src/scripts/lint_composition_review.ts +619 -0
  466. package/src/scripts/lint_consolidation_lineage.ts +666 -0
  467. package/src/scripts/lint_eval_specs.ts +593 -0
  468. package/src/scripts/lint_hook_manifest.ts +19 -0
  469. package/src/scripts/lint_host_portability.ts +373 -0
  470. package/src/scripts/lint_judge_prompt_expectation.ts +27 -1
  471. package/src/scripts/lint_memory_twin_parity.ts +335 -0
  472. package/src/scripts/lint_metric_consumers.ts +355 -0
  473. package/src/scripts/lint_plan_risk_register.ts +39 -19
  474. package/src/scripts/lint_promotion_paths.ts +779 -0
  475. package/src/scripts/lint_skill_descriptions.ts +18 -1
  476. package/src/scripts/lint_skill_frontmatter_safety.ts +58 -0
  477. package/src/scripts/lint_skill_link_reach.ts +252 -0
  478. package/src/scripts/lint_skill_trigger_corpus.ts +426 -23
  479. package/src/scripts/lint_ticket_buildable.ts +17 -1
  480. package/src/scripts/llm_propose.ts +256 -0
  481. package/src/scripts/mcp_server/consumer_tool_catalog.json +1 -1
  482. package/src/scripts/mcp_server/tool_catalog_source.ts +1 -1
  483. package/src/scripts/measure_delivery_sets.ts +361 -0
  484. package/src/scripts/measure_docs_dead_links.ts +348 -0
  485. package/src/scripts/measure_host_capture.ts +461 -0
  486. package/src/scripts/measure_routing_signal.ts +307 -0
  487. package/src/scripts/migration_status.ts +3 -3
  488. package/src/scripts/model_rule_injection.ts +76 -0
  489. package/src/scripts/orchestration_record.ts +14 -0
  490. package/src/scripts/preamble_byte_census.ts +139 -10
  491. package/src/scripts/prepack-check.mjs +4 -1
  492. package/src/scripts/probe_council_retention.ts +495 -0
  493. package/src/scripts/probe_turnaround.ts +384 -0
  494. package/src/scripts/probe_unblocked_ask.ts +279 -0
  495. package/src/scripts/release.ts +21 -37
  496. package/src/scripts/release_drill.ts +143 -0
  497. package/src/scripts/release_env.ts +35 -0
  498. package/src/scripts/release_publication.ts +84 -0
  499. package/src/scripts/render_benchmark_md.ts +1 -1
  500. package/src/scripts/rule_activation_census.ts +70 -9
  501. package/src/scripts/rule_backlinks.ts +1 -1
  502. package/src/scripts/run_lifecycle_suite.ts +208 -0
  503. package/src/scripts/run_skill_evals.ts +40 -0
  504. package/src/scripts/schemas/delivery-manifest.schema.json +43 -0
  505. package/src/scripts/schemas/drafting-channels.schema.json +43 -0
  506. package/src/scripts/schemas/evals.schema.json +24 -1
  507. package/src/scripts/schemas/rule.schema.json +52 -1
  508. package/src/scripts/schemas/skill.schema.json +17 -2
  509. package/src/scripts/skill_overlap.ts +7 -1
  510. package/src/scripts/skill_tools/run_block_d_eval.ts +8 -1
  511. package/src/scripts/skill_tools/score_skill_relevance.ts +84 -3
  512. package/src/scripts/skill_tools/suggest_skill_for_task.ts +8 -1
  513. package/src/scripts/skill_usage_report.ts +2 -1
  514. package/src/scripts/stubs_due.ts +211 -0
  515. package/src/scripts/sweep_source_surfaces.ts +678 -0
  516. package/src/scripts/sync_pr_branch.ts +3 -3
  517. package/src/scripts/trigger_eval_grandfather.json +202 -222
  518. package/src/scripts/utilization_report.ts +22 -2
  519. package/src/server/schemas/settings.ts +5 -0
  520. package/src/templates/marketing-copy.yml +1 -1
  521. package/dist/ui/assets/index-Cxgy63kz.js +0 -26
@@ -0,0 +1,601 @@
1
+ /**
2
+ * The candidate record: its arity, its mutation alphabet, and its lifecycle.
3
+ *
4
+ * `road-to-governed-harness-evolution` Phase 3, steps 3.2, 3.3 and 3.4.
5
+ *
6
+ * Three invariants live here because they are three properties of ONE record
7
+ * and separating them would let a caller satisfy each in isolation while
8
+ * violating the conjunction:
9
+ *
10
+ * 3.2 ONE PRIMARY DIMENSION PER CANDIDATE. If routing and body both change
11
+ * and the score moves, the credit is ambiguous and the Phase 4 metric
12
+ * vector cannot be read per candidate. Multi-dimension consolidation is a
13
+ * DISTINCT record type ({@link ConsolidationRecord}), not a candidate
14
+ * with a wider field.
15
+ *
16
+ * 3.3 THE MUTATION ALPHABET IS EXACTLY THREE — `activation`, `routing`,
17
+ * `content`. Precedence, composition, verification, tool strategy, budget
18
+ * and scope are named and unimplemented until the three carry.
19
+ *
20
+ * 3.4 A LIFECYCLE STATE ENUM, so `mutated` and `accepted` cannot be confused.
21
+ * Both parent designs made this the structural guard, one tracing the
22
+ * defect to a reference implementation passing `mutated` in where
23
+ * `accepted` was expected.
24
+ *
25
+ * ## E10 was a SPLIT, and this file takes the conservative side
26
+ *
27
+ * AI council 2026-08-30, anthropic + openai — **not convergent, 1/1**. The
28
+ * anthropic seat argued for FOUR dimensions, adding `verification` now, on an
29
+ * irreversibility argument: dimensions are metadata on candidate records, so
30
+ * adding one later makes prior candidates permanently unclassifiable. The
31
+ * openai seat argued for THREE, adding `verification` only when a demonstrable
32
+ * need appears.
33
+ *
34
+ * Per this repository's escalation handling a split takes the **conservative**
35
+ * side, so the alphabet is three — which is what step 3.3 already specified, so
36
+ * its verify clause ("the schema rejects a mutation naming a fourth dimension")
37
+ * stands unchanged. This is recorded as a split, not as a verdict.
38
+ *
39
+ * **The losing seat's concern is a design constraint this schema satisfies.**
40
+ * Adding a dimension later must be an ADDITIVE change, never a migration that
41
+ * orphans historical records. Two mechanisms, and both are load-bearing:
42
+ *
43
+ * 1. {@link CANDIDATE_RECORD_VERSION} is written into every record, so a
44
+ * later reader can tell which alphabet a record was authored against
45
+ * rather than inferring it from the values present.
46
+ * 2. The unknown-dimension refusal lives in the VALIDATOR
47
+ * ({@link parseCandidateRecord}) and NOT in the reader
48
+ * ({@link readCandidateRecord}). A historical record naming a dimension
49
+ * this build does not know stays READABLE — it comes back flagged, not
50
+ * as a throw. Putting the refusal in the reader is what would make the
51
+ * record unreadable, which is exactly the irreversibility the anthropic
52
+ * seat named.
53
+ *
54
+ * Nothing here writes, spends, or fetches. Pure functions over declared state.
55
+ */
56
+
57
+ /** Schema version stamped into every record. Bump when a field's meaning moves. */
58
+ export const CANDIDATE_RECORD_VERSION = 1;
59
+
60
+ // --- 3.3 — the mutation alphabet --------------------------------------------
61
+
62
+ /**
63
+ * The three implemented mutation dimensions.
64
+ *
65
+ * The six named-and-unimplemented ones — precedence, composition, verification,
66
+ * tool strategy, budget, scope — are deliberately absent rather than present
67
+ * and disabled. A member that exists but is refused downstream reads as a
68
+ * capability to a caller and as a gap to a reviewer; absence reads the same to
69
+ * both.
70
+ */
71
+ export const MUTATION_DIMENSIONS = ['activation', 'routing', 'content'] as const;
72
+ export type MutationDimension = (typeof MUTATION_DIMENSIONS)[number];
73
+
74
+ export function isMutationDimension(v: unknown): v is MutationDimension {
75
+ return typeof v === 'string' && (MUTATION_DIMENSIONS as readonly string[]).includes(v);
76
+ }
77
+
78
+ // --- 3.4 — the lifecycle ----------------------------------------------------
79
+
80
+ /**
81
+ * The candidate lifecycle, in spine order followed by the two off-spine exits.
82
+ *
83
+ * The ordering of the first seven is the ONLY thing that makes "a transition
84
+ * skipping a stage" decidable, so it is the array's contract and not an
85
+ * incidental listing order.
86
+ */
87
+ export const LIFECYCLE_SPINE = [
88
+ 'proposed',
89
+ 'diagnostic-evaluated',
90
+ 'selection-evaluated',
91
+ 'promotion-eligible',
92
+ 'sealed-evaluated',
93
+ 'promotion-proposed',
94
+ 'promoted',
95
+ ] as const;
96
+
97
+ export const LIFECYCLE_STATES = [...LIFECYCLE_SPINE, 'rejected', 'retired'] as const;
98
+ export type LifecycleState = (typeof LIFECYCLE_STATES)[number];
99
+
100
+ export function isLifecycleState(v: unknown): v is LifecycleState {
101
+ return typeof v === 'string' && (LIFECYCLE_STATES as readonly string[]).includes(v);
102
+ }
103
+
104
+ /**
105
+ * The ONE state that means a candidate was accepted.
106
+ *
107
+ * Exported as a named constant rather than compared inline so that a grep for
108
+ * the acceptance decision finds one site. Step 3.4's exit criterion is that no
109
+ * code path reads a candidate as accepted from the mere fact that it exists;
110
+ * one accessor is what makes that auditable.
111
+ */
112
+ export const ACCEPTED_STATE: LifecycleState = 'promoted';
113
+
114
+ /**
115
+ * Is this candidate accepted?
116
+ *
117
+ * Existence is not acceptance and neither is any evaluated state:
118
+ * `sealed-evaluated` means it was measured, `promotion-eligible` means it may
119
+ * be proposed, `promotion-proposed` means a human has been asked. Only
120
+ * {@link ACCEPTED_STATE} answers yes.
121
+ */
122
+ export function isAccepted(record: { readonly lifecycle: LifecycleState }): boolean {
123
+ return record.lifecycle === ACCEPTED_STATE;
124
+ }
125
+
126
+ export class LifecycleTransitionError extends Error {
127
+ readonly from: LifecycleState;
128
+ readonly to: LifecycleState;
129
+ constructor(from: LifecycleState, to: LifecycleState, why: string) {
130
+ super(`lifecycle transition '${from}' -> '${to}' refused: ${why}`);
131
+ this.name = 'LifecycleTransitionError';
132
+ this.from = from;
133
+ this.to = to;
134
+ }
135
+ }
136
+
137
+ /**
138
+ * A named human who approved a promotion. There is no anonymous form.
139
+ *
140
+ * See {@link assertTransition} for why this type exists at all — it is the
141
+ * mechanical half of Phase 0's carried non-promotion condition.
142
+ */
143
+ export interface HumanApproval {
144
+ /** A person, not a process. Empty or whitespace-only is refused. */
145
+ readonly approver: string;
146
+ /** ISO-8601 date the approval was given. */
147
+ readonly approvedAt: string;
148
+ }
149
+
150
+ function spineIndex(s: LifecycleState): number {
151
+ return (LIFECYCLE_SPINE as readonly string[]).indexOf(s);
152
+ }
153
+
154
+ /**
155
+ * Refuse any transition that is not exactly one legal step.
156
+ *
157
+ * The legal moves, and nothing else:
158
+ *
159
+ * - one step FORWARD along the spine — `proposed → diagnostic-evaluated`,
160
+ * and so on. A jump of two or more is refused, which is step 3.4's
161
+ * "a state transition skipping a stage is refused" verbatim.
162
+ * - any non-terminal state → `rejected`. A candidate can die at any stage,
163
+ * and forcing it down the spine first would manufacture evaluated states
164
+ * for candidates that were never evaluated.
165
+ * - `promoted` → `retired`, and only from there. RETIRE is a first-class
166
+ * anti-sprawl operation (E6, 2/2 convergent on the 7-op set) and it acts
167
+ * on something that was promoted; retiring a candidate that never landed
168
+ * is a rejection wearing the wrong name.
169
+ *
170
+ * Backwards moves are refused. Self-transitions are refused — a no-op that
171
+ * type-checks is how a stalled pipeline looks like a progressing one.
172
+ *
173
+ * ## The promotion gate — Phase 0's carried condition, discharged here
174
+ *
175
+ * Phase 0 carried a council condition UNMET (AI council 2026-08-29, anthropic +
176
+ * openai, 2/2): the non-promotion property of Phases 1–6 must be MECHANICALLY
177
+ * ENFORCED, not merely stated. It was carried unmet honestly, because nothing
178
+ * in the tree promoted anything and a gate over a population of zero exits
179
+ * green while looking like enforcement. The roadmap named where the population
180
+ * stops being empty: *"the 3.4 lifecycle enum's `promoted` transition and the
181
+ * 3.6 verb set are where the population stops being empty, so the check lands
182
+ * there"*.
183
+ *
184
+ * This is that check for the transition half: **`→ promoted` requires a named
185
+ * human approver.** No default, no service account, no `approver: 'ci'` — a
186
+ * blank or whitespace-only name is refused, so the cheapest way to satisfy the
187
+ * gate is to actually name someone.
188
+ *
189
+ * The verb half (3.6) is out of this change's scope and is NOT claimed
190
+ * discharged. What holds now is narrower and worth stating exactly: no code
191
+ * path can move a candidate into `promoted` without a name, on any surface that
192
+ * calls this function.
193
+ *
194
+ * @throws {LifecycleTransitionError} on any refused move.
195
+ */
196
+ export function assertTransition(
197
+ from: LifecycleState,
198
+ to: LifecycleState,
199
+ approval?: HumanApproval,
200
+ ): void {
201
+ if (from === to) {
202
+ throw new LifecycleTransitionError(from, to, 'a self-transition records no progress');
203
+ }
204
+ if (from === 'rejected' || from === 'retired') {
205
+ throw new LifecycleTransitionError(from, to, `'${from}' is terminal`);
206
+ }
207
+ if (to === 'rejected') {
208
+ return;
209
+ }
210
+ if (to === 'retired') {
211
+ if (from !== 'promoted') {
212
+ throw new LifecycleTransitionError(
213
+ from,
214
+ to,
215
+ "only a promoted candidate can be retired; a candidate that never landed is 'rejected'",
216
+ );
217
+ }
218
+ return;
219
+ }
220
+ const fromIdx = spineIndex(from);
221
+ const toIdx = spineIndex(to);
222
+ if (fromIdx < 0 || toIdx < 0) {
223
+ throw new LifecycleTransitionError(from, to, 'not a spine state');
224
+ }
225
+ if (toIdx < fromIdx) {
226
+ throw new LifecycleTransitionError(from, to, 'the lifecycle does not run backwards');
227
+ }
228
+ if (toIdx - fromIdx > 1) {
229
+ const skipped = LIFECYCLE_SPINE.slice(fromIdx + 1, toIdx).join(', ');
230
+ throw new LifecycleTransitionError(from, to, `it skips ${skipped}`);
231
+ }
232
+ if (to === 'promoted') {
233
+ assertHumanApproval(approval);
234
+ }
235
+ }
236
+
237
+ function assertHumanApproval(approval: HumanApproval | undefined): void {
238
+ if (approval === undefined || approval.approver.trim() === '') {
239
+ throw new LifecycleTransitionError(
240
+ 'promotion-proposed',
241
+ 'promoted',
242
+ 'promotion into canonical agent-config requires a NAMED human approver. ' +
243
+ 'This is the mechanical half of the non-promotion property the ' +
244
+ 'merge-authority council required (2026-08-29, anthropic + openai, 2/2); ' +
245
+ 'an unnamed or blank approver is refused rather than defaulted.',
246
+ );
247
+ }
248
+ }
249
+
250
+ // --- Path ownership ---------------------------------------------------------
251
+
252
+ /**
253
+ * The only paths a candidate mutation may write.
254
+ *
255
+ * Declared here rather than imported from `bench_ab_clone` so this module stays
256
+ * usable without the bench, and pinned equal to that script's `WITH_SURFACES`
257
+ * and to `bench_ab_integrity`'s `ALLOWED_DELTA_PATHS` by a parity test. Three
258
+ * copies of a list is a drift hazard; a test that fails when they diverge is
259
+ * the cheapest form of one source of truth available without a refactor that
260
+ * would touch the byte-exact CLI contract of both scripts.
261
+ */
262
+ export const CANDIDATE_OWNED_PATHS: readonly string[] = ['.claude', '.augment', 'AGENTS.md', 'CLAUDE.md'];
263
+
264
+ /**
265
+ * May a candidate mutation write this repo-relative path?
266
+ *
267
+ * Refuses absolute paths, empty paths, and any traversal segment — `..`
268
+ * anywhere in the path is refused BEFORE the head component is inspected,
269
+ * because `.claude/../src/x.ts` has an owned head and an unowned target.
270
+ */
271
+ export function isCandidateOwnedPath(rel: string): boolean {
272
+ if (rel === '' || rel.startsWith('/') || /^[A-Za-z]:[\\/]/.test(rel)) {
273
+ return false;
274
+ }
275
+ const parts = rel.split(/[\\/]/).filter((p) => p !== '' && p !== '.');
276
+ if (parts.length === 0 || parts.includes('..')) {
277
+ return false;
278
+ }
279
+ const head = parts[0] as string;
280
+ if (parts.length === 1) {
281
+ return CANDIDATE_OWNED_PATHS.includes(head);
282
+ }
283
+ // A nested path is owned only when its head is an owned DIRECTORY. `AGENTS.md`
284
+ // is a file, so `AGENTS.md/x` is not ownership, it is nonsense.
285
+ return head === '.claude' || head === '.augment';
286
+ }
287
+
288
+ export class PathOwnershipError extends Error {
289
+ readonly path: string;
290
+ constructor(p: string) {
291
+ super(
292
+ `path ownership: '${p}' is outside the candidate surface ` +
293
+ `(${CANDIDATE_OWNED_PATHS.join(', ')}). A candidate that writes a task-target ` +
294
+ 'file is not a harness variant — it is a different experiment, and the ' +
295
+ 'paired verdict would attribute its effect to the harness.',
296
+ );
297
+ this.name = 'PathOwnershipError';
298
+ this.path = p;
299
+ }
300
+ }
301
+
302
+ /** One file a candidate rewrites, and the bytes it writes. */
303
+ export interface Mutation {
304
+ /** Repo-relative, inside {@link CANDIDATE_OWNED_PATHS}. */
305
+ readonly path: string;
306
+ readonly content: string;
307
+ }
308
+
309
+ /**
310
+ * Refuse a mutation set that reaches outside the candidate surface.
311
+ *
312
+ * @throws {PathOwnershipError} on the first unowned path.
313
+ */
314
+ export function assertMutationPathsOwned(mutations: readonly Mutation[]): void {
315
+ for (const m of mutations) {
316
+ if (!isCandidateOwnedPath(m.path)) {
317
+ throw new PathOwnershipError(m.path);
318
+ }
319
+ }
320
+ }
321
+
322
+ // --- The records ------------------------------------------------------------
323
+
324
+ /**
325
+ * A single candidate: exactly one primary dimension, one lifecycle state.
326
+ *
327
+ * `dimension` is a SCALAR and not an array. That is step 3.2's invariant
328
+ * expressed in the type rather than in a validator, so the arity cannot be
329
+ * violated by a caller that constructs the record in TypeScript and skips the
330
+ * parser. The parser exists for the untrusted-input path (a JSON file), where
331
+ * the type buys nothing.
332
+ */
333
+ export interface CandidateRecord {
334
+ readonly kind: 'candidate';
335
+ readonly version: number;
336
+ readonly id: string;
337
+ readonly dimension: MutationDimension;
338
+ readonly lifecycle: LifecycleState;
339
+ readonly mutations: readonly Mutation[];
340
+ }
341
+
342
+ /**
343
+ * A consolidation run: two or more dimensions, deliberately a DIFFERENT type.
344
+ *
345
+ * Step 3.2 requires this to be a distinct record type rather than a candidate
346
+ * with a wider field, and the reason is not tidiness. A metric vector read per
347
+ * candidate assumes single-dimension attribution; a multi-dimension record
348
+ * flowing through the same reader would be read under that assumption and
349
+ * silently mis-attributed. Two types make the mis-read a type error.
350
+ *
351
+ * `sourceCandidates` is required and must name at least two: a consolidation
352
+ * with one source is that candidate, and with none it is a candidate that
353
+ * evaded the arity rule by choosing the other type.
354
+ */
355
+ export interface ConsolidationRecord {
356
+ readonly kind: 'consolidation';
357
+ readonly version: number;
358
+ readonly id: string;
359
+ readonly dimensions: readonly MutationDimension[];
360
+ readonly lifecycle: LifecycleState;
361
+ readonly sourceCandidates: readonly string[];
362
+ }
363
+
364
+ export class CandidateSchemaError extends Error {
365
+ constructor(msg: string) {
366
+ super(`candidate schema: ${msg}`);
367
+ this.name = 'CandidateSchemaError';
368
+ }
369
+ }
370
+
371
+ function asObject(input: unknown): Record<string, unknown> {
372
+ if (typeof input !== 'object' || input === null || Array.isArray(input)) {
373
+ throw new CandidateSchemaError('record must be a JSON object');
374
+ }
375
+ return input as Record<string, unknown>;
376
+ }
377
+
378
+ function requireNonEmptyString(obj: Record<string, unknown>, key: string): string {
379
+ const v = obj[key];
380
+ if (typeof v !== 'string' || v.trim() === '') {
381
+ throw new CandidateSchemaError(`'${key}' must be a non-empty string`);
382
+ }
383
+ return v;
384
+ }
385
+
386
+ function requireLifecycle(obj: Record<string, unknown>): LifecycleState {
387
+ // Fail-closed and DELIBERATELY not defaulted. A record with no lifecycle is
388
+ // refused rather than read as `proposed`, because a default is a value the
389
+ // author did not choose, and every downstream reader would treat it as one
390
+ // they did. Step 3.4 exists because `mutated` was once read as `accepted`.
391
+ if (!('lifecycle' in obj)) {
392
+ throw new CandidateSchemaError(
393
+ "'lifecycle' is required and is never defaulted — an absent state is not 'proposed'",
394
+ );
395
+ }
396
+ const v = obj['lifecycle'];
397
+ if (!isLifecycleState(v)) {
398
+ throw new CandidateSchemaError(
399
+ `'lifecycle' must be one of ${LIFECYCLE_STATES.join(', ')} (got ${JSON.stringify(v)})`,
400
+ );
401
+ }
402
+ return v;
403
+ }
404
+
405
+ function requireVersion(obj: Record<string, unknown>): number {
406
+ const v = obj['version'];
407
+ if (typeof v !== 'number' || !Number.isInteger(v) || v < 1) {
408
+ throw new CandidateSchemaError("'version' must be a positive integer");
409
+ }
410
+ if (v > CANDIDATE_RECORD_VERSION) {
411
+ throw new CandidateSchemaError(
412
+ `record version ${String(v)} is newer than this build understands ` +
413
+ `(${String(CANDIDATE_RECORD_VERSION)})`,
414
+ );
415
+ }
416
+ return v;
417
+ }
418
+
419
+ function parseMutations(obj: Record<string, unknown>): readonly Mutation[] {
420
+ const raw = obj['mutations'];
421
+ if (!Array.isArray(raw)) {
422
+ throw new CandidateSchemaError("'mutations' must be an array (use [] for none)");
423
+ }
424
+ const out: Mutation[] = [];
425
+ for (const item of raw) {
426
+ const m = asObject(item);
427
+ const p = requireNonEmptyString(m, 'path');
428
+ const content = m['content'];
429
+ if (typeof content !== 'string') {
430
+ throw new CandidateSchemaError(`mutation '${p}': 'content' must be a string`);
431
+ }
432
+ out.push({ path: p, content });
433
+ }
434
+ assertMutationPathsOwned(out);
435
+ return out;
436
+ }
437
+
438
+ /**
439
+ * Validate an untrusted candidate record — the REFUSING path.
440
+ *
441
+ * Rejects, in this order and each with its own message:
442
+ *
443
+ * - `kind` that is not `'candidate'` (a consolidation record routed here);
444
+ * - a `dimensions` key at all — the plural is how a two-dimension candidate
445
+ * gets written, so it is refused by NAME rather than by counting values;
446
+ * - `dimension` supplied as an array, even a one-element one. An array is a
447
+ * field that can hold two, and step 3.2's invariant is about what the field
448
+ * CAN hold, not about what this instance happens to hold;
449
+ * - a `dimension` outside the three-member alphabet (step 3.3);
450
+ * - an absent or unrecognised `lifecycle` (step 3.4);
451
+ * - a mutation path outside the candidate surface.
452
+ *
453
+ * @throws {CandidateSchemaError} on the first violation.
454
+ */
455
+ export function parseCandidateRecord(input: unknown): CandidateRecord {
456
+ const obj = asObject(input);
457
+ if (obj['kind'] !== 'candidate') {
458
+ throw new CandidateSchemaError(
459
+ `'kind' must be 'candidate' (got ${JSON.stringify(obj['kind'])}); a multi-dimension ` +
460
+ "consolidation is the distinct 'consolidation' record type",
461
+ );
462
+ }
463
+ const version = requireVersion(obj);
464
+ const id = requireNonEmptyString(obj, 'id');
465
+ if ('dimensions' in obj) {
466
+ throw new CandidateSchemaError(
467
+ "a candidate carries exactly ONE primary dimension, so it has no 'dimensions' field. " +
468
+ "A run changing several dimensions is a 'consolidation' record, not a candidate — " +
469
+ 'if routing and content both change and the score moves, the credit is ambiguous',
470
+ );
471
+ }
472
+ const dim = obj['dimension'];
473
+ if (Array.isArray(dim)) {
474
+ throw new CandidateSchemaError(
475
+ "'dimension' must be a single string, not an array — a field that can hold two " +
476
+ 'dimensions violates the one-primary-dimension invariant even when it holds one',
477
+ );
478
+ }
479
+ if (!isMutationDimension(dim)) {
480
+ throw new CandidateSchemaError(
481
+ `'dimension' must be one of ${MUTATION_DIMENSIONS.join(', ')} (got ${JSON.stringify(dim)}). ` +
482
+ 'Precedence, composition, verification, tool strategy, budget and scope are named ' +
483
+ 'and unimplemented until the three carry',
484
+ );
485
+ }
486
+ const lifecycle = requireLifecycle(obj);
487
+ const mutations = parseMutations(obj);
488
+ return { kind: 'candidate', version, id, dimension: dim, lifecycle, mutations };
489
+ }
490
+
491
+ /**
492
+ * Validate an untrusted consolidation record.
493
+ *
494
+ * Requires ≥2 DISTINCT dimensions and ≥2 source candidates. Both floors exist
495
+ * so the second record type cannot be used as an escape hatch from the first:
496
+ * a one-dimension "consolidation" is a candidate that chose the other type.
497
+ *
498
+ * @throws {CandidateSchemaError} on the first violation.
499
+ */
500
+ export function parseConsolidationRecord(input: unknown): ConsolidationRecord {
501
+ const obj = asObject(input);
502
+ if (obj['kind'] !== 'consolidation') {
503
+ throw new CandidateSchemaError(
504
+ `'kind' must be 'consolidation' (got ${JSON.stringify(obj['kind'])})`,
505
+ );
506
+ }
507
+ const version = requireVersion(obj);
508
+ const id = requireNonEmptyString(obj, 'id');
509
+ const raw = obj['dimensions'];
510
+ if (!Array.isArray(raw)) {
511
+ throw new CandidateSchemaError("'dimensions' must be an array of at least two dimensions");
512
+ }
513
+ for (const d of raw) {
514
+ if (!isMutationDimension(d)) {
515
+ throw new CandidateSchemaError(
516
+ `'dimensions' member ${JSON.stringify(d)} is not one of ${MUTATION_DIMENSIONS.join(', ')}`,
517
+ );
518
+ }
519
+ }
520
+ const dimensions = [...new Set(raw as MutationDimension[])];
521
+ if (dimensions.length < 2) {
522
+ throw new CandidateSchemaError(
523
+ 'a consolidation touches at least two DISTINCT dimensions; with one it is a candidate, ' +
524
+ 'and routing it here would evade the one-primary-dimension invariant',
525
+ );
526
+ }
527
+ const sources = obj['sourceCandidates'];
528
+ if (!Array.isArray(sources) || sources.length < 2) {
529
+ throw new CandidateSchemaError(
530
+ "'sourceCandidates' must name at least two candidate ids — a consolidation of one " +
531
+ 'candidate is that candidate',
532
+ );
533
+ }
534
+ for (const s of sources) {
535
+ if (typeof s !== 'string' || s.trim() === '') {
536
+ throw new CandidateSchemaError("'sourceCandidates' members must be non-empty strings");
537
+ }
538
+ }
539
+ const lifecycle = requireLifecycle(obj);
540
+ return { kind: 'consolidation', version, id, dimensions, lifecycle, sourceCandidates: sources as string[] };
541
+ }
542
+
543
+ /** What a structural read produced, and whether this build understood it. */
544
+ export interface CandidateReadResult {
545
+ readonly kind: 'candidate';
546
+ readonly version: number;
547
+ readonly id: string;
548
+ /** The raw value, which may not be in this build's alphabet. */
549
+ readonly dimension: string;
550
+ readonly lifecycle: LifecycleState;
551
+ /** `true` when `dimension` is outside {@link MUTATION_DIMENSIONS}. */
552
+ readonly unknownDimension: boolean;
553
+ }
554
+
555
+ /**
556
+ * Read a historical candidate record WITHOUT refusing an unknown dimension.
557
+ *
558
+ * This is the forward-compatibility half of the E10 split. If the alphabet ever
559
+ * grows to four, every record authored under the three-member alphabet still
560
+ * parses here, and every record authored under a four-member alphabet still
561
+ * READS on a three-member build — flagged, not thrown.
562
+ *
563
+ * The refusal stays in {@link parseCandidateRecord}, which is what a RUN calls.
564
+ * So an unknown dimension cannot enter a run, and cannot make an archive
565
+ * unreadable. Those are different failures and this is where they are kept
566
+ * apart.
567
+ *
568
+ * Everything else is still validated: `kind`, `version`, `id` and `lifecycle`
569
+ * are structural, not alphabet-dependent, and a record missing one of them is
570
+ * malformed under every alphabet. In particular an absent `lifecycle` is still
571
+ * refused here — a reader that invented a state would reintroduce exactly the
572
+ * `mutated`-read-as-`accepted` defect step 3.4 exists for.
573
+ *
574
+ * @throws {CandidateSchemaError} on a structural violation.
575
+ */
576
+ export function readCandidateRecord(input: unknown): CandidateReadResult {
577
+ const obj = asObject(input);
578
+ if (obj['kind'] !== 'candidate') {
579
+ throw new CandidateSchemaError(`'kind' must be 'candidate' (got ${JSON.stringify(obj['kind'])})`);
580
+ }
581
+ const version = requireVersion(obj);
582
+ const id = requireNonEmptyString(obj, 'id');
583
+ const dim = obj['dimension'];
584
+ if (typeof dim !== 'string' || dim.trim() === '') {
585
+ throw new CandidateSchemaError("'dimension' must be a non-empty string");
586
+ }
587
+ const lifecycle = requireLifecycle(obj);
588
+ return { kind: 'candidate', version, id, dimension: dim, lifecycle, unknownDimension: !isMutationDimension(dim) };
589
+ }
590
+
591
+ /** Serialise a candidate record for the clone manifest. Key order is stable. */
592
+ export function candidateRecordToJson(record: CandidateRecord): Record<string, unknown> {
593
+ return {
594
+ kind: record.kind,
595
+ version: record.version,
596
+ id: record.id,
597
+ dimension: record.dimension,
598
+ lifecycle: record.lifecycle,
599
+ mutations: record.mutations.map((m) => ({ path: m.path, content: m.content })),
600
+ };
601
+ }