@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,461 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Measure the runtime event journal's HOST capture rate.
4
+ *
5
+ * `road-to-journal-host-capture-measurement` Phase 2 step 2.1. Produces the
6
+ * number that step, and its parent roadmap's step 1.4, asked for — or the
7
+ * stated reason a given population's rate cannot exist.
8
+ *
9
+ * ## What it measures, and the one thing it is not
10
+ *
11
+ * The DENOMINATOR is host-authored: it is reconstructed from Claude Code's own
12
+ * per-session transcripts by the pinned rules in `_lib/host_denominator.ts`.
13
+ * The NUMERATOR is this package's journal store. Neither is derived from the
14
+ * other, which is the property that makes the ratio a capture rate.
15
+ *
16
+ * It is emphatically **not** the dispatch-path figure published by
17
+ * `agents/evidence/analysis/runtime-journal-capture-2026-08-28.md` (100.00 %,
18
+ * 1,000 envelopes). That measured envelopes handed to the concern by a test —
19
+ * a floor on the writer. This measures events a real host emitted. Reporting
20
+ * either as the other is the category substitution both evidence pages refuse.
21
+ *
22
+ * ## One population, and it is the numerator's — R2 finding 1
23
+ *
24
+ * The journal lives at `<git-common-dir>/agent-journal/journal.sqlite`: one
25
+ * store per REPOSITORY, shared by its worktrees, reaching nothing else. So the
26
+ * denominator defaults to `--scope repository`, which counts only the
27
+ * transcripts of that repository's worktrees. `--scope machine` is available
28
+ * and is a different figure about the host; the rate printed under it is
29
+ * labelled UNMATCHED, because dividing a machine-wide denominator by a
30
+ * repository-scoped numerator is the defect this flag exists to make visible.
31
+ *
32
+ * ## Populations
33
+ *
34
+ * Per the unanimous AI-council resolution of `measurement-population-default-off`
35
+ * (option c), two install populations are reported and neither is "the" capture
36
+ * rate:
37
+ *
38
+ * - **default** — settings as shipped; `hooks.runtime_journal.enabled`
39
+ * absent, resolving to false.
40
+ * - **opted-in** — `hooks.runtime_journal.enabled: true`.
41
+ *
42
+ * The script reports which one the measured machine is actually in, and
43
+ * censuses the settings layers rather than assuming. A population with no
44
+ * opted-in layer is reported as measured-empty, never as 0 %.
45
+ *
46
+ * Usage:
47
+ * measure_host_capture # human-readable
48
+ * measure_host_capture --json # machine-readable
49
+ * measure_host_capture --days 30 # window length in CALENDAR
50
+ * # days, inclusive both ends
51
+ * # (default 30 — the journal's
52
+ * # retention TTL)
53
+ * measure_host_capture --scope machine # widen the denominator, and
54
+ * # label the rate unmatched
55
+ * measure_host_capture --projects-root P # override ~/.claude/projects
56
+ */
57
+
58
+ import * as fs from 'node:fs';
59
+ import * as os from 'node:os';
60
+ import * as path from 'node:path';
61
+ import { fileURLToPath } from 'node:url';
62
+
63
+ import {
64
+ accumulate,
65
+ COUNTED_EVENTS,
66
+ countTranscriptFile,
67
+ DENOMINATOR_SCOPES,
68
+ type DenominatorScope,
69
+ emptyDenominator,
70
+ findTranscripts,
71
+ type HostDenominator,
72
+ JOURNAL_BOUND_COUNTED_EVENTS,
73
+ RECONSTRUCTION_RULE_VERSION,
74
+ repositoryScopeSlugs,
75
+ STOP_CANDIDATES,
76
+ totalCountedEvents,
77
+ totalJournalBoundEvents,
78
+ } from './_lib/host_denominator.js';
79
+ import {
80
+ isJournalAvailable,
81
+ openJournal,
82
+ resolveJournal,
83
+ RETENTION_TTL_DAYS,
84
+ } from './_lib/runtime_journal.js';
85
+
86
+ /** Why a numerator is what it is. A blind zero is what this enum prevents. */
87
+ export type NumeratorStatus =
88
+ | 'counted'
89
+ | 'store-absent'
90
+ | 'sqlite-unavailable'
91
+ | 'store-unreadable';
92
+
93
+ /**
94
+ * The settings layers a hook on this machine would consult for
95
+ * `hooks.runtime_journal.enabled`, and what each one says.
96
+ *
97
+ * A census of LAYERS, and the field names say so. v1 called them `observable` /
98
+ * `opted_in` and the evidence page published them as "installs", which is a
99
+ * different unit: one machine carrying both a project and a user-global layer
100
+ * would have reported two installs (R2 finding 7).
101
+ *
102
+ * `parse_failed` exists because a non-match used to be indistinguishable from
103
+ * "key absent", and both resolved silently toward the `default` population
104
+ * label that both published captions rest on (R2 finding 4).
105
+ */
106
+ export interface LayerCensus {
107
+ /** Settings files present and readable. */
108
+ layers_present: number;
109
+ /** Of those, how many carry the key at all. */
110
+ layers_with_key: number;
111
+ /** Of those, how many set it `true`. */
112
+ layers_enabled: number;
113
+ /** Files that were readable but whose `hooks:` block could not be parsed. */
114
+ layers_parse_failed: number;
115
+ /** The resolved value — the first layer that carries the key wins. */
116
+ resolved_enabled: boolean;
117
+ /** True when no layer carries the key, so the shipped default applies. */
118
+ resolved_from_default: boolean;
119
+ }
120
+
121
+ export interface CaptureMeasurement {
122
+ measured_on: string;
123
+ window_days: number;
124
+ denominator: HostDenominator;
125
+ /** Worktrees the repository scope resolved to. 0 means an empty scope. */
126
+ scope_worktrees: number;
127
+ denominator_scope: DenominatorScope;
128
+ /** False when the denominator's scope cannot be divided by this numerator. */
129
+ scope_matches_numerator: boolean;
130
+ /** Which install population the measured machine is in. */
131
+ measured_population: 'default' | 'opted-in';
132
+ layers: LayerCensus;
133
+ numerator_status: NumeratorStatus;
134
+ /** Journal records in-window on the six counted cells. */
135
+ numerator_counted_cells: number;
136
+ /** Journal records in-window on the five journal-bound counted cells. */
137
+ numerator_journal_bound_cells: number;
138
+ /** All in-window journal records, on any event. Context, not the numerator. */
139
+ numerator_all_events: number;
140
+ }
141
+
142
+ function isoDay(d: Date): string {
143
+ return d.toISOString().slice(0, 10);
144
+ }
145
+
146
+ /**
147
+ * Parse one settings file for `hooks.runtime_journal.enabled`.
148
+ *
149
+ * Anchored to the `hooks:` parent and tolerant of any consistent indentation,
150
+ * because v1 hard-coded 2-space / 4-space nesting and matched a
151
+ * `runtime_journal:` under any section at all. Returns `null` when the key is
152
+ * absent and `'parse-failed'` when a `hooks:` block exists but no verdict could
153
+ * be read from it — the two are different facts and v1 reported them the same.
154
+ */
155
+ export function readJournalKey(text: string): boolean | null | 'parse-failed' {
156
+ const lines = text.split('\n');
157
+ const hooksAt = lines.findIndex((l) => /^hooks:\s*$/.test(l));
158
+ if (hooksAt === -1) return null;
159
+
160
+ let sectionIndent: number | null = null;
161
+ let inSection = false;
162
+ for (let i = hooksAt + 1; i < lines.length; i++) {
163
+ const line = lines[i] ?? '';
164
+ if (line.trim().length === 0 || line.trimStart().startsWith('#')) continue;
165
+ const indent = line.length - line.trimStart().length;
166
+ if (indent === 0) break; // out of the `hooks:` block
167
+
168
+ if (/^runtime_journal:\s*$/.test(line.trim())) {
169
+ inSection = true;
170
+ sectionIndent = indent;
171
+ continue;
172
+ }
173
+ if (!inSection) continue;
174
+ if (sectionIndent !== null && indent <= sectionIndent) {
175
+ // Left the `runtime_journal:` block without finding the key.
176
+ return 'parse-failed';
177
+ }
178
+ const m = line.trim().match(/^enabled:\s*(\S+)/);
179
+ if (m) return (m[1] ?? '').trim() === 'true';
180
+ }
181
+ return inSection ? 'parse-failed' : null;
182
+ }
183
+
184
+ function layerCensus(root: string): LayerCensus {
185
+ const candidates = [
186
+ path.join(root, '.agent-settings.yml'),
187
+ path.join(os.homedir(), '.event4u', 'agent-config', 'settings', '.agent-settings.yml'),
188
+ ];
189
+ const census: LayerCensus = {
190
+ layers_present: 0,
191
+ layers_with_key: 0,
192
+ layers_enabled: 0,
193
+ layers_parse_failed: 0,
194
+ resolved_enabled: false,
195
+ resolved_from_default: true,
196
+ };
197
+ for (const file of candidates) {
198
+ let text: string;
199
+ try {
200
+ text = fs.readFileSync(file, 'utf8');
201
+ } catch {
202
+ continue;
203
+ }
204
+ census.layers_present += 1;
205
+ const verdict = readJournalKey(text);
206
+ if (verdict === 'parse-failed') {
207
+ census.layers_parse_failed += 1;
208
+ continue;
209
+ }
210
+ if (verdict === null) continue;
211
+ census.layers_with_key += 1;
212
+ if (verdict) census.layers_enabled += 1;
213
+ if (census.resolved_from_default) {
214
+ census.resolved_enabled = verdict;
215
+ census.resolved_from_default = false;
216
+ }
217
+ }
218
+ return census;
219
+ }
220
+
221
+ export async function measure(options: {
222
+ root: string;
223
+ projectsRoot: string;
224
+ days: number;
225
+ scope?: DenominatorScope;
226
+ now?: Date;
227
+ }): Promise<CaptureMeasurement> {
228
+ const scope = options.scope ?? 'repository';
229
+ const now = options.now ?? new Date();
230
+ const windowEnd = isoDay(now);
231
+ // `days - 1`: both comparisons are inclusive, so `--days 30` must span 30
232
+ // calendar days and not 31. v1 spanned 31 while the caption said 30, which
233
+ // gave the denominator one day the numerator's TTL cannot retain (R2
234
+ // finding 3).
235
+ const windowStart = isoDay(new Date(now.getTime() - (options.days - 1) * 86_400_000));
236
+
237
+ const repoScope = scope === 'repository' ? repositoryScopeSlugs(options.root) : null;
238
+ const walk = findTranscripts(options.projectsRoot, repoScope?.slugs);
239
+
240
+ const denominator = emptyDenominator(windowStart, windowEnd, scope);
241
+ denominator.transcripts_out_of_scope = walk.outOfScope;
242
+ denominator.unreadable_directories = walk.unreadable;
243
+ for (const file of walk.files) {
244
+ accumulate(denominator, await countTranscriptFile(file), windowStart, windowEnd);
245
+ }
246
+
247
+ const layers = layerCensus(options.root);
248
+ const measured_population = layers.resolved_enabled ? 'opted-in' : 'default';
249
+
250
+ let numerator_status: NumeratorStatus = 'counted';
251
+ let counted = 0;
252
+ let bound = 0;
253
+ let all = 0;
254
+
255
+ const location = resolveJournal(options.root);
256
+ if (!fs.existsSync(location.path)) {
257
+ numerator_status = 'store-absent';
258
+ } else if (!isJournalAvailable()) {
259
+ numerator_status = 'sqlite-unavailable';
260
+ } else {
261
+ try {
262
+ const handle = openJournal(options.root);
263
+ try {
264
+ // Windowed in SQL rather than by materialising the whole table
265
+ // and filtering in JS (R2 finding 17). `substr(at, 1, 10)` is
266
+ // the same day-string comparison the denominator uses, so the
267
+ // two sides window identically.
268
+ const rows = handle.db
269
+ .prepare(
270
+ `SELECT event, COUNT(*) AS n FROM journal_event
271
+ WHERE repository_id = ?
272
+ AND substr(at, 1, 10) >= ?
273
+ AND substr(at, 1, 10) <= ?
274
+ GROUP BY event`,
275
+ )
276
+ .all(location.repository_id, windowStart, windowEnd) as {
277
+ event: string;
278
+ n: number;
279
+ }[];
280
+ for (const row of rows) {
281
+ all += row.n;
282
+ if ((COUNTED_EVENTS as readonly string[]).includes(row.event)) counted += row.n;
283
+ if ((JOURNAL_BOUND_COUNTED_EVENTS as readonly string[]).includes(row.event)) {
284
+ bound += row.n;
285
+ }
286
+ }
287
+ } finally {
288
+ handle.close();
289
+ }
290
+ } catch {
291
+ numerator_status = 'store-unreadable';
292
+ // Reset, or a partial count ships as if it were counted while the
293
+ // status says it could not be read (R2 finding 5).
294
+ counted = 0;
295
+ bound = 0;
296
+ all = 0;
297
+ }
298
+ }
299
+
300
+ return {
301
+ measured_on: windowEnd,
302
+ window_days: options.days,
303
+ denominator,
304
+ scope_worktrees: repoScope?.worktrees.length ?? 0,
305
+ denominator_scope: scope,
306
+ scope_matches_numerator: scope === 'repository',
307
+ measured_population,
308
+ layers,
309
+ numerator_status,
310
+ numerator_counted_cells: counted,
311
+ numerator_journal_bound_cells: bound,
312
+ numerator_all_events: all,
313
+ };
314
+ }
315
+
316
+ function rate(numerator: number, denominator: number): string {
317
+ if (denominator === 0) return 'undefined (denominator 0)';
318
+ return `${((numerator / denominator) * 100).toFixed(2)} %`;
319
+ }
320
+
321
+ function render(m: CaptureMeasurement): string {
322
+ const d = m.denominator;
323
+ const lines: string[] = [];
324
+ lines.push(`Host capture rate — runtime event journal`);
325
+ lines.push(` measured on ............ ${m.measured_on}`);
326
+ lines.push(
327
+ ` window ................. ${d.window_start} .. ${d.window_end} (${m.window_days} calendar days, inclusive; journal TTL is ${RETENTION_TTL_DAYS})`,
328
+ );
329
+ lines.push(` reconstruction rules ... v${RECONSTRUCTION_RULE_VERSION}`);
330
+ lines.push(` platform ............... ${d.platform} (the only cell set with a host denominator)`);
331
+ lines.push(
332
+ ` denominator scope ...... ${d.scope}${m.scope_matches_numerator ? '' : ' ⚠️ UNMATCHED — a machine-wide denominator may not be divided by this repository-scoped numerator'}`,
333
+ );
334
+ if (d.scope === 'repository') {
335
+ lines.push(` worktrees in scope ..... ${m.scope_worktrees}`);
336
+ }
337
+ lines.push('');
338
+ lines.push(`Population of sessions`);
339
+ lines.push(` transcripts in scope ... ${d.transcripts_found}`);
340
+ lines.push(` project dirs skipped ... ${d.transcripts_out_of_scope} (outside the scope)`);
341
+ lines.push(` in window .............. ${d.sessions_in_window}`);
342
+ lines.push(` before window .......... ${d.sessions_before_window}`);
343
+ lines.push(` after window ........... ${d.sessions_after_window}`);
344
+ lines.push(` undatable .............. ${d.sessions_undatable}`);
345
+ lines.push(` unreadable dirs ........ ${d.unreadable_directories}`);
346
+ lines.push(` unparseable lines ...... ${d.unparseable_lines}`);
347
+ lines.push('');
348
+ lines.push(`Denominator — host events, per counted cell`);
349
+ for (const event of COUNTED_EVENTS) {
350
+ const isBound = (JOURNAL_BOUND_COUNTED_EVENTS as readonly string[]).includes(event);
351
+ lines.push(
352
+ ` ${event.padEnd(20)} ${String(d[event]).padStart(8)} ${isBound ? 'journal-bound' : 'NOT journal-bound — numerator 0 by construction'}`,
353
+ );
354
+ }
355
+ lines.push(` ${'TOTAL (6 cells)'.padEnd(20)} ${String(totalCountedEvents(d)).padStart(8)}`);
356
+ lines.push(
357
+ ` ${'TOTAL (5 bound)'.padEnd(20)} ${String(totalJournalBoundEvents(d)).padStart(8)}`,
358
+ );
359
+ lines.push(
360
+ ` of which sidechain ..... ${d.sidechain_tool_use_blocks} tool_use / ${d.sidechain_agent_tool_use_blocks} Agent-or-Task blocks (INCLUDED; subtract to disagree)`,
361
+ );
362
+ lines.push('');
363
+ lines.push(`Settings-layer census — the opted-in population, measured not assumed`);
364
+ lines.push(` layers present ......... ${m.layers.layers_present}`);
365
+ lines.push(` carrying the key ....... ${m.layers.layers_with_key}`);
366
+ lines.push(` set to true ............ ${m.layers.layers_enabled}`);
367
+ lines.push(` parse failed ........... ${m.layers.layers_parse_failed}`);
368
+ lines.push(
369
+ ` resolved from .......... ${m.layers.resolved_from_default ? 'the shipped default (no layer carries the key)' : 'an explicit layer value'}`,
370
+ );
371
+ lines.push(
372
+ ` opted-in population .... ${m.layers.layers_enabled === 0 ? 'EMPTY in measurement scope — no denominator for a rate to be over' : 'non-empty'}`,
373
+ );
374
+ lines.push('');
375
+ lines.push(`Numerator — journal records`);
376
+ lines.push(` measured population .... ${m.measured_population}`);
377
+ lines.push(` status ................. ${m.numerator_status}`);
378
+ lines.push(` on 6 counted cells ..... ${m.numerator_counted_cells}`);
379
+ lines.push(` on 5 bound cells ....... ${m.numerator_journal_bound_cells}`);
380
+ lines.push(` on any event ........... ${m.numerator_all_events}`);
381
+ lines.push(
382
+ ` host-agnostic .......... yes — \`JournalEvent\` carries no platform field, so an event`,
383
+ );
384
+ lines.push(
385
+ ` written by another bound host on this repository would count`,
386
+ );
387
+ lines.push(
388
+ ` into the numerator against a claude-only denominator`,
389
+ );
390
+ lines.push('');
391
+ lines.push(
392
+ `Rate — ${m.measured_population} install, ${d.platform}, ${d.scope} scope, ${d.window_start}..${d.window_end}`,
393
+ );
394
+ lines.push(
395
+ ` over 6 counted cells ... ${rate(m.numerator_counted_cells, totalCountedEvents(d))}`,
396
+ );
397
+ lines.push(
398
+ ` over 5 bound cells ..... ${rate(m.numerator_journal_bound_cells, totalJournalBoundEvents(d))}`,
399
+ );
400
+ if (!m.scope_matches_numerator) {
401
+ lines.push(` ⚠️ UNMATCHED SCOPE — the two rates above are not capture rates.`);
402
+ }
403
+ lines.push('');
404
+ lines.push(`Refused denominators for \`stop\` (journal-bound, not counted)`);
405
+ for (const c of STOP_CANDIDATES) {
406
+ lines.push(` ${String(c.reading).padStart(5)} ${c.candidate}`);
407
+ }
408
+ return lines.join('\n');
409
+ }
410
+
411
+ export async function main(argv: readonly string[]): Promise<number> {
412
+ const json = argv.includes('--json');
413
+
414
+ const daysAt = argv.indexOf('--days');
415
+ const days = daysAt >= 0 ? Number(argv[daysAt + 1] ?? NaN) : RETENTION_TTL_DAYS;
416
+ if (!Number.isInteger(days) || days <= 0) {
417
+ process.stderr.write('--days must be a positive integer\n');
418
+ return 2;
419
+ }
420
+
421
+ const scopeAt = argv.indexOf('--scope');
422
+ const scopeArg = scopeAt >= 0 ? argv[scopeAt + 1] : undefined;
423
+ if (scopeAt >= 0 && !(DENOMINATOR_SCOPES as readonly string[]).includes(scopeArg ?? '')) {
424
+ process.stderr.write(`--scope must be one of ${DENOMINATOR_SCOPES.join(' | ')}\n`);
425
+ return 2;
426
+ }
427
+
428
+ const rootAt = argv.indexOf('--projects-root');
429
+ const overrideRoot = rootAt >= 0 ? argv[rootAt + 1] : undefined;
430
+ if (rootAt >= 0 && (overrideRoot === undefined || overrideRoot.startsWith('--'))) {
431
+ process.stderr.write('--projects-root needs a directory\n');
432
+ return 2;
433
+ }
434
+ const projectsRoot = overrideRoot ?? path.join(os.homedir(), '.claude', 'projects');
435
+
436
+ const measurement = await measure({
437
+ root: process.cwd(),
438
+ projectsRoot,
439
+ days,
440
+ scope: (scopeArg as DenominatorScope | undefined) ?? 'repository',
441
+ });
442
+
443
+ process.stdout.write(
444
+ json ? `${JSON.stringify(measurement, null, 2)}\n` : `${render(measurement)}\n`,
445
+ );
446
+ return 0;
447
+ }
448
+
449
+ function _isCliEntry(): boolean {
450
+ try {
451
+ const here = fs.realpathSync(fileURLToPath(import.meta.url));
452
+ const argv = fs.realpathSync(path.resolve(process.argv[1] ?? ''));
453
+ return here === argv;
454
+ } catch {
455
+ return false;
456
+ }
457
+ }
458
+
459
+ if (_isCliEntry()) {
460
+ process.exitCode = await main(process.argv.slice(2));
461
+ }
@@ -10,7 +10,7 @@
10
10
  * dashboard (default: `agents/evidence/migration-status.md`).
11
11
  *
12
12
  * Usage:
13
- * npx tsx src/scripts/migration_status.ts [--out <path>]
13
+ * npx tsx migration_status [--out <path>]
14
14
  *
15
15
  * Node builtins only — no third-party imports.
16
16
  */
@@ -240,7 +240,7 @@ function renderDashboard(
240
240
  lines.push('# Python → TypeScript Migration Status');
241
241
  lines.push('');
242
242
  lines.push(
243
- `> Generated by \`src/scripts/migration_status.ts\` — do not edit by hand. Timestamp: ${timestamp}`,
243
+ `> Generated by \`migration_status\` — do not edit by hand. Timestamp: ${timestamp}`,
244
244
  );
245
245
  lines.push('');
246
246
  lines.push(
@@ -311,7 +311,7 @@ function main(): void {
311
311
  process.stdout.write(`Tracked .py after exclusions: ${pyFiles.length}\n`);
312
312
  }
313
313
 
314
- // Run the CLI only when executed directly (`npx tsx src/scripts/migration_status.ts`),
314
+ // Run the CLI only when executed directly (`npx tsx migration_status`),
315
315
  // not when imported (e.g. by src/scripts/parity/phase_gate.ts for `categorize`).
316
316
  function _isCliEntry(): boolean {
317
317
  if (process.argv[1] === undefined) {
@@ -63,6 +63,12 @@ import {
63
63
  triggerlessRuleIds,
64
64
  type Router,
65
65
  } from './_lib/rule_injection.js';
66
+ import {
67
+ renderArmExperiment,
68
+ runArmExperiment,
69
+ type ArmName,
70
+ type ArmRow,
71
+ } from './_lib/delivery_arm_experiment.js';
66
72
  import { thin_entry } from './project_thin_rules.js';
67
73
  import { CAP_BYTES, buildInjection } from './hooks/rule_inject_hook.js';
68
74
 
@@ -802,11 +808,44 @@ export function runSelftest(corpusDir: string): SelftestCase[] {
802
808
  return out;
803
809
  }
804
810
 
811
+ /**
812
+ * Step 6.1's three-arm run, assembled from parts that already exist.
813
+ *
814
+ * The standing token figures come from `standingCorpora` — the SAME function
815
+ * the price grid reads — so the delivery table and the price table can never
816
+ * disagree about what a shape costs to stand up. `capBytes` is a parameter
817
+ * rather than a constant so the run can be shown sensitive to the mechanism it
818
+ * reports on; the default is the concern's own `CAP_BYTES`.
819
+ */
820
+ export function runThreeArm(
821
+ corpusDir: string,
822
+ capBytes: number = CAP_BYTES,
823
+ ): { rows: ArmRow[]; lines: string[] } {
824
+ const router = loadRouter(REPO_ROOT);
825
+ const cases = loadCorpus(corpusDir);
826
+ const sc = standingCorpora(router);
827
+ const standing: Record<ArmName, number> = {
828
+ 'eager-all': sc.eagerTokens,
829
+ thin: sc.thinTokens,
830
+ delivery: sc.thinTokens,
831
+ };
832
+ const rows = runArmExperiment({
833
+ repoRoot: REPO_ROOT,
834
+ router,
835
+ cases,
836
+ capBytes,
837
+ standing,
838
+ tokensOf,
839
+ });
840
+ return { rows, lines: renderArmExperiment(rows, capBytes) };
841
+ }
842
+
805
843
  // ── CLI ──────────────────────────────────────────────────────────────────
806
844
 
807
845
  const USAGE = `usage: model_rule_injection [--corpus DIR] [--baseline-comparison]
808
846
  [--honour-open-files]
809
847
  [--selftest] [--endpoints] [--json]
848
+ [--three-arm] [--cap-bytes N]
810
849
 
811
850
  Offline recall + cost model for trigger-delivered rule bodies. No metered call
812
851
  on any path.
@@ -820,6 +859,8 @@ export function main(argv: string[] | null = null): number {
820
859
  let selftest = false;
821
860
  let endpoints = false;
822
861
  let json = false;
862
+ let threeArm = false;
863
+ let capBytes = CAP_BYTES;
823
864
  for (let i = 0; i < args.length; i += 1) {
824
865
  const a = args[i] as string;
825
866
  if (a === '--corpus') {
@@ -835,6 +876,15 @@ export function main(argv: string[] | null = null): number {
835
876
  endpoints = true;
836
877
  } else if (a === '--json') {
837
878
  json = true;
879
+ } else if (a === '--three-arm') {
880
+ threeArm = true;
881
+ } else if (a === '--cap-bytes') {
882
+ i += 1;
883
+ capBytes = Number.parseInt(args[i] as string, 10);
884
+ if (!Number.isFinite(capBytes) || capBytes < 1) {
885
+ process.stderr.write(`model_rule_injection: --cap-bytes needs a positive integer\n`);
886
+ return 2;
887
+ }
838
888
  } else if (a === '-h' || a === '--help') {
839
889
  process.stdout.write(USAGE);
840
890
  return 0;
@@ -844,6 +894,16 @@ export function main(argv: string[] | null = null): number {
844
894
  }
845
895
  }
846
896
 
897
+ if (threeArm) {
898
+ const res = runThreeArm(corpus, capBytes);
899
+ if (json) {
900
+ process.stdout.write(`${JSON.stringify(res.rows, null, 2)}\n`);
901
+ } else {
902
+ process.stdout.write(`${res.lines.join('\n')}\n`);
903
+ }
904
+ return 0;
905
+ }
906
+
847
907
  if (selftest) {
848
908
  const results = runSelftest(corpus);
849
909
  const failed = results.filter((r) => !r.passed);
@@ -127,6 +127,20 @@ export function main(argv: string[] = process.argv.slice(2)): number {
127
127
  tier_source: str(flags, 'tier-source') as TierSource | undefined,
128
128
  task_class: str(flags, 'task-class'),
129
129
  dispatch_mode: str(flags, 'dispatch-mode') as never,
130
+ // `--skills-applied=a,b` records ids; `--skills-applied=` (empty)
131
+ // records the EMPTY array, which is a real observation ("none
132
+ // applied") and deliberately not the same as omitting the flag
133
+ // ("not recorded"). The empty-string check therefore cannot be folded
134
+ // into the `?.split()` chain above, which would map both onto
135
+ // undefined and destroy the distinction the field exists for.
136
+ expected_output: str(flags, 'expected-output') as never,
137
+ diff_lines: int(flags, 'diff-lines'),
138
+ empty_cycles: int(flags, 'empty-cycles'),
139
+ skills_applied: (() => {
140
+ const raw = str(flags, 'skills-applied');
141
+ if (raw === undefined) return undefined;
142
+ return raw.split(',').map((v) => v.trim()).filter(Boolean);
143
+ })(),
130
144
  task_size_estimate: int(flags, 'task-size-estimate'),
131
145
  wall_clock_ms: int(flags, 'wall-clock-ms'),
132
146
  dispatch_tokens: int(flags, 'dispatch-tokens'),