@event4u/agent-config 14.12.0 → 14.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (521) hide show
  1. package/.augment-plugin/marketplace.json +3 -3
  2. package/.augment-plugin/plugin.json +1 -1
  3. package/.claude-plugin/marketplace.json +1 -1
  4. package/CHANGELOG.md +118 -155
  5. package/CONTRIBUTING.md +38 -0
  6. package/CREDITS.md +135 -0
  7. package/NOTICE +13 -0
  8. package/README.md +8 -6
  9. package/dist/agent-src/commands/analyze/inbox.md +145 -2
  10. package/dist/agent-src/commands/feature/dev.md +7 -2
  11. package/dist/agent-src/commands/ghostwriter/write.md +5 -1
  12. package/dist/agent-src/commands/implement-ticket.md +1 -1
  13. package/dist/agent-src/commands/mission/upgrade.md +1 -1
  14. package/dist/agent-src/commands/orchestrate.md +2 -2
  15. package/dist/agent-src/commands/post-as/me.md +5 -1
  16. package/dist/agent-src/commands/pr/merge.md +19 -6
  17. package/dist/agent-src/commands/roadmap/process-full.md +19 -5
  18. package/dist/agent-src/commands/tdd/red.md +12 -2
  19. package/dist/agent-src/commands/work.md +1 -1
  20. package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +40 -0
  21. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +5 -2
  22. package/dist/agent-src/contexts/execution/autonomy-mechanics.md +21 -0
  23. package/dist/agent-src/contexts/execution/orchestration-telemetry.md +1 -0
  24. package/dist/agent-src/contexts/execution/subagent-response-contract.md +40 -0
  25. package/dist/agent-src/contexts/execution/subagent-steering.md +13 -1
  26. package/dist/agent-src/contexts/execution/terminal-states.md +96 -0
  27. package/dist/agent-src/rules/artifact-drafting-protocol.md +1 -1
  28. package/dist/agent-src/rules/broken-access-control.md +4 -0
  29. package/dist/agent-src/rules/code-comment-discipline.md +6 -0
  30. package/dist/agent-src/rules/code-provenance.md +4 -0
  31. package/dist/agent-src/rules/design-fidelity.md +1 -1
  32. package/dist/agent-src/rules/domain-safety-pii.md +4 -0
  33. package/dist/agent-src/rules/domain-safety-retention.md +4 -0
  34. package/dist/agent-src/rules/engineering-safety-floor.md +2 -0
  35. package/dist/agent-src/rules/external-code-graph-interop.md +14 -12
  36. package/dist/agent-src/rules/improve-before-implement.md +6 -8
  37. package/dist/agent-src/rules/laravel-routing.md +1 -1
  38. package/dist/agent-src/rules/lethal-trifecta-guard.md +4 -0
  39. package/dist/agent-src/rules/secret-vcs-guard.md +2 -0
  40. package/dist/agent-src/rules/security-sensitive-stop.md +2 -0
  41. package/dist/agent-src/rules/source-confidentiality.md +12 -34
  42. package/dist/agent-src/rules/symfony-routing.md +1 -1
  43. package/dist/agent-src/rules/token-efficiency.md +14 -0
  44. package/dist/agent-src/rules/tool-safety.md +4 -0
  45. package/dist/agent-src/rules/untrusted-input-defense.md +4 -0
  46. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +252 -8
  47. package/dist/agent-src/scripts/guarded_baseline.ts +343 -0
  48. package/dist/agent-src/scripts/roadmap_set_step.ts +253 -0
  49. package/dist/agent-src/scripts/stub_queue.ts +82 -0
  50. package/dist/agent-src/scripts/stubs_due.ts +516 -0
  51. package/dist/agent-src/scripts/ticket_bundles.ts +84 -0
  52. package/dist/agent-src/scripts/update_roadmap_progress.ts +16 -12
  53. package/dist/agent-src/skills/brand-asset-generation/SKILL.md +17 -4
  54. package/dist/agent-src/skills/brand-audit/SKILL.md +33 -0
  55. package/dist/agent-src/skills/code-intelligence/SKILL.md +57 -0
  56. package/dist/agent-src/skills/database/SKILL.md +8 -0
  57. package/dist/agent-src/skills/dependency-upgrade/SKILL.md +27 -0
  58. package/dist/agent-src/skills/design-review/SKILL.md +1 -1
  59. package/dist/agent-src/skills/doc-coauthoring/SKILL.md +1 -1
  60. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +17 -1
  61. package/dist/agent-src/skills/feature-planning/SKILL.md +9 -2
  62. package/dist/agent-src/skills/frontend-render-security/SKILL.md +44 -0
  63. package/dist/agent-src/skills/git-workflow/SKILL.md +1 -1
  64. package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.ts +38 -4
  65. package/dist/agent-src/skills/judge-artifact-completeness/rubrics/ticket-quality-score.json +2 -2
  66. package/dist/agent-src/skills/laravel/SKILL.md +35 -0
  67. package/dist/agent-src/skills/laravel-migration/SKILL.md +57 -3
  68. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +26 -0
  69. package/dist/agent-src/skills/playbook-authoring/SKILL.md +28 -1
  70. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +1 -1
  71. package/dist/agent-src/skills/skill-writing/references/procedure.md +5 -5
  72. package/dist/agent-src/skills/sql-writing/SKILL.md +7 -1
  73. package/dist/agent-src/skills/standards-from-config/SKILL.md +27 -4
  74. package/dist/agent-src/skills/supply-chain-intake/SKILL.md +11 -4
  75. package/dist/agent-src/skills/symfony-workflow/SKILL.md +35 -0
  76. package/dist/agent-src/skills/test-case-discovery/SKILL.md +85 -0
  77. package/dist/agent-src/skills/test-driven-development/SKILL.md +33 -9
  78. package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
  79. package/dist/agent-src/skills/testing-anti-patterns/process-anti-patterns.md +37 -0
  80. package/dist/agent-src/skills/ui-component-architect/SKILL.md +45 -2
  81. package/dist/agent-src/skills/upstream-contribute/SKILL.md +38 -1
  82. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +9 -4
  83. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  84. package/dist/agent-src/templates/roadmaps.md +97 -3
  85. package/dist/agent-src/templates/scripts/check_memory.ts +258 -17
  86. package/dist/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
  87. package/dist/agent-src/templates/scripts/memory_lookup.ts +86 -0
  88. package/dist/agent-src/templates/scripts/memory_signal.ts +44 -0
  89. package/dist/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
  90. package/dist/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
  91. package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
  92. package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
  93. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
  94. package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
  95. package/dist/cli/commands/uiAudit.js +124 -5
  96. package/dist/cli/registry.js +2 -0
  97. package/dist/cli-delegate/{chunk-HYWSRNUX.js → chunk-2DK2VJWG.js} +3 -3
  98. package/dist/cli-delegate/{chunk-JCW7ZLHK.js → chunk-4FS4WRXP.js} +5 -0
  99. package/dist/cli-delegate/{chunk-OMIVVCG2.js → chunk-A4QJ6ENT.js} +24 -0
  100. package/dist/cli-delegate/{chunk-JJA2QEWA.js → chunk-AKJGUQNO.js} +466 -285
  101. package/dist/cli-delegate/{chunk-E46KPN6K.js → chunk-BTWUYDGN.js} +424 -363
  102. package/dist/cli-delegate/{chunk-K4FFODTS.js → chunk-ILMUPLGW.js} +1227 -316
  103. package/dist/cli-delegate/{chunk-FF7WAFMR.js → chunk-KPBWFOPZ.js} +5 -1
  104. package/dist/cli-delegate/cmd_adr_effective.js +102 -0
  105. package/dist/cli-delegate/cmd_conformance.js +80 -11
  106. package/dist/cli-delegate/cmd_doctor.js +3 -3
  107. package/dist/cli-delegate/cmd_export.js +3 -2
  108. package/dist/cli-delegate/cmd_fleet.js +2 -2
  109. package/dist/cli-delegate/cmd_handoff.js +1 -1
  110. package/dist/cli-delegate/cmd_preflight.js +2 -2
  111. package/dist/cli-delegate/cmd_prune.js +3 -2
  112. package/dist/cli-delegate/cmd_settings_get.js +1 -1
  113. package/dist/cli-delegate/cmd_settings_migrate.js +3 -2
  114. package/dist/cli-delegate/cmd_settings_set.js +2 -2
  115. package/dist/cli-delegate/cmd_sync.js +3 -2
  116. package/dist/cli-delegate/cmd_uninstall.js +3 -2
  117. package/dist/cli-delegate/cmd_validate.js +3 -2
  118. package/dist/discovery/deprecation-report.md +1 -1
  119. package/dist/discovery/discovery-manifest.json +58 -58
  120. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  121. package/dist/discovery/discovery-manifest.summary.md +1 -1
  122. package/dist/discovery/dormancy-report.md +1 -1
  123. package/dist/discovery/orphan-report.md +1 -1
  124. package/dist/discovery/packs.json +2 -2
  125. package/dist/discovery/trust-report.md +1 -1
  126. package/dist/discovery/workspaces.json +2 -2
  127. package/dist/hooks/dispatch.js +2900 -1049
  128. package/dist/install/claudeRuleRewrite.js +254 -0
  129. package/dist/install/detect.js +29 -16
  130. package/dist/install/detect_php_shape.js +159 -0
  131. package/dist/install/install.mjs +634 -428
  132. package/dist/mcp/awesome-mcp-servers.row.md +1 -1
  133. package/dist/mcp/mcp-cloudflare-catalogue.json +1 -1
  134. package/dist/mcp/registry-manifest.json +3 -3
  135. package/dist/mcp/server.json +3 -3
  136. package/dist/mcp/server.mjs +4895 -2627
  137. package/dist/server/schemas/settings.js +3 -0
  138. package/dist/ui/assets/index-D0jaCRPM.js +29 -0
  139. package/dist/ui/index.html +1 -1
  140. package/docs/MIGRATION.md +1 -1
  141. package/docs/THIRD-PARTY-NOTICES.md +25 -0
  142. package/docs/contracts/provider-lifecycle.md +1 -1
  143. package/docs/contracts/settings-classes.md +10 -4
  144. package/docs/guidelines/agent-infra/5w2h-analysis.md +3 -3
  145. package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +1 -0
  146. package/docs/guidelines/agent-infra/artifact-drafting-protocol-mechanics.md +58 -3
  147. package/docs/guidelines/agent-infra/ask-when-uncertain-demos.md +2 -2
  148. package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +3 -3
  149. package/docs/guidelines/agent-infra/break-glass-usage.md +7 -7
  150. package/docs/guidelines/agent-infra/carve-out-predicates.md +3 -3
  151. package/docs/guidelines/agent-infra/comparison-matrix.md +1 -1
  152. package/docs/guidelines/agent-infra/critical-thinking.md +4 -4
  153. package/docs/guidelines/agent-infra/direct-answers-demos.md +2 -2
  154. package/docs/guidelines/agent-infra/domain-eval-anti-pattern.md +1 -1
  155. package/docs/guidelines/agent-infra/engineering-memory-data-format.md +3 -3
  156. package/docs/guidelines/agent-infra/existence-question-verdicts.md +80 -0
  157. package/docs/guidelines/agent-infra/first-principles.md +2 -2
  158. package/docs/guidelines/agent-infra/framework-neutrality-patterns.md +2 -2
  159. package/docs/guidelines/agent-infra/guarded-baseline.md +39 -0
  160. package/docs/guidelines/agent-infra/inversion-thinking.md +5 -5
  161. package/docs/guidelines/agent-infra/language-and-tone-examples.md +1 -1
  162. package/docs/guidelines/agent-infra/layered-settings.md +10 -10
  163. package/docs/guidelines/agent-infra/memory-access.md +1 -1
  164. package/docs/guidelines/agent-infra/mental-models.md +3 -3
  165. package/docs/guidelines/agent-infra/reuse-verdict-mechanics.md +71 -0
  166. package/docs/guidelines/agent-infra/review-routing-data-format.md +7 -7
  167. package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +13 -7
  168. package/docs/guidelines/agent-infra/role-contracts.md +2 -2
  169. package/docs/guidelines/agent-infra/role-mode-router.md +3 -3
  170. package/docs/guidelines/agent-infra/rule-type-governance.md +2 -2
  171. package/docs/guidelines/agent-infra/scqa-framework.md +5 -5
  172. package/docs/guidelines/agent-infra/self-improvement-pipeline.md +6 -6
  173. package/docs/guidelines/agent-infra/simplicity-and-goal-demos.md +2 -2
  174. package/docs/guidelines/agent-infra/six-hats.md +3 -3
  175. package/docs/guidelines/agent-infra/skill-quality-checklist.md +6 -6
  176. package/docs/guidelines/agent-infra/source-confidentiality-mechanics.md +109 -0
  177. package/docs/guidelines/agent-infra/systems-thinking.md +1 -1
  178. package/docs/guidelines/agent-infra/verify-before-complete-demos.md +2 -2
  179. package/docs/guidelines/augment-portability-patterns.md +6 -4
  180. package/docs/guidelines/code-clarity.md +18 -0
  181. package/docs/guidelines/component-oriented-and-oop-development.md +3 -2
  182. package/docs/guidelines/cross-role-handoff.md +2 -2
  183. package/docs/guidelines/design-fidelity-mechanics.md +1 -1
  184. package/docs/guidelines/docs/readme-size-and-splitting.md +3 -3
  185. package/docs/guidelines/php/database.md +90 -7
  186. package/docs/guidelines/prompt-templates.md +7 -7
  187. package/llms.txt +2 -2
  188. package/package.json +5 -2
  189. package/src/agent-src/scripts/archive_completed_roadmaps.ts +252 -8
  190. package/src/agent-src/scripts/guarded_baseline.ts +343 -0
  191. package/src/agent-src/scripts/roadmap_set_step.ts +253 -0
  192. package/src/agent-src/scripts/stub_queue.ts +82 -0
  193. package/src/agent-src/scripts/stubs_due.ts +516 -0
  194. package/src/agent-src/scripts/ticket_bundles.ts +84 -0
  195. package/src/agent-src/scripts/update_roadmap_progress.ts +16 -12
  196. package/src/agent-src/templates/scripts/check_memory.ts +258 -17
  197. package/src/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
  198. package/src/agent-src/templates/scripts/memory_lookup.ts +86 -0
  199. package/src/agent-src/templates/scripts/memory_signal.ts +44 -0
  200. package/src/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
  201. package/src/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
  202. package/src/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
  203. package/src/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
  204. package/src/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
  205. package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
  206. package/src/config/agent-settings.template.yml +32 -3
  207. package/src/config/assurance-capability-registry.json +21 -9
  208. package/src/config/canonical-terms.yml +119 -0
  209. package/src/config/capability-native-outcome-bars.json +81 -0
  210. package/src/config/ci-local-parity.yml +80 -0
  211. package/src/config/drafting-channels.yml +43 -0
  212. package/src/config/estate-count-budget.json +57 -36
  213. package/src/config/evaluator-budgets.json +14 -14
  214. package/src/config/gate-coverage.yml +729 -63
  215. package/src/config/gate-reachability-exemptions.json +21 -0
  216. package/src/config/gate-violation-baselines.json +42 -19
  217. package/src/config/harness-evolution-budget.json +25 -0
  218. package/src/config/lapsed-beta-baseline.json +96 -0
  219. package/src/config/memory-twin-verdicts.yml +129 -0
  220. package/src/config/metric-registry.yml +124 -0
  221. package/src/config/pack-size-budget.json +16 -15
  222. package/src/config/preamble-payload-budget.json +12 -4
  223. package/src/config/profiles/balanced.ini +27 -0
  224. package/src/config/profiles/full.ini +27 -0
  225. package/src/config/profiles/minimal.ini +27 -0
  226. package/src/config/publish-surface.json +9 -2
  227. package/src/config/routing-coverage-seed.json +16 -2
  228. package/src/config/rule-stub-ceilings.json +133 -112
  229. package/src/config/turnaround-budget.json +66 -0
  230. package/src/install/claudeRuleRewrite.ts +288 -0
  231. package/src/install/detect.ts +60 -17
  232. package/src/install/detect_php_shape.ts +191 -0
  233. package/src/scripts/_cli/cmd_doctor.ts +27 -112
  234. package/src/scripts/_dispatch.bash +23 -0
  235. package/src/scripts/_lib/activation_ladder.ts +255 -0
  236. package/src/scripts/_lib/activation_receipt_producer.ts +341 -0
  237. package/src/scripts/_lib/activation_states.ts +88 -0
  238. package/src/scripts/_lib/adherence_detectors.ts +143 -0
  239. package/src/scripts/_lib/adr_frontmatter.ts +26 -0
  240. package/src/scripts/_lib/arith_claims.ts +181 -0
  241. package/src/scripts/_lib/arm_ranking.ts +62 -0
  242. package/src/scripts/_lib/asset_delivery_ledger.ts +303 -0
  243. package/src/scripts/_lib/audit_field_provenance.ts +54 -0
  244. package/src/scripts/_lib/auto_dispatch.ts +32 -3
  245. package/src/scripts/_lib/bench_ab_size_claim.ts +98 -4
  246. package/src/scripts/_lib/benchmark_cache_fields.ts +158 -0
  247. package/src/scripts/_lib/candidate_pair_delta.ts +349 -0
  248. package/src/scripts/_lib/candidate_proposer.ts +402 -0
  249. package/src/scripts/_lib/candidate_record.ts +601 -0
  250. package/src/scripts/_lib/capture_rate.ts +319 -0
  251. package/src/scripts/_lib/carrier_status.ts +118 -0
  252. package/src/scripts/_lib/cascade_stage_enumeration.ts +92 -0
  253. package/src/scripts/_lib/collector_denominator.ts +771 -0
  254. package/src/scripts/_lib/collector_record.ts +340 -0
  255. package/src/scripts/_lib/collector_store.ts +664 -0
  256. package/src/scripts/_lib/collector_supervision.ts +827 -0
  257. package/src/scripts/_lib/concern_estate.ts +77 -0
  258. package/src/scripts/_lib/config_chain.ts +477 -0
  259. package/src/scripts/_lib/config_cost.ts +209 -0
  260. package/src/scripts/_lib/corpus_manifest.ts +726 -0
  261. package/src/scripts/_lib/council_settings_block.ts +6 -0
  262. package/src/scripts/_lib/curator_ops.ts +172 -0
  263. package/src/scripts/_lib/delivery_arm_experiment.ts +282 -0
  264. package/src/scripts/_lib/delivery_criticality.ts +126 -0
  265. package/src/scripts/_lib/doctor_runtime_checks.ts +70 -0
  266. package/src/scripts/_lib/empty_cycles.ts +88 -0
  267. package/src/scripts/_lib/estate_carrier_cases.ts +72 -0
  268. package/src/scripts/_lib/eval_publication.ts +354 -0
  269. package/src/scripts/_lib/evaluation_cascade.ts +452 -0
  270. package/src/scripts/_lib/evaluation_vector.ts +283 -0
  271. package/src/scripts/_lib/evaluator_promotion.ts +225 -0
  272. package/src/scripts/_lib/evidence_basis.ts +118 -0
  273. package/src/scripts/_lib/evolution_roi.ts +562 -0
  274. package/src/scripts/_lib/exec_evidence.ts +8 -0
  275. package/src/scripts/_lib/experience_card.ts +272 -0
  276. package/src/scripts/_lib/experience_report.ts +151 -0
  277. package/src/scripts/_lib/experiment_freeze.ts +112 -0
  278. package/src/scripts/_lib/generated_by.ts +66 -0
  279. package/src/scripts/_lib/harness_evolution_guards.ts +239 -0
  280. package/src/scripts/_lib/hook_effect_probe.ts +141 -0
  281. package/src/scripts/_lib/host_denominator.ts +687 -0
  282. package/src/scripts/_lib/host_projection_reach.ts +157 -0
  283. package/src/scripts/_lib/ignored_blocker.ts +148 -0
  284. package/src/scripts/_lib/install_reach_checks.ts +495 -0
  285. package/src/scripts/_lib/json_duplicate_keys.ts +150 -0
  286. package/src/scripts/_lib/judge_hygiene.ts +228 -0
  287. package/src/scripts/_lib/legacy_boundary_map.ts +228 -0
  288. package/src/scripts/_lib/lexical_shortlist.ts +215 -0
  289. package/src/scripts/_lib/llm_candidate_proposer.ts +461 -0
  290. package/src/scripts/_lib/llm_proposer_transport.ts +153 -0
  291. package/src/scripts/_lib/loop_guards.ts +299 -0
  292. package/src/scripts/_lib/loss_class.ts +129 -0
  293. package/src/scripts/_lib/machine_wake.ts +51 -0
  294. package/src/scripts/_lib/md_prose_lines.ts +177 -0
  295. package/src/scripts/_lib/minimality_tiebreak.ts +168 -0
  296. package/src/scripts/_lib/one_resolver_invariant.ts +449 -0
  297. package/src/scripts/_lib/orchestration_record.ts +253 -5
  298. package/src/scripts/_lib/outcome_envelope.ts +227 -0
  299. package/src/scripts/_lib/outcome_vocabularies.ts +125 -0
  300. package/src/scripts/_lib/paired_stats.ts +245 -0
  301. package/src/scripts/_lib/paired_verdict.ts +226 -0
  302. package/src/scripts/_lib/pathology_archive.ts +393 -0
  303. package/src/scripts/_lib/prefix_stable_surfaces.ts +123 -0
  304. package/src/scripts/_lib/privacy_class.ts +47 -0
  305. package/src/scripts/_lib/promotion_capability.ts +315 -0
  306. package/src/scripts/_lib/promotion_evidence.ts +414 -0
  307. package/src/scripts/_lib/promotion_review.ts +294 -0
  308. package/src/scripts/_lib/prompt_shape.ts +92 -0
  309. package/src/scripts/_lib/regression_neighbourhood.ts +259 -0
  310. package/src/scripts/_lib/release_highlights.ts +70 -1
  311. package/src/scripts/_lib/release_material.ts +125 -2
  312. package/src/scripts/_lib/repeated_failure.ts +105 -0
  313. package/src/scripts/_lib/repo_root.ts +111 -0
  314. package/src/scripts/_lib/review_skipped_record.ts +37 -0
  315. package/src/scripts/_lib/role_split.ts +338 -0
  316. package/src/scripts/_lib/routing_corpus.ts +307 -0
  317. package/src/scripts/_lib/routing_index_input.ts +104 -0
  318. package/src/scripts/_lib/rule_injection.ts +22 -1
  319. package/src/scripts/_lib/runtime_journal.ts +1499 -0
  320. package/src/scripts/_lib/runtime_wiring_checks.ts +430 -0
  321. package/src/scripts/_lib/semantic_noop.ts +167 -0
  322. package/src/scripts/_lib/skill_catalogue.ts +11 -1
  323. package/src/scripts/_lib/source_digest.ts +200 -0
  324. package/src/scripts/_lib/source_redact.ts +260 -0
  325. package/src/scripts/_lib/source_shape.ts +502 -0
  326. package/src/scripts/_lib/source_snapshot_dedup.ts +199 -0
  327. package/src/scripts/_lib/strip_comments.d.mts +8 -0
  328. package/src/scripts/_lib/strip_comments.mjs +65 -0
  329. package/src/scripts/_lib/test_red_state.ts +154 -0
  330. package/src/scripts/_lib/trigger_shift.ts +144 -0
  331. package/src/scripts/_lib/untrusted_content.ts +82 -7
  332. package/src/scripts/activation_receipt.ts +258 -0
  333. package/src/scripts/adoption_report.ts +1 -1
  334. package/src/scripts/adr/evidence_census.ts +1 -1
  335. package/src/scripts/adr/regenerate_index.ts +26 -2
  336. package/src/scripts/adr_cite_check.ts +164 -1
  337. package/src/scripts/ai_council/blind_review.ts +11 -1
  338. package/src/scripts/ai_council/clients.ts +4 -0
  339. package/src/scripts/ai_council/config.ts +3 -0
  340. package/src/scripts/ai_council/consensus.ts +28 -8
  341. package/src/scripts/ai_council/consensus_round.ts +226 -0
  342. package/src/scripts/ai_council/cross_exam.ts +128 -0
  343. package/src/scripts/ai_council/disagreement_signal.ts +338 -0
  344. package/src/scripts/ai_council/explain_route.ts +157 -0
  345. package/src/scripts/ai_council/information_gain.ts +293 -0
  346. package/src/scripts/ai_council/inline_findings.ts +340 -0
  347. package/src/scripts/ai_council/judge_position_bias.ts +197 -0
  348. package/src/scripts/ai_council/leakage_corpus.ts +385 -0
  349. package/src/scripts/ai_council/leakage_patterns.ts +453 -0
  350. package/src/scripts/ai_council/minority_retention.ts +171 -0
  351. package/src/scripts/ai_council/orchestrator.ts +16 -203
  352. package/src/scripts/ai_council/orchestrator_results.ts +23 -3
  353. package/src/scripts/ai_council/pricing.ts +106 -0
  354. package/src/scripts/ai_council/prompts.ts +74 -7
  355. package/src/scripts/ai_council/provider_leakage_bench.ts +327 -0
  356. package/src/scripts/ai_council/py_format.ts +14 -3
  357. package/src/scripts/ai_council/recouncil_guard.ts +293 -0
  358. package/src/scripts/ai_council/recouncil_savings.ts +299 -0
  359. package/src/scripts/ai_council/replay_route.ts +223 -0
  360. package/src/scripts/ai_council/response_record.ts +50 -0
  361. package/src/scripts/ai_council/reviewer_assignment.ts +279 -0
  362. package/src/scripts/ai_council/routing_training_row.ts +197 -0
  363. package/src/scripts/ai_council/synthesis_strategy.ts +159 -0
  364. package/src/scripts/ai_council/topology_bench_manifest.ts +860 -0
  365. package/src/scripts/ai_council/topology_vocabulary.ts +175 -0
  366. package/src/scripts/asset_delivery_ledger.ts +157 -0
  367. package/src/scripts/attest_artifact.ts +193 -0
  368. package/src/scripts/audit_auto_rules.ts +2 -1
  369. package/src/scripts/audit_command_surface.ts +1 -1
  370. package/src/scripts/audit_mcp_tools.ts +2 -2
  371. package/src/scripts/audit_skill_overlap_allowlist.json +6 -1
  372. package/src/scripts/audit_user_type_axis.ts +2 -1
  373. package/src/scripts/bench_ab_clone.ts +215 -10
  374. package/src/scripts/bench_ab_integrity.ts +119 -5
  375. package/src/scripts/bench_ab_v2_stats.ts +40 -213
  376. package/src/scripts/build_archive_index.ts +1 -1
  377. package/src/scripts/build_linear_digest.ts +1 -1
  378. package/src/scripts/build_proof.ts +11 -4
  379. package/src/scripts/build_rule_trigger_matrix.ts +1 -1
  380. package/src/scripts/build_source_digests.ts +157 -0
  381. package/src/scripts/cache_realization_report.ts +103 -0
  382. package/src/scripts/check_adr_frontmatter.ts +131 -10
  383. package/src/scripts/check_benchmark_report_fields.ts +207 -0
  384. package/src/scripts/check_beta_review_markers.ts +235 -6
  385. package/src/scripts/check_bundle_path_leakage.ts +34 -1
  386. package/src/scripts/check_claims.ts +576 -6
  387. package/src/scripts/check_composite_arming.ts +35 -0
  388. package/src/scripts/check_concern_admissions.ts +365 -0
  389. package/src/scripts/check_enforcement_coverage.ts +28 -0
  390. package/src/scripts/check_estate_count.ts +347 -25
  391. package/src/scripts/check_gate_reachability.ts +383 -0
  392. package/src/scripts/check_host_loadability.ts +104 -0
  393. package/src/scripts/check_loss_class_declared.ts +308 -0
  394. package/src/scripts/check_md_language.ts +15 -98
  395. package/src/scripts/check_memory_proposal.ts +18 -11
  396. package/src/scripts/check_no_currency_in_cost_surfaces.ts +225 -0
  397. package/src/scripts/check_no_external_sources.ts +281 -6
  398. package/src/scripts/check_pack_conformance_fixture.ts +11 -1
  399. package/src/scripts/check_pack_size.ts +59 -2
  400. package/src/scripts/check_preamble_payload_budget.ts +114 -3
  401. package/src/scripts/check_prefix_stable_mutation.ts +372 -0
  402. package/src/scripts/check_publish_surface.ts +10 -1
  403. package/src/scripts/check_references.ts +24 -1
  404. package/src/scripts/check_release_highlights.ts +96 -13
  405. package/src/scripts/check_roadmap_trackable.ts +17 -2
  406. package/src/scripts/check_rule_evidence_declaration.ts +316 -0
  407. package/src/scripts/check_rule_projection_integrity.ts +14 -4
  408. package/src/scripts/check_score_contract.ts +26 -3
  409. package/src/scripts/check_static_parity.ts +285 -0
  410. package/src/scripts/check_supervision_claim_atomicity.ts +498 -0
  411. package/src/scripts/check_suppression_hygiene.ts +15 -0
  412. package/src/scripts/ci_settle.ts +39 -2
  413. package/src/scripts/code_graph/build.ts +60 -3
  414. package/src/scripts/code_graph/extract.ts +44 -0
  415. package/src/scripts/code_graph/types.ts +24 -0
  416. package/src/scripts/collector_daemon.ts +714 -0
  417. package/src/scripts/config_cost_report.ts +302 -0
  418. package/src/scripts/consumer_matrix.ts +74 -1
  419. package/src/scripts/corpus_manifest.ts +235 -0
  420. package/src/scripts/cost/budget.mjs +10 -3
  421. package/src/scripts/cost/track.mjs +10 -3
  422. package/src/scripts/council_cli.ts +37 -54
  423. package/src/scripts/dispatch_r2_reviewer.ts +46 -5
  424. package/src/scripts/evolution_lab.ts +1153 -0
  425. package/src/scripts/external_sources_denylist.json +5 -18
  426. package/src/scripts/extract_audit_patterns.ts +21 -0
  427. package/src/scripts/fold_intake.ts +12 -1
  428. package/src/scripts/gen_discovery_baseline.ts +1 -1
  429. package/src/scripts/generate_capabilities_index.ts +12 -5
  430. package/src/scripts/generate_capability_matrix.ts +3 -3
  431. package/src/scripts/generate_command_flows.ts +2 -2
  432. package/src/scripts/generate_cookbook.ts +2 -2
  433. package/src/scripts/generate_index.ts +8 -1
  434. package/src/scripts/generate_knowledge_index.ts +2 -1
  435. package/src/scripts/generate_ownership_matrix.ts +2 -1
  436. package/src/scripts/generate_pack_manifests.ts +10 -2
  437. package/src/scripts/generate_role_experiences_catalog.ts +2 -2
  438. package/src/scripts/generate_settings_reference.ts +1 -1
  439. package/src/scripts/git_authorization_hook.ts +22 -1
  440. package/src/scripts/grade_target_readiness.ts +48 -5
  441. package/src/scripts/hook_effect_doctor.ts +261 -0
  442. package/src/scripts/hook_manifest.json +1 -1
  443. package/src/scripts/hook_manifest.yaml +125 -16
  444. package/src/scripts/hooks/block_speaking_inbox_dir.ts +271 -0
  445. package/src/scripts/hooks/block_unauthorized_git.ts +18 -0
  446. package/src/scripts/hooks/comment_discipline_hook.ts +146 -0
  447. package/src/scripts/hooks/concern_registry.ts +6 -0
  448. package/src/scripts/hooks/dispatch_hook.ts +32 -0
  449. package/src/scripts/hooks/journal_record_hook.ts +345 -0
  450. package/src/scripts/hooks/prepush_metadata_sources.sh +110 -0
  451. package/src/scripts/hooks/run_continuation_hook.ts +44 -9
  452. package/src/scripts/hooks/shims/install.sh +61 -0
  453. package/src/scripts/hooks/shims/php +101 -0
  454. package/src/scripts/hooks/suggestion_capture_hook.ts +10 -0
  455. package/src/scripts/hooks/turn_end_gate_hook.ts +9 -1
  456. package/src/scripts/hot_context_hook.ts +16 -0
  457. package/src/scripts/install-hooks.sh +20 -5
  458. package/src/scripts/install.ts +17 -35
  459. package/src/scripts/inventory_frontmatter.ts +2 -1
  460. package/src/scripts/language_mirror_hook.ts +14 -2
  461. package/src/scripts/lint_adr_sweep_routing.ts +12 -0
  462. package/src/scripts/lint_canonical_terms.ts +604 -0
  463. package/src/scripts/lint_carrier_integrity.ts +820 -0
  464. package/src/scripts/lint_code_comments.ts +643 -0
  465. package/src/scripts/lint_composition_review.ts +619 -0
  466. package/src/scripts/lint_consolidation_lineage.ts +666 -0
  467. package/src/scripts/lint_eval_specs.ts +593 -0
  468. package/src/scripts/lint_hook_manifest.ts +19 -0
  469. package/src/scripts/lint_host_portability.ts +373 -0
  470. package/src/scripts/lint_judge_prompt_expectation.ts +27 -1
  471. package/src/scripts/lint_memory_twin_parity.ts +335 -0
  472. package/src/scripts/lint_metric_consumers.ts +355 -0
  473. package/src/scripts/lint_plan_risk_register.ts +39 -19
  474. package/src/scripts/lint_promotion_paths.ts +779 -0
  475. package/src/scripts/lint_skill_descriptions.ts +18 -1
  476. package/src/scripts/lint_skill_frontmatter_safety.ts +58 -0
  477. package/src/scripts/lint_skill_link_reach.ts +252 -0
  478. package/src/scripts/lint_skill_trigger_corpus.ts +426 -23
  479. package/src/scripts/lint_ticket_buildable.ts +17 -1
  480. package/src/scripts/llm_propose.ts +256 -0
  481. package/src/scripts/mcp_server/consumer_tool_catalog.json +1 -1
  482. package/src/scripts/mcp_server/tool_catalog_source.ts +1 -1
  483. package/src/scripts/measure_delivery_sets.ts +361 -0
  484. package/src/scripts/measure_docs_dead_links.ts +348 -0
  485. package/src/scripts/measure_host_capture.ts +461 -0
  486. package/src/scripts/measure_routing_signal.ts +307 -0
  487. package/src/scripts/migration_status.ts +3 -3
  488. package/src/scripts/model_rule_injection.ts +76 -0
  489. package/src/scripts/orchestration_record.ts +14 -0
  490. package/src/scripts/preamble_byte_census.ts +139 -10
  491. package/src/scripts/prepack-check.mjs +4 -1
  492. package/src/scripts/probe_council_retention.ts +495 -0
  493. package/src/scripts/probe_turnaround.ts +384 -0
  494. package/src/scripts/probe_unblocked_ask.ts +279 -0
  495. package/src/scripts/release.ts +21 -37
  496. package/src/scripts/release_drill.ts +143 -0
  497. package/src/scripts/release_env.ts +35 -0
  498. package/src/scripts/release_publication.ts +84 -0
  499. package/src/scripts/render_benchmark_md.ts +1 -1
  500. package/src/scripts/rule_activation_census.ts +70 -9
  501. package/src/scripts/rule_backlinks.ts +1 -1
  502. package/src/scripts/run_lifecycle_suite.ts +208 -0
  503. package/src/scripts/run_skill_evals.ts +40 -0
  504. package/src/scripts/schemas/delivery-manifest.schema.json +43 -0
  505. package/src/scripts/schemas/drafting-channels.schema.json +43 -0
  506. package/src/scripts/schemas/evals.schema.json +24 -1
  507. package/src/scripts/schemas/rule.schema.json +52 -1
  508. package/src/scripts/schemas/skill.schema.json +17 -2
  509. package/src/scripts/skill_overlap.ts +7 -1
  510. package/src/scripts/skill_tools/run_block_d_eval.ts +8 -1
  511. package/src/scripts/skill_tools/score_skill_relevance.ts +84 -3
  512. package/src/scripts/skill_tools/suggest_skill_for_task.ts +8 -1
  513. package/src/scripts/skill_usage_report.ts +2 -1
  514. package/src/scripts/stubs_due.ts +211 -0
  515. package/src/scripts/sweep_source_surfaces.ts +678 -0
  516. package/src/scripts/sync_pr_branch.ts +3 -3
  517. package/src/scripts/trigger_eval_grandfather.json +202 -222
  518. package/src/scripts/utilization_report.ts +22 -2
  519. package/src/server/schemas/settings.ts +5 -0
  520. package/src/templates/marketing-copy.yml +1 -1
  521. package/dist/ui/assets/index-Cxgy63kz.js +0 -26
@@ -0,0 +1,293 @@
1
+ /**
2
+ * Expected information gain per cost — step 8.4.
3
+ *
4
+ * `road-to-inbox-harvest-2026-08-e-council-topology-evidence` step 8.4: *"Score
5
+ * optional next calls by expected information gain per cost, deterministic and
6
+ * inspectable to start"*, verified by *"the score is reproducible from the
7
+ * recorded inputs"*.
8
+ *
9
+ * ## Every feature is one the tree already computes
10
+ *
11
+ * The gain terms are read from {@link DisagreementSignal}
12
+ * (`disagreement_signal.ts:134`), which 6.1 already established as **zero-cost
13
+ * and structural** — every input arrives from a verdict the run has already
14
+ * paid for. No new similarity measure, no new threshold, no model call to
15
+ * decide whether to make a model call. Forking a second feature set here would
16
+ * be the same defect 1A.1 forbids for the question hash: two answers to one
17
+ * question, and the second is the one nobody updates.
18
+ *
19
+ * ## "Deterministic and inspectable" is enforced, not promised
20
+ *
21
+ * - {@link scoreNextCall} is pure: same record in, same bytes out.
22
+ * - Terms are summed in a FIXED declared order, so floating-point association
23
+ * cannot vary with input ordering.
24
+ * - The result carries every term's raw value, weight and contribution, so the
25
+ * number can be re-derived by hand from what is printed.
26
+ * - The published figures are rounded to {@link SCORE_PRECISION} decimals, so a
27
+ * record round-tripped through JSON reproduces bit-identically.
28
+ * - {@link reproduceScore} is the verify clause made executable: recompute from
29
+ * a record's own inputs and compare.
30
+ *
31
+ * ## What an UNAVAILABLE component does, and why it is not zero
32
+ *
33
+ * A component the run could not observe is dropped from BOTH the numerator and
34
+ * the weight denominator. Treating it as 0 would read "not measured" as
35
+ * "measured, and it showed agreement" — the same NOT-RUN-is-not-a-null failure
36
+ * this roadmap records elsewhere. `basisComponents` reports how many terms the
37
+ * gain actually rests on, so a gain over one component is distinguishable from
38
+ * a gain over five, and {@link scoreNextCall} refuses to produce a gain at all
39
+ * when nothing is available.
40
+ *
41
+ * ## Honest scope
42
+ *
43
+ * This scores; it does not decide. 8.5 — stopping when the next call has low
44
+ * expected value — is explicitly gated on Phase 2 evidence
45
+ * (`blocker: phase-2-benchmark-cost`), and the weights below are **declared
46
+ * priors, not fitted values**: nothing has been benchmarked against them.
47
+ * `revisit-if`: the Phase 2 benchmark shows a term that does not predict a
48
+ * changed finding, or shows one that does and is absent here.
49
+ */
50
+ import type { DisagreementSignal, SignalComponent } from './disagreement_signal.js';
51
+
52
+ /** Decimals every published figure is rounded to. Makes JSON round-trip exact. */
53
+ export const SCORE_PRECISION = 6;
54
+
55
+ /**
56
+ * The gain terms, in the FIXED order they are summed.
57
+ *
58
+ * `direction` says how the raw component relates to expected gain:
59
+ * `'rising'` — the component rises with DISAGREEMENT, so it is used as-is;
60
+ * `'falling'` — it rises with AGREEMENT, so `1 - value` is the gain.
61
+ *
62
+ * `weight` is a declared prior. The two divergence terms carry the most because
63
+ * an unresolved split is the one state where another call can still change the
64
+ * verdict; `selfSimilarity` is inverted and weighted low because high
65
+ * self-similarity is exhaustion, which 6.2 already treats as a stop condition
66
+ * rather than as a gain signal.
67
+ */
68
+ export const GAIN_TERMS: readonly {
69
+ readonly key: keyof DisagreementSignal & string;
70
+ readonly weight: number;
71
+ readonly direction: 'rising' | 'falling';
72
+ readonly why: string;
73
+ }[] = [
74
+ {
75
+ key: 'stanceDivergence',
76
+ weight: 0.30,
77
+ direction: 'rising',
78
+ why: 'an unresolved split is the one state where another call can still change the verdict',
79
+ },
80
+ {
81
+ key: 'contradictionCount',
82
+ weight: 0.25,
83
+ direction: 'rising',
84
+ why: 'an explicit disagree vote names a specific thing a rebuttal can settle',
85
+ },
86
+ {
87
+ key: 'rankUncertainty',
88
+ weight: 0.20,
89
+ direction: 'rising',
90
+ why: 'tied findings mean the ranking has not resolved and one more input may break it',
91
+ },
92
+ {
93
+ key: 'confidenceSpread',
94
+ weight: 0.15,
95
+ direction: 'rising',
96
+ why: 'a wide confidence range means the members disagree about how sure to be, not only about what',
97
+ },
98
+ {
99
+ key: 'findingOverlap',
100
+ weight: 0.07,
101
+ direction: 'falling',
102
+ why: 'high overlap means the members are already covering the same ground',
103
+ },
104
+ {
105
+ key: 'selfSimilarity',
106
+ weight: 0.03,
107
+ direction: 'falling',
108
+ why: 'high self-similarity is exhaustion, which 6.2 handles as a stop rather than as a gain',
109
+ },
110
+ ];
111
+
112
+ /** `contradictionCount` is a count, not 0..1; this is its saturation point. */
113
+ export const CONTRADICTION_SATURATION = 5;
114
+
115
+ /** The cost half. Both figures come from the caller's own estimate. */
116
+ export interface CallCost {
117
+ /** Provider calls the option would issue. Must be > 0 to be scorable. */
118
+ readonly calls: number;
119
+ /** Estimated spend in USD. */
120
+ readonly costUsd: number;
121
+ }
122
+
123
+ /** One scorable option, exactly as recorded. */
124
+ export interface NextCallInputs {
125
+ /** Stable identifier for the option — `cross-exam:c-001`, `round-3`, … */
126
+ readonly optionId: string;
127
+ readonly signal: DisagreementSignal;
128
+ /** Open adversarial triggers. Rising with gain: an open objection is unfinished argument. */
129
+ readonly unresolvedAdversarialTriggers: number;
130
+ readonly cost: CallCost;
131
+ }
132
+
133
+ /** One term's full arithmetic, so the total can be re-derived by hand. */
134
+ export interface TermBreakdown {
135
+ readonly key: string;
136
+ readonly available: boolean;
137
+ /** The component's raw value, or `null` when unavailable. */
138
+ readonly raw: number | null;
139
+ /** Why it is unavailable, verbatim from the signal. `null` when available. */
140
+ readonly reason: string | null;
141
+ /** Raw mapped into 0..1 gain space (direction applied, count saturated). */
142
+ readonly normalised: number | null;
143
+ readonly weight: number;
144
+ /** `normalised * weight`, or 0 when unavailable. */
145
+ readonly contribution: number;
146
+ }
147
+
148
+ export interface NextCallScore {
149
+ readonly optionId: string;
150
+ /** 0..1 expected gain, or `null` when NO component was observable. */
151
+ readonly gain: number | null;
152
+ /** How many terms the gain rests on. 0..6. */
153
+ readonly basisComponents: number;
154
+ /** Sum of the weights of the available terms — the gain's denominator. */
155
+ readonly weightUsed: number;
156
+ /** `gain / costUsd`, or `null` when gain is null or cost is not positive. */
157
+ readonly gainPerCost: number | null;
158
+ /** `gain / calls`, or `null` on the same conditions. */
159
+ readonly gainPerCall: number | null;
160
+ readonly cost: CallCost;
161
+ readonly terms: readonly TermBreakdown[];
162
+ /** The trigger bonus applied to the gain, already included in it. */
163
+ readonly triggerBonus: number;
164
+ }
165
+
166
+ /** Round to {@link SCORE_PRECISION}. `-0` normalised to `0` so JSON round-trips. */
167
+ export function roundScore(v: number): number {
168
+ const f = 10 ** SCORE_PRECISION;
169
+ const r = Math.round(v * f) / f;
170
+ return Object.is(r, -0) ? 0 : r;
171
+ }
172
+
173
+ function _normalise(key: string, c: SignalComponent, direction: 'rising' | 'falling'): number {
174
+ const raw = (c as { value: number }).value;
175
+ // `contradictionCount` is the one count-valued component; everything else
176
+ // is already 0..1 by its own contract.
177
+ const scaled = key === 'contradictionCount' ? Math.min(1, raw / CONTRADICTION_SATURATION) : Math.min(1, Math.max(0, raw));
178
+ return direction === 'rising' ? scaled : 1 - scaled;
179
+ }
180
+
181
+ /**
182
+ * Score one option. Pure — no clock, no randomness, no file, no network.
183
+ *
184
+ * The trigger bonus is additive and capped: an unresolved adversarial trigger
185
+ * raises expected gain because an open objection is unfinished argument (6.2's
186
+ * own reasoning), but it may not by itself drive the gain to 1 — that would let
187
+ * one open trigger outvote every measured component.
188
+ */
189
+ export function scoreNextCall(inputs: NextCallInputs): NextCallScore {
190
+ const terms: TermBreakdown[] = [];
191
+ let weighted = 0;
192
+ let weightUsed = 0;
193
+ let basisComponents = 0;
194
+
195
+ for (const t of GAIN_TERMS) {
196
+ const c = inputs.signal[t.key] as SignalComponent;
197
+ if (c !== undefined && c.available) {
198
+ const normalised = _normalise(t.key, c, t.direction);
199
+ const contribution = normalised * t.weight;
200
+ weighted += contribution;
201
+ weightUsed += t.weight;
202
+ basisComponents += 1;
203
+ terms.push({
204
+ key: t.key,
205
+ available: true,
206
+ raw: roundScore(c.value),
207
+ reason: null,
208
+ normalised: roundScore(normalised),
209
+ weight: t.weight,
210
+ contribution: roundScore(contribution),
211
+ });
212
+ } else {
213
+ terms.push({
214
+ key: t.key,
215
+ available: false,
216
+ raw: null,
217
+ reason: c === undefined ? 'component-absent' : c.reason,
218
+ normalised: null,
219
+ weight: t.weight,
220
+ contribution: 0,
221
+ });
222
+ }
223
+ }
224
+
225
+ const triggerBonus = roundScore(Math.min(0.2, 0.1 * Math.max(0, inputs.unresolvedAdversarialTriggers)));
226
+ const gain =
227
+ basisComponents === 0 ? null : roundScore(Math.min(1, weighted / weightUsed + triggerBonus));
228
+
229
+ const scorable = gain !== null;
230
+ return {
231
+ optionId: inputs.optionId,
232
+ gain,
233
+ basisComponents,
234
+ weightUsed: roundScore(weightUsed),
235
+ gainPerCost:
236
+ scorable && inputs.cost.costUsd > 0 ? roundScore((gain as number) / inputs.cost.costUsd) : null,
237
+ gainPerCall: scorable && inputs.cost.calls > 0 ? roundScore((gain as number) / inputs.cost.calls) : null,
238
+ cost: inputs.cost,
239
+ terms,
240
+ triggerBonus,
241
+ };
242
+ }
243
+
244
+ /** Inputs plus the score they produced — the thing 8.4 calls "the recorded inputs". */
245
+ export interface NextCallRecord {
246
+ readonly inputs: NextCallInputs;
247
+ readonly score: NextCallScore;
248
+ }
249
+
250
+ export function recordNextCall(inputs: NextCallInputs): NextCallRecord {
251
+ return { inputs, score: scoreNextCall(inputs) };
252
+ }
253
+
254
+ /**
255
+ * The verify clause, executable: recompute the score from the record's OWN
256
+ * inputs and report whether it matches byte-for-byte under JSON.
257
+ */
258
+ export function reproduceScore(record: NextCallRecord): { reproduced: boolean; recomputed: NextCallScore } {
259
+ const recomputed = scoreNextCall(record.inputs);
260
+ return { reproduced: JSON.stringify(recomputed) === JSON.stringify(record.score), recomputed };
261
+ }
262
+
263
+ /** Rank options by gain per USD, then by gain per call, then by id. Deterministic. */
264
+ export function rankByGainPerCost(scores: readonly NextCallScore[]): NextCallScore[] {
265
+ return [...scores].sort(
266
+ (a, b) =>
267
+ (b.gainPerCost ?? -1) - (a.gainPerCost ?? -1) ||
268
+ (b.gainPerCall ?? -1) - (a.gainPerCall ?? -1) ||
269
+ (a.optionId < b.optionId ? -1 : a.optionId > b.optionId ? 1 : 0),
270
+ );
271
+ }
272
+
273
+ /** Inspectable rendering — every term's arithmetic, so the total is re-derivable by hand. */
274
+ export function renderNextCallScore(s: NextCallScore): string {
275
+ const lines = [`option ${s.optionId}`];
276
+ for (const t of s.terms) {
277
+ lines.push(
278
+ t.available
279
+ ? ` ${t.key.padEnd(20)} raw ${String(t.raw).padEnd(10)} × w ${t.weight.toFixed(2)} = ${String(t.contribution)}`
280
+ : ` ${t.key.padEnd(20)} unavailable (${t.reason ?? '—'}) — excluded from numerator AND denominator`,
281
+ );
282
+ }
283
+ lines.push(
284
+ ` trigger bonus ${String(s.triggerBonus)}`,
285
+ ` weight used ${String(s.weightUsed)} over ${String(s.basisComponents)} component(s)`,
286
+ ` gain ${s.gain === null ? 'null (nothing observable)' : String(s.gain)}`,
287
+ ` cost ${String(s.cost.calls)} call(s), $${s.cost.costUsd.toFixed(4)}`,
288
+ ` gain per USD ${s.gainPerCost === null ? 'null' : String(s.gainPerCost)}`,
289
+ ` gain per call ${s.gainPerCall === null ? 'null' : String(s.gainPerCall)}`,
290
+ '',
291
+ );
292
+ return lines.join('\n');
293
+ }
@@ -0,0 +1,340 @@
1
+ // Phase 1B — inline findings, the whole concern in one module.
2
+ //
3
+ // The consensus round's pass 1 asks every member a SECOND time, in a separate
4
+ // paid call, to restate its own analysis as a JSON findings array. Phase 1B of
5
+ // `road-to-inbox-harvest-2026-08-e-council-topology-evidence` asks for that
6
+ // array in the FIRST reply instead, and keeps the extraction call as the
7
+ // repair path.
8
+ //
9
+ // It lives here rather than spread across `orchestrator.ts`, `consensus.ts` and
10
+ // `council_cli.ts` for a reason the source-size budget made concrete: all three
11
+ // are far past the 1500-line ceiling, so a new concern added to them is new
12
+ // budget excess with nowhere to go. Concentrating it also puts the four pieces
13
+ // that have to agree — the contract text's promise, the locator, the harvest
14
+ // and the config predicate — where a reader meets them together.
15
+ import type { ExternalAIClient, CouncilResponse } from './clients.js';
16
+ import type { Finding, FindingsExtraction } from './consensus.js';
17
+ import { _BARE_ARRAY_SRC, _JSON_BLOCK_SRC, parse_findings_outcome } from './consensus.js';
18
+ import { INLINE_FINDINGS_CONTRACT, STANCE_LINE_CONTRACT } from './prompts.js';
19
+
20
+ /** Python `str.strip()` parity, as everywhere else in this package. */
21
+ const _strip = (s: string): string => s.replace(/^\s+|\s+$/g, '');
22
+
23
+ /**
24
+ * Phase 1B — the deliberation reply split into argument and findings block.
25
+ *
26
+ * `deliberation_text` is what every downstream consumer should see: peer
27
+ * review, chairman synthesis, and the rendered artifact evaluate the member's
28
+ * REASONING, and a schema block restating selected conclusions is scaffolding,
29
+ * not argument. Leaving it in amplifies a concise finding simply because it
30
+ * appears twice — the AI council's stated reason (2026-08-30, 2 of 2 seats) for
31
+ * choosing to strip.
32
+ *
33
+ * `block` is the exact consumed span. One locator produces both halves, so the
34
+ * text that is parsed and the text that is removed cannot disagree — the
35
+ * council's other requirement, and the reason there is no separate
36
+ * "find and remove a JSON fence" function anywhere in this change.
37
+ */
38
+ export interface InlineFindingsSplit {
39
+ /** The reply with the consumed block removed. Equals the input when `found` is false. */
40
+ readonly deliberation_text: string;
41
+ /** The consumed span, ready for `parse_findings_outcome`. `''` when `found` is false. */
42
+ readonly block: string;
43
+ readonly found: boolean;
44
+ }
45
+
46
+ /**
47
+ * Split a full analysis reply at its TRAILING findings block.
48
+ *
49
+ * A locator, deliberately not a second parser: `parse_findings_outcome` stays
50
+ * the only thing that decides whether a candidate IS a findings block, and this
51
+ * narrows where it looks.
52
+ *
53
+ * The narrowing is not cosmetic. `_extract_json_array` returns the FIRST match,
54
+ * which is correct for an extraction reply (the reply IS the array) and wrong
55
+ * for an analysis reply, where the prose above may legitimately quote a JSON
56
+ * array — the analysis lens exists to critique analyser OUTPUT, so a quoted
57
+ * array is an ordinary thing to find there. First-match would read the quoted
58
+ * array as the member's findings and never reach the real block.
59
+ *
60
+ * `INLINE_FINDINGS_CONTRACT` asks for the block LAST, so LAST is what this
61
+ * reads. `found: false` when nothing array-shaped is present, which the caller
62
+ * treats as "no inline block" and repairs with the extraction call — the same
63
+ * outcome as today, never worse.
64
+ *
65
+ * **Precisely: "last FENCED, else last bare" — not "last in the text."** The
66
+ * two patterns are tried in `_extract_json_array`'s precedence order and the
67
+ * first pattern that matches at all wins, so a reply carrying a quoted FENCED
68
+ * array above its own trailing BARE array selects the quoted one. Stated
69
+ * because the docstring used to claim the simpler rule, which a completion
70
+ * review of 2026-08-30 found untrue against that ordering; the precedence test
71
+ * puts the bare array first and so never exercises the collision.
72
+ *
73
+ * The consequence is bounded rather than eliminated. `_isOwnFindingsBlock`
74
+ * below now rejects any array whose items are not all well-formed findings, so
75
+ * the common shape of a quoted array — evidence rows, log lines, a schema
76
+ * fragment — no longer wins. What survives is a quoted array of well-formed
77
+ * findings sitting fenced above the member's own bare one, and that is recorded
78
+ * as a known residual of 1B.4's gate rather than claimed away.
79
+ */
80
+ export function split_inline_findings(text: string): InlineFindingsSplit {
81
+ const none: InlineFindingsSplit = { deliberation_text: text, block: '', found: false };
82
+ if (!text) {
83
+ return none;
84
+ }
85
+ // Deliberately the same two patterns `_extract_json_array` uses, in the same
86
+ // precedence order — fenced beats bare — so a block this locator returns is
87
+ // one that function can also read. Only the match SELECTION differs: last,
88
+ // not first.
89
+ for (const src of [_JSON_BLOCK_SRC, _BARE_ARRAY_SRC]) {
90
+ const re = new RegExp(src, 'gs');
91
+ let last: RegExpExecArray | null = null;
92
+ let m: RegExpExecArray | null;
93
+ while ((m = re.exec(text)) !== null) {
94
+ last = m;
95
+ // A zero-length match would spin forever; the patterns cannot produce
96
+ // one (both require at least `[]`), but the guard costs nothing and a
97
+ // future pattern edit is exactly when it would matter.
98
+ if (m.index === re.lastIndex) {
99
+ re.lastIndex += 1;
100
+ }
101
+ }
102
+ if (last) {
103
+ const start = last.index;
104
+ const end = start + last[0].length;
105
+ return {
106
+ deliberation_text: `${text.slice(0, start)}${text.slice(end)}`,
107
+ block: text.slice(start, end),
108
+ found: true,
109
+ };
110
+ }
111
+ }
112
+ return none;
113
+ }
114
+
115
+ /**
116
+ * How a member's findings were obtained — the RECORDED provenance, wider than
117
+ * `FindingsParseOutcome`, which describes one parse of one piece of text.
118
+ *
119
+ * Typed rather than a bare string because Phase 1B's promotion gate is computed
120
+ * off exactly these values: an untyped `Map<string, string>` makes the number
121
+ * that decides the experiment vulnerable to a misspelling no compiler would
122
+ * catch. The AI council (2026-08-30, 2 of 2 seats) called the pre-existing bare
123
+ * `'parsed-after-reask'` technical debt rather than a precedent to extend.
124
+ *
125
+ * `'parsed'` keeps its shipped meaning — read from the separate extraction
126
+ * call — and is unambiguous now that `'parsed-inline'` names the other source.
127
+ * One seat asked for a rename to `'parsed-extraction'`; renaming a value that
128
+ * is already recorded and compared against is a separate change with its own
129
+ * migration, and is recorded here as declined-with-a-reason, not overlooked.
130
+ */
131
+ export type RecordedExtractionOutcome =
132
+ | 'parsed'
133
+ | 'empty'
134
+ | 'parse_failed'
135
+ | 'parsed-after-reask'
136
+ | 'parsed-inline';
137
+
138
+ /**
139
+ * Phase 1B — harvest the inline findings block out of each deliberation reply.
140
+ *
141
+ * Runs BETWEEN the deliberation and every consumer of its text. That placement
142
+ * is the load-bearing part and it was a defect the AI council caught
143
+ * (2026-08-30, 2 of 2 seats): peer review and chairman synthesis read the
144
+ * responses BEFORE the consensus round does, so parsing inside
145
+ * `run_consensus_scoring` would have left the schema block in the text those
146
+ * two evaluate — which is precisely the amplification the strip exists to
147
+ * prevent.
148
+ *
149
+ * MUTATES `text` on each response whose block parsed, replacing the consumed
150
+ * span with a one-line marker. Mutation rather than a parallel clean copy
151
+ * because two representations of one response means every downstream consumer
152
+ * has to know which one it holds, and the one that forgets is a silent bug.
153
+ * `CouncilResponse.text` is already mutated on the stance-repair path, so this
154
+ * is the established seam rather than a new one.
155
+ *
156
+ * The marker is deliberately visible. Stripping without an observable trace is
157
+ * a silent mutation of the artifact a reader takes for a transcript, and one
158
+ * seat made an observable marker a condition of its verdict; the other reached
159
+ * the same concern from the auditability side. ~90 characters replaces ~300 of
160
+ * JSON, so the scaffolding is gone and the fact of its removal is not.
161
+ *
162
+ * Returns the per-member extraction keyed by `provider:model` — the same key
163
+ * `run_consensus_scoring` records outcomes under. A member whose block did not
164
+ * parse gets NO entry and its `text` is left exactly as the model wrote it, so
165
+ * the repair extraction call downstream still sees the raw reply.
166
+ */
167
+ /**
168
+ * Is this extraction the member's OWN findings block, or just some JSON it quoted?
169
+ *
170
+ * `outcome === 'parsed'` was the whole test until a completion review of
171
+ * 2026-08-30 showed it decides nothing: `parse_findings_outcome` returns
172
+ * `'parsed'` for ANY syntactically valid JSON array, and `_collect_findings`
173
+ * silently skips items missing `id` or `text` while the outcome stays `'parsed'`.
174
+ * So a reply carrying no findings block at all, but quoting
175
+ * `[{"file":"src/a.ts","line":42}]` as evidence, was recorded as a successful
176
+ * inline extraction with zero findings — and its quoted evidence was DELETED
177
+ * from the text the peer review, the chairman and the artifact read. Worse, the
178
+ * failure was recorded as a success in the rate the 1B.4 promotion gate reads,
179
+ * so the gate could not see it.
180
+ *
181
+ * Two conjuncts, and both are needed:
182
+ *
183
+ * - **it parsed** — unchanged;
184
+ * - **every item it saw became a finding** — `findings.length === item_count`.
185
+ * A findings block from a member following the contract has well-formed items
186
+ * throughout. An array where some or all items lack `id`/`text` is something
187
+ * else, whatever it parsed to.
188
+ *
189
+ * The bare-`[]` answer keeps working: `item_count` is 0 and `findings.length`
190
+ * is 0, so the conjunction holds and "I found nothing" is still an answer
191
+ * rather than a re-ask.
192
+ *
193
+ * **What this does NOT decide, stated rather than implied away.** A member that
194
+ * quotes ANOTHER member's well-formed `[{"id":…,"text":…}]` array, as the last
195
+ * block in its reply, is indistinguishable from its own by shape — and would
196
+ * still be attributed to the quoting member. Shape cannot separate those; only
197
+ * provenance could, and the reply carries none. It is narrower than the case
198
+ * fixed here (the quote must be well-formed AND last AND the member must have
199
+ * emitted no block of its own), it is visible in the emitted marker, and it is
200
+ * carried into 1B.4's gate as a known residual rather than counted as a success.
201
+ */
202
+ function _isOwnFindingsBlock(ex: {
203
+ outcome: string;
204
+ findings: readonly unknown[];
205
+ item_count: number;
206
+ }): boolean {
207
+ return ex.outcome === 'parsed' && ex.findings.length === ex.item_count;
208
+ }
209
+
210
+ export function harvest_inline_findings(
211
+ members: readonly ExternalAIClient[],
212
+ responses: readonly CouncilResponse[],
213
+ ): Map<string, FindingsExtraction> {
214
+ const out = new Map<string, FindingsExtraction>();
215
+ const model_by_name = new Map<string, string>();
216
+ for (const m of members) {
217
+ model_by_name.set(m.name, m.model);
218
+ }
219
+ for (const resp of responses) {
220
+ const model = model_by_name.get(resp.provider);
221
+ if (model === undefined || resp.error || !_strip(resp.text)) {
222
+ continue;
223
+ }
224
+ const split = split_inline_findings(resp.text);
225
+ if (!split.found) {
226
+ continue;
227
+ }
228
+ const source = `${resp.provider}:${model}`;
229
+ const ex = parse_findings_outcome(split.block, { source });
230
+ if (!_isOwnFindingsBlock(ex)) {
231
+ // Not a findings block after all — most likely a JSON array the member
232
+ // quoted from the artifact. Leave the reply untouched: stripping text
233
+ // we could not read would remove evidence and buy nothing.
234
+ continue;
235
+ }
236
+ out.set(source, ex);
237
+ // Retain the reply BEFORE rewriting it — this is the single write of
238
+ // `CouncilResponse.raw_text`, and the reason that field exists.
239
+ //
240
+ // The marker appended below promises "the raw reply is retained in the
241
+ // session record". Until 2026-08-30 that promise was false, and a
242
+ // completion review is what caught it: the persisted record is
243
+ // serialized from these same objects AFTER this harvest runs
244
+ // (`council_cli._serialise_responses`), so the stripped text was the
245
+ // only text that survived anywhere, and the auditability condition the
246
+ // council attached to this feature was unmet.
247
+ //
248
+ // `null` stays the honest value for a reply nothing rewrote — it means
249
+ // "`text` IS the raw reply", never "the raw reply was lost" — which is
250
+ // also why the serializer omits the key entirely in that case rather
251
+ // than writing a duplicate of the reply into every session record.
252
+ resp.raw_text = resp.text;
253
+ const marker = `_[inline findings block extracted: ${String(ex.findings.length)} item(s); the raw reply is retained in the session record.]_`;
254
+ resp.text = `${_strip(split.deliberation_text)}\n\n${marker}`;
255
+ }
256
+ return out;
257
+ }
258
+
259
+
260
+ /**
261
+ * The FINAL deliberation round's volatile suffix.
262
+ *
263
+ * Two opt-in contracts ride it and their ORDER is load-bearing:
264
+ * `STANCE_LINE_CONTRACT` requires the stance to be the last line of the reply,
265
+ * so it is appended last and the findings block sits above it. A findings block
266
+ * appended after the stance line would contradict the instruction the member is
267
+ * reading, which is the one composition bug this function exists to make
268
+ * impossible to reintroduce.
269
+ *
270
+ * Both off → the caller's suffix is returned unchanged, so the composed default
271
+ * is byte-identical to a run without either feature.
272
+ */
273
+ export function composeFinalRoundSuffix(
274
+ suffix: string,
275
+ opts: { is_final: boolean; inline_findings: boolean; stance_tally: boolean },
276
+ ): string {
277
+ if (!opts.is_final) {
278
+ return suffix;
279
+ }
280
+ let out = suffix;
281
+ if (opts.inline_findings) {
282
+ out = `${out}\n\n---\n\n${INLINE_FINDINGS_CONTRACT}`;
283
+ }
284
+ if (opts.stance_tally) {
285
+ out = `${out}\n\n---\n\n${STANCE_LINE_CONTRACT}`;
286
+ }
287
+ return out;
288
+ }
289
+
290
+ /**
291
+ * Consume a member's harvested findings, or report that it has none.
292
+ *
293
+ * Returns `true` when the caller should SKIP its extraction call. An entry in
294
+ * the map is always a short-circuit and never a partial one, because
295
+ * `harvest_inline_findings` records only a member whose block PARSED — a member
296
+ * with no entry had its reply left raw and takes the shipped extraction path
297
+ * over the full text.
298
+ */
299
+ export function takeInlineFindings(
300
+ inline_extractions: ReadonlyMap<string, FindingsExtraction> | null,
301
+ source: string,
302
+ parse_outcomes: Map<string, RecordedExtractionOutcome>,
303
+ all_findings: Finding[],
304
+ ): boolean {
305
+ const inline = inline_extractions?.get(source);
306
+ if (inline === undefined) {
307
+ return false;
308
+ }
309
+ parse_outcomes.set(source, 'parsed-inline');
310
+ all_findings.push(...inline.findings);
311
+ return true;
312
+ }
313
+
314
+ /**
315
+ * Is the inline-findings contract active for this run?
316
+ *
317
+ * Read BEFORE the deliberation, because the contract is a prompt change and the
318
+ * prompt is built first; the harvest reads the same predicate so the two cannot
319
+ * disagree about whether a member was asked for the block. Three conjuncts, all
320
+ * required: consensus scoring on, this lens in its lens list, and
321
+ * `inline_findings` explicitly on. Any missing → `false`, and `false` is a
322
+ * byte-identical prompt.
323
+ *
324
+ * Reads the SYNTHESISED settings dict, not the typed config. That distinction
325
+ * is not academic: `_lib/council_settings_block.ts` projects the typed config
326
+ * into this dict, and when it did not carry the key a `true` in the YAML
327
+ * resolved to `undefined` and the feature was silently off with every unit test
328
+ * green — found by a live analysis run on 2026-08-30, not by review.
329
+ */
330
+ export function inlineFindingsActive(
331
+ ai_cfg: Record<string, unknown>,
332
+ mode: string,
333
+ ): boolean {
334
+ const cs = (ai_cfg['consensus_scoring'] as Record<string, unknown> | undefined) ?? {};
335
+ if (cs['enabled'] !== true || cs['inline_findings'] !== true) {
336
+ return false;
337
+ }
338
+ const lenses = (cs['lenses'] as string[] | undefined) ?? ['analysis'];
339
+ return lenses.includes(mode);
340
+ }