@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,181 @@
1
+ /**
2
+ * Check an arithmetic claim written in prose against itself.
3
+ *
4
+ * The defect this exists for, observed rather than imagined: a fixture states
5
+ * the same number twice — once as a declared `expected` and once inside the
6
+ * rationale that derives it — and the two disagree. A judge then prefers the
7
+ * declared value over the recomputed one and scores a correct response as a
8
+ * loss. Both numbers are in the file, so nothing has to be inferred; they
9
+ * simply were never compared.
10
+ *
11
+ * The scanner reads CHAINS (`a x b / c = d / c = e`), because that is how the
12
+ * derivations in this tree are actually written. Comparing only the outermost
13
+ * pair would mis-read every intermediate step as a claim of its own — the
14
+ * first version of this check did exactly that and produced three false
15
+ * findings on a corpus that was correct.
16
+ *
17
+ * Prose rounding is legitimate and is tolerated to the PRECISION THE PROSE
18
+ * ITSELF USES: `1.333` agrees with 4/3, `1.33` does not have to. A fixed
19
+ * epsilon would either reject honest rounding or accept a real disagreement,
20
+ * depending on the magnitude of the numbers, which is the wrong axis.
21
+ */
22
+
23
+ /** One prose arithmetic chain and what it evaluates to. */
24
+ export interface ArithChain {
25
+ /** The chain as written. */
26
+ text: string;
27
+ /** Every `=`-separated segment that evaluated to a number. */
28
+ values: readonly { segment: string; value: number }[];
29
+ }
30
+
31
+ /** A chain whose segments disagree beyond the precision the prose claims. */
32
+ export interface ArithDisagreement {
33
+ text: string;
34
+ leftSegment: string;
35
+ left: number;
36
+ rightSegment: string;
37
+ right: number;
38
+ /** The tolerance the right-hand segment's own precision earns it. */
39
+ tolerance: number;
40
+ }
41
+
42
+ const CHAIN = /(?:[-+]?[\d,]*\.?\d+[\s\d,.+\-*/x×^()%]*=\s*)+[-+]?[\d,]*\.?\d+/g;
43
+
44
+ /**
45
+ * Evaluate one prose segment, or `null` when it is not pure arithmetic.
46
+ *
47
+ * Deliberately narrow: digits, the four operators, `^`, parentheses and the
48
+ * separators prose uses. Anything else returns `null` rather than being
49
+ * coerced — a segment carrying a word is a sentence, not a claim, and guessing
50
+ * at it is how a checker starts inventing findings.
51
+ */
52
+ export function evaluateSegment(segment: string): number | null {
53
+ const t = segment
54
+ .trim()
55
+ .replace(/,/g, '')
56
+ .replace(/[×x]/g, '*')
57
+ .replace(/%/g, '')
58
+ .replace(/\$/g, '');
59
+ if (!/\d/.test(t)) return null;
60
+ if (!/^[\d\s.+\-*/^()]+$/.test(t)) return null;
61
+ // `^` is exponentiation in prose and XOR in JS — translate before eval.
62
+ const js = t.replace(/\^/g, '**');
63
+ try {
64
+ // Input is whitelisted above to digits, operators and parentheses — a
65
+ // segment carrying anything else returned null before reaching here.
66
+ const fn = new Function(`"use strict"; return (${js});`) as () => unknown;
67
+ const v = fn();
68
+ return typeof v === 'number' && Number.isFinite(v) ? v : null;
69
+ } catch {
70
+ return null;
71
+ }
72
+ }
73
+
74
+ /** Decimal places written in a literal, used as the rounding tolerance. */
75
+ function precisionTolerance(segment: string, magnitude: number): number {
76
+ const m = /\.(\d+)\s*$/.exec(segment.trim());
77
+ const decimals = m?.[1];
78
+ if (decimals !== undefined) return 0.5 * 10 ** -decimals.length;
79
+ // An integer-looking claim is tolerated to half a unit, plus float noise
80
+ // proportional to the magnitude — `20,000` may legitimately stand for
81
+ // 20000.000000001 produced by a chain of divisions.
82
+ return Math.max(0.5, Math.abs(magnitude) * 1e-9);
83
+ }
84
+
85
+ /** Every arithmetic chain in a piece of prose. */
86
+ export function findArithChains(prose: string): ArithChain[] {
87
+ const out: ArithChain[] = [];
88
+ for (const m of prose.matchAll(CHAIN)) {
89
+ const values: { segment: string; value: number }[] = [];
90
+ for (const segment of m[0].split('=')) {
91
+ const value = evaluateSegment(segment);
92
+ if (value !== null) values.push({ segment, value });
93
+ }
94
+ if (values.length >= 2) out.push({ text: m[0], values });
95
+ }
96
+ return out;
97
+ }
98
+
99
+ /**
100
+ * Every chain whose own segments disagree.
101
+ *
102
+ * Each segment is compared against the FIRST evaluable one rather than against
103
+ * its neighbour: a chain is a claim that all of its forms are the same number,
104
+ * and comparing neighbours lets an error accumulate quietly across three steps.
105
+ */
106
+ export function findArithDisagreements(prose: string): ArithDisagreement[] {
107
+ const out: ArithDisagreement[] = [];
108
+ for (const chain of findArithChains(prose)) {
109
+ const first = chain.values[0];
110
+ if (first === undefined) continue;
111
+ for (const later of chain.values.slice(1)) {
112
+ const tolerance = precisionTolerance(later.segment, first.value);
113
+ if (Math.abs(later.value - first.value) > tolerance) {
114
+ out.push({
115
+ text: chain.text,
116
+ leftSegment: first.segment.trim(),
117
+ left: first.value,
118
+ rightSegment: later.segment.trim(),
119
+ right: later.value,
120
+ tolerance,
121
+ });
122
+ break;
123
+ }
124
+ }
125
+ }
126
+ return out;
127
+ }
128
+
129
+ /**
130
+ * Does a prose derivation ever state the declared value?
131
+ *
132
+ * Returns `null` when the prose carries no evaluable chain at all — an absent
133
+ * derivation is not a disagreement, and treating it as one would make the
134
+ * check fire on every fixture that simply cites a source instead.
135
+ */
136
+ export function chainSupportsExpected(
137
+ prose: string,
138
+ expected: number,
139
+ tolerance: number,
140
+ ): boolean | null {
141
+ const chains = findArithChains(prose);
142
+ if (chains.length === 0) return null;
143
+ for (const chain of chains) {
144
+ for (const v of chain.values) {
145
+ const tol = Math.max(tolerance, precisionTolerance(v.segment, expected));
146
+ if (Math.abs(v.value - expected) <= tol) return true;
147
+ if (sameMantissa(v.value, expected, tol)) return true;
148
+ }
149
+ }
150
+ return false;
151
+ }
152
+
153
+ /**
154
+ * Do two numbers agree once a UNIT SCALE is allowed?
155
+ *
156
+ * A measured false positive is what this exists for, not a hypothetical: a
157
+ * fixture derives `4,200,000,000 x 0.006 = 25,200,000 = $25.2M` and declares
158
+ * `expected: 25.2`, because the scenario asks for the figure "in $M". The
159
+ * derivation works in dollars and the expectation in millions. Nothing in the
160
+ * file states the unit in a machine-readable way, so demanding exact agreement
161
+ * reports a correct fixture as broken.
162
+ *
163
+ * **The weakening this accepts, stated rather than buried.** A real defect that
164
+ * happens to be a pure power of ten away — `0.85` written where `8.5` is meant —
165
+ * is no longer caught by THIS check. It is a narrow hole: a transcription or
166
+ * arithmetic error almost always changes the digit sequence, and the
167
+ * self-consistency check above still reads the derivation on its own terms,
168
+ * where no scale tolerance applies at all. The alternative was worse: a check
169
+ * that fires on every unit-scaled fixture is a check that gets suppressed.
170
+ *
171
+ * Bounded to 10^±12 so an unrelated number cannot be dragged into agreement by
172
+ * an arbitrarily large exponent.
173
+ */
174
+ function sameMantissa(a: number, b: number, tolerance: number): boolean {
175
+ if (a === 0 || b === 0) return false;
176
+ const ratio = Math.abs(a / b);
177
+ const exp = Math.round(Math.log10(ratio));
178
+ if (!Number.isFinite(exp) || Math.abs(exp) > 12 || exp === 0) return false;
179
+ const scaled = a / 10 ** exp;
180
+ return Math.abs(scaled - b) <= Math.max(tolerance, Math.abs(b) * 1e-9);
181
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Arm ranking metrics (`road-to-runtime-context-floors` step 4.2).
3
+ *
4
+ * `tokens` stays the default and `cost-per-solved` becomes AVAILABLE — not a
5
+ * replacement. The reason it has to exist at all is the same one behind the
6
+ * mandatory cache fields: an arm can reduce token volume and cost more, because
7
+ * rewriting a prefix pays the cache-write rate rather than the cache-read rate.
8
+ * A comparison that can only rank on tokens cannot see that.
9
+ *
10
+ * The reason it must NOT become the default is the sibling risk: a single
11
+ * mandatory score invites tuning the score. Keeping both available, and keeping
12
+ * the cache ratio diagnostic rather than scored, is what stops this from being
13
+ * the Goodhart shape that `road-to-cache-economy`'s falsified C-5 already
14
+ * demonstrated for token count.
15
+ */
16
+
17
+ export const RANKING_METRICS = ['tokens', 'cost-per-solved'] as const;
18
+ export type RankingMetric = (typeof RANKING_METRICS)[number];
19
+ export const DEFAULT_RANKING_METRIC: RankingMetric = 'tokens';
20
+
21
+ export interface ArmResult {
22
+ arm: string;
23
+ /** Total tokens consumed by the arm across the run. */
24
+ tokens: number;
25
+ /** Total cost in USD. */
26
+ cost_usd: number;
27
+ /** Tasks the arm actually solved — the denominator of cost-per-solved. */
28
+ solved: number;
29
+ }
30
+
31
+ export interface RankedArm extends ArmResult {
32
+ /** The value ranked on. `null` when the metric is undefined for this arm. */
33
+ score: number | null;
34
+ /** Present only when `score` is null. */
35
+ reason?: string;
36
+ }
37
+
38
+ export function isRankingMetric(v: unknown): v is RankingMetric {
39
+ return typeof v === 'string' && (RANKING_METRICS as readonly string[]).includes(v);
40
+ }
41
+
42
+ function score(arm: ArmResult, metric: RankingMetric): { score: number | null; reason?: string } {
43
+ if (metric === 'tokens') return { score: arm.tokens };
44
+ if (arm.solved === 0) {
45
+ // Not Infinity and not 0: an arm that solved nothing has no
46
+ // cost-per-solved, and ranking it as "infinitely expensive" would be a
47
+ // number nobody measured.
48
+ return { score: null, reason: 'the arm solved nothing, so cost-per-solved is undefined' };
49
+ }
50
+ return { score: arm.cost_usd / arm.solved };
51
+ }
52
+
53
+ /**
54
+ * Rank ascending — lower is better under both metrics. Arms with an undefined
55
+ * score sort last, in input order, and carry their reason.
56
+ */
57
+ export function rankArms(arms: readonly ArmResult[], metric: RankingMetric = DEFAULT_RANKING_METRIC): RankedArm[] {
58
+ const scored: RankedArm[] = arms.map((a) => ({ ...a, ...score(a, metric) }));
59
+ const defined = scored.filter((a) => a.score !== null).sort((a, b) => (a.score as number) - (b.score as number) || a.arm.localeCompare(b.arm));
60
+ const undef = scored.filter((a) => a.score === null);
61
+ return [...defined, ...undef];
62
+ }
@@ -0,0 +1,303 @@
1
+ /**
2
+ * Per-asset delivery ledger — which assets produce the standing payload
3
+ * (`road-to-delivered-cost-truth` step 2.1).
4
+ *
5
+ * `check_preamble_payload_budget` measures three BUCKET totals and refuses
6
+ * growth. It cannot say which asset inside a bucket is producing the cost, so a
7
+ * reduction effort has a number and no target. This module ranks the assets.
8
+ *
9
+ * WHAT "DELIVERY" MEANS PER BUCKET, because the two are not the same shape:
10
+ *
11
+ * - a RULE in the standing set delivers its whole body on every spawn;
12
+ * - a SKILL delivers only its catalogue line — `- <name>: <description>` — on
13
+ * every spawn. Its body is loaded on activation, which is not standing cost
14
+ * and is deliberately not counted here.
15
+ *
16
+ * Ranking the two together without that distinction would put every skill body
17
+ * above every rule and send a reduction effort at the wrong half of the tree.
18
+ *
19
+ * MEASUREMENT HONESTY. Each row states whether it was measured with the exact
20
+ * BPE tokenizer or the `chars/4` proxy, and a proxy reading within its own error
21
+ * margin of a threshold is reported `unresolved` rather than classified — the
22
+ * discipline `lint_token_budget_discipline` already applies to the rich band,
23
+ * reused here rather than reinvented.
24
+ */
25
+ import * as fs from 'node:fs';
26
+ import * as path from 'node:path';
27
+
28
+ import { parseFrontmatter } from '../preamble_byte_census.js';
29
+ import { gpt_tokens, gpt_tokens_proxy } from './token_count.js';
30
+
31
+ /** Worst-case per-file error of the character proxy, as measured for the rich band. */
32
+ export const PROXY_ERROR_MARGIN = 0.06;
33
+
34
+ export type AssetKind = 'rule' | 'skill-catalogue-line';
35
+
36
+ export interface AssetRow {
37
+ /** Repo-relative path of the asset. */
38
+ file: string;
39
+ /** Asset name as the preamble names it. */
40
+ name: string;
41
+ kind: AssetKind;
42
+ /** Tokens this asset contributes to EVERY spawn. */
43
+ tokens: number;
44
+ /**
45
+ * The same asset under the `chars/4` proxy.
46
+ *
47
+ * Carried alongside the BPE figure, not instead of it, because the payload
48
+ * gate counts chars/4 and reconciling a BPE total against a chars/4 total
49
+ * measures the METHODS, not the ledger. See {@link reconcile}.
50
+ */
51
+ proxy_tokens: number;
52
+ /** `exact` when the BPE tokenizer resolved, `proxy` otherwise. */
53
+ method: 'exact' | 'proxy';
54
+ /** Share of the ledger total. */
55
+ share: number;
56
+ }
57
+
58
+ export interface LedgerVerdict {
59
+ rows: AssetRow[];
60
+ total_tokens: number;
61
+ /** True only when EVERY row came from the exact tokenizer. */
62
+ exact_throughout: boolean;
63
+ by_kind: Record<AssetKind, { count: number; tokens: number; proxy_tokens: number }>;
64
+ }
65
+
66
+ /**
67
+ * Is a proxy reading too close to `threshold` to be classified?
68
+ *
69
+ * Symmetric, deliberately: the measured proxy error runs in BOTH directions
70
+ * (−5.3 % on the largest rich artifact), so a band that straddles the threshold
71
+ * yields no verdict rather than a confident wrong one.
72
+ */
73
+ export function unresolvedAgainst(tokens: number, method: 'exact' | 'proxy', threshold: number): boolean {
74
+ if (method === 'exact') return false;
75
+ const margin = Math.ceil(tokens * PROXY_ERROR_MARGIN);
76
+ return tokens - margin <= threshold && tokens + margin > threshold;
77
+ }
78
+
79
+ /** Walk the standing rule directory. Each rule delivers its whole body. */
80
+ export function measureRules(rulesDir: string, repoRoot: string): AssetRow[] {
81
+ if (!fs.existsSync(rulesDir)) return [];
82
+ const rows: AssetRow[] = [];
83
+ for (const entry of fs.readdirSync(rulesDir, { withFileTypes: true })) {
84
+ if (!entry.isFile() || !entry.name.endsWith('.md')) continue;
85
+ const abs = path.join(rulesDir, entry.name);
86
+ const text = fs.readFileSync(abs, 'utf-8');
87
+ const count = gpt_tokens(text);
88
+ rows.push({
89
+ file: path.relative(repoRoot, abs),
90
+ name: entry.name.replace(/\.md$/, ''),
91
+ kind: 'rule',
92
+ tokens: count.tokens,
93
+ proxy_tokens: gpt_tokens_proxy(text).tokens,
94
+ method: count.exact ? 'exact' : 'proxy',
95
+ share: 0,
96
+ });
97
+ }
98
+ return rows;
99
+ }
100
+
101
+ /**
102
+ * Walk the skill catalogue. Each skill delivers ONE line, not its body.
103
+ *
104
+ * The line is built the same way `censusSkillsCatalog` builds it — `- <name>:
105
+ * <description>\n` — because a ledger that measured the body would rank a skill
106
+ * that is never activated above a rule that is always delivered.
107
+ */
108
+ export function measureSkillCatalogue(skillsDir: string, repoRoot: string): AssetRow[] {
109
+ if (!fs.existsSync(skillsDir)) return [];
110
+ const rows: AssetRow[] = [];
111
+ for (const entry of fs.readdirSync(skillsDir, { withFileTypes: true })) {
112
+ if (!entry.isDirectory()) continue;
113
+ const skillMd = path.join(skillsDir, entry.name, 'SKILL.md');
114
+ let text: string;
115
+ try {
116
+ text = fs.readFileSync(skillMd, 'utf-8');
117
+ } catch {
118
+ continue;
119
+ }
120
+ // The SAME parser the payload census uses, not a second reader of the
121
+ // same bytes. A regex version reconciled 17.1 % low because a folded
122
+ // multi-line `description:` truncates at the first newline.
123
+ const fm = parseFrontmatter(text);
124
+ const name = typeof fm.name === 'string' && fm.name.length > 0 ? fm.name : entry.name;
125
+ const description = typeof fm.description === 'string' ? fm.description : '';
126
+ const line = `- ${name}: ${description}\n`;
127
+ const count = gpt_tokens(line);
128
+ rows.push({
129
+ file: path.relative(repoRoot, skillMd),
130
+ name,
131
+ kind: 'skill-catalogue-line',
132
+ tokens: count.tokens,
133
+ proxy_tokens: gpt_tokens_proxy(line).tokens,
134
+ method: count.exact ? 'exact' : 'proxy',
135
+ share: 0,
136
+ });
137
+ }
138
+ return rows;
139
+ }
140
+
141
+ export function buildLedger(rulesDir: string, skillsDir: string, repoRoot: string): LedgerVerdict {
142
+ const rows = [...measureRules(rulesDir, repoRoot), ...measureSkillCatalogue(skillsDir, repoRoot)];
143
+ const total = rows.reduce((n, r) => n + r.tokens, 0);
144
+ for (const r of rows) r.share = total > 0 ? r.tokens / total : 0;
145
+ rows.sort((a, b) => b.tokens - a.tokens || a.file.localeCompare(b.file));
146
+
147
+ const byKind: Record<AssetKind, { count: number; tokens: number; proxy_tokens: number }> = {
148
+ rule: { count: 0, tokens: 0, proxy_tokens: 0 },
149
+ 'skill-catalogue-line': { count: 0, tokens: 0, proxy_tokens: 0 },
150
+ };
151
+ for (const r of rows) {
152
+ byKind[r.kind].count += 1;
153
+ byKind[r.kind].tokens += r.tokens;
154
+ byKind[r.kind].proxy_tokens += r.proxy_tokens;
155
+ }
156
+ return { rows, total_tokens: total, exact_throughout: rows.every((r) => r.method === 'exact'), by_kind: byKind };
157
+ }
158
+
159
+ export interface Reconciliation {
160
+ kind: AssetKind;
161
+ bucket: string;
162
+ /** The ledger's chars/4 total — the SAME method the bucket uses. */
163
+ ledger_proxy_tokens: number;
164
+ /** The ledger's BPE total, reported for contrast, never reconciled against. */
165
+ ledger_exact_tokens: number;
166
+ bucket_tokens: number;
167
+ /** Absolute relative difference, like-for-like. */
168
+ drift: number;
169
+ within_margin: boolean;
170
+ }
171
+
172
+ /**
173
+ * Reconcile the ledger against the payload gate's own bucket totals.
174
+ *
175
+ * LIKE-FOR-LIKE, and this took a correction. The first cut compared the
176
+ * ledger's BPE total against the gate's `chars/4` bucket and set a 15 % margin
177
+ * to absorb the difference. That margin was GUESSED, which is the exact defect
178
+ * this roadmap's own budget file is careful about — and it did not even work:
179
+ * rules reconciled at 1.6 % while skill catalogue lines drifted 28.1 %, because
180
+ * `chars/4` overestimates short structured lines far more than it does prose.
181
+ * The 15 % would have hidden the rule drift and failed the skill drift, and
182
+ * neither verdict would have been about the ledger.
183
+ *
184
+ * So the ledger carries BOTH figures and reconciles the proxy against the
185
+ * proxy. What remains is real disagreement — a different corpus, a different
186
+ * line format, a missed file — which is what a reconciliation is for. The
187
+ * margin can then be tight, because two implementations of one arithmetic
188
+ * should agree closely or one of them is wrong.
189
+ */
190
+ export const RECONCILE_MARGIN = 0.02;
191
+
192
+ export function reconcile(
193
+ ledger: LedgerVerdict,
194
+ buckets: ReadonlyArray<{ name: string; tokens: number }>,
195
+ ): Reconciliation[] {
196
+ const map: Array<{ kind: AssetKind; bucket: string }> = [
197
+ { kind: 'rule', bucket: 'project-scope rules' },
198
+ { kind: 'skill-catalogue-line', bucket: 'preloaded skills catalog' },
199
+ ];
200
+ const out: Reconciliation[] = [];
201
+ for (const m of map) {
202
+ const bucket = buckets.find((b) => b.name === m.bucket);
203
+ if (bucket === undefined) continue;
204
+ const proxyTokens = ledger.by_kind[m.kind].proxy_tokens;
205
+ const drift =
206
+ bucket.tokens === 0 ? (proxyTokens === 0 ? 0 : 1) : Math.abs(proxyTokens - bucket.tokens) / bucket.tokens;
207
+ out.push({
208
+ kind: m.kind,
209
+ bucket: m.bucket,
210
+ ledger_proxy_tokens: proxyTokens,
211
+ ledger_exact_tokens: ledger.by_kind[m.kind].tokens,
212
+ bucket_tokens: bucket.tokens,
213
+ drift,
214
+ within_margin: drift <= RECONCILE_MARGIN,
215
+ });
216
+ }
217
+ return out;
218
+ }
219
+
220
+ // ─────────────────────────────────────────── growth attribution (step 2.2)
221
+
222
+ export interface GrowthEntry {
223
+ name: string;
224
+ kind: AssetKind;
225
+ /** Positive = this asset grew or arrived. */
226
+ delta: number;
227
+ status: 'added' | 'grew' | 'shrank' | 'removed';
228
+ }
229
+
230
+ export interface GrowthAttribution {
231
+ /** Assets that grew or arrived, largest first. */
232
+ increases: GrowthEntry[];
233
+ /** Assets that shrank or left, largest saving first. */
234
+ decreases: GrowthEntry[];
235
+ net_delta: number;
236
+ }
237
+
238
+ /**
239
+ * Attribute a payload change to the assets that caused it (step 2.2).
240
+ *
241
+ * A ratchet that says "the payload grew past the ceiling" states a fact and
242
+ * leaves the reader to find the cause; the same refusal naming the asset and its
243
+ * token delta reads as a quantified saving instead of an obstacle. That is the
244
+ * whole difference this function buys, and it is a presentation difference with
245
+ * a real consequence: a refusal nobody can act on gets suppressed rather than
246
+ * fixed.
247
+ *
248
+ * Pure and order-independent — both sides are keyed on `kind:name`, so a
249
+ * reordered ledger produces the same attribution.
250
+ */
251
+ export function attributeGrowth(before: readonly AssetRow[], after: readonly AssetRow[]): GrowthAttribution {
252
+ const key = (r: AssetRow): string => `${r.kind}:${r.name}`;
253
+ const b = new Map(before.map((r) => [key(r), r.tokens]));
254
+ const a = new Map(after.map((r) => [key(r), r.tokens]));
255
+
256
+ const entries: GrowthEntry[] = [];
257
+ for (const [k, tokens] of a) {
258
+ const prev = b.get(k);
259
+ const [kind, ...rest] = k.split(':');
260
+ const name = rest.join(':');
261
+ if (prev === undefined) {
262
+ entries.push({ name, kind: kind as AssetKind, delta: tokens, status: 'added' });
263
+ } else if (tokens !== prev) {
264
+ entries.push({ name, kind: kind as AssetKind, delta: tokens - prev, status: tokens > prev ? 'grew' : 'shrank' });
265
+ }
266
+ }
267
+ for (const [k, tokens] of b) {
268
+ if (a.has(k)) continue;
269
+ const [kind, ...rest] = k.split(':');
270
+ entries.push({ name: rest.join(':'), kind: kind as AssetKind, delta: -tokens, status: 'removed' });
271
+ }
272
+
273
+ const increases = entries.filter((e) => e.delta > 0).sort((x, y) => y.delta - x.delta || x.name.localeCompare(y.name));
274
+ const decreases = entries.filter((e) => e.delta < 0).sort((x, y) => x.delta - y.delta || x.name.localeCompare(y.name));
275
+ return { increases, decreases, net_delta: entries.reduce((n, e) => n + e.delta, 0) };
276
+ }
277
+
278
+ /**
279
+ * Render an attribution as the lines a refusing gate appends to its message.
280
+ *
281
+ * Capped, because a refusal listing 400 assets is as unactionable as one listing
282
+ * none — and the cap is stated rather than silent, so a reader knows the list is
283
+ * a head and not the whole story.
284
+ */
285
+ export function renderAttribution(g: GrowthAttribution, limit = 5): string[] {
286
+ if (g.increases.length === 0 && g.decreases.length === 0) return [];
287
+ const out: string[] = [];
288
+ const sign = (n: number): string => (n >= 0 ? `+${String(n)}` : String(n));
289
+ out.push(` net delivered-token change: ${sign(g.net_delta)} tok`);
290
+ if (g.increases.length > 0) {
291
+ out.push(` grew or arrived (top ${String(Math.min(limit, g.increases.length))} of ${String(g.increases.length)}):`);
292
+ for (const e of g.increases.slice(0, limit)) {
293
+ out.push(` ${sign(e.delta).padStart(7)} tok ${e.name} (${e.kind}, ${e.status})`);
294
+ }
295
+ }
296
+ if (g.decreases.length > 0) {
297
+ out.push(` shrank or left (top ${String(Math.min(limit, g.decreases.length))} of ${String(g.decreases.length)}):`);
298
+ for (const e of g.decreases.slice(0, limit)) {
299
+ out.push(` ${sign(e.delta).padStart(7)} tok ${e.name} (${e.kind}, ${e.status})`);
300
+ }
301
+ }
302
+ return out;
303
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Which audit-log fields are OBSERVED and which are producer constants.
3
+ *
4
+ * This module exists because a prose sentence was wrong for months and nothing
5
+ * could tell. `docs/contracts/audit-log-v1.md` described `rules_applied` as
6
+ * "stable rule ids whose Iron Law fired this phase" — an observation — while
7
+ * both shipped producers write the literal `['delegation-policy']` on every
8
+ * line. A consumer following the contract computes a per-rule win rate of 100 %
9
+ * for one rule and `undefined` for the other 118, and that reads as a finding.
10
+ *
11
+ * It was found by the loop rather than by review: mining the real audit stream
12
+ * with `extract_audit_patterns --min-count 2` mints exactly ONE pattern,
13
+ * `implement:success:delegation-policy`, at count 914 over 935 lines. A
14
+ * regularity that strong in a field that varied would be remarkable; in a field
15
+ * that does not vary it is arithmetic.
16
+ *
17
+ * The prose was DELETED rather than softened, and this check replaces it. A
18
+ * sentence cannot stop a consumer from aggregating over a constant; a function
19
+ * the consumer must call can, and it goes stale loudly instead of silently
20
+ * because the producers are named here and a test asserts they still match.
21
+ *
22
+ * road-to-experience-loop-broadening step 9.3 — the removal the loop motivated.
23
+ */
24
+
25
+ /**
26
+ * Fields a shipped producer writes as a fixed value, with the value.
27
+ *
28
+ * A field listed here is NOT evidence about the run. Adding a row is how a
29
+ * future producer records the same honesty; removing one requires that the
30
+ * producer actually compute the field.
31
+ */
32
+ export const PRODUCER_CONSTANT_FIELDS: ReadonlyMap<string, readonly string[]> = new Map([
33
+ // Written identically by `orchestration_record.ts` and
34
+ // `review_skipped_record.ts`. Neither computes it from rules that fired.
35
+ ['rules_applied', ['delegation-policy']],
36
+ ]);
37
+
38
+ /** True when a per-asset rate over this field would measure the producer. */
39
+ export function isProducerConstantField(field: string): boolean {
40
+ return PRODUCER_CONSTANT_FIELDS.has(field);
41
+ }
42
+
43
+ /**
44
+ * The reason, for a consumer that wants to say why it skipped a column.
45
+ * `null` when the field is genuinely observed.
46
+ */
47
+ export function constantFieldReason(field: string): string | null {
48
+ const v = PRODUCER_CONSTANT_FIELDS.get(field);
49
+ if (v === undefined) return null;
50
+ return (
51
+ `'${field}' is written as the fixed value [${v.map((x) => `'${x}'`).join(', ')}] by every shipped ` +
52
+ 'producer, so any rate computed over it measures the writer rather than the work.'
53
+ );
54
+ }
@@ -156,14 +156,43 @@ const LOOKUP_PATTERNS: Array<{ cls: LookupClass; primitive: LookupPrimitive; re:
156
156
  * silently degraded answer; an index-miss at execution time escalates the
157
157
  * same way (runtime concern, documented in the classification context).
158
158
  */
159
- export function classifyLookup(taskText: string): LookupRoute {
159
+ export function classifyLookup(
160
+ taskText: string,
161
+ opts: { codeGraphEnabled?: boolean | undefined } = {},
162
+ ): LookupRoute {
163
+ // The graph is an OPPORTUNISTIC ACCELERANT, gated on the setting — which is
164
+ // what `auto-dispatch-classification.md` § Task pattern has always said and
165
+ // what this function did not do.
166
+ //
167
+ // road-to-inbox-harvest-2026-08-f-code-graph-evidence-refresh 2.1 required
168
+ // deciding which of the two was right and changing the other, not splitting
169
+ // the difference. The CONTRACT is right, on the only evidence that exists:
170
+ // the pre-registered benchmark behind `claim:code-graph-retrieval-null`
171
+ // measured native-graph recall 0.365 against grep's 0.797 on exactly these
172
+ // graph-shaped questions. Routing to the graph unconditionally routed to the
173
+ // arm that lost, and no re-measurement has replaced that figure — Phase 3.1
174
+ // is blocked on inputs this repository does not hold.
175
+ //
176
+ // Default FALSE, deliberately, and not because the setting's default is
177
+ // false: an absent flag means nobody said the index is present and fresh,
178
+ // and an accelerant taken on an absent index is a miss that escalates —
179
+ // slower than the grep it replaced. When the flag is on, the class still
180
+ // routes to `code-graph-query`, so turning it on is the whole change needed
181
+ // to use the graph.
182
+ const graphOk = opts.codeGraphEnabled === true;
160
183
  for (const p of LOOKUP_PATTERNS) {
161
184
  if (p.re.test(taskText)) {
185
+ const primitive: LookupPrimitive =
186
+ p.primitive === 'code-graph-query' && !graphOk ? 'fts-or-capped-grep' : p.primitive;
162
187
  return {
163
188
  lookup_class: p.cls,
164
189
  route: 'primitive',
165
- primitive: p.primitive,
166
- reason: `lookup-class ${p.cls} — deterministic primitive, no spawn`,
190
+ primitive,
191
+ reason:
192
+ primitive === p.primitive
193
+ ? `lookup-class ${p.cls} — deterministic primitive, no spawn`
194
+ : `lookup-class ${p.cls} — capped grep; the code-graph accelerant is ` +
195
+ 'gated on hooks.code_graph.enabled and it is not on',
167
196
  };
168
197
  }
169
198
  }