@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,338 @@
1
+ /**
2
+ * The zero-cost structural disagreement signal.
3
+ *
4
+ * `road-to-inbox-harvest-2026-08-e-council-topology-evidence` Phase 6.1: six
5
+ * components — stance divergence, finding overlap, contradiction count,
6
+ * confidence spread, rank uncertainty, novelty / self-similarity — computed from
7
+ * outputs the run **already paid for**.
8
+ *
9
+ * ## The contract is the absence of a call
10
+ *
11
+ * The step's verify is not "the numbers look right"; it is *"no extra model call
12
+ * is issued; call count is unchanged"*. So this module is a pure function of
13
+ * retained output: it imports no client, opens no socket, spawns no process, and
14
+ * reads no file. `argument_exhaustion.ts:40-42` already states that property as
15
+ * 6.1's contract while consuming it; this is the module it was pointing at.
16
+ *
17
+ * Purity is enforced structurally rather than by discipline: every input arrives
18
+ * as an argument, so there is no path from here to a provider even if a future
19
+ * edit wanted one. A test asserts the import surface directly, because a
20
+ * regression here is silent — an added import spends money without changing a
21
+ * single number this module returns.
22
+ *
23
+ * ## Nothing is re-derived
24
+ *
25
+ * Each component reads the verdict the tree already computes rather than a second
26
+ * opinion about the same bytes:
27
+ *
28
+ * - stance divergence and confidence spread read `StanceTallyResult`
29
+ * (`stance_tally.ts:146`) — never a re-parse of the stance lines. Two parses
30
+ * are two chances to disagree.
31
+ * - contradiction count and rank uncertainty read the `ConsensusMetadata` map
32
+ * `aggregate_scores` (`consensus.ts:157`) produced — self-scores already
33
+ * dropped, strengths already rounded.
34
+ * - finding overlap and self-similarity reuse `jaccardSimilarity`
35
+ * (`_lib/text_similarity.ts:33`), the same primitive `debate_gates.ts:40` and
36
+ * `recouncil_guard.ts:29` consume.
37
+ *
38
+ * ## An unavailable component is a result, never a zero
39
+ *
40
+ * A component whose evidence the run does not carry returns
41
+ * `{ available: false, reason }`. It does **not** return `0`, and the reason is
42
+ * an enumerated value rather than prose. A fabricated zero is worse than a
43
+ * declared gap in both directions this signal can be read: `0` divergence reads
44
+ * as unanimity and `0` contradictions reads as agreement, so silently defaulting
45
+ * would make an unmeasured round look like the most convergent one — the same
46
+ * inversion `argument_exhaustion.ts:91-95` guards against for an empty council.
47
+ *
48
+ * ## No composite score, deliberately
49
+ *
50
+ * The six are returned separately and are **not** combined. Two of them —
51
+ * `findingOverlap` and `selfSimilarity` — rise with AGREEMENT while the other
52
+ * four rise with DISAGREEMENT, so a consumer summing them would be adding
53
+ * opposing axes; and weighting them against each other needs numbers no
54
+ * measurement in this tree supplies. Phase 8.4 asks for a score that is
55
+ * "deterministic and inspectable to start" and Phase 10.3 asks which of finding,
56
+ * stance, confidence or evidence a call moved — both want the components, not a
57
+ * scalar that has already discarded which axis moved.
58
+ *
59
+ * `revisit-if`: a benchmark arm produces measured weights for a composite. Then
60
+ * the composite belongs in the consumer that has the measurement, still reading
61
+ * these components as its inputs.
62
+ */
63
+
64
+ import { findMostSimilar, jaccardSimilarity, MERGE_THRESHOLD } from '../_lib/text_similarity.js';
65
+
66
+ import type { ConsensusMetadata, Finding } from './consensus.js';
67
+ import { CONFIDENCE_FACTOR, type StanceTallyResult } from './stance_tally.js';
68
+
69
+ /**
70
+ * The bar at which two members' findings count as the same finding — and it is
71
+ * REUSED, not chosen. `MERGE_THRESHOLD` was fixed by the 2026-07-05 council
72
+ * verdict as the point at which two texts are duplicates, long before this
73
+ * signal existed, which is the same pre-registration argument
74
+ * `recouncil_guard.ts:50` makes for reusing it there.
75
+ *
76
+ * It is a strict bar for prose that says the same thing in different words, so
77
+ * `findingOverlap` UNDER-estimates agreement. That is the fail-safe direction
78
+ * here and the reason a stricter-than-ideal number is acceptable rather than
79
+ * merely tolerated: under-estimating overlap over-estimates disagreement, and
80
+ * Phase 6's failure mode is stopping deliberation too early, not too late.
81
+ *
82
+ * `revisit-if`: two members raise a finding a human calls identical and it
83
+ * scores below this value. The fix then belongs in `text_similarity.ts` where
84
+ * every other consumer can see the number move.
85
+ */
86
+ export const FINDING_MATCH_THRESHOLD = MERGE_THRESHOLD;
87
+
88
+ /** Why a component carries no value. Enumerated — never free prose. */
89
+ export type SignalGap =
90
+ /** Stance tallying is off for this run, so there is no tally to read. */
91
+ | 'no-stance-tally'
92
+ /** A tally exists and no member backed an option (all abstained or unparsed). */
93
+ | 'no-parsed-stances'
94
+ /** Fewer than two confidence observations; a spread needs two points. */
95
+ | 'too-few-confidence-observations'
96
+ /** Fewer than two sources carried a finding, so there is no pair to compare. */
97
+ | 'too-few-sourced-findings'
98
+ /** No finding was scored by anyone, so no contradiction was observable. */
99
+ | 'no-scored-findings'
100
+ /** Fewer than two scored findings; a ranking needs two positions. */
101
+ | 'too-few-ranked-findings'
102
+ /** No member had a non-empty prior round to be compared against. */
103
+ | 'no-prior-round';
104
+
105
+ /**
106
+ * One component. `basis` is the observation count the value rests on, so a
107
+ * consumer can tell a 0 measured over 40 pairs from a 0 measured over one — the
108
+ * distinction a bare number destroys, and the reason a degenerate-but-real
109
+ * measurement is reported rather than suppressed.
110
+ */
111
+ export type SignalComponent =
112
+ | { readonly available: true; readonly value: number; readonly basis: number }
113
+ | { readonly available: false; readonly reason: SignalGap };
114
+
115
+ /** Per present member: this round's text, and its own prior round's. */
116
+ export interface MemberRound {
117
+ readonly member: string;
118
+ readonly current: string;
119
+ /** `null` on round 1 — there is no prior round, which is not an empty one. */
120
+ readonly prior: string | null;
121
+ }
122
+
123
+ export interface DisagreementInputs {
124
+ /** The ONE tally of the round (`tallyFromResponses`), or `null` when off. */
125
+ readonly stance: StanceTallyResult | null;
126
+ /** Findings as already extracted, each carrying its authoring source. */
127
+ readonly findings: readonly Finding[];
128
+ /** The ONE `aggregate_scores` map, keyed by finding id. */
129
+ readonly consensus: ReadonlyMap<string, ConsensusMetadata>;
130
+ /** Present members with their current and prior round texts. */
131
+ readonly memberRounds: readonly MemberRound[];
132
+ }
133
+
134
+ export interface DisagreementSignal {
135
+ /**
136
+ * 0..1, rising with disagreement. `1 − topOptionWeight / backedWeight`:
137
+ * 0 when every backer chose one option.
138
+ */
139
+ readonly stanceDivergence: SignalComponent;
140
+ /**
141
+ * 0..1, rising with AGREEMENT. Mean symmetric share of one source's findings
142
+ * that another source also raised.
143
+ */
144
+ readonly findingOverlap: SignalComponent;
145
+ /** A count ≥ 0, rising with disagreement: scored `agree: false` votes. */
146
+ readonly contradictionCount: SignalComponent;
147
+ /** 0..1, rising with disagreement: normalised range of backer confidences. */
148
+ readonly confidenceSpread: SignalComponent;
149
+ /** 0..1, rising with disagreement: share of adjacent ranked pairs that tie. */
150
+ readonly rankUncertainty: SignalComponent;
151
+ /**
152
+ * 0..1, rising with AGREEMENT (and with exhaustion): mean similarity of each
153
+ * member's round to its own prior round.
154
+ */
155
+ readonly selfSimilarity: SignalComponent;
156
+ /** How many of the six carry a value. 0..6. */
157
+ readonly availableCount: number;
158
+ }
159
+
160
+ const gap = (reason: SignalGap): SignalComponent => ({ available: false, reason });
161
+ const ok = (value: number, basis: number): SignalComponent => ({ available: true, value, basis });
162
+
163
+ /**
164
+ * Spread among the options members actually BACKED.
165
+ *
166
+ * The denominator is the summed option weight, deliberately not the tally's own
167
+ * `w_total`: `w_total` counts abstainers and unparsed responses (see the
168
+ * refusal-preservation invariant at `stance_tally.ts:160-176`), and dividing by
169
+ * it would make a council where half abstained look MORE divergent than one
170
+ * where half disagreed. Abstention and unparsed responses are already surfaced
171
+ * separately by the tally; conflating them into divergence here would double-count
172
+ * them as a position.
173
+ */
174
+ function stanceDivergence(stance: StanceTallyResult | null): SignalComponent {
175
+ if (stance === null) return gap('no-stance-tally');
176
+ const backedWeight = stance.options.reduce((acc, o) => acc + o.weight, 0);
177
+ const top = stance.options[0];
178
+ if (top === undefined || backedWeight <= 0) return gap('no-parsed-stances');
179
+ const backers = stance.options.reduce((acc, o) => acc + o.backers.length, 0);
180
+ return ok(1 - top.weight / backedWeight, backers);
181
+ }
182
+
183
+ /**
184
+ * Normalised range of the confidence tiers the backers declared.
185
+ *
186
+ * Only BACKERS are observable: `tally_stances` counts an abstention and drops
187
+ * its confidence (`stance_tally.ts:182-185`), so an abstainer's declared
188
+ * confidence is not in the tally and is not reconstructed here — re-parsing the
189
+ * reply to recover it would fork the one parse this module refuses to duplicate.
190
+ * The scope is therefore "spread among members who took a position", which is
191
+ * stated rather than implied.
192
+ *
193
+ * The denominator comes from `CONFIDENCE_FACTOR` rather than a literal, so a
194
+ * change to the tier table moves this number with it instead of forking it.
195
+ */
196
+ function confidenceSpread(stance: StanceTallyResult | null): SignalComponent {
197
+ if (stance === null) return gap('no-stance-tally');
198
+ const factors = stance.options.flatMap((o) => o.backers.map((b) => CONFIDENCE_FACTOR[b.confidence]));
199
+ if (factors.length < 2) return gap('too-few-confidence-observations');
200
+ const span = CONFIDENCE_FACTOR.high - CONFIDENCE_FACTOR.low;
201
+ return ok((Math.max(...factors) - Math.min(...factors)) / span, factors.length);
202
+ }
203
+
204
+ /**
205
+ * How much of what one source raised, another source raised too.
206
+ *
207
+ * Symmetric per pair, because the one-directional share is a different question
208
+ * for each side when the two sources produced different numbers of findings: a
209
+ * source with one finding matched inside a source with twenty scores 1.0 in one
210
+ * direction and 0.05 in the other, and neither alone describes the pair.
211
+ */
212
+ function findingOverlap(findings: readonly Finding[]): SignalComponent {
213
+ const bySource = new Map<string, Finding[]>();
214
+ for (const f of findings) {
215
+ const bucket = bySource.get(f.source);
216
+ if (bucket === undefined) bySource.set(f.source, [f]);
217
+ else bucket.push(f);
218
+ }
219
+ const sources = [...bySource.values()];
220
+ if (sources.length < 2) return gap('too-few-sourced-findings');
221
+
222
+ /** Share of `from`'s findings with a match at or above the threshold in `to`. */
223
+ const matchedShare = (from: readonly Finding[], to: readonly Finding[]): number => {
224
+ if (from.length === 0) return 0;
225
+ const candidates = to.map((f) => ({ id: f.id, text: f.text }));
226
+ let matched = 0;
227
+ for (const f of from) {
228
+ const best = findMostSimilar(f.text, candidates);
229
+ if (best !== null && best.score >= FINDING_MATCH_THRESHOLD) matched += 1;
230
+ }
231
+ return matched / from.length;
232
+ };
233
+
234
+ let total = 0;
235
+ let pairs = 0;
236
+ for (let i = 0; i < sources.length; i += 1) {
237
+ for (let j = i + 1; j < sources.length; j += 1) {
238
+ const a = sources[i] as Finding[];
239
+ const b = sources[j] as Finding[];
240
+ total += (matchedShare(a, b) + matchedShare(b, a)) / 2;
241
+ pairs += 1;
242
+ }
243
+ }
244
+ return ok(total / pairs, pairs);
245
+ }
246
+
247
+ /**
248
+ * Scored findings only — an entry with no scorer is not a zero-contradiction
249
+ * finding, it is an unmeasured one.
250
+ *
251
+ * `aggregate_scores` writes an entry for EVERY finding, including ones nobody
252
+ * scored (`consensus.ts:179-194` sets `dissent_count: 0`). Summing the map
253
+ * wholesale would therefore report a confident `0` for a round where no scoring
254
+ * happened at all, which is the fabricated zero this module exists not to emit.
255
+ */
256
+ function scoredEntries(consensus: ReadonlyMap<string, ConsensusMetadata>): ConsensusMetadata[] {
257
+ return [...consensus.values()].filter((m) => m.scorers.length > 0);
258
+ }
259
+
260
+ function contradictionCount(consensus: ReadonlyMap<string, ConsensusMetadata>): SignalComponent {
261
+ const scored = scoredEntries(consensus);
262
+ if (scored.length === 0) return gap('no-scored-findings');
263
+ return ok(
264
+ scored.reduce((acc, m) => acc + m.dissent_count, 0),
265
+ scored.length,
266
+ );
267
+ }
268
+
269
+ /**
270
+ * How much of the finding ranking the record cannot resolve.
271
+ *
272
+ * The ranking is by `consensus_strength` descending (`consensus.ts:272-274`), and
273
+ * two findings whose strengths are EQUAL have an order that comes from input
274
+ * position rather than from evidence. So the measure is the share of adjacent
275
+ * pairs that tie: 0 when every neighbour is separated, 1 when the whole order is
276
+ * arbitrary.
277
+ *
278
+ * Equality is used rather than a tolerance on purpose — no new tunable. The
279
+ * strengths arrive already rounded to three places by `pyRound`
280
+ * (`consensus.ts:211`), so the record's own resolution is what decides a tie and
281
+ * this module adds no threshold of its own to argue about.
282
+ *
283
+ * Unscored findings are excluded for the same reason as above: they all sit at
284
+ * strength 0 and would report as a near-total tie, which measures the absence of
285
+ * scoring rather than the uncertainty of a ranking.
286
+ */
287
+ function rankUncertainty(consensus: ReadonlyMap<string, ConsensusMetadata>): SignalComponent {
288
+ const strengths = scoredEntries(consensus)
289
+ .map((m) => m.consensus_strength)
290
+ .sort((a, b) => b - a);
291
+ if (strengths.length < 2) return gap('too-few-ranked-findings');
292
+ let ties = 0;
293
+ for (let i = 1; i < strengths.length; i += 1) {
294
+ if (strengths[i] === strengths[i - 1]) ties += 1;
295
+ }
296
+ return ok(ties / (strengths.length - 1), strengths.length);
297
+ }
298
+
299
+ /**
300
+ * Each member against its own prior round — the novelty axis, as a scalar.
301
+ *
302
+ * The boolean gate over the same primitive stays in `debate_gates.ts:32`
303
+ * (`is_near_duplicate`) and is not duplicated here; what this adds is the
304
+ * underlying magnitude, which a stop predicate does not need and an
305
+ * information-gain estimate does.
306
+ *
307
+ * A member with an empty current or prior text contributes nothing rather than a
308
+ * value. That mirrors `is_near_duplicate`'s own guard (`debate_gates.ts:37-39`)
309
+ * and it matters arithmetically: `jaccardSimilarity` defines two empty strings as
310
+ * identical (1.0, `text_similarity.ts:36`), so an errored member would otherwise
311
+ * enter the mean as maximal self-repetition.
312
+ */
313
+ function selfSimilarity(memberRounds: readonly MemberRound[]): SignalComponent {
314
+ const scores: number[] = [];
315
+ for (const r of memberRounds) {
316
+ if (r.prior === null) continue;
317
+ if (r.prior.trim().length === 0 || r.current.trim().length === 0) continue;
318
+ scores.push(jaccardSimilarity(r.prior, r.current));
319
+ }
320
+ if (scores.length === 0) return gap('no-prior-round');
321
+ return ok(scores.reduce((acc, s) => acc + s, 0) / scores.length, scores.length);
322
+ }
323
+
324
+ /** Compute all six components. Pure: no I/O, no client, no model call. */
325
+ export function computeDisagreementSignal(x: DisagreementInputs): DisagreementSignal {
326
+ const components = {
327
+ stanceDivergence: stanceDivergence(x.stance),
328
+ findingOverlap: findingOverlap(x.findings),
329
+ contradictionCount: contradictionCount(x.consensus),
330
+ confidenceSpread: confidenceSpread(x.stance),
331
+ rankUncertainty: rankUncertainty(x.consensus),
332
+ selfSimilarity: selfSimilarity(x.memberRounds),
333
+ };
334
+ return {
335
+ ...components,
336
+ availableCount: Object.values(components).filter((c) => c.available).length,
337
+ };
338
+ }
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Free explain mode — step 12.2.
3
+ *
4
+ * `road-to-inbox-harvest-2026-08-e-council-topology-evidence` step 12.2: *"Add
5
+ * a free explain mode: why task-side orchestration resolved to council, which
6
+ * topology would run, estimated spend and calls, evidence source — with no paid
7
+ * model call to explain routing"*, verified by *"explain mode issues zero
8
+ * provider calls"*.
9
+ *
10
+ * ## Free is the load-bearing word, and it is structural
11
+ *
12
+ * This module imports **no client, no transport and no dispatch**. It reads
13
+ * `explainLadder` (`_lib/judgment_ladder.ts:499`, itself regex-only) and
14
+ * `estimate_cost` (`pricing.ts:121`, arithmetic over a price table). There is
15
+ * nothing here to make a call WITH, which is a stronger guarantee than a
16
+ * documented promise not to — and the test asserts the import graph rather than
17
+ * trusting this paragraph.
18
+ *
19
+ * ## Three of the four fields are answerable today; one is not
20
+ *
21
+ * 1. **why it resolved to council** — `explainLadder`'s full per-rung trail,
22
+ * including rungs that were evaluated-and-rejected with the detector's own
23
+ * reason and rungs the short-circuit never reached. Free.
24
+ * 2. **which topology would run** — NOT ANSWERABLE. 7.2 is open, no selector
25
+ * exists, and naming a topology here would be a guess dressed as an
26
+ * explanation. Reported as {@link TOPOLOGY_UNAVAILABLE}, never omitted:
27
+ * a field silently missing from an explanation reads as "not applicable".
28
+ * 3. **estimated spend and calls** — arithmetic over the configured members,
29
+ * the round count and the price table, with the subscription-seat
30
+ * distinction `pricing.ts` already draws: a non-billable seat contributes
31
+ * calls but **zero** dollars, and the estimate says so per member rather
32
+ * than folding it into a total.
33
+ * 4. **evidence source** — which artefact, if any, licenses the routing.
34
+ * `none` is a legal and common value today and is rendered as such.
35
+ *
36
+ * Pure and offline.
37
+ */
38
+ import { explainLadder } from '../_lib/judgment_ladder.js';
39
+ import type { LadderExplanation, LadderInputs } from '../_lib/judgment_ladder.js';
40
+ import { estimate_cost, estimate_input_tokens } from './pricing.js';
41
+ import type { PriceTable } from './pricing.js';
42
+
43
+ /** The exact string the topology field carries while no selector exists. */
44
+ export const TOPOLOGY_UNAVAILABLE = 'unavailable — no topology selector exists (step 7.2 open)';
45
+
46
+ /** One member, as the estimate needs it. */
47
+ export interface EstimateMember {
48
+ readonly name: string;
49
+ readonly provider: string;
50
+ readonly model: string;
51
+ /**
52
+ * `false` for a vendor-official CLI seat running under the user's
53
+ * subscription auth — it contributes CALLS but no dollars, per
54
+ * `pricing.ts` § billable-aware aggregation.
55
+ */
56
+ readonly billable: boolean;
57
+ }
58
+
59
+ export interface SpendEstimate {
60
+ readonly calls: number;
61
+ readonly usd: number;
62
+ readonly perMember: readonly {
63
+ readonly name: string;
64
+ readonly calls: number;
65
+ readonly usd: number;
66
+ readonly billable: boolean;
67
+ }[];
68
+ /** Members whose calls are real but whose spend is zero. Named, not hidden. */
69
+ readonly nonBillableMembers: readonly string[];
70
+ }
71
+
72
+ export interface RouteExplanation {
73
+ /** Field 1 — free, from the regex-only resolver. */
74
+ readonly ladder: LadderExplanation;
75
+ /** Field 2 — always {@link TOPOLOGY_UNAVAILABLE} today. Present, never omitted. */
76
+ readonly topology: string;
77
+ /** Field 3 — arithmetic, no call. */
78
+ readonly spend: SpendEstimate;
79
+ /** Field 4 — the artefact licensing the route, or `'none'`. */
80
+ readonly evidenceSource: string;
81
+ }
82
+
83
+ /**
84
+ * Estimate calls and spend without issuing one.
85
+ *
86
+ * `calls` counts every member on every round; `usd` counts only the billable
87
+ * ones. Reporting a subscription seat's answer at API rates is the defect
88
+ * `pricing.ts` records finding on 2026-08-27, and this keeps the two figures
89
+ * separate rather than reproducing it.
90
+ */
91
+ export function estimateSpend(
92
+ members: readonly EstimateMember[],
93
+ rounds: number,
94
+ questionText: string,
95
+ maxOutputTokens: number,
96
+ table: PriceTable,
97
+ ): SpendEstimate {
98
+ const inputTokens = estimate_input_tokens(questionText);
99
+ const perMember = members.map((m) => {
100
+ const calls = Math.max(0, rounds);
101
+ if (!m.billable) return { name: m.name, calls, usd: 0, billable: false };
102
+ const c = estimate_cost(m.provider, m.model, inputTokens, maxOutputTokens, table);
103
+ return { name: m.name, calls, usd: (c.input_usd + c.output_usd) * calls, billable: true };
104
+ });
105
+ return {
106
+ calls: perMember.reduce((a, m) => a + m.calls, 0),
107
+ usd: perMember.reduce((a, m) => a + m.usd, 0),
108
+ perMember,
109
+ nonBillableMembers: perMember.filter((m) => !m.billable).map((m) => m.name),
110
+ };
111
+ }
112
+
113
+ /** Build the whole explanation. No call is issued and none can be. */
114
+ export function explainRoute(
115
+ ladderInputs: LadderInputs,
116
+ members: readonly EstimateMember[],
117
+ rounds: number,
118
+ questionText: string,
119
+ maxOutputTokens: number,
120
+ table: PriceTable,
121
+ evidenceSource: string = 'none',
122
+ ): RouteExplanation {
123
+ return {
124
+ ladder: explainLadder(ladderInputs),
125
+ topology: TOPOLOGY_UNAVAILABLE,
126
+ spend: estimateSpend(members, rounds, questionText, maxOutputTokens, table),
127
+ evidenceSource,
128
+ };
129
+ }
130
+
131
+ /** Human-readable rendering. Every one of the four fields appears, including the unavailable one. */
132
+ export function renderRouteExplanation(e: RouteExplanation): string {
133
+ const lines = [
134
+ 'council: explain (free — no provider call was issued)',
135
+ '',
136
+ ` resolution rung ${String(e.ladder.result.rung)} / ${e.ladder.result.verdict}`,
137
+ ` because ${e.ladder.result.reason}`,
138
+ ' ladder trail',
139
+ ];
140
+ for (const r of e.ladder.trail) {
141
+ lines.push(` rung ${String(r.rung)} → ${r.resolves_to.padEnd(8)} ${r.status.padEnd(12)} ${r.reason}`);
142
+ }
143
+ if (e.ladder.no_spawn_reason !== undefined) lines.push(` no spawn ${e.ladder.no_spawn_reason}`);
144
+ lines.push(
145
+ '',
146
+ ` topology ${e.topology}`,
147
+ ` estimated ${String(e.spend.calls)} call(s), $${e.spend.usd.toFixed(4)}`,
148
+ );
149
+ for (const m of e.spend.perMember) {
150
+ lines.push(
151
+ ` ${m.name.padEnd(14)} ${String(m.calls)} call(s), $${m.usd.toFixed(4)}` +
152
+ (m.billable ? '' : ' (subscription seat — calls are real, spend is not)'),
153
+ );
154
+ }
155
+ lines.push(` evidence ${e.evidenceSource}`, '');
156
+ return lines.join('\n');
157
+ }