@event4u/agent-config 14.12.0 → 14.13.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 (466) 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 +234 -0
  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 +109 -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-provenance.md +4 -0
  30. package/dist/agent-src/rules/design-fidelity.md +1 -1
  31. package/dist/agent-src/rules/domain-safety-pii.md +4 -0
  32. package/dist/agent-src/rules/domain-safety-retention.md +4 -0
  33. package/dist/agent-src/rules/engineering-safety-floor.md +2 -0
  34. package/dist/agent-src/rules/external-code-graph-interop.md +14 -12
  35. package/dist/agent-src/rules/improve-before-implement.md +6 -8
  36. package/dist/agent-src/rules/laravel-routing.md +1 -1
  37. package/dist/agent-src/rules/lethal-trifecta-guard.md +4 -0
  38. package/dist/agent-src/rules/secret-vcs-guard.md +2 -0
  39. package/dist/agent-src/rules/security-sensitive-stop.md +2 -0
  40. package/dist/agent-src/rules/source-confidentiality.md +12 -34
  41. package/dist/agent-src/rules/symfony-routing.md +1 -1
  42. package/dist/agent-src/rules/token-efficiency.md +14 -0
  43. package/dist/agent-src/rules/tool-safety.md +4 -0
  44. package/dist/agent-src/rules/untrusted-input-defense.md +4 -0
  45. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +247 -3
  46. package/dist/agent-src/scripts/guarded_baseline.ts +328 -0
  47. package/dist/agent-src/scripts/roadmap_set_step.ts +253 -0
  48. package/dist/agent-src/scripts/stub_queue.ts +82 -0
  49. package/dist/agent-src/scripts/stubs_due.ts +400 -0
  50. package/dist/agent-src/scripts/ticket_bundles.ts +84 -0
  51. package/dist/agent-src/scripts/update_roadmap_progress.ts +8 -4
  52. package/dist/agent-src/skills/brand-asset-generation/SKILL.md +17 -4
  53. package/dist/agent-src/skills/brand-audit/SKILL.md +33 -0
  54. package/dist/agent-src/skills/code-intelligence/SKILL.md +57 -0
  55. package/dist/agent-src/skills/database/SKILL.md +8 -0
  56. package/dist/agent-src/skills/dependency-upgrade/SKILL.md +27 -0
  57. package/dist/agent-src/skills/design-review/SKILL.md +1 -1
  58. package/dist/agent-src/skills/doc-coauthoring/SKILL.md +1 -1
  59. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +17 -1
  60. package/dist/agent-src/skills/feature-planning/SKILL.md +9 -2
  61. package/dist/agent-src/skills/frontend-render-security/SKILL.md +44 -0
  62. package/dist/agent-src/skills/git-workflow/SKILL.md +1 -1
  63. package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.ts +38 -4
  64. package/dist/agent-src/skills/judge-artifact-completeness/rubrics/ticket-quality-score.json +2 -2
  65. package/dist/agent-src/skills/laravel/SKILL.md +35 -0
  66. package/dist/agent-src/skills/laravel-migration/SKILL.md +57 -3
  67. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +26 -0
  68. package/dist/agent-src/skills/playbook-authoring/SKILL.md +28 -1
  69. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +1 -1
  70. package/dist/agent-src/skills/skill-writing/references/procedure.md +5 -5
  71. package/dist/agent-src/skills/sql-writing/SKILL.md +7 -1
  72. package/dist/agent-src/skills/standards-from-config/SKILL.md +27 -4
  73. package/dist/agent-src/skills/supply-chain-intake/SKILL.md +11 -4
  74. package/dist/agent-src/skills/symfony-workflow/SKILL.md +35 -0
  75. package/dist/agent-src/skills/test-case-discovery/SKILL.md +85 -0
  76. package/dist/agent-src/skills/test-driven-development/SKILL.md +33 -9
  77. package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
  78. package/dist/agent-src/skills/testing-anti-patterns/process-anti-patterns.md +37 -0
  79. package/dist/agent-src/skills/ui-component-architect/SKILL.md +45 -2
  80. package/dist/agent-src/skills/upstream-contribute/SKILL.md +38 -1
  81. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +9 -4
  82. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  83. package/dist/agent-src/templates/roadmaps.md +97 -3
  84. package/dist/agent-src/templates/scripts/check_memory.ts +258 -17
  85. package/dist/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
  86. package/dist/agent-src/templates/scripts/memory_lookup.ts +86 -0
  87. package/dist/agent-src/templates/scripts/memory_signal.ts +44 -0
  88. package/dist/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
  89. package/dist/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
  90. package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
  91. package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
  92. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
  93. package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
  94. package/dist/cli/commands/uiAudit.js +124 -5
  95. package/dist/cli/registry.js +2 -0
  96. package/dist/cli-delegate/{chunk-HYWSRNUX.js → chunk-2DK2VJWG.js} +3 -3
  97. package/dist/cli-delegate/{chunk-JCW7ZLHK.js → chunk-4FS4WRXP.js} +5 -0
  98. package/dist/cli-delegate/{chunk-OMIVVCG2.js → chunk-A4QJ6ENT.js} +24 -0
  99. package/dist/cli-delegate/{chunk-JJA2QEWA.js → chunk-AKJGUQNO.js} +466 -285
  100. package/dist/cli-delegate/{chunk-E46KPN6K.js → chunk-BTWUYDGN.js} +424 -363
  101. package/dist/cli-delegate/{chunk-K4FFODTS.js → chunk-ILMUPLGW.js} +1227 -316
  102. package/dist/cli-delegate/{chunk-FF7WAFMR.js → chunk-KPBWFOPZ.js} +5 -1
  103. package/dist/cli-delegate/cmd_adr_effective.js +102 -0
  104. package/dist/cli-delegate/cmd_conformance.js +42 -10
  105. package/dist/cli-delegate/cmd_doctor.js +3 -3
  106. package/dist/cli-delegate/cmd_export.js +3 -2
  107. package/dist/cli-delegate/cmd_fleet.js +2 -2
  108. package/dist/cli-delegate/cmd_handoff.js +1 -1
  109. package/dist/cli-delegate/cmd_preflight.js +2 -2
  110. package/dist/cli-delegate/cmd_prune.js +3 -2
  111. package/dist/cli-delegate/cmd_settings_get.js +1 -1
  112. package/dist/cli-delegate/cmd_settings_migrate.js +3 -2
  113. package/dist/cli-delegate/cmd_settings_set.js +2 -2
  114. package/dist/cli-delegate/cmd_sync.js +3 -2
  115. package/dist/cli-delegate/cmd_uninstall.js +3 -2
  116. package/dist/cli-delegate/cmd_validate.js +3 -2
  117. package/dist/discovery/deprecation-report.md +1 -1
  118. package/dist/discovery/discovery-manifest.json +57 -57
  119. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  120. package/dist/discovery/discovery-manifest.summary.md +1 -1
  121. package/dist/discovery/dormancy-report.md +1 -1
  122. package/dist/discovery/orphan-report.md +1 -1
  123. package/dist/discovery/packs.json +2 -2
  124. package/dist/discovery/trust-report.md +1 -1
  125. package/dist/discovery/workspaces.json +2 -2
  126. package/dist/hooks/dispatch.js +1836 -712
  127. package/dist/install/claudeRuleRewrite.js +254 -0
  128. package/dist/install/detect.js +29 -16
  129. package/dist/install/detect_php_shape.js +159 -0
  130. package/dist/install/install.mjs +634 -428
  131. package/dist/mcp/awesome-mcp-servers.row.md +1 -1
  132. package/dist/mcp/mcp-cloudflare-catalogue.json +1 -1
  133. package/dist/mcp/registry-manifest.json +3 -3
  134. package/dist/mcp/server.json +3 -3
  135. package/dist/mcp/server.mjs +4818 -2645
  136. package/dist/server/schemas/settings.js +3 -0
  137. package/dist/ui/assets/index-D0jaCRPM.js +29 -0
  138. package/dist/ui/index.html +1 -1
  139. package/docs/MIGRATION.md +1 -1
  140. package/docs/THIRD-PARTY-NOTICES.md +25 -0
  141. package/docs/contracts/provider-lifecycle.md +1 -1
  142. package/docs/contracts/settings-classes.md +10 -4
  143. package/docs/guidelines/agent-infra/5w2h-analysis.md +3 -3
  144. package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +1 -0
  145. package/docs/guidelines/agent-infra/artifact-drafting-protocol-mechanics.md +58 -3
  146. package/docs/guidelines/agent-infra/ask-when-uncertain-demos.md +2 -2
  147. package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +3 -3
  148. package/docs/guidelines/agent-infra/break-glass-usage.md +7 -7
  149. package/docs/guidelines/agent-infra/carve-out-predicates.md +3 -3
  150. package/docs/guidelines/agent-infra/comparison-matrix.md +1 -1
  151. package/docs/guidelines/agent-infra/critical-thinking.md +4 -4
  152. package/docs/guidelines/agent-infra/direct-answers-demos.md +2 -2
  153. package/docs/guidelines/agent-infra/domain-eval-anti-pattern.md +1 -1
  154. package/docs/guidelines/agent-infra/engineering-memory-data-format.md +3 -3
  155. package/docs/guidelines/agent-infra/existence-question-verdicts.md +80 -0
  156. package/docs/guidelines/agent-infra/first-principles.md +2 -2
  157. package/docs/guidelines/agent-infra/framework-neutrality-patterns.md +2 -2
  158. package/docs/guidelines/agent-infra/guarded-baseline.md +39 -0
  159. package/docs/guidelines/agent-infra/inversion-thinking.md +5 -5
  160. package/docs/guidelines/agent-infra/language-and-tone-examples.md +1 -1
  161. package/docs/guidelines/agent-infra/layered-settings.md +10 -10
  162. package/docs/guidelines/agent-infra/memory-access.md +1 -1
  163. package/docs/guidelines/agent-infra/mental-models.md +3 -3
  164. package/docs/guidelines/agent-infra/reuse-verdict-mechanics.md +71 -0
  165. package/docs/guidelines/agent-infra/review-routing-data-format.md +7 -7
  166. package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +13 -7
  167. package/docs/guidelines/agent-infra/role-contracts.md +2 -2
  168. package/docs/guidelines/agent-infra/role-mode-router.md +3 -3
  169. package/docs/guidelines/agent-infra/rule-type-governance.md +2 -2
  170. package/docs/guidelines/agent-infra/scqa-framework.md +5 -5
  171. package/docs/guidelines/agent-infra/self-improvement-pipeline.md +6 -6
  172. package/docs/guidelines/agent-infra/simplicity-and-goal-demos.md +2 -2
  173. package/docs/guidelines/agent-infra/six-hats.md +3 -3
  174. package/docs/guidelines/agent-infra/skill-quality-checklist.md +6 -6
  175. package/docs/guidelines/agent-infra/source-confidentiality-mechanics.md +109 -0
  176. package/docs/guidelines/agent-infra/systems-thinking.md +1 -1
  177. package/docs/guidelines/agent-infra/verify-before-complete-demos.md +2 -2
  178. package/docs/guidelines/augment-portability-patterns.md +6 -4
  179. package/docs/guidelines/component-oriented-and-oop-development.md +3 -2
  180. package/docs/guidelines/cross-role-handoff.md +2 -2
  181. package/docs/guidelines/design-fidelity-mechanics.md +1 -1
  182. package/docs/guidelines/docs/readme-size-and-splitting.md +3 -3
  183. package/docs/guidelines/php/database.md +90 -7
  184. package/docs/guidelines/prompt-templates.md +7 -7
  185. package/llms.txt +2 -2
  186. package/package.json +5 -2
  187. package/src/agent-src/scripts/archive_completed_roadmaps.ts +247 -3
  188. package/src/agent-src/scripts/guarded_baseline.ts +328 -0
  189. package/src/agent-src/scripts/roadmap_set_step.ts +253 -0
  190. package/src/agent-src/scripts/stub_queue.ts +82 -0
  191. package/src/agent-src/scripts/stubs_due.ts +400 -0
  192. package/src/agent-src/scripts/ticket_bundles.ts +84 -0
  193. package/src/agent-src/scripts/update_roadmap_progress.ts +8 -4
  194. package/src/agent-src/templates/scripts/check_memory.ts +258 -17
  195. package/src/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
  196. package/src/agent-src/templates/scripts/memory_lookup.ts +86 -0
  197. package/src/agent-src/templates/scripts/memory_signal.ts +44 -0
  198. package/src/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
  199. package/src/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
  200. package/src/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
  201. package/src/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
  202. package/src/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
  203. package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
  204. package/src/config/agent-settings.template.yml +32 -3
  205. package/src/config/assurance-capability-registry.json +21 -9
  206. package/src/config/canonical-terms.yml +119 -0
  207. package/src/config/capability-native-outcome-bars.json +81 -0
  208. package/src/config/ci-local-parity.yml +80 -0
  209. package/src/config/drafting-channels.yml +43 -0
  210. package/src/config/estate-count-budget.json +38 -36
  211. package/src/config/evaluator-budgets.json +14 -14
  212. package/src/config/gate-coverage.yml +579 -63
  213. package/src/config/gate-reachability-exemptions.json +21 -0
  214. package/src/config/gate-violation-baselines.json +37 -19
  215. package/src/config/harness-evolution-budget.json +25 -0
  216. package/src/config/lapsed-beta-baseline.json +96 -0
  217. package/src/config/memory-twin-verdicts.yml +129 -0
  218. package/src/config/metric-registry.yml +124 -0
  219. package/src/config/pack-size-budget.json +16 -15
  220. package/src/config/preamble-payload-budget.json +8 -8
  221. package/src/config/profiles/balanced.ini +27 -0
  222. package/src/config/profiles/full.ini +27 -0
  223. package/src/config/profiles/minimal.ini +27 -0
  224. package/src/config/publish-surface.json +9 -2
  225. package/src/config/routing-coverage-seed.json +16 -2
  226. package/src/config/rule-stub-ceilings.json +126 -112
  227. package/src/config/turnaround-budget.json +66 -0
  228. package/src/install/claudeRuleRewrite.ts +288 -0
  229. package/src/install/detect.ts +60 -17
  230. package/src/install/detect_php_shape.ts +191 -0
  231. package/src/scripts/_cli/cmd_doctor.ts +27 -112
  232. package/src/scripts/_dispatch.bash +27 -0
  233. package/src/scripts/_lib/activation_ladder.ts +211 -0
  234. package/src/scripts/_lib/activation_states.ts +88 -0
  235. package/src/scripts/_lib/adherence_detectors.ts +143 -0
  236. package/src/scripts/_lib/arith_claims.ts +181 -0
  237. package/src/scripts/_lib/arm_ranking.ts +62 -0
  238. package/src/scripts/_lib/asset_delivery_ledger.ts +303 -0
  239. package/src/scripts/_lib/audit_field_provenance.ts +54 -0
  240. package/src/scripts/_lib/auto_dispatch.ts +32 -3
  241. package/src/scripts/_lib/bench_ab_size_claim.ts +98 -4
  242. package/src/scripts/_lib/benchmark_cache_fields.ts +158 -0
  243. package/src/scripts/_lib/candidate_proposer.ts +402 -0
  244. package/src/scripts/_lib/candidate_record.ts +601 -0
  245. package/src/scripts/_lib/capture_rate.ts +319 -0
  246. package/src/scripts/_lib/collector_denominator.ts +771 -0
  247. package/src/scripts/_lib/collector_record.ts +340 -0
  248. package/src/scripts/_lib/collector_store.ts +664 -0
  249. package/src/scripts/_lib/collector_supervision.ts +827 -0
  250. package/src/scripts/_lib/concern_estate.ts +77 -0
  251. package/src/scripts/_lib/config_chain.ts +477 -0
  252. package/src/scripts/_lib/config_cost.ts +209 -0
  253. package/src/scripts/_lib/council_settings_block.ts +6 -0
  254. package/src/scripts/_lib/curator_ops.ts +172 -0
  255. package/src/scripts/_lib/delivery_arm_experiment.ts +266 -0
  256. package/src/scripts/_lib/delivery_criticality.ts +126 -0
  257. package/src/scripts/_lib/doctor_runtime_checks.ts +70 -0
  258. package/src/scripts/_lib/empty_cycles.ts +88 -0
  259. package/src/scripts/_lib/eval_publication.ts +354 -0
  260. package/src/scripts/_lib/evaluation_vector.ts +283 -0
  261. package/src/scripts/_lib/evaluator_promotion.ts +225 -0
  262. package/src/scripts/_lib/evidence_basis.ts +118 -0
  263. package/src/scripts/_lib/exec_evidence.ts +8 -0
  264. package/src/scripts/_lib/experience_card.ts +272 -0
  265. package/src/scripts/_lib/experience_report.ts +151 -0
  266. package/src/scripts/_lib/experiment_freeze.ts +112 -0
  267. package/src/scripts/_lib/generated_by.ts +66 -0
  268. package/src/scripts/_lib/harness_evolution_guards.ts +229 -0
  269. package/src/scripts/_lib/hook_effect_probe.ts +141 -0
  270. package/src/scripts/_lib/host_denominator.ts +687 -0
  271. package/src/scripts/_lib/host_projection_reach.ts +157 -0
  272. package/src/scripts/_lib/ignored_blocker.ts +148 -0
  273. package/src/scripts/_lib/install_reach_checks.ts +495 -0
  274. package/src/scripts/_lib/json_duplicate_keys.ts +150 -0
  275. package/src/scripts/_lib/judge_hygiene.ts +228 -0
  276. package/src/scripts/_lib/legacy_boundary_map.ts +228 -0
  277. package/src/scripts/_lib/loop_guards.ts +299 -0
  278. package/src/scripts/_lib/loss_class.ts +129 -0
  279. package/src/scripts/_lib/machine_wake.ts +51 -0
  280. package/src/scripts/_lib/md_prose_lines.ts +177 -0
  281. package/src/scripts/_lib/minimality_tiebreak.ts +168 -0
  282. package/src/scripts/_lib/one_resolver_invariant.ts +449 -0
  283. package/src/scripts/_lib/orchestration_record.ts +253 -5
  284. package/src/scripts/_lib/outcome_envelope.ts +227 -0
  285. package/src/scripts/_lib/outcome_vocabularies.ts +125 -0
  286. package/src/scripts/_lib/paired_stats.ts +245 -0
  287. package/src/scripts/_lib/paired_verdict.ts +226 -0
  288. package/src/scripts/_lib/prefix_stable_surfaces.ts +123 -0
  289. package/src/scripts/_lib/privacy_class.ts +47 -0
  290. package/src/scripts/_lib/regression_neighbourhood.ts +259 -0
  291. package/src/scripts/_lib/repeated_failure.ts +105 -0
  292. package/src/scripts/_lib/repo_root.ts +111 -0
  293. package/src/scripts/_lib/review_skipped_record.ts +37 -0
  294. package/src/scripts/_lib/role_split.ts +338 -0
  295. package/src/scripts/_lib/runtime_journal.ts +1499 -0
  296. package/src/scripts/_lib/runtime_wiring_checks.ts +430 -0
  297. package/src/scripts/_lib/skill_catalogue.ts +11 -1
  298. package/src/scripts/_lib/source_digest.ts +200 -0
  299. package/src/scripts/_lib/source_redact.ts +260 -0
  300. package/src/scripts/_lib/source_shape.ts +502 -0
  301. package/src/scripts/_lib/source_snapshot_dedup.ts +199 -0
  302. package/src/scripts/_lib/strip_comments.d.mts +8 -0
  303. package/src/scripts/_lib/strip_comments.mjs +65 -0
  304. package/src/scripts/_lib/test_red_state.ts +154 -0
  305. package/src/scripts/_lib/trigger_shift.ts +144 -0
  306. package/src/scripts/_lib/untrusted_content.ts +82 -7
  307. package/src/scripts/adoption_report.ts +1 -1
  308. package/src/scripts/adr/evidence_census.ts +1 -1
  309. package/src/scripts/adr/regenerate_index.ts +26 -2
  310. package/src/scripts/adr_cite_check.ts +164 -1
  311. package/src/scripts/ai_council/blind_review.ts +11 -1
  312. package/src/scripts/ai_council/clients.ts +4 -0
  313. package/src/scripts/ai_council/config.ts +3 -0
  314. package/src/scripts/ai_council/consensus.ts +28 -8
  315. package/src/scripts/ai_council/consensus_round.ts +226 -0
  316. package/src/scripts/ai_council/disagreement_signal.ts +338 -0
  317. package/src/scripts/ai_council/inline_findings.ts +340 -0
  318. package/src/scripts/ai_council/judge_position_bias.ts +197 -0
  319. package/src/scripts/ai_council/orchestrator.ts +16 -203
  320. package/src/scripts/ai_council/orchestrator_results.ts +23 -3
  321. package/src/scripts/ai_council/pricing.ts +106 -0
  322. package/src/scripts/ai_council/prompts.ts +74 -7
  323. package/src/scripts/ai_council/provider_leakage_bench.ts +327 -0
  324. package/src/scripts/ai_council/py_format.ts +14 -3
  325. package/src/scripts/ai_council/recouncil_guard.ts +293 -0
  326. package/src/scripts/ai_council/response_record.ts +50 -0
  327. package/src/scripts/ai_council/topology_bench_manifest.ts +860 -0
  328. package/src/scripts/ai_council/topology_vocabulary.ts +175 -0
  329. package/src/scripts/asset_delivery_ledger.ts +157 -0
  330. package/src/scripts/attest_artifact.ts +193 -0
  331. package/src/scripts/audit_auto_rules.ts +2 -1
  332. package/src/scripts/audit_command_surface.ts +1 -1
  333. package/src/scripts/audit_mcp_tools.ts +2 -2
  334. package/src/scripts/audit_skill_overlap_allowlist.json +6 -1
  335. package/src/scripts/audit_user_type_axis.ts +2 -1
  336. package/src/scripts/bench_ab_clone.ts +215 -10
  337. package/src/scripts/bench_ab_integrity.ts +119 -5
  338. package/src/scripts/bench_ab_v2_stats.ts +40 -213
  339. package/src/scripts/build_archive_index.ts +1 -1
  340. package/src/scripts/build_linear_digest.ts +1 -1
  341. package/src/scripts/build_proof.ts +11 -4
  342. package/src/scripts/build_rule_trigger_matrix.ts +1 -1
  343. package/src/scripts/build_source_digests.ts +157 -0
  344. package/src/scripts/cache_realization_report.ts +103 -0
  345. package/src/scripts/check_adr_frontmatter.ts +126 -0
  346. package/src/scripts/check_benchmark_report_fields.ts +207 -0
  347. package/src/scripts/check_beta_review_markers.ts +235 -6
  348. package/src/scripts/check_bundle_path_leakage.ts +34 -1
  349. package/src/scripts/check_claims.ts +576 -6
  350. package/src/scripts/check_composite_arming.ts +35 -0
  351. package/src/scripts/check_concern_admissions.ts +365 -0
  352. package/src/scripts/check_enforcement_coverage.ts +28 -0
  353. package/src/scripts/check_estate_count.ts +142 -1
  354. package/src/scripts/check_gate_reachability.ts +383 -0
  355. package/src/scripts/check_host_loadability.ts +104 -0
  356. package/src/scripts/check_loss_class_declared.ts +308 -0
  357. package/src/scripts/check_md_language.ts +15 -98
  358. package/src/scripts/check_memory_proposal.ts +18 -11
  359. package/src/scripts/check_no_currency_in_cost_surfaces.ts +225 -0
  360. package/src/scripts/check_no_external_sources.ts +281 -6
  361. package/src/scripts/check_pack_conformance_fixture.ts +11 -1
  362. package/src/scripts/check_pack_size.ts +59 -2
  363. package/src/scripts/check_preamble_payload_budget.ts +114 -3
  364. package/src/scripts/check_prefix_stable_mutation.ts +372 -0
  365. package/src/scripts/check_publish_surface.ts +10 -1
  366. package/src/scripts/check_references.ts +24 -1
  367. package/src/scripts/check_rule_evidence_declaration.ts +316 -0
  368. package/src/scripts/check_rule_projection_integrity.ts +14 -4
  369. package/src/scripts/check_score_contract.ts +26 -3
  370. package/src/scripts/check_static_parity.ts +285 -0
  371. package/src/scripts/check_supervision_claim_atomicity.ts +498 -0
  372. package/src/scripts/check_suppression_hygiene.ts +15 -0
  373. package/src/scripts/ci_settle.ts +39 -2
  374. package/src/scripts/code_graph/build.ts +60 -3
  375. package/src/scripts/code_graph/extract.ts +44 -0
  376. package/src/scripts/code_graph/types.ts +24 -0
  377. package/src/scripts/collector_daemon.ts +714 -0
  378. package/src/scripts/config_cost_report.ts +302 -0
  379. package/src/scripts/consumer_matrix.ts +74 -1
  380. package/src/scripts/cost/budget.mjs +10 -3
  381. package/src/scripts/cost/track.mjs +10 -3
  382. package/src/scripts/council_cli.ts +37 -54
  383. package/src/scripts/dispatch_r2_reviewer.ts +46 -5
  384. package/src/scripts/evolution_lab.ts +980 -0
  385. package/src/scripts/external_sources_denylist.json +5 -18
  386. package/src/scripts/extract_audit_patterns.ts +21 -0
  387. package/src/scripts/fold_intake.ts +12 -1
  388. package/src/scripts/gen_discovery_baseline.ts +1 -1
  389. package/src/scripts/generate_capabilities_index.ts +12 -5
  390. package/src/scripts/generate_capability_matrix.ts +3 -3
  391. package/src/scripts/generate_command_flows.ts +2 -2
  392. package/src/scripts/generate_cookbook.ts +2 -2
  393. package/src/scripts/generate_index.ts +8 -1
  394. package/src/scripts/generate_knowledge_index.ts +2 -1
  395. package/src/scripts/generate_ownership_matrix.ts +2 -1
  396. package/src/scripts/generate_pack_manifests.ts +10 -2
  397. package/src/scripts/generate_role_experiences_catalog.ts +2 -2
  398. package/src/scripts/generate_settings_reference.ts +1 -1
  399. package/src/scripts/git_authorization_hook.ts +22 -1
  400. package/src/scripts/grade_target_readiness.ts +48 -5
  401. package/src/scripts/hook_effect_doctor.ts +261 -0
  402. package/src/scripts/hook_manifest.json +1 -1
  403. package/src/scripts/hook_manifest.yaml +98 -11
  404. package/src/scripts/hooks/block_speaking_inbox_dir.ts +271 -0
  405. package/src/scripts/hooks/block_unauthorized_git.ts +18 -0
  406. package/src/scripts/hooks/concern_registry.ts +4 -0
  407. package/src/scripts/hooks/dispatch_hook.ts +32 -0
  408. package/src/scripts/hooks/journal_record_hook.ts +345 -0
  409. package/src/scripts/hooks/prepush_metadata_sources.sh +110 -0
  410. package/src/scripts/hooks/run_continuation_hook.ts +44 -9
  411. package/src/scripts/hooks/shims/install.sh +61 -0
  412. package/src/scripts/hooks/shims/php +101 -0
  413. package/src/scripts/hooks/suggestion_capture_hook.ts +10 -0
  414. package/src/scripts/hot_context_hook.ts +16 -0
  415. package/src/scripts/install-hooks.sh +20 -5
  416. package/src/scripts/install.ts +17 -35
  417. package/src/scripts/inventory_frontmatter.ts +2 -1
  418. package/src/scripts/lint_adr_sweep_routing.ts +12 -0
  419. package/src/scripts/lint_canonical_terms.ts +604 -0
  420. package/src/scripts/lint_composition_review.ts +619 -0
  421. package/src/scripts/lint_consolidation_lineage.ts +666 -0
  422. package/src/scripts/lint_eval_specs.ts +593 -0
  423. package/src/scripts/lint_hook_manifest.ts +19 -0
  424. package/src/scripts/lint_host_portability.ts +373 -0
  425. package/src/scripts/lint_judge_prompt_expectation.ts +27 -1
  426. package/src/scripts/lint_memory_twin_parity.ts +335 -0
  427. package/src/scripts/lint_metric_consumers.ts +355 -0
  428. package/src/scripts/lint_skill_descriptions.ts +18 -1
  429. package/src/scripts/lint_skill_frontmatter_safety.ts +58 -0
  430. package/src/scripts/lint_skill_link_reach.ts +252 -0
  431. package/src/scripts/lint_skill_trigger_corpus.ts +426 -23
  432. package/src/scripts/lint_ticket_buildable.ts +17 -1
  433. package/src/scripts/mcp_server/consumer_tool_catalog.json +1 -1
  434. package/src/scripts/mcp_server/tool_catalog_source.ts +1 -1
  435. package/src/scripts/measure_docs_dead_links.ts +348 -0
  436. package/src/scripts/measure_host_capture.ts +461 -0
  437. package/src/scripts/migration_status.ts +3 -3
  438. package/src/scripts/model_rule_injection.ts +60 -0
  439. package/src/scripts/orchestration_record.ts +14 -0
  440. package/src/scripts/preamble_byte_census.ts +139 -10
  441. package/src/scripts/prepack-check.mjs +4 -1
  442. package/src/scripts/probe_turnaround.ts +384 -0
  443. package/src/scripts/probe_unblocked_ask.ts +279 -0
  444. package/src/scripts/render_benchmark_md.ts +1 -1
  445. package/src/scripts/rule_activation_census.ts +70 -9
  446. package/src/scripts/rule_backlinks.ts +1 -1
  447. package/src/scripts/run_lifecycle_suite.ts +208 -0
  448. package/src/scripts/run_skill_evals.ts +40 -0
  449. package/src/scripts/schemas/delivery-manifest.schema.json +43 -0
  450. package/src/scripts/schemas/drafting-channels.schema.json +43 -0
  451. package/src/scripts/schemas/evals.schema.json +24 -1
  452. package/src/scripts/schemas/rule.schema.json +52 -1
  453. package/src/scripts/schemas/skill.schema.json +17 -2
  454. package/src/scripts/skill_overlap.ts +7 -1
  455. package/src/scripts/skill_tools/run_block_d_eval.ts +8 -1
  456. package/src/scripts/skill_tools/score_skill_relevance.ts +84 -3
  457. package/src/scripts/skill_tools/suggest_skill_for_task.ts +8 -1
  458. package/src/scripts/skill_usage_report.ts +2 -1
  459. package/src/scripts/stubs_due.ts +211 -0
  460. package/src/scripts/sweep_source_surfaces.ts +678 -0
  461. package/src/scripts/sync_pr_branch.ts +3 -3
  462. package/src/scripts/trigger_eval_grandfather.json +202 -222
  463. package/src/scripts/utilization_report.ts +22 -2
  464. package/src/server/schemas/settings.ts +5 -0
  465. package/src/templates/marketing-copy.yml +1 -1
  466. package/dist/ui/assets/index-Cxgy63kz.js +0 -26
@@ -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
  }
@@ -13,6 +13,8 @@
13
13
  * change to either has to touch the record and the code together.
14
14
  */
15
15
 
16
+ import { decidePairedVerdict, floorWarning, MIN_DISCORDANT } from './paired_verdict.js';
17
+
16
18
  /** T1 — median added lines must fall by at least this much. */
17
19
  export const T1_MEDIAN_LINES_PCT = -10;
18
20
  /** Two-sided significance for every endpoint in the pair. */
@@ -25,7 +27,15 @@ export interface PairedContinuous {
25
27
  /** `null` when the baseline median is 0 — no percent change exists. */
26
28
  median_delta_pct: number | null;
27
29
  median_delta: number;
30
+ /**
31
+ * Retained for TRIAGE and reporting. Since PREREG amendment v2 it decides
32
+ * nothing — see {@link evaluateSizeClaim}.
33
+ */
28
34
  wilcoxon_p: number;
35
+ /** Non-tied pairs in the direction of interest. Absent on a pre-amendment report. */
36
+ direction_wins?: number | undefined;
37
+ /** Non-tied pairs against the direction of interest. Absent on a pre-amendment report. */
38
+ direction_losses?: number | undefined;
29
39
  }
30
40
 
31
41
  /** A paired binary endpoint (the safety tier). */
@@ -56,6 +66,44 @@ export interface SizeClaimVerdict {
56
66
  safety_measured: boolean;
57
67
  }
58
68
 
69
+
70
+
71
+ /** One clause naming the directional evidence, printable in a verdict reason. */
72
+ function describeDirection(v: ReturnType<typeof decidePairedVerdict> | null): string {
73
+ if (v === null) {
74
+ return `no direction counts in the report — pre-amendment or unmeasured, so the direction bar is not met`;
75
+ }
76
+ if (v.kind === 'underpowered') {
77
+ return `underpowered: ${String(v.discordant)} non-tied pair(s) below the derived floor of ${String(MIN_DISCORDANT)}`;
78
+ }
79
+ const warn = floorWarning(v);
80
+ return `${String(v.wins)}/${String(v.discordant)} non-tied pairs, one-sided exact p=${v.p.toFixed(4)}` +
81
+ (warn === null ? '' : ` — ${warn}`);
82
+ }
83
+
84
+ /**
85
+ * The directional verdict for one endpoint, or `null` when it cannot be formed.
86
+ *
87
+ * `null` means the report carries no direction counts — a pre-amendment report,
88
+ * or an unmeasured endpoint. The caller treats that as "not significant" rather
89
+ * than reaching for `wilcoxon_p`, which is the whole point of the amendment.
90
+ *
91
+ * The counts are reconstructed into a delta vector of ±1 rather than carrying
92
+ * raw deltas through the report: the exact sign test needs direction only, and
93
+ * a council seat noted the raw deltas are preferable for auditability but not
94
+ * mathematically required. The raw values remain in the trial artifacts.
95
+ */
96
+ function directionVerdict(e: PairedContinuous): ReturnType<typeof decidePairedVerdict> | null {
97
+ if (!e.measured) return null;
98
+ const w = e.direction_wins;
99
+ const l = e.direction_losses;
100
+ if (w === undefined || l === undefined) return null;
101
+ return decidePairedVerdict({
102
+ deltas: [...Array<number>(w).fill(1), ...Array<number>(l).fill(-1)],
103
+ alpha: ALPHA,
104
+ });
105
+ }
106
+
59
107
  /**
60
108
  * Evaluate the size claim for one comparison — binding, and structurally unable
61
109
  * to report a win on size alone.
@@ -98,9 +146,52 @@ export function evaluateSizeClaim(input: SizeClaimInput): SizeClaimVerdict {
98
146
  };
99
147
  }
100
148
 
101
- const cx_rose = cx.measured && cx.median_delta > 0 && cx.wilcoxon_p < ALPHA;
149
+ // ── PREREG amendment v2, 2026-08-26 — direction decides significance ────
150
+ //
151
+ // The significance half of every endpoint below was a Wilcoxon signed-rank
152
+ // p, which ranks by |difference| and is therefore magnitude-weighted. That
153
+ // was shown to disagree with the exact test on twelve records up to ten
154
+ // trials, PERMISSIVE in every one, with the visible symptom inverted: an
155
+ // artifact winning every trial still failed, because a few large
156
+ // opposite-direction deltas outweighed a clean sweep of small ones.
157
+ //
158
+ // TWO PROPOSITIONS, KEPT SEPARATE — this is the refinement both council
159
+ // seats independently required (2026-08-26, 2/2) and it is the half that
160
+ // makes the amendment safe. A sign test answers "did this help more often
161
+ // than it hurt" and says NOTHING about how much. Replacing Wilcoxon with it
162
+ // outright would let a clean sweep of negligible improvements claim a SIZE
163
+ // win. So:
164
+ // · directional reliability → exact one-sided sign test over non-tied pairs
165
+ // · practical magnitude → the pre-registered T1_MEDIAN_LINES_PCT bar,
166
+ // unchanged and still independently binding
167
+ // Both must hold. Dropping either is a different claim and needs its own
168
+ // amendment.
169
+ //
170
+ // A report predating the amendment carries no direction counts. It is
171
+ // treated as UNMEASURED for the significance half rather than falling back
172
+ // to `wilcoxon_p`, because a silent fallback to the defective test is
173
+ // exactly what this amendment removes.
174
+ const sizeDir = directionVerdict(size);
175
+ const cxDir = directionVerdict(cx);
176
+ // ASYMMETRY, deliberate and the conservative direction of it. A PASS needs
177
+ // the direction bar MET; a REFUSAL fires on EITHER signal. Applying the
178
+ // strict reading to both would make the anti-golfing refusal disappear on
179
+ // any report without direction counts — a missing input silently rescuing
180
+ // an arm is the failure mode a refusal exists to prevent, and it is the
181
+ // opposite of what the amendment is for. So the refusal keeps the legacy
182
+ // Wilcoxon signal as a second trigger; the claim does not.
183
+ const cx_rose =
184
+ cx.measured &&
185
+ cx.median_delta > 0 &&
186
+ (cxDir === null ? cx.wilcoxon_p < ALPHA : cxDir.kind === 'regression');
187
+ // `regression`, NOT `pass`, and the distinction cost a test run to find.
188
+ // `direction_wins` counts the endpoint's IMPROVEMENT direction — a negative
189
+ // delta — for every continuous endpoint, so on complexity a `pass` means
190
+ // complexity FELL. What `cx_rose` needs is the opposite tail, which is
191
+ // exactly what `regression` names. Writing `pass` here reads correctly in
192
+ // English and inverts the anti-golfing guard.
102
193
  const pct = size.measured ? size.median_delta_pct : null;
103
- const lines_fell = pct !== null && pct <= T1_MEDIAN_LINES_PCT && size.wilcoxon_p < ALPHA;
194
+ const lines_fell = pct !== null && pct <= T1_MEDIAN_LINES_PCT && sizeDir?.kind === 'pass';
104
195
 
105
196
  // (2b) Golfing is refused as soon as T2 shows it, and does NOT wait for T4.
106
197
  //
@@ -161,8 +252,11 @@ export function evaluateSizeClaim(input: SizeClaimInput): SizeClaimVerdict {
161
252
  ...base,
162
253
  verdict: lines_fell ? 'PASS' : 'NO-SIZE-WIN',
163
254
  reason: lines_fell
164
- ? `median added lines ${pct}% at p=${size.wilcoxon_p} with no significant complexity rise and no safety regression`
165
- : `T1 not met (median added lines ${pct}% at p=${size.wilcoxon_p}; bar is <= ${T1_MEDIAN_LINES_PCT}% at p<${ALPHA})`,
255
+ ? `median added lines ${pct}% (magnitude bar) AND ${describeDirection(sizeDir)} (direction bar) ` +
256
+ 'with no significant complexity rise and no safety regression'
257
+ : `T1 not met (median added lines ${pct}%, bar <= ${T1_MEDIAN_LINES_PCT}%; ` +
258
+ `direction: ${describeDirection(sizeDir)}). Wilcoxon p=${size.wilcoxon_p} is reported for ` +
259
+ 'triage and decides nothing.',
166
260
  lines_fell,
167
261
  size_measured: true,
168
262
  complexity_measured: true,
@@ -0,0 +1,158 @@
1
+ /**
2
+ * The `cache` block of a benchmark / cost report — required fields, and the one
3
+ * legitimate way to not have a number (`road-to-runtime-context-floors` step 4.1).
4
+ *
5
+ * Both fields are REQUIRED. A report that cannot compute one states a reason; it
6
+ * does not omit the key and it does not emit a zero. A blank reads as "no cache
7
+ * activity" and a zero reads as "the worst possible ratio" — both are claims, and
8
+ * neither is the claim "this was not measured".
9
+ *
10
+ * Contract: `docs/contracts/benchmark-report-schema.md` § The `cache` block.
11
+ */
12
+
13
+ export const REQUIRED_CACHE_FIELDS = ['read_write_ratio', 'stable_prefix_share'] as const;
14
+ export type RequiredCacheField = (typeof REQUIRED_CACHE_FIELDS)[number];
15
+
16
+ /**
17
+ * What produced the report (`road-to-delivered-cost-truth` step 4.2).
18
+ *
19
+ * A benchmark number without its provenance cannot be reproduced or challenged,
20
+ * and this repository carries a measured instance of that failure: an external
21
+ * round's headline figures are recorded `unverifiable` precisely because the run
22
+ * behind them is unreachable. These four keep a report here from becoming that.
23
+ */
24
+ export const REQUIRED_PROVENANCE_FIELDS = [
25
+ 'host_binary_hash',
26
+ 'harness_commit',
27
+ 'harness_dirty',
28
+ 'reproducibility',
29
+ ] as const;
30
+ export type RequiredProvenanceField = (typeof REQUIRED_PROVENANCE_FIELDS)[number];
31
+
32
+ /** A measured number, or a stated reason there is none. Never a bare absence. */
33
+ export type CacheFieldValue = number | { unavailable: string };
34
+
35
+ export interface CacheBlock {
36
+ read_write_ratio: CacheFieldValue;
37
+ stable_prefix_share: CacheFieldValue;
38
+ }
39
+
40
+ export type AnyRequiredField = RequiredCacheField | RequiredProvenanceField;
41
+
42
+ export type FieldProblem =
43
+ | { field: AnyRequiredField; kind: 'missing' }
44
+ | { field: AnyRequiredField; kind: 'blank-unavailable' }
45
+ | { field: AnyRequiredField; kind: 'not-a-number'; value: unknown }
46
+ | { field: AnyRequiredField; kind: 'out-of-range'; value: number }
47
+ | { field: AnyRequiredField; kind: 'blank-value' };
48
+
49
+ export function unavailable(reason: string): CacheFieldValue {
50
+ return { unavailable: reason };
51
+ }
52
+
53
+ function validateField(field: RequiredCacheField, raw: unknown): FieldProblem | null {
54
+ if (raw === undefined || raw === null) return { field, kind: 'missing' };
55
+ if (typeof raw === 'object') {
56
+ const reason = (raw as { unavailable?: unknown }).unavailable;
57
+ if (typeof reason !== 'string' || reason.trim().length === 0) {
58
+ return { field, kind: 'blank-unavailable' };
59
+ }
60
+ return null;
61
+ }
62
+ if (typeof raw !== 'number' || !Number.isFinite(raw)) return { field, kind: 'not-a-number', value: raw };
63
+ // A share is a fraction; a ratio is unbounded above but never negative.
64
+ if (raw < 0) return { field, kind: 'out-of-range', value: raw };
65
+ if (field === 'stable_prefix_share' && raw > 1) return { field, kind: 'out-of-range', value: raw };
66
+ return null;
67
+ }
68
+
69
+ /** Validate a report's `cache` block. Empty array = valid. */
70
+ export function validateCacheBlock(report: unknown): FieldProblem[] {
71
+ const cache = (report as { cache?: unknown } | null)?.cache;
72
+ if (cache === undefined || cache === null || typeof cache !== 'object') {
73
+ return REQUIRED_CACHE_FIELDS.map((field) => ({ field, kind: 'missing' as const }));
74
+ }
75
+ const rec = cache as Record<string, unknown>;
76
+ return REQUIRED_CACHE_FIELDS.map((f) => validateField(f, rec[f])).filter((p): p is FieldProblem => p !== null);
77
+ }
78
+
79
+ function blockOf(field: AnyRequiredField): string {
80
+ return (REQUIRED_PROVENANCE_FIELDS as readonly string[]).includes(field) ? 'provenance' : 'cache';
81
+ }
82
+
83
+ export function describeProblem(p: FieldProblem): string {
84
+ const q = `${blockOf(p.field)}.${p.field}`;
85
+ switch (p.kind) {
86
+ case 'missing':
87
+ return `${q} is missing — it is required; emit { unavailable: "<reason>" } when it cannot be supplied`;
88
+ case 'blank-unavailable':
89
+ return `${q} declares itself unavailable with no reason — a reason is the whole point of the form`;
90
+ case 'blank-value':
91
+ return `${q} is an empty string, which states nothing; emit { unavailable: "<reason>" } instead`;
92
+ case 'not-a-number':
93
+ return `${q} is ${JSON.stringify(p.value)}, which is neither a number nor { unavailable: "<reason>" }`;
94
+ case 'out-of-range':
95
+ return `${q} is ${String(p.value)}, outside its valid range`;
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Validate a report's `provenance` block.
101
+ *
102
+ * `harness_dirty` is a BOOLEAN and the others are strings, so the shape check is
103
+ * per-field rather than uniform — and `false` must pass, which a truthiness
104
+ * check would silently reject. That is the bug this comment exists to prevent on
105
+ * the next edit: a dirty flag of `false` is the good case.
106
+ */
107
+ export function validateProvenanceBlock(report: unknown): FieldProblem[] {
108
+ const block = (report as { provenance?: unknown } | null)?.provenance;
109
+ if (block === undefined || block === null || typeof block !== 'object') {
110
+ return REQUIRED_PROVENANCE_FIELDS.map((field) => ({ field, kind: 'missing' as const }));
111
+ }
112
+ const rec = block as Record<string, unknown>;
113
+ const out: FieldProblem[] = [];
114
+ for (const field of REQUIRED_PROVENANCE_FIELDS) {
115
+ const raw = rec[field];
116
+ if (raw === undefined || raw === null) {
117
+ out.push({ field, kind: 'missing' });
118
+ continue;
119
+ }
120
+ if (typeof raw === 'object') {
121
+ const reason = (raw as { unavailable?: unknown }).unavailable;
122
+ if (typeof reason !== 'string' || reason.trim().length === 0) out.push({ field, kind: 'blank-unavailable' });
123
+ continue;
124
+ }
125
+ if (field === 'harness_dirty') {
126
+ if (typeof raw !== 'boolean') out.push({ field, kind: 'not-a-number', value: raw });
127
+ continue;
128
+ }
129
+ if (typeof raw !== 'string') out.push({ field, kind: 'not-a-number', value: raw });
130
+ else if (raw.trim().length === 0) out.push({ field, kind: 'blank-value' });
131
+ }
132
+ return out;
133
+ }
134
+
135
+ /**
136
+ * Compute the ratio from token totals, or state why not.
137
+ *
138
+ * Zero cache-creation tokens is the interesting case: the ratio is undefined,
139
+ * not infinite and not zero, and the honest report says so.
140
+ */
141
+ export function readWriteRatio(cacheRead: number, cacheCreation: number): CacheFieldValue {
142
+ if (!Number.isFinite(cacheRead) || !Number.isFinite(cacheCreation)) {
143
+ return unavailable('the session source carries no cache_read/cache_creation token fields');
144
+ }
145
+ if (cacheCreation === 0) {
146
+ return unavailable('no cache-creation tokens were recorded in this window, so the ratio is undefined rather than zero');
147
+ }
148
+ return cacheRead / cacheCreation;
149
+ }
150
+
151
+ /** The STABLE cohort as a fraction of dispatches carrying the field, or why not. */
152
+ export function stablePrefixShare(stableN: number, unstableN: number): CacheFieldValue {
153
+ const total = stableN + unstableN;
154
+ if (total === 0) {
155
+ return unavailable('no dispatch in this window recorded both payload_hash and cache_hit');
156
+ }
157
+ return stableN / total;
158
+ }