@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,338 @@
1
+ /**
2
+ * Three roles, three prompts, three input sets — and a judge that cannot see
3
+ * outcome truth.
4
+ *
5
+ * `road-to-governed-harness-evolution` Phase 5, step 5.3.
6
+ *
7
+ * > *Split the roles: analyzer, curator, proposer. Do not collapse them into
8
+ * > one unconstrained rewrite prompt. An optional judge model grades rubric
9
+ * > questions only, under a frozen evaluator contract.*
10
+ * > verify: **the three roles are separate prompts with separate input sets,
11
+ * > and the judge cannot see outcome truth.**
12
+ *
13
+ * ## Separate input sets, enforced at the boundary rather than by convention
14
+ *
15
+ * {@link ROLE_INPUTS} declares which input kinds each role may receive, and
16
+ * {@link buildPrompt} REFUSES an input whose kind is not in that role's set.
17
+ * Separation therefore survives a caller who assembles one bag of everything
18
+ * and hands it to all three, which is precisely how three roles collapse back
19
+ * into one unconstrained rewrite prompt in practice: nobody decides to collapse
20
+ * them, the input set just widens one field at a time until the roles differ
21
+ * only in their preamble.
22
+ *
23
+ * The sets are deliberately not disjoint — every role sees `defect-observation`,
24
+ * because a curator deciding `RETIRE` without the evidence that motivated it is
25
+ * guessing. What no role sees is the UNION, and a test pins that: the widest
26
+ * role's set is a strict subset of the vocabulary.
27
+ *
28
+ * ## The judge, and why "absent" was not good enough
29
+ *
30
+ * The load-bearing half of the verify clause is that the judge cannot see
31
+ * outcome truth. A judge that merely is not GIVEN the outcome is one careless
32
+ * spread away from seeing it, and the spread reads as harmless in review. So
33
+ * the property is structural in two independent layers:
34
+ *
35
+ * 1. {@link JudgeInput} has no field capable of carrying an outcome. It is
36
+ * three fields — a contract id, rubric question ids, and the artifact text
37
+ * — and none of them can hold a verdict, an arm label, a metric, or a
38
+ * winner. `tests/scripts/role_split.test.ts` scans the declared interface
39
+ * for the outcome-truth field vocabulary, and proves the scanner fires on
40
+ * a synthetic interface before trusting it to be silent on this one.
41
+ * 2. {@link buildJudgePrompt} rejects any key outside {@link JUDGE_INPUT_KEYS}.
42
+ * Types vanish at runtime, so a caller casting a wider object through
43
+ * `as JudgeInput` would defeat layer 1 alone; layer 2 throws on that
44
+ * object rather than quietly serialising the surplus field into the prompt.
45
+ *
46
+ * The judge's own output vocabulary is closed and outcome-free
47
+ * ({@link JUDGE_GRADES}): it answers a rubric question, and there is no value it
48
+ * can return that names an arm or declares a winner.
49
+ *
50
+ * ## The frozen evaluator contract is the one that already exists
51
+ *
52
+ * The contract id travels on the prompt, and {@link promoteJudgeContract} is the
53
+ * only way to change it — it delegates to
54
+ * `evaluator_promotion.assertEvaluatorPromotable`, so a judge-contract change
55
+ * inherits the cross-grade and discrimination-plant requirements step 4.7
56
+ * already built rather than getting a second, weaker gate of its own.
57
+ */
58
+ import { CURATOR_OPS } from './curator_ops.js';
59
+ import { assertEvaluatorPromotable, type EvaluatorChange } from './evaluator_promotion.js';
60
+ import { classifyOverfit } from './judge_hygiene.js';
61
+
62
+ /** The three roles. The judge is deliberately NOT one of them — it is optional. */
63
+ export const ROLES = ['analyzer', 'curator', 'proposer'] as const;
64
+ export type Role = (typeof ROLES)[number];
65
+
66
+ /** The closed vocabulary of input kinds a role may be given. */
67
+ export const INPUT_KINDS = [
68
+ 'defect-observation',
69
+ 'trigger-census',
70
+ 'corpus-inventory',
71
+ 'lifecycle-history',
72
+ 'analyzer-finding',
73
+ 'curator-decision',
74
+ 'authoring-contract',
75
+ ] as const;
76
+ export type InputKind = (typeof INPUT_KINDS)[number];
77
+
78
+ export interface RoleInput {
79
+ kind: InputKind;
80
+ id: string;
81
+ text: string;
82
+ }
83
+
84
+ /**
85
+ * Which input kinds each role may receive.
86
+ *
87
+ * The analyzer reads evidence and nothing about the corpus, so it cannot
88
+ * propose a lifecycle op. The curator reads the corpus and the analyzer's
89
+ * findings, so it decides WHICH artifact changes without ever seeing the
90
+ * authoring contract that would let it write one. The proposer reads the
91
+ * curator's decision and the authoring contract, so it writes text for a
92
+ * decision that was already made elsewhere.
93
+ */
94
+ export const ROLE_INPUTS: Readonly<Record<Role, readonly InputKind[]>> = {
95
+ analyzer: ['defect-observation', 'trigger-census'],
96
+ curator: ['defect-observation', 'corpus-inventory', 'lifecycle-history', 'analyzer-finding'],
97
+ proposer: ['defect-observation', 'curator-decision', 'authoring-contract'],
98
+ };
99
+
100
+ /** What each role is asked to produce. One sentence, and they do not overlap. */
101
+ const ROLE_TASK: Readonly<Record<Role, string>> = {
102
+ analyzer:
103
+ 'Name the defect classes the evidence supports, each with the observation ids that carry it. ' +
104
+ 'Do not name an artifact to change and do not propose text.',
105
+ curator:
106
+ `Choose exactly one lifecycle operation from ${CURATOR_OPS.join(' / ')} per finding, with its targets. ` +
107
+ 'Do not write the artifact body — that decision is not yours to author.',
108
+ proposer:
109
+ 'Write the candidate body for the curator decision you were given, against the authoring contract. ' +
110
+ 'Do not revisit the operation, the targets, or whether the change is warranted.',
111
+ };
112
+
113
+ export class RoleContractViolation extends Error {
114
+ readonly reasons: readonly string[];
115
+ constructor(reasons: readonly string[]) {
116
+ super(`role contract violated: ${reasons.join('; ')}`);
117
+ this.name = 'RoleContractViolation';
118
+ this.reasons = reasons;
119
+ }
120
+ }
121
+
122
+ export interface RolePrompt {
123
+ role: Role;
124
+ text: string;
125
+ /** The kinds actually supplied, sorted — the prompt's declared input set. */
126
+ input_kinds: readonly InputKind[];
127
+ }
128
+
129
+ /**
130
+ * Build one role's prompt, refusing any input kind outside that role's set.
131
+ *
132
+ * Fail-closed by construction: there is no option object that widens a role's
133
+ * set, so a caller who wants to feed the curator an authoring contract has to
134
+ * edit {@link ROLE_INPUTS}, which is visible in a diff.
135
+ */
136
+ export function buildPrompt(role: Role, inputs: readonly RoleInput[]): RolePrompt {
137
+ const allowed = new Set<InputKind>(ROLE_INPUTS[role]);
138
+ const rejected = inputs.filter((i) => !allowed.has(i.kind));
139
+ if (rejected.length > 0) {
140
+ throw new RoleContractViolation(
141
+ rejected.map(
142
+ (i) =>
143
+ `role '${role}' may not receive input kind '${i.kind}' (input '${i.id}') — ` +
144
+ `its set is ${[...allowed].join(', ')}`,
145
+ ),
146
+ );
147
+ }
148
+ const kinds = [...new Set(inputs.map((i) => i.kind))].sort((a, b) => a.localeCompare(b));
149
+ const body = inputs
150
+ .map((i) => `[${i.kind}:${i.id}]\n${i.text}`)
151
+ .sort((a, b) => a.localeCompare(b))
152
+ .join('\n\n');
153
+ return {
154
+ role,
155
+ text: `## Role: ${role}\n\n${ROLE_TASK[role]}\n\n## Inputs\n\n${body}`,
156
+ input_kinds: kinds,
157
+ };
158
+ }
159
+
160
+ /* ─────────────────────────── the optional judge ─────────────────────────── */
161
+
162
+ /**
163
+ * Every key a judge prompt may be built from. Frozen, and checked at runtime,
164
+ * because a cast defeats the type but not this list.
165
+ */
166
+ export const JUDGE_INPUT_KEYS = ['evaluator_contract_id', 'rubric_question_ids', 'artifact_text'] as const;
167
+
168
+ /**
169
+ * The judge's entire view.
170
+ *
171
+ * No field here can carry an outcome: not a verdict, not an arm label, not a
172
+ * metric, not a winner, not a ground-truth label. That is the point, and it is
173
+ * asserted mechanically rather than left to review.
174
+ */
175
+ export interface JudgeInput {
176
+ evaluator_contract_id: string;
177
+ rubric_question_ids: readonly string[];
178
+ artifact_text: string;
179
+ }
180
+
181
+ /** The judge's closed answer vocabulary. Nothing here names an arm or a winner. */
182
+ export const JUDGE_GRADES = ['yes', 'no', 'not-assessable'] as const;
183
+ export type JudgeGrade = (typeof JUDGE_GRADES)[number];
184
+
185
+ export class EvaluatorContractViolation extends Error {
186
+ readonly reasons: readonly string[];
187
+ constructor(reasons: readonly string[]) {
188
+ super(`evaluator contract violated: ${reasons.join('; ')}`);
189
+ this.name = 'EvaluatorContractViolation';
190
+ this.reasons = reasons;
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Words that would make a rubric question an outcome question.
196
+ *
197
+ * A rubric question asks a property of ONE artifact. The moment it asks which
198
+ * of two did better, the judge is grading the experiment rather than the text,
199
+ * and its answer becomes a second verdict beside `paired_verdict` — Risk 1 on
200
+ * this roadmap.
201
+ */
202
+ const OUTCOME_QUESTION_MARKERS = [
203
+ 'which arm',
204
+ 'which candidate',
205
+ 'which version',
206
+ 'treatment',
207
+ 'control arm',
208
+ 'baseline arm',
209
+ 'winner',
210
+ 'won',
211
+ 'better than',
212
+ 'outperform',
213
+ 'ground truth',
214
+ 'correct answer',
215
+ 'passed the eval',
216
+ 'regression',
217
+ ];
218
+
219
+ export interface RubricQuestion {
220
+ id: string;
221
+ text: string;
222
+ }
223
+
224
+ export interface RubricAudit {
225
+ /** Advisory shape per `judge_hygiene.classifyOverfit`. Gates nothing. */
226
+ shapes: readonly { id: string; shape: string; reason: string }[];
227
+ }
228
+
229
+ /**
230
+ * Throw {@link EvaluatorContractViolation} on any question that asks about
231
+ * outcome truth, and return the advisory shape audit for the rest.
232
+ */
233
+ export function assertRubricOnly(questions: readonly RubricQuestion[]): RubricAudit {
234
+ const reasons: string[] = [];
235
+ for (const q of questions) {
236
+ const lower = q.text.toLowerCase();
237
+ const hit = OUTCOME_QUESTION_MARKERS.find((m) => lower.includes(m));
238
+ if (hit !== undefined) {
239
+ reasons.push(`question '${q.id}' asks about outcome truth ("${hit}") — the judge grades text, not runs`);
240
+ }
241
+ }
242
+ if (reasons.length > 0) throw new EvaluatorContractViolation(reasons);
243
+ return {
244
+ shapes: questions.map((q) => {
245
+ const c = classifyOverfit(q.text);
246
+ return { id: q.id, shape: c.shape, reason: c.reason };
247
+ }),
248
+ };
249
+ }
250
+
251
+ export interface JudgePrompt {
252
+ /** Deliberately not a {@link Role}: the judge is optional and outside the split. */
253
+ role: 'judge';
254
+ evaluator_contract_id: string;
255
+ text: string;
256
+ }
257
+
258
+ /**
259
+ * Build the judge prompt from the allowlist and nothing else.
260
+ *
261
+ * The surplus-key check is the layer that survives a cast. `JudgeInput` cannot
262
+ * DECLARE an outcome field, but `x as JudgeInput` can still carry one at
263
+ * runtime, and a builder that spread its input would serialise it into the
264
+ * prompt. This one enumerates {@link JUDGE_INPUT_KEYS} and refuses anything else.
265
+ */
266
+ export function buildJudgePrompt(input: JudgeInput, questions: readonly RubricQuestion[]): JudgePrompt {
267
+ const allowed = new Set<string>(JUDGE_INPUT_KEYS);
268
+ const surplus = Object.keys(input as unknown as Record<string, unknown>).filter((k) => !allowed.has(k));
269
+ if (surplus.length > 0) {
270
+ throw new EvaluatorContractViolation(
271
+ surplus.map((k) => `judge input carries '${k}', which is outside the frozen key set`),
272
+ );
273
+ }
274
+ assertRubricOnly(questions);
275
+ const asked = questions
276
+ .filter((q) => input.rubric_question_ids.includes(q.id))
277
+ .map((q) => `- ${q.id}: ${q.text}`)
278
+ .join('\n');
279
+ return {
280
+ role: 'judge',
281
+ evaluator_contract_id: input.evaluator_contract_id,
282
+ text:
283
+ `## Role: judge (contract ${input.evaluator_contract_id})\n\n` +
284
+ `Answer each rubric question with exactly one of ${JUDGE_GRADES.join(' / ')}. ` +
285
+ 'You are grading one artifact against the question. You are not told how any run went, ' +
286
+ 'and no answer you can give names an arm or a winner.\n\n' +
287
+ `## Rubric\n\n${asked}\n\n## Artifact\n\n${input.artifact_text}`,
288
+ };
289
+ }
290
+
291
+ /** Refuse a judge prompt built against a contract id other than the frozen one. */
292
+ export function assertJudgeContractFrozen(prompt: JudgePrompt, frozenId: string): void {
293
+ if (prompt.evaluator_contract_id !== frozenId) {
294
+ throw new EvaluatorContractViolation([
295
+ `judge prompt cites contract '${prompt.evaluator_contract_id}' but the frozen contract is ` +
296
+ `'${frozenId}' — change it through promoteJudgeContract, not by editing the prompt`,
297
+ ]);
298
+ }
299
+ }
300
+
301
+ /**
302
+ * The only way to move the frozen judge contract forward.
303
+ *
304
+ * Delegates to step 4.7's `assertEvaluatorPromotable`, so a judge-contract
305
+ * change requires the same cross-grade over a frozen candidate set and the same
306
+ * discrimination plants as any other evaluator change. Returns the new id only
307
+ * once that gate has passed.
308
+ */
309
+ export function promoteJudgeContract(change: EvaluatorChange): string {
310
+ assertEvaluatorPromotable(change);
311
+ return change.to;
312
+ }
313
+
314
+ /* ───────────────────────────── the pipeline ─────────────────────────────── */
315
+
316
+ export interface SplitPipeline {
317
+ prompts: readonly RolePrompt[];
318
+ /** `null` when no judge is configured — the judge is optional, per the step. */
319
+ judge: JudgePrompt | null;
320
+ }
321
+
322
+ /**
323
+ * Assemble the three role prompts, each from its own input set, plus the
324
+ * optional judge.
325
+ *
326
+ * `inputsFor` is called once per role and its result passes through
327
+ * {@link buildPrompt}, so a supplier that returns one undifferentiated bag is
328
+ * refused rather than silently accepted.
329
+ */
330
+ export function buildSplitPipeline(
331
+ inputsFor: (role: Role) => readonly RoleInput[],
332
+ judge: { input: JudgeInput; questions: readonly RubricQuestion[] } | null = null,
333
+ ): SplitPipeline {
334
+ return {
335
+ prompts: ROLES.map((r) => buildPrompt(r, inputsFor(r))),
336
+ judge: judge === null ? null : buildJudgePrompt(judge.input, judge.questions),
337
+ };
338
+ }
@@ -0,0 +1,307 @@
1
+ /**
2
+ * The corpus and catalogue substrate for the two routing measurements of
3
+ * `road-to-governed-harness-evolution` — step 5.1 (description vs body) and
4
+ * step 6.4 (delivery sets).
5
+ *
6
+ * ONE LOADER, TWO MEASUREMENTS. Both runs need the same three things: the
7
+ * frozen train/holdout partition, the trigger cases, and the skill catalogue
8
+ * the prompts are ranked against. Two loaders over one corpus is how two
9
+ * measurements start disagreeing about what they measured, so there is one.
10
+ *
11
+ * THE SEAL IS ENFORCED BY REFUSAL, NOT BY FILTERING. The holdout partition
12
+ * frozen in `agents/evidence/analysis/trigger-corpus-holdout-2026-08-30.md`
13
+ * says: no analyzer authored in Phase 5 may read the sealed corpora. So
14
+ * `loadTrainCases` never opens a holdout `evals/triggers.json` at all — the
15
+ * partition is computed from the DIRECTORY NAME, before any file is read.
16
+ * Filtering after the read would satisfy the letter and not the seal.
17
+ *
18
+ * The seal covers the corpus files and not the catalogue: a holdout skill's
19
+ * `SKILL.md` is still ranked against, because removing it would measure a
20
+ * catalogue that does not exist. The boundary is stated in the 5.1
21
+ * pre-registration rather than left to be inferred here.
22
+ *
23
+ * NO SCORER OF ITS OWN. Every score comes from `src/shared/skillRanking.ts`,
24
+ * the module the production ranker and the MCP handler already share. A second
25
+ * scorer in a measurement module would measure the measurement.
26
+ *
27
+ * Pure of network and of clock; reads files and nothing else.
28
+ */
29
+ import * as fs from 'node:fs';
30
+ import { createHash } from 'node:crypto';
31
+ import * as path from 'node:path';
32
+
33
+ import { scoreSkill, tokenize, type RankableSkill } from '../../shared/skillRanking.js';
34
+
35
+ /**
36
+ * The partition constant the freeze artefact fixes. Changing it re-partitions
37
+ * the corpus and voids every result measured under the old one, which is why
38
+ * it is a named export a test can pin rather than a literal.
39
+ */
40
+ export const HOLDOUT_CEILING = 51;
41
+
42
+ export type Partition = 'holdout' | 'train';
43
+
44
+ /** `holdout iff sha256(<skill-directory-name>)[0] < 51`, from the freeze artefact. */
45
+ export function partitionOf(skill: string): Partition {
46
+ const bucket = parseInt(createHash('sha256').update(skill).digest('hex').slice(0, 2), 16);
47
+ return bucket < HOLDOUT_CEILING ? 'holdout' : 'train';
48
+ }
49
+
50
+ /** One adjudicated case: a prompt, and whether the owning skill must be delivered. */
51
+ export interface CorpusCase {
52
+ readonly skill: string;
53
+ readonly prompt: string;
54
+ /** `true` = positive (must be delivered) · `false` = negative (must not). */
55
+ readonly expect: boolean;
56
+ /** Step 2.3's vocabulary where the file declares it; 876 of 931 cases do not. */
57
+ readonly caseClass: 'exemplar' | 'near-miss' | 'counterexample' | null;
58
+ readonly language: string | null;
59
+ }
60
+
61
+ interface RawQuery {
62
+ q?: unknown;
63
+ trigger?: unknown;
64
+ class?: unknown;
65
+ language?: unknown;
66
+ }
67
+
68
+ /**
69
+ * The two corpus shapes this tree carries.
70
+ *
71
+ * `queries[]` is the modern one. Two train files — `brand-asset-generation` and
72
+ * `estimate-ticket` — are the legacy `should_trigger` / `should_not_trigger`
73
+ * pair that step 2.3 grandfathered, and `lint_skill_trigger_corpus` returns
74
+ * before its class rules for exactly those two. A reader that understood only
75
+ * the modern shape would drop them SILENTLY, which is worse than refusing them:
76
+ * the run would report 80 train corpora where the partition says 82 and nothing
77
+ * would say which two were missing. So both shapes are read, and
78
+ * `legacyShaped` records which file used which.
79
+ */
80
+ interface RawCorpus {
81
+ queries?: RawQuery[];
82
+ should_trigger?: unknown;
83
+ should_not_trigger?: unknown;
84
+ }
85
+
86
+ export function skillsDir(repoRoot: string): string {
87
+ return path.join(repoRoot, 'src', 'skills');
88
+ }
89
+
90
+ /**
91
+ * Is this `src/skills/<name>` entry test scaffolding rather than a skill?
92
+ *
93
+ * A `__`-prefixed directory is scaffolding by convention, and a real skill can
94
+ * never be named one: `skill.schema.json` pins `name` to `^[a-z][a-z0-9-]*$`
95
+ * and requires it to match the parent directory, so a leading underscore fails
96
+ * `validate_frontmatter`. This predicate therefore cannot hide a shipped skill.
97
+ *
98
+ * WHY IT EXISTS, measured rather than assumed.
99
+ * `tests/scripts/lint_originality.test.ts:64` writes a re-skin fixture to
100
+ * `src/skills/__origtest_reskin_fixture/SKILL.md` in the REAL tree and removes
101
+ * it in `afterEach`, because the linter resolves its corpus from a
102
+ * module-level ROOT and takes no root argument. During that window any
103
+ * concurrently-running test file that counts the catalogue sees 300 where the
104
+ * commit holds 299 — which is what failed
105
+ * `tests/scripts/routing_signal_measurement.test.ts` on
106
+ * `Node Tests (ubuntu-latest, shard 2/4)` in runs 33418425604 and 33424783559,
107
+ * intermittently, while passing in isolation and passing on the next run over
108
+ * two markdown files nothing reads.
109
+ *
110
+ * Reproduced locally before this line was written: with the fixture present on
111
+ * disk the assertion fails `300` vs `299`, character for character the CI
112
+ * message; with this predicate active it passes.
113
+ *
114
+ * Excluding the prefix here rather than threading a root through the linter is
115
+ * the smaller change by an order of magnitude: ROOT is baked into ten
116
+ * module-level constants there, and refactoring a shipped gate to suit a test
117
+ * is a worse trade than a naming convention the tree already follows.
118
+ */
119
+ export function isScaffoldingSkillDir(name: string): boolean {
120
+ return name.startsWith('__');
121
+ }
122
+
123
+ /** Every skill directory that carries a trigger corpus, with its partition. */
124
+ export function corpusSkills(repoRoot: string): { skill: string; partition: Partition }[] {
125
+ const dir = skillsDir(repoRoot);
126
+ if (!fs.existsSync(dir)) return [];
127
+ return fs
128
+ .readdirSync(dir)
129
+ .sort()
130
+ .filter((skill) => !isScaffoldingSkillDir(skill))
131
+ .filter((skill) => fs.existsSync(path.join(dir, skill, 'evals', 'triggers.json')))
132
+ .map((skill) => ({ skill, partition: partitionOf(skill) }));
133
+ }
134
+
135
+ /**
136
+ * The train cases. A holdout corpus is never opened — the partition is decided
137
+ * from the directory name and the sealed path is skipped before any read.
138
+ */
139
+ export function loadTrainCases(repoRoot: string): CorpusCase[] {
140
+ const dir = skillsDir(repoRoot);
141
+ const out: CorpusCase[] = [];
142
+ for (const { skill, partition } of corpusSkills(repoRoot)) {
143
+ if (partition === 'holdout') continue;
144
+ const raw = JSON.parse(
145
+ fs.readFileSync(path.join(dir, skill, 'evals', 'triggers.json'), 'utf8'),
146
+ ) as RawCorpus;
147
+ if (Array.isArray(raw.queries)) {
148
+ for (const q of raw.queries) {
149
+ if (typeof q.q !== 'string' || typeof q.trigger !== 'boolean') continue;
150
+ const declared = typeof q.class === 'string' ? q.class : null;
151
+ out.push({
152
+ skill,
153
+ prompt: q.q,
154
+ expect: q.trigger,
155
+ caseClass:
156
+ declared === 'exemplar' ||
157
+ declared === 'near-miss' ||
158
+ declared === 'counterexample'
159
+ ? declared
160
+ : null,
161
+ language: typeof q.language === 'string' ? q.language : null,
162
+ });
163
+ }
164
+ continue;
165
+ }
166
+ for (const [key, expect] of [
167
+ ['should_trigger', true],
168
+ ['should_not_trigger', false],
169
+ ] as const) {
170
+ const list = raw[key];
171
+ if (!Array.isArray(list)) continue;
172
+ for (const prompt of list) {
173
+ if (typeof prompt !== 'string') continue;
174
+ out.push({ skill, prompt, expect, caseClass: null, language: null });
175
+ }
176
+ }
177
+ }
178
+ return out;
179
+ }
180
+
181
+ /** Which train corpora use the legacy shape. Reported so the count is explainable. */
182
+ export function legacyShaped(repoRoot: string): string[] {
183
+ const dir = skillsDir(repoRoot);
184
+ const out: string[] = [];
185
+ for (const { skill, partition } of corpusSkills(repoRoot)) {
186
+ if (partition === 'holdout') continue;
187
+ const raw = JSON.parse(
188
+ fs.readFileSync(path.join(dir, skill, 'evals', 'triggers.json'), 'utf8'),
189
+ ) as RawCorpus;
190
+ if (!Array.isArray(raw.queries)) out.push(skill);
191
+ }
192
+ return out;
193
+ }
194
+
195
+ /** A catalogue entry: what the ranker sees, plus the body the 5.1 arm adds. */
196
+ export interface CatalogueEntry extends RankableSkill {
197
+ readonly name: string;
198
+ readonly description: string;
199
+ readonly personas: readonly string[];
200
+ /** SKILL.md with its frontmatter removed. Empty when the file has none. */
201
+ readonly body: string;
202
+ }
203
+
204
+ /** Minimal frontmatter split. Returns `[block, body]`; `['', text]` when absent. */
205
+ export function splitFrontmatter(text: string): [string, string] {
206
+ if (!text.startsWith('---')) return ['', text];
207
+ const end = text.indexOf('\n---', 3);
208
+ if (end === -1) return ['', text];
209
+ return [text.slice(3, end), text.slice(end + 4)];
210
+ }
211
+
212
+ /** `name`, `description` and `personas` out of a frontmatter block. */
213
+ export function readMeta(block: string): { name: string; description: string; personas: string[] } {
214
+ let name = '';
215
+ let description = '';
216
+ const personas: string[] = [];
217
+ let inPersonas = false;
218
+ for (const raw of block.split('\n')) {
219
+ const line = raw.replace(/\s+$/, '');
220
+ if (inPersonas && /^ {2}- /.test(line)) {
221
+ personas.push(line.slice(4).trim().replace(/^["']|["']$/g, ''));
222
+ continue;
223
+ }
224
+ inPersonas = false;
225
+ const m = /^([a-zA-Z_][\w-]*)[ \t]*:[ \t]*(.*)$/.exec(line);
226
+ if (!m) continue;
227
+ const key = m[1] as string;
228
+ const value = (m[2] as string).trim().replace(/^["']|["']$/g, '');
229
+ if (key === 'personas' && value === '') inPersonas = true;
230
+ else if (key === 'name') name = value;
231
+ else if (key === 'description') description = value;
232
+ }
233
+ return { name, description, personas };
234
+ }
235
+
236
+ /** Every skill directory`s `SKILL.md`, name-sorted. The ranking universe. */
237
+ export function loadCatalogue(repoRoot: string): CatalogueEntry[] {
238
+ const dir = skillsDir(repoRoot);
239
+ if (!fs.existsSync(dir)) return [];
240
+ const out: CatalogueEntry[] = [];
241
+ for (const skill of fs.readdirSync(dir).sort()) {
242
+ if (isScaffoldingSkillDir(skill)) continue;
243
+ const file = path.join(dir, skill, 'SKILL.md');
244
+ if (!fs.existsSync(file)) continue;
245
+ const [block, body] = splitFrontmatter(fs.readFileSync(file, 'utf8'));
246
+ const meta = readMeta(block);
247
+ out.push({
248
+ name: meta.name || skill,
249
+ description: meta.description,
250
+ personas: meta.personas,
251
+ body,
252
+ });
253
+ }
254
+ return out;
255
+ }
256
+
257
+ /** The two 5.1 arms. `description` is today's production condition. */
258
+ export const ARMS = ['description', 'description+body'] as const;
259
+ export type Arm = (typeof ARMS)[number];
260
+
261
+ /**
262
+ * The indexed term set per arm.
263
+ *
264
+ * The `description` arm reproduces `skillTerms(skill, {})` exactly — same
265
+ * inputs, same tokenizer — so the control arm IS the shipped behaviour rather
266
+ * than a re-implementation of it.
267
+ */
268
+ export function armTerms(entry: CatalogueEntry, arm: Arm): Set<string> {
269
+ const parts = [entry.name, entry.description];
270
+ if (arm === 'description+body') parts.push(entry.body);
271
+ return tokenize(parts.join(' '));
272
+ }
273
+
274
+ export interface RankedName {
275
+ readonly name: string;
276
+ readonly score: number;
277
+ }
278
+
279
+ /**
280
+ * Top-k by score, ties broken on name — the total order `rankSkills` already
281
+ * defines. Zero scores are dropped, because a skill the scorer gives 0 is not
282
+ * delivered by the shipped ranker either.
283
+ */
284
+ export function topK(
285
+ prompt: string,
286
+ catalogue: readonly CatalogueEntry[],
287
+ terms: ReadonlyMap<string, Set<string>>,
288
+ k: number,
289
+ ): RankedName[] {
290
+ const taskTerms = tokenize(prompt);
291
+ const rows: RankedName[] = [];
292
+ for (const entry of catalogue) {
293
+ const t = terms.get(entry.name);
294
+ if (t === undefined) continue;
295
+ const score = scoreSkill(taskTerms, entry, t);
296
+ if (score > 0) rows.push({ name: entry.name, score });
297
+ }
298
+ rows.sort((a, b) => b.score - a.score || (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
299
+ return rows.slice(0, k);
300
+ }
301
+
302
+ /** Term sets for one arm, keyed by the name `topK` ranks on. */
303
+ export function termIndex(catalogue: readonly CatalogueEntry[], arm: Arm): Map<string, Set<string>> {
304
+ const index = new Map<string, Set<string>>();
305
+ for (const entry of catalogue) index.set(entry.name, armTerms(entry, arm));
306
+ return index;
307
+ }