@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,461 @@
1
+ /**
2
+ * The METERED candidate proposer — the second arm, and the one that costs money.
3
+ *
4
+ * `road-to-governed-evidence-production` step 2.1, built under the
5
+ * **NARROWED 2026-09-01** disposition of `blocker: metered-backend-park`: a
6
+ * metered PROPOSER is admitted, a metered EVALUATOR stays forbidden.
7
+ *
8
+ * `_lib/candidate_proposer.ts` is the deterministic arm and the surface this
9
+ * mirrors — same {@link DefectObservation} input, same {@link CandidateRecord}
10
+ * output, same id scheme — so the two are comparable pair-wise over one input
11
+ * rather than being two different experiments wearing one name.
12
+ *
13
+ * ## The role constraint, and where each half of it is enforced
14
+ *
15
+ * > *A metered call may generate candidate text. It may not score, rank,
16
+ * > filter, select between, or supply any input to the verdict for the arms
17
+ * > being compared — whatever the module is called.*
18
+ *
19
+ * Held by construction, not by intention. Six places:
20
+ *
21
+ * | Forbidden role | What makes it unavailable |
22
+ * |---|---|
23
+ * | supply a score | {@link GenerationResult} carries `text` and `model` and nothing else, and {@link NoDecisionField} makes adding a scoring key a BUILD ERROR |
24
+ * | rank | no function here accepts more than one generation for one observation; there is no code path that holds two |
25
+ * | select between candidates | exactly one record per observation, asserted at the return by {@link CandidateCountError} |
26
+ * | filter | an observation that cannot be satisfied THROWS; it is never dropped, so the output can never be a subset |
27
+ * | reorder | the output order is `byteCompare` over the INPUT, reusing the deterministic arm's own comparator — model output is never an ordering key |
28
+ * | reach the verdict | this module imports no verdict module, asserted by its test |
29
+ *
30
+ * The retry loop is the one place a reader should look twice. It stops at the
31
+ * FIRST output that satisfies the record contract; it never holds two valid
32
+ * generations and never compares them. First-valid is a retry policy. Choosing
33
+ * the better of two valid generations would be selection, and there is no code
34
+ * path here that could express it.
35
+ *
36
+ * ## Who decides escalation
37
+ *
38
+ * The **pathology of a deterministic refusal**, never the model's opinion of its
39
+ * own output. The first attempt runs on `reason_unknown`, whose ladder is
40
+ * exactly `['lite']` — *"escalating on a reason nobody established is spending
41
+ * on a guess"* (`_lib/evolution_roi.ts:136-138`). A refusal is then classified
42
+ * into a {@link PathologyWhy} by {@link classifyRefusal}, and the walk continues
43
+ * on THAT class's ladder from its cheapest untried rung. A class with an empty
44
+ * ladder stops the walk.
45
+ *
46
+ * Every attempt is recorded and the whole list is checked by
47
+ * `assertCheapestFirst` (`_lib/evolution_roi.ts:215`) before this module
48
+ * returns — the production caller AC-3 asks for.
49
+ *
50
+ * ## No transport lives here
51
+ *
52
+ * The metered call arrives as an injected {@link TextGenerator} port. The
53
+ * shipped binding is `_lib/llm_proposer_transport.ts`; this module imports it
54
+ * nowhere, so the arm is testable with a stub and the transport is one small
55
+ * file a reviewer can read whole.
56
+ */
57
+
58
+ import {
59
+ RECIPES,
60
+ byteCompare,
61
+ candidateId,
62
+ type DefectObservation,
63
+ type SubjectReader,
64
+ } from './candidate_proposer.js';
65
+ import {
66
+ CANDIDATE_RECORD_VERSION,
67
+ CandidateSchemaError,
68
+ assertMutationPathsOwned,
69
+ type CandidateRecord,
70
+ type Mutation,
71
+ } from './candidate_record.js';
72
+ import {
73
+ assertCheapestFirst,
74
+ ladderFor,
75
+ nextTier,
76
+ type LadderAttempt,
77
+ type ModelTier,
78
+ } from './evolution_roi.js';
79
+ import type { PathologyWhy } from './pathology_archive.js';
80
+
81
+ type Assert<T extends true> = T;
82
+
83
+ /**
84
+ * Keys that would turn a generation into a decision.
85
+ *
86
+ * The same mechanism `_lib/runtime_journal.ts`'s `FREE_FORM_KEYS` uses for the
87
+ * privacy floor, pointed at a different failure: there, a field that could hold
88
+ * content; here, a field that could hold a judgement. A closed deny-list is
89
+ * blunt on purpose — a guard that only rejects the keys someone thought of is a
90
+ * guard that has to be re-argued at every edit.
91
+ */
92
+ export const DECISION_FIELD_KEYS = [
93
+ 'score',
94
+ 'scores',
95
+ 'rank',
96
+ 'ranking',
97
+ 'rating',
98
+ 'grade',
99
+ 'confidence',
100
+ 'probability',
101
+ 'logprob',
102
+ 'logprobs',
103
+ 'best',
104
+ 'chosen',
105
+ 'selected',
106
+ 'preferred',
107
+ 'winner',
108
+ 'verdict',
109
+ 'order',
110
+ 'priority',
111
+ 'weight',
112
+ 'quality',
113
+ ] as const;
114
+ export type DecisionFieldKey = (typeof DECISION_FIELD_KEYS)[number];
115
+
116
+ /** `T` when `T` carries no {@link DecisionFieldKey}, and `never` when it does. */
117
+ export type NoDecisionField<T> = Extract<keyof T, DecisionFieldKey> extends never ? T : never;
118
+
119
+ // --- the port ----------------------------------------------------------------
120
+
121
+ /** One metered request. The tier is the ladder's, never the model's choice. */
122
+ export interface GenerationRequest {
123
+ readonly tier: ModelTier;
124
+ readonly system: string;
125
+ readonly prompt: string;
126
+ }
127
+
128
+ /**
129
+ * What a metered call may return: text, and which model produced it.
130
+ *
131
+ * `model` is provenance and not a judgement — the protocol document needs it to
132
+ * record what was run. Nothing in this module reads it.
133
+ */
134
+ export interface GenerationResult {
135
+ readonly text: string;
136
+ readonly model: string;
137
+ }
138
+
139
+ /**
140
+ * The metered port. One request in, one text out.
141
+ *
142
+ * It cannot express a batch, so it cannot express a comparison: a signature
143
+ * taking `readonly GenerationRequest[]` and returning a sorted list would be a
144
+ * ranking surface even if today's implementation ignored the order.
145
+ */
146
+ export type TextGenerator = (req: GenerationRequest) => Promise<GenerationResult>;
147
+
148
+ /** A generation the record contract refused. Carries WHY, as a pathology. */
149
+ export class GenerationRefusedError extends Error {
150
+ readonly why: PathologyWhy;
151
+ constructor(why: PathologyWhy, message: string) {
152
+ super(message);
153
+ this.name = 'GenerationRefusedError';
154
+ this.why = why;
155
+ }
156
+ }
157
+
158
+ /** One observation produced no record and was not dropped. */
159
+ export class CandidateCountError extends Error {
160
+ constructor(message: string) {
161
+ super(message);
162
+ this.name = 'CandidateCountError';
163
+ }
164
+ }
165
+
166
+ // --- prompts -----------------------------------------------------------------
167
+
168
+ /**
169
+ * The system prompt. FROZEN — its bytes are part of the execution protocol
170
+ * (`docs/contracts/metered-proposer-protocol.md`), so an edit here is an edit to
171
+ * the protocol and invalidates a comparison already captured against it.
172
+ */
173
+ export const SYSTEM_PROMPT =
174
+ 'You rewrite one Markdown artifact to remove one named defect.\n' +
175
+ 'Return ONLY the complete rewritten artifact body. No preamble, no fences,\n' +
176
+ 'no commentary, no explanation of what you changed.\n' +
177
+ 'Do not judge, score, rank, or compare anything. Produce one body.';
178
+
179
+ /** The user prompt for one observation. Pure — same inputs, same bytes. */
180
+ export function buildPrompt(obs: DefectObservation, body: string): string {
181
+ const recipe = RECIPES[obs.defectClass];
182
+ const route = obs.routeTo === undefined ? '' : `\nThe obligation must be routed to: ${obs.routeTo}\n`;
183
+ return (
184
+ `Defect class: ${obs.defectClass}\n` +
185
+ `What that means: ${recipe.summary}\n` +
186
+ `Artifact path: ${obs.subject}\n` +
187
+ route +
188
+ '\n--- BEGIN CURRENT BODY ---\n' +
189
+ body +
190
+ '\n--- END CURRENT BODY ---\n'
191
+ );
192
+ }
193
+
194
+ // --- the output contract ------------------------------------------------------
195
+
196
+ /**
197
+ * The largest generated body accepted, in bytes.
198
+ *
199
+ * A STATED CEILING, not a measured one, and it is a runaway guard rather than a
200
+ * quality bar: 256 KiB is far above any artifact in the candidate surface and
201
+ * far below a generation that has stopped producing an artifact. *Revisit-if* a
202
+ * legitimate subject approaches it.
203
+ */
204
+ export const MAX_BODY_BYTES = 256 * 1024;
205
+
206
+ /** The NUL code unit, built rather than typed so no source file carries one. */
207
+ const NUL = String.fromCharCode(0);
208
+
209
+ /**
210
+ * Refuse a generation the record contract cannot accept.
211
+ *
212
+ * Every check here is a SHAPE check with an objective predicate, and none of
213
+ * them compares two generations or asks whether one is good. That distinction
214
+ * is the role constraint: `output_contract_violated` is a fact about one string,
215
+ * `better` is a judgement about two.
216
+ *
217
+ * @throws {GenerationRefusedError} carrying the pathology of the refusal.
218
+ */
219
+ export function assertGenerationAcceptable(
220
+ obs: DefectObservation,
221
+ before: string,
222
+ after: string,
223
+ ): void {
224
+ if (after.trim() === '') {
225
+ throw new GenerationRefusedError('output_contract_violated', 'the generation is empty');
226
+ }
227
+ const bytes = Buffer.byteLength(after, 'utf8');
228
+ if (bytes > MAX_BODY_BYTES) {
229
+ throw new GenerationRefusedError(
230
+ 'output_contract_violated',
231
+ `the generation is ${String(bytes)} bytes, over the ${String(MAX_BODY_BYTES)}-byte ceiling`,
232
+ );
233
+ }
234
+ if (after.includes(NUL)) {
235
+ throw new GenerationRefusedError('output_contract_violated', 'the generation contains a NUL byte');
236
+ }
237
+ if (after === before) {
238
+ throw new GenerationRefusedError(
239
+ 'output_contract_violated',
240
+ 'the generation is byte-identical to the input — a proposal that changes nothing is not a proposal',
241
+ );
242
+ }
243
+ const recipe = RECIPES[obs.defectClass];
244
+ if (recipe.needsRouteTo && obs.routeTo !== undefined && !after.includes(obs.routeTo)) {
245
+ throw new GenerationRefusedError(
246
+ 'output_contract_violated',
247
+ `the generation does not name the required route target '${obs.routeTo}'`,
248
+ );
249
+ }
250
+ }
251
+
252
+ /**
253
+ * The pathology of a thrown failure.
254
+ *
255
+ * Deterministic and total. A refusal carries its own class; anything else is
256
+ * `execution_failed`, which is the honest reading of a transport or runtime
257
+ * error and licenses the full ladder because capability plausibly helps there.
258
+ */
259
+ export function classifyRefusal(e: unknown): PathologyWhy {
260
+ if (e instanceof GenerationRefusedError) return e.why;
261
+ if (e instanceof CandidateSchemaError) return 'output_contract_violated';
262
+ return 'execution_failed';
263
+ }
264
+
265
+ // --- the ladder walk -----------------------------------------------------------
266
+
267
+ /** The class the FIRST attempt runs on, before any refusal has been observed. */
268
+ export const INITIAL_CLASS: PathologyWhy = 'reason_unknown';
269
+
270
+ export interface MeteredProposal {
271
+ readonly records: readonly CandidateRecord[];
272
+ /** Every attempt, in the order it was made. The audit trail for AC-3. */
273
+ readonly attempts: readonly LadderAttempt[];
274
+ /** Which model produced each accepted record, by candidate id. Provenance only. */
275
+ readonly models: Readonly<Record<string, string>>;
276
+ }
277
+
278
+ /**
279
+ * Walk the ladder for one observation until a generation is accepted.
280
+ *
281
+ * Throws when the ladder runs out — it never returns "no record", because a
282
+ * silently absent record is the filtering the role constraint forbids.
283
+ */
284
+ async function proposeOne(
285
+ obs: DefectObservation,
286
+ before: string,
287
+ generate: TextGenerator,
288
+ attempts: LadderAttempt[],
289
+ seq: { n: number },
290
+ ): Promise<{ record: CandidateRecord; model: string }> {
291
+ let cls: PathologyWhy = INITIAL_CLASS;
292
+ // Per OBSERVATION, deliberately. A new observation is a new proposal and
293
+ // starts at the cheapest rung again; the guard allows that explicitly — a
294
+ // repeat of an already-spent rung "is not an escalation"
295
+ // (`_lib/evolution_roi.ts:201-202`). Sharing one map across observations would
296
+ // exhaust the ladder on the second subject, which is what the first version
297
+ // of this function did and what its test caught.
298
+ const spentByClass = new Map<PathologyWhy, ModelTier[]>();
299
+ let lastError: unknown = null;
300
+
301
+ for (;;) {
302
+ const spent = spentByClass.get(cls) ?? [];
303
+ const tier = nextTier(cls, spent);
304
+ if (tier === null) {
305
+ // STOP. Either the ladder is empty for this class or every licensed
306
+ // rung is spent. `null` means stop in both cases — a caller reading
307
+ // it as "escalate" has inverted the policy.
308
+ throw new GenerationRefusedError(
309
+ cls,
310
+ `no tier left for '${obs.defectClass}' on ${obs.subject}: class '${cls}' licenses ` +
311
+ `${ladderFor(cls).join(' < ') || 'nothing'}` +
312
+ (lastError === null ? '' : ` — last refusal: ${(lastError as Error).message}`),
313
+ );
314
+ }
315
+ spent.push(tier);
316
+ spentByClass.set(cls, spent);
317
+ seq.n += 1;
318
+ attempts.push({ defect_class: cls, tier, sequence: seq.n });
319
+
320
+ try {
321
+ const gen = await generate({ tier, system: SYSTEM_PROMPT, prompt: buildPrompt(obs, before) });
322
+ assertGenerationAcceptable(obs, before, gen.text);
323
+ const mutations: Mutation[] = [{ path: obs.subject, content: gen.text }];
324
+ assertMutationPathsOwned(mutations);
325
+ return {
326
+ record: {
327
+ kind: 'candidate',
328
+ version: CANDIDATE_RECORD_VERSION,
329
+ // The SAME id function as the deterministic arm: a content
330
+ // hash over class, subject and mutation bytes. Two arms
331
+ // producing the same bytes therefore produce the same id,
332
+ // which is what makes a pair-wise comparison legible.
333
+ id: candidateId(obs.defectClass, obs.subject, mutations),
334
+ // The dimension comes from the RECIPE, never from the model.
335
+ // A model that could pick the dimension would be choosing
336
+ // which arm of the alphabet its own candidate sits on, and
337
+ // that is a decision.
338
+ dimension: RECIPES[obs.defectClass].dimension,
339
+ lifecycle: 'proposed',
340
+ mutations,
341
+ },
342
+ model: gen.model,
343
+ };
344
+ } catch (e) {
345
+ lastError = e;
346
+ cls = classifyRefusal(e);
347
+ }
348
+ }
349
+ }
350
+
351
+ /**
352
+ * Propose one candidate per observation, using a metered generator.
353
+ *
354
+ * The metered twin of `proposeCandidates`. Ordering is fixed EXACTLY ONCE, on
355
+ * the input, with the deterministic arm's own comparator — so the two arms walk
356
+ * the same observations in the same order and a pair is a pair.
357
+ *
358
+ * `priorAttempts` carries what an earlier, budget-aborted run of the same corpus
359
+ * already spent, so the ordering guard sees the whole run rather than its tail.
360
+ * It is UNTRUSTED input and is validated against the ladder by the same
361
+ * `assertCheapestFirst` call the fresh path uses — which is what makes that
362
+ * guard's red producible from this function's own arguments.
363
+ *
364
+ * @throws {CandidateCountError} if the output would not be one record per
365
+ * observation. It is not reachable through this function's own logic, which is
366
+ * why it is asserted rather than trusted: the invariant is what makes "no
367
+ * filtering" checkable by a reader who does not want to re-derive the loop.
368
+ */
369
+ export async function proposeCandidatesWithModel(
370
+ observations: readonly DefectObservation[],
371
+ read: SubjectReader,
372
+ generate: TextGenerator,
373
+ priorAttempts: readonly LadderAttempt[] = [],
374
+ ): Promise<MeteredProposal> {
375
+ const ordered = [...observations].sort(
376
+ (a, b) => byteCompare(a.defectClass, b.defectClass) || byteCompare(a.subject, b.subject),
377
+ );
378
+ const records: CandidateRecord[] = [];
379
+ // A resumed run's history LEADS the attempt list. The budget guard ABORTS
380
+ // rather than truncating (`_lib/harness_evolution_guards.ts:140`), so a run
381
+ // that hits `max_spend_cents` stops mid-corpus; the resume passes the
382
+ // observations it has left plus what the aborted run already spent, and the
383
+ // ordering guard below then sees the whole run rather than its tail.
384
+ //
385
+ // It does NOT seed the per-observation ladder. Resume happens at the
386
+ // observation level — a completed observation is simply absent from the new
387
+ // input — and a fresh observation legitimately starts at the cheapest rung.
388
+ const attempts: LadderAttempt[] = [...priorAttempts];
389
+ const models: Record<string, string> = {};
390
+ const seq = { n: attempts.reduce((m, a) => Math.max(m, a.sequence), 0) };
391
+
392
+ for (const obs of ordered) {
393
+ const { record, model } = await proposeOne(obs, read(obs.subject), generate, attempts, seq);
394
+ records.push(record);
395
+ models[record.id] = model;
396
+ }
397
+
398
+ if (records.length !== ordered.length) {
399
+ throw new CandidateCountError(
400
+ `${String(ordered.length)} observation(s) produced ${String(records.length)} record(s) — a ` +
401
+ 'proposer that returns fewer records than observations has filtered, which is an evaluator role',
402
+ );
403
+ }
404
+ // AC-3's production caller, over a REAL population: the history a caller
405
+ // supplied plus what the walk above actually did.
406
+ //
407
+ // Its red is producible from this function's own inputs, which is the
408
+ // property that distinguishes a guard from a comment. Over an empty
409
+ // `priorAttempts` it cannot fire — `nextTier` per class makes an
410
+ // out-of-order sequence unconstructible — so on its own the walk would be
411
+ // exactly the un-provable guard this repository has caught before
412
+ // (`_lib/candidate_proposer.ts:343-347`, one ordering site, one guard, one
413
+ // red). What makes it falsifiable is the resumed-run path: a caller that
414
+ // hands back a history in which a costlier tier was spent before a cheaper
415
+ // one for the same class is refused here, and that is a real failure of a
416
+ // real resume rather than a hypothetical.
417
+ assertCheapestFirst(attempts);
418
+ return { records, attempts, models };
419
+ }
420
+
421
+ /**
422
+ * The attempt sequence a run WOULD make if every generation were accepted first
423
+ * try — one `lite` attempt per observation, on {@link INITIAL_CLASS}.
424
+ *
425
+ * The dry-run population, and it is not a fixture: it is derived from the real
426
+ * observations by the same `nextTier` call the live walk uses, so a dry run puts
427
+ * the guard over a real, non-empty attempt list without spending anything.
428
+ */
429
+ export function plannedAttempts(observations: readonly DefectObservation[]): LadderAttempt[] {
430
+ const ordered = [...observations].sort(
431
+ (a, b) => byteCompare(a.defectClass, b.defectClass) || byteCompare(a.subject, b.subject),
432
+ );
433
+ const attempts: LadderAttempt[] = [];
434
+ let n = 0;
435
+ for (let i = 0; i < ordered.length; i += 1) {
436
+ const tier = nextTier(INITIAL_CLASS, []);
437
+ if (tier === null) {
438
+ throw new GenerationRefusedError(
439
+ INITIAL_CLASS,
440
+ `class '${INITIAL_CLASS}' licenses no tier, so no metered attempt is planned`,
441
+ );
442
+ }
443
+ n += 1;
444
+ attempts.push({ defect_class: INITIAL_CLASS, tier, sequence: n });
445
+ }
446
+ assertCheapestFirst(attempts);
447
+ return attempts;
448
+ }
449
+
450
+ /**
451
+ * The role constraint, at compile time.
452
+ *
453
+ * Adding `score`, `rank`, `confidence` or any other {@link DecisionFieldKey} to
454
+ * the metered port's result type makes this `Assert<false>` and stops the build.
455
+ * A metered call that returns a judgement is an evaluator whatever the module is
456
+ * named, and this is the one place that can be made unavailable rather than
457
+ * merely discouraged.
458
+ */
459
+ type _GenerationResultCarriesNoDecisionField = Assert<
460
+ [NoDecisionField<GenerationResult>] extends [never] ? false : true
461
+ >;
@@ -0,0 +1,153 @@
1
+ /**
2
+ * The metered transport for the LLM proposer arm — one provider, one call shape.
3
+ *
4
+ * `road-to-governed-evidence-production` step 2.1. Deliberately a SEPARATE file
5
+ * from `_lib/llm_candidate_proposer.ts`: the arm holds the role constraint and
6
+ * must stay transport-free so it can be exercised with a stub, and the transport
7
+ * holds the one thing a reviewer has to read whole before money moves.
8
+ *
9
+ * ## What this file may and may not do
10
+ *
11
+ * It may send a prompt and return the text that came back. It may not score,
12
+ * rank, filter, or select — and structurally it cannot: {@link GenerationResult}
13
+ * has no field that could carry a judgement, and this module never sees more
14
+ * than one request at a time. The narrowed park admits exactly this role; see
15
+ * `docs/contracts/metered-proposer-protocol.md`.
16
+ *
17
+ * ## The model per tier is PINNED TO A DATED ID, or refused
18
+ *
19
+ * A frozen execution protocol whose model is a floating alias is not frozen: the
20
+ * alias moves and a later run answers a different question. So {@link TIER_MODEL}
21
+ * carries dated ids only, and the `high` tier is deliberately `null` because no
22
+ * dated `claude-opus-4-1-*` id exists anywhere in this tree to pin it to.
23
+ * Requesting `high` therefore REFUSES with a message naming what has to be
24
+ * pinned first, rather than resolving an alias and calling the protocol frozen.
25
+ *
26
+ * `high` is reachable only through an `execution_failed` escalation
27
+ * (`_lib/evolution_roi.ts:128`), so a run that never hits a transport error
28
+ * never touches it.
29
+ *
30
+ * ## Nothing here has been executed
31
+ *
32
+ * As of the commit that adds it, this module has made zero live calls. Its
33
+ * request shape is proven by {@link describeRequest}, which returns exactly what
34
+ * would be sent without sending it, and by a unit test over that description.
35
+ * The live path is unexercised, and saying so is cheaper than implying a probe
36
+ * that the park forbids.
37
+ */
38
+
39
+ import { load_anthropic_key } from '../ai_council/clients.js';
40
+ import type {
41
+ GenerationRequest,
42
+ GenerationResult,
43
+ TextGenerator,
44
+ } from './llm_candidate_proposer.js';
45
+ import type { ModelTier } from './evolution_roi.js';
46
+
47
+ export const ANTHROPIC_URL = 'https://api.anthropic.com/v1/messages';
48
+ export const ANTHROPIC_VERSION = '2023-06-01';
49
+
50
+ /**
51
+ * Dated model id per tier, or `null` where this tree pins none.
52
+ *
53
+ * The two dated ids are the ones already used elsewhere in this repository
54
+ * (`src/scripts/rdp_gate_classify.ts:66`, `src/scripts/bench_ab_v2_run.ts`), so
55
+ * they are not invented here.
56
+ */
57
+ export const TIER_MODEL: Readonly<Record<ModelTier, string | null>> = {
58
+ lite: 'claude-haiku-4-5-20251001',
59
+ medium: 'claude-sonnet-4-5-20250929',
60
+ high: null,
61
+ };
62
+
63
+ /** Sampling parameters. Frozen with the protocol; not tuned per run. */
64
+ export const MAX_TOKENS = 8192;
65
+ export const TEMPERATURE = 0;
66
+
67
+ export class TransportRefusedError extends Error {
68
+ constructor(message: string) {
69
+ super(message);
70
+ this.name = 'TransportRefusedError';
71
+ }
72
+ }
73
+
74
+ /** The model id for a tier, or a refusal naming what must be pinned. */
75
+ export function modelForTier(tier: ModelTier): string {
76
+ const model = TIER_MODEL[tier];
77
+ if (model === null) {
78
+ throw new TransportRefusedError(
79
+ `tier '${tier}' has no dated model id pinned in TIER_MODEL, so it cannot be sent: a ` +
80
+ 'floating alias would make the frozen execution protocol answer a different ' +
81
+ 'question on a later run. Pin a dated id and record it in ' +
82
+ 'docs/contracts/metered-proposer-protocol.md before using this tier',
83
+ );
84
+ }
85
+ return model;
86
+ }
87
+
88
+ /** The exact HTTP request body a call would carry. Sends nothing. */
89
+ export function describeRequest(req: GenerationRequest): {
90
+ url: string;
91
+ model: string;
92
+ body: Record<string, unknown>;
93
+ } {
94
+ const model = modelForTier(req.tier);
95
+ return {
96
+ url: ANTHROPIC_URL,
97
+ model,
98
+ body: {
99
+ model,
100
+ max_tokens: MAX_TOKENS,
101
+ temperature: TEMPERATURE,
102
+ system: req.system,
103
+ messages: [{ role: 'user', content: req.prompt }],
104
+ },
105
+ };
106
+ }
107
+
108
+ /** Rough token estimate for a dry-run cost line. Characters over four. */
109
+ export function estimateTokens(text: string): number {
110
+ return Math.ceil(text.length / 4);
111
+ }
112
+
113
+ interface AnthropicResponse {
114
+ content?: Array<{ type?: string; text?: string }>;
115
+ }
116
+
117
+ /**
118
+ * Bind the metered port to the Anthropic messages API.
119
+ *
120
+ * The key is read at CALL time rather than at module load, so importing this
121
+ * module — which the tests do — never touches the filesystem for a credential
122
+ * and never fails on a machine that has none.
123
+ */
124
+ export function anthropicGenerator(keyPath: string | null = null): TextGenerator {
125
+ return async (req: GenerationRequest): Promise<GenerationResult> => {
126
+ const described = describeRequest(req);
127
+ const key = load_anthropic_key(keyPath);
128
+ const resp = await fetch(described.url, {
129
+ method: 'POST',
130
+ headers: {
131
+ 'x-api-key': key,
132
+ 'anthropic-version': ANTHROPIC_VERSION,
133
+ 'content-type': 'application/json',
134
+ },
135
+ body: JSON.stringify(described.body),
136
+ });
137
+ if (!resp.ok) {
138
+ throw new TransportRefusedError(
139
+ `${described.model} returned HTTP ${String(resp.status)}: ${(await resp.text()).slice(0, 300)}`,
140
+ );
141
+ }
142
+ const data = (await resp.json()) as AnthropicResponse;
143
+ const text = (data.content ?? [])
144
+ .filter((b) => b.type === 'text')
145
+ .map((b) => b.text ?? '')
146
+ .join('');
147
+ // An empty body is returned AS an empty body rather than repaired here.
148
+ // The arm's own output contract refuses it and classifies the refusal;
149
+ // repairing it in the transport would move a decision into the layer
150
+ // that is supposed to have none.
151
+ return { text, model: described.model };
152
+ };
153
+ }