@event4u/agent-config 16.2.0 → 16.4.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 (651) 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 +337 -234
  5. package/README.md +15 -13
  6. package/agents/templates/.ai-council.yml.example +26 -8
  7. package/dist/agent-src/commands/analyze/inbox.md +11 -8
  8. package/dist/agent-src/commands/analyze/roadmap-repos.md +1 -1
  9. package/dist/agent-src/commands/bug/fix.md +17 -2
  10. package/dist/agent-src/commands/bug/investigate.md +1 -1
  11. package/dist/agent-src/commands/commit/in-chunks.md +40 -31
  12. package/dist/agent-src/commands/commit.md +72 -33
  13. package/dist/agent-src/commands/condense.md +2 -8
  14. package/dist/agent-src/commands/council/debate.md +11 -7
  15. package/dist/agent-src/commands/council/default.md +10 -9
  16. package/dist/agent-src/commands/council.md +1 -1
  17. package/dist/agent-src/commands/estimate-ticket.md +1 -1
  18. package/dist/agent-src/commands/feature/explore.md +3 -3
  19. package/dist/agent-src/commands/feature/plan.md +2 -2
  20. package/dist/agent-src/commands/feature/roadmap.md +1 -1
  21. package/dist/agent-src/commands/fix/ci.md +18 -4
  22. package/dist/agent-src/commands/fix/commit-messages.md +48 -23
  23. package/dist/agent-src/commands/fix/pr-comments.md +3 -6
  24. package/dist/agent-src/commands/implement-ticket.md +4 -4
  25. package/dist/agent-src/commands/jira-ticket.md +1 -1
  26. package/dist/agent-src/commands/memory/add.md +4 -16
  27. package/dist/agent-src/commands/memory/load.md +5 -6
  28. package/dist/agent-src/commands/memory/promote.md +3 -16
  29. package/dist/agent-src/commands/mission/upgrade.md +3 -2
  30. package/dist/agent-src/commands/optimize/agents-dir.md +2 -2
  31. package/dist/agent-src/commands/optimize/deep.md +4 -2
  32. package/dist/agent-src/commands/optimize/rtk.md +4 -26
  33. package/dist/agent-src/commands/pr/create/description-only.md +18 -15
  34. package/dist/agent-src/commands/pr/create.md +42 -34
  35. package/dist/agent-src/commands/pr/merge.md +136 -9
  36. package/dist/agent-src/commands/prepare-for-review.md +13 -11
  37. package/dist/agent-src/commands/project/analyze.md +7 -35
  38. package/dist/agent-src/commands/refine-ticket.md +1 -1
  39. package/dist/agent-src/commands/review/changes.md +14 -19
  40. package/dist/agent-src/commands/roadmap/create.md +1 -1
  41. package/dist/agent-src/commands/roadmap/materialize.md +1 -1
  42. package/dist/agent-src/commands/roadmap/next.md +10 -1
  43. package/dist/agent-src/commands/roadmap/process-full.md +56 -42
  44. package/dist/agent-src/commands/roadmap/resolve-blockers.md +411 -0
  45. package/dist/agent-src/commands/roadmap/triage-parked.md +325 -0
  46. package/dist/agent-src/commands/roadmap.md +18 -4
  47. package/dist/agent-src/commands/tests/create.md +17 -3
  48. package/dist/agent-src/commands/tests/execute.md +22 -5
  49. package/dist/agent-src/commands/worktree/create.md +7 -3
  50. package/dist/agent-src/commands/worktree/verify.md +2 -1
  51. package/dist/agent-src/contexts/authority/decision-revisit-gate-enforcement.md +43 -0
  52. package/dist/agent-src/contexts/communication/rules-auto/design-fidelity-enforcement.md +24 -0
  53. package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +5 -3
  54. package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +7 -9
  55. package/dist/agent-src/contexts/contracts/command-suggestion-flow.md +8 -6
  56. package/dist/agent-src/contexts/contracts/frugality-charter.md +8 -5
  57. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +7 -7
  58. package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +0 -1
  59. package/dist/agent-src/contexts/execution/evidence-discipline.md +2 -2
  60. package/dist/agent-src/contexts/execution/non-interactive-contract.md +5 -8
  61. package/dist/agent-src/contexts/execution/rdp-gate.md +4 -4
  62. package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +9 -8
  63. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +99 -54
  64. package/dist/agent-src/contexts/execution/session-canary-enforcement-history.md +67 -0
  65. package/dist/agent-src/contexts/execution/subagent-routing.md +8 -8
  66. package/dist/agent-src/contexts/execution/subagent-steering.md +6 -4
  67. package/dist/agent-src/contexts/execution/terminal-states.md +2 -2
  68. package/dist/agent-src/contexts/execution/toolchain-resolver.md +95 -7
  69. package/dist/agent-src/contexts/subagent-configuration.md +1 -1
  70. package/dist/agent-src/guidelines/agent-infra/active-remediation-mechanics.md +39 -0
  71. package/dist/agent-src/guidelines/agent-infra/context-hygiene-mechanics.md +1 -1
  72. package/dist/agent-src/guidelines/agent-infra/cross-source-consistency-mechanics.md +8 -10
  73. package/dist/agent-src/guidelines/agent-infra/frontier-reasoning-operating-profile.md +3 -2
  74. package/dist/agent-src/guidelines/agent-infra/layered-settings.md +13 -1
  75. package/dist/agent-src/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
  76. package/dist/agent-src/guidelines/agent-infra/self-improvement-pipeline.md +10 -3
  77. package/dist/agent-src/guidelines/agent-infra/size-and-scope.md +36 -0
  78. package/dist/agent-src/guidelines/php/git.md +15 -2
  79. package/dist/agent-src/rules/active-remediation.md +1 -2
  80. package/dist/agent-src/rules/analysis-skill-routing.md +0 -1
  81. package/dist/agent-src/rules/architecture.md +0 -1
  82. package/dist/agent-src/rules/artifact-drafting-protocol.md +0 -1
  83. package/dist/agent-src/rules/artifact-engagement-recording.md +0 -1
  84. package/dist/agent-src/rules/augment-edit-discipline.md +0 -1
  85. package/dist/agent-src/rules/autonomous-execution.md +1 -1
  86. package/dist/agent-src/rules/brand-consistency.md +0 -1
  87. package/dist/agent-src/rules/brand-source-of-truth.md +0 -1
  88. package/dist/agent-src/rules/broken-access-control.md +1 -1
  89. package/dist/agent-src/rules/cli-output-handling.md +0 -1
  90. package/dist/agent-src/rules/code-comment-discipline.md +0 -1
  91. package/dist/agent-src/rules/code-provenance.md +0 -1
  92. package/dist/agent-src/rules/command-suggestion-policy.md +1 -1
  93. package/dist/agent-src/rules/commit-conventions.md +1 -2
  94. package/dist/agent-src/rules/communication-through-line.md +1 -2
  95. package/dist/agent-src/rules/content-quoting-floor.md +1 -2
  96. package/dist/agent-src/rules/context-hygiene.md +6 -6
  97. package/dist/agent-src/rules/copilot-routing.md +1 -2
  98. package/dist/agent-src/rules/council-availability.md +4 -4
  99. package/dist/agent-src/rules/cross-source-consistency.md +4 -6
  100. package/dist/agent-src/rules/decision-revisit-gate.md +17 -35
  101. package/dist/agent-src/rules/delegation-policy.md +2 -3
  102. package/dist/agent-src/rules/design-fidelity.md +12 -16
  103. package/dist/agent-src/rules/design-review-after-ui-write.md +3 -3
  104. package/dist/agent-src/rules/devcontainer-routing.md +1 -2
  105. package/dist/agent-src/rules/doc-screenshot-hygiene.md +1 -1
  106. package/dist/agent-src/rules/docker-commands.md +0 -1
  107. package/dist/agent-src/rules/domain-adoption-policy.md +0 -1
  108. package/dist/agent-src/rules/domain-safety-disclaimer.md +1 -1
  109. package/dist/agent-src/rules/domain-safety-pii.md +1 -1
  110. package/dist/agent-src/rules/domain-safety-retention.md +1 -1
  111. package/dist/agent-src/rules/downstream-changes.md +0 -1
  112. package/dist/agent-src/rules/engineering-safety-floor.md +1 -1
  113. package/dist/agent-src/rules/evaluator-independence.md +3 -2
  114. package/dist/agent-src/rules/external-code-graph-interop.md +0 -1
  115. package/dist/agent-src/rules/external-reference-deep-dive.md +0 -1
  116. package/dist/agent-src/rules/fast-path-marker-visibility.md +2 -2
  117. package/dist/agent-src/rules/finance-safety-floor.md +1 -1
  118. package/dist/agent-src/rules/fix-what-you-see.md +6 -32
  119. package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +0 -1
  120. package/dist/agent-src/rules/git-history-discipline.md +2 -2
  121. package/dist/agent-src/rules/guidelines.md +0 -1
  122. package/dist/agent-src/rules/history-discipline.md +0 -1
  123. package/dist/agent-src/rules/icon-consistency.md +0 -1
  124. package/dist/agent-src/rules/image-likeness-and-rights.md +1 -1
  125. package/dist/agent-src/rules/improve-before-implement.md +0 -1
  126. package/dist/agent-src/rules/invite-challenge.md +0 -1
  127. package/dist/agent-src/rules/laravel-routing.md +1 -2
  128. package/dist/agent-src/rules/laravel-translations.md +0 -1
  129. package/dist/agent-src/rules/legal-safety-floor.md +3 -3
  130. package/dist/agent-src/rules/lethal-trifecta-guard.md +1 -1
  131. package/dist/agent-src/rules/linked-projects-onboarding-gate.md +0 -1
  132. package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +1 -1
  133. package/dist/agent-src/rules/markdown-safe-codeblocks.md +0 -1
  134. package/dist/agent-src/rules/media-governance-routing.md +13 -17
  135. package/dist/agent-src/rules/media-sync-ground-truth.md +0 -1
  136. package/dist/agent-src/rules/minimal-safe-diff.md +0 -1
  137. package/dist/agent-src/rules/missing-skill-recovery.md +0 -1
  138. package/dist/agent-src/rules/missing-tool-handling.md +0 -1
  139. package/dist/agent-src/rules/model-recommendation.md +0 -1
  140. package/dist/agent-src/rules/neighbour-precedence.md +64 -0
  141. package/dist/agent-src/rules/no-attribution-footers.md +0 -1
  142. package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +0 -1
  143. package/dist/agent-src/rules/no-pr-progress-comments.md +0 -1
  144. package/dist/agent-src/rules/no-roadmap-references.md +0 -1
  145. package/dist/agent-src/rules/notes-first-reasoning.md +0 -1
  146. package/dist/agent-src/rules/onboarding-gate.md +0 -1
  147. package/dist/agent-src/rules/output-discipline.md +0 -1
  148. package/dist/agent-src/rules/package-ci-checks.md +0 -1
  149. package/dist/agent-src/rules/persona-governance.md +4 -5
  150. package/dist/agent-src/rules/php-coding.md +0 -1
  151. package/dist/agent-src/rules/prefer-enums-over-literals.md +0 -1
  152. package/dist/agent-src/rules/preservation-guard.md +0 -1
  153. package/dist/agent-src/rules/provider-lifecycle-discipline.md +3 -4
  154. package/dist/agent-src/rules/question-not-instruction.md +1 -1
  155. package/dist/agent-src/rules/reviewer-awareness.md +0 -1
  156. package/dist/agent-src/rules/roadmap-ci-steps-policy.md +0 -1
  157. package/dist/agent-src/rules/roadmap-progress-sync.md +4 -7
  158. package/dist/agent-src/rules/role-mode-adherence.md +0 -1
  159. package/dist/agent-src/rules/rule-type-governance.md +0 -1
  160. package/dist/agent-src/rules/runtime-safety.md +1 -1
  161. package/dist/agent-src/rules/scale-discipline.md +0 -1
  162. package/dist/agent-src/rules/secret-vcs-guard.md +1 -1
  163. package/dist/agent-src/rules/security-sensitive-stop.md +3 -3
  164. package/dist/agent-src/rules/self-repair-loop.md +0 -1
  165. package/dist/agent-src/rules/senior-engineering-discipline.md +0 -1
  166. package/dist/agent-src/rules/session-canary.md +7 -62
  167. package/dist/agent-src/rules/settings-ask-protocol.md +6 -6
  168. package/dist/agent-src/rules/size-enforcement.md +0 -1
  169. package/dist/agent-src/rules/skill-improvement-trigger.md +2 -3
  170. package/dist/agent-src/rules/skill-quality.md +0 -1
  171. package/dist/agent-src/rules/slash-command-routing-policy.md +0 -1
  172. package/dist/agent-src/rules/source-confidentiality.md +1 -1
  173. package/dist/agent-src/rules/source-discovery-gate.md +0 -1
  174. package/dist/agent-src/rules/source-of-truth.md +0 -1
  175. package/dist/agent-src/rules/spreadsheet-source-quality.md +1 -2
  176. package/dist/agent-src/rules/strategy-safety-floor.md +1 -1
  177. package/dist/agent-src/rules/symfony-routing.md +1 -2
  178. package/dist/agent-src/rules/think-before-action.md +0 -1
  179. package/dist/agent-src/rules/token-budget-discipline.md +12 -46
  180. package/dist/agent-src/rules/token-efficiency.md +0 -1
  181. package/dist/agent-src/rules/token-optimizer-maintenance.md +0 -1
  182. package/dist/agent-src/rules/tool-safety.md +1 -1
  183. package/dist/agent-src/rules/ui-audit-gate.md +1 -2
  184. package/dist/agent-src/rules/untrusted-input-defense.md +1 -1
  185. package/dist/agent-src/rules/upstream-proposal.md +0 -1
  186. package/dist/agent-src/rules/user-interaction.md +0 -1
  187. package/dist/agent-src/rules/user-interrupt-priority.md +1 -1
  188. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +115 -20
  189. package/dist/agent-src/scripts/deferral_carry.ts +339 -0
  190. package/dist/agent-src/scripts/gate_budget.ts +47 -23
  191. package/dist/agent-src/scripts/gate_execute.ts +12 -4
  192. package/dist/agent-src/scripts/update_roadmap_progress.ts +4 -1
  193. package/dist/agent-src/skills/ai-council/SKILL.md +7 -4
  194. package/dist/agent-src/skills/ai-council/references/cost-and-redaction.md +21 -11
  195. package/dist/agent-src/skills/ai-council/references/procedure.md +12 -6
  196. package/dist/agent-src/skills/analysis-autonomous-mode/SKILL.md +1 -1
  197. package/dist/agent-src/skills/api-design/data/manifest.json +2 -2
  198. package/dist/agent-src/skills/api-testing/SKILL.md +17 -0
  199. package/dist/agent-src/skills/bug-analyzer/SKILL.md +1 -1
  200. package/dist/agent-src/skills/code-intelligence/SKILL.md +14 -2
  201. package/dist/agent-src/skills/command-routing/SKILL.md +3 -4
  202. package/dist/agent-src/skills/conventional-commits-writing/SKILL.md +127 -139
  203. package/dist/agent-src/skills/corpus-grounding/ATTRIBUTION.md +39 -0
  204. package/dist/agent-src/skills/corpus-grounding/SKILL.md +8 -2
  205. package/dist/agent-src/skills/database/data/manifest.json +2 -2
  206. package/dist/agent-src/skills/database/data/query-tuning.csv +13 -13
  207. package/dist/agent-src/skills/design-system-capture/SKILL.md +0 -3
  208. package/dist/agent-src/skills/design-system-capture/references/import-procedure.md +1 -1
  209. package/dist/agent-src/skills/estimate-ticket/SKILL.md +1 -1
  210. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +2 -2
  211. package/dist/agent-src/skills/fe-design/SKILL.md +1 -1
  212. package/dist/agent-src/skills/feature-planning/SKILL.md +1 -1
  213. package/dist/agent-src/skills/git-workflow/SKILL.md +44 -44
  214. package/dist/agent-src/skills/git-workflow/references/branch-update.md +312 -0
  215. package/dist/agent-src/skills/git-workflow/references/commit-subject.md +205 -0
  216. package/dist/agent-src/skills/iconography/SKILL.md +1 -1
  217. package/dist/agent-src/skills/jira-integration/SKILL.md +3 -3
  218. package/dist/agent-src/skills/js-library-packaging/SKILL.md +2 -2
  219. package/dist/agent-src/skills/merge-conflicts/SKILL.md +10 -4
  220. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +1 -1
  221. package/dist/agent-src/skills/po-discovery/SKILL.md +1 -1
  222. package/dist/agent-src/skills/quality-tools/SKILL.md +11 -1
  223. package/dist/agent-src/skills/quality-tools/references/go-tools.md +76 -0
  224. package/dist/agent-src/skills/quality-tools/references/python-tools.md +104 -0
  225. package/dist/agent-src/skills/refine-ticket/SKILL.md +4 -4
  226. package/dist/agent-src/skills/review-routing/SKILL.md +2 -2
  227. package/dist/agent-src/skills/roadmap-writing/SKILL.md +2 -2
  228. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +5 -3
  229. package/dist/agent-src/skills/source-discovery/SKILL.md +1 -1
  230. package/dist/agent-src/skills/storybook-workshop/SKILL.md +3 -3
  231. package/dist/agent-src/skills/tailwind-engineer/SKILL.md +4 -2
  232. package/dist/agent-src/skills/test-case-discovery/SKILL.md +7 -0
  233. package/dist/agent-src/skills/test-driven-development/SKILL.md +17 -0
  234. package/dist/agent-src/skills/test-performance/SKILL.md +19 -1
  235. package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
  236. package/dist/agent-src/skills/ui-component-architect/SKILL.md +2 -2
  237. package/dist/agent-src/skills/using-git-worktrees/SKILL.md +1 -1
  238. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +2 -2
  239. package/dist/agent-src/templates/AGENTS.md +1 -1
  240. package/dist/agent-src/templates/agent-settings.md +46 -129
  241. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +3 -3
  242. package/dist/agent-src/templates/command.md +2 -2
  243. package/dist/agent-src/templates/roadmaps.md +6 -1
  244. package/dist/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -6
  245. package/dist/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +11 -7
  246. package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +48 -6
  247. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.ts +3 -2
  248. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.ts +2 -1
  249. package/dist/agent-src/templates/scripts/work_engine/hooks/settings.ts +0 -6
  250. package/dist/agent-src/templates/scripts/work_engine/scoring/decision_engine.ts +9 -12
  251. package/dist/agent-src/templates/scripts/work_engine/scoring/memory_visibility.ts +2 -1
  252. package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
  253. package/dist/agent-src/templates/skill.md +1 -1
  254. package/dist/cli/registry.js +2 -1
  255. package/dist/cli-delegate/archive_completed_roadmaps.js +92 -12
  256. package/dist/cli-delegate/check_update_banner.js +207 -120
  257. package/dist/cli-delegate/chunk-523HCFYO.js +90 -0
  258. package/dist/cli-delegate/{chunk-FP36SWJD.js → chunk-5GPULQBE.js} +2797 -338
  259. package/dist/cli-delegate/{chunk-IGD6ERX6.js → chunk-6SRJTYJS.js} +42 -176
  260. package/dist/cli-delegate/chunk-6V5FMA3P.js +186 -0
  261. package/dist/cli-delegate/{chunk-M2DPGFZ4.js → chunk-6V6TA25H.js} +22 -152
  262. package/dist/cli-delegate/chunk-6YQC2HLF.js +415 -0
  263. package/dist/cli-delegate/{chunk-E4XIZDIB.js → chunk-7HKRE54K.js} +1 -64
  264. package/dist/cli-delegate/chunk-7IQE3D5S.js +191 -0
  265. package/dist/cli-delegate/{chunk-YJ72UIAK.js → chunk-AED2VQGM.js} +1245 -249
  266. package/dist/cli-delegate/{chunk-7HQ52DHU.js → chunk-AL3RZ22D.js} +1 -1
  267. package/dist/cli-delegate/chunk-DEIV7XP7.js +108 -0
  268. package/dist/cli-delegate/{chunk-DBH4AHDK.js → chunk-ED7KCMLB.js} +9 -11
  269. package/dist/cli-delegate/chunk-F3QDG2GT.js +2569 -0
  270. package/dist/cli-delegate/{chunk-6KFEC3G7.js → chunk-G5VVIZRC.js} +3 -3
  271. package/dist/cli-delegate/{chunk-FC75PGJE.js → chunk-H76PHZBI.js} +149 -61
  272. package/dist/cli-delegate/chunk-IAYTIIQW.js +67 -0
  273. package/dist/cli-delegate/chunk-JQOM7TTM.js +1201 -0
  274. package/dist/cli-delegate/chunk-KB5FZ655.js +208 -0
  275. package/dist/cli-delegate/{chunk-7RQP4UDH.js → chunk-KR6EM23A.js} +235 -1455
  276. package/dist/cli-delegate/{chunk-LTYVIY76.js → chunk-KXXWJTDO.js} +6 -11
  277. package/dist/cli-delegate/{chunk-T7L2QK3K.js → chunk-LQOCRFWT.js} +1 -1
  278. package/dist/cli-delegate/{chunk-6KM6ORRY.js → chunk-MDPPKQCQ.js} +58 -9
  279. package/dist/cli-delegate/{chunk-4XFP2Y3E.js → chunk-MSUL5NYP.js} +5 -5
  280. package/dist/cli-delegate/chunk-OAFSJBHH.js +272 -0
  281. package/dist/cli-delegate/{chunk-4E2W63DA.js → chunk-OKJUIAPS.js} +62 -1
  282. package/dist/cli-delegate/{chunk-QAJS5YWY.js → chunk-PHD7OOLE.js} +2 -1
  283. package/dist/cli-delegate/{chunk-P6ZHP5W2.js → chunk-PWX7CKMD.js} +4 -4
  284. package/dist/cli-delegate/{chunk-NDJLNC6Q.js → chunk-T6BP34WI.js} +1 -0
  285. package/dist/cli-delegate/{chunk-7XGBX6ZH.js → chunk-T7XSJSUQ.js} +1144 -589
  286. package/dist/cli-delegate/chunk-ULQRUR23.js +208 -0
  287. package/dist/cli-delegate/chunk-WQWXGIWB.js +1779 -0
  288. package/dist/cli-delegate/{chunk-RGNIWTEA.js → chunk-XQTPXKFA.js} +1 -1
  289. package/dist/cli-delegate/{chunk-NUHLI2RX.js → chunk-YCU3TIXH.js} +2 -0
  290. package/dist/cli-delegate/chunk-ZBZV2G5R.js +210 -0
  291. package/dist/cli-delegate/{chunk-WGXTVKCQ.js → chunk-ZUZKZYCN.js} +5 -3
  292. package/dist/cli-delegate/cmd_analyze_session.js +223 -43
  293. package/dist/cli-delegate/cmd_brand_status.js +3 -2
  294. package/dist/cli-delegate/cmd_conformance.js +1252 -249
  295. package/dist/cli-delegate/cmd_converge.js +3 -3
  296. package/dist/cli-delegate/cmd_doctor.js +19 -9
  297. package/dist/cli-delegate/cmd_doctor_neighbours.js +30 -0
  298. package/dist/cli-delegate/cmd_explain.js +45 -21
  299. package/dist/cli-delegate/cmd_export.js +13 -10
  300. package/dist/cli-delegate/cmd_fleet.js +3 -3
  301. package/dist/cli-delegate/cmd_git_convention.js +1851 -0
  302. package/dist/cli-delegate/cmd_handoff.js +44 -22
  303. package/dist/cli-delegate/cmd_mcp_available.js +3 -2
  304. package/dist/cli-delegate/cmd_memory_get.js +3 -1
  305. package/dist/cli-delegate/cmd_migrate.js +3 -3
  306. package/dist/cli-delegate/cmd_packs_active.js +5 -4
  307. package/dist/cli-delegate/cmd_preflight.js +6 -6
  308. package/dist/cli-delegate/cmd_prune.js +14 -11
  309. package/dist/cli-delegate/cmd_refresh.js +2 -1
  310. package/dist/cli-delegate/cmd_route_audit.js +10 -8
  311. package/dist/cli-delegate/cmd_route_explain.js +4 -4
  312. package/dist/cli-delegate/cmd_session_recycle.js +10 -7
  313. package/dist/cli-delegate/cmd_settings_check.js +54 -7
  314. package/dist/cli-delegate/cmd_settings_get.js +18 -8
  315. package/dist/cli-delegate/cmd_settings_migrate.js +13 -10
  316. package/dist/cli-delegate/cmd_settings_set.js +4 -4
  317. package/dist/cli-delegate/cmd_sync.js +14 -11
  318. package/dist/cli-delegate/cmd_uninstall.js +15 -12
  319. package/dist/cli-delegate/cmd_update.js +7 -7
  320. package/dist/cli-delegate/cmd_upgrade.js +9 -8
  321. package/dist/cli-delegate/cmd_validate.js +15 -12
  322. package/dist/cli-delegate/cmd_versions.js +5 -5
  323. package/dist/cli-delegate/deferral_carry.js +16 -0
  324. package/dist/cli-delegate/gate_budget.js +1 -1
  325. package/dist/cli-delegate/gate_execute.js +3 -3
  326. package/dist/cli-delegate/roadmap_gates.js +6 -6
  327. package/dist/cli-delegate/update_roadmap_progress.js +1 -1
  328. package/dist/discovery/deprecation-report.md +1 -1
  329. package/dist/discovery/discovery-manifest.json +232 -141
  330. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  331. package/dist/discovery/discovery-manifest.summary.md +3 -3
  332. package/dist/discovery/dormancy-report.md +1 -1
  333. package/dist/discovery/orphan-report.md +1 -1
  334. package/dist/discovery/packs.json +26 -9
  335. package/dist/discovery/trust-report.md +3 -3
  336. package/dist/discovery/workspaces.json +7 -4
  337. package/dist/hooks/dispatch.js +5655 -6623
  338. package/dist/hooks/dispatch.sha256 +1 -1
  339. package/dist/install/claudePathsPlan.js +47 -6
  340. package/dist/install/claudeRuleRewrite.js +7 -0
  341. package/dist/install/emit_host_rules_cli.js +39 -36
  342. package/dist/install/globalRuleScope.js +87 -0
  343. package/dist/install/host_rule_ownership.js +160 -0
  344. package/dist/install/install.mjs +2336 -1249
  345. package/dist/install/installThinLayer.js +289 -0
  346. package/dist/install/installedRuleLinks.js +262 -0
  347. package/dist/install/wizard-plan.js +24 -0
  348. package/dist/mcp/awesome-mcp-servers.row.md +1 -1
  349. package/dist/mcp/mcp-cloudflare-catalogue.json +2 -2
  350. package/dist/mcp/registry-manifest.json +5 -5
  351. package/dist/mcp/server.json +2 -2
  352. package/dist/mcp/server.mjs +36504 -30986
  353. package/dist/router.json +1 -1
  354. package/dist/scripts/_lib/agent_settings.js +26 -120
  355. package/dist/scripts/_lib/claude_settings_hooks.js +10 -8
  356. package/dist/scripts/_lib/compile_time_toggles.js +12 -21
  357. package/dist/scripts/_lib/git_convention.js +232 -0
  358. package/dist/scripts/_lib/global_deploy_inventory.js +730 -0
  359. package/dist/scripts/_lib/installed_layer.js +704 -0
  360. package/dist/scripts/_lib/lean_projection_mode.js +218 -15
  361. package/dist/scripts/_lib/package_root.js +68 -0
  362. package/dist/scripts/_lib/rule_consequence_class.js +45 -0
  363. package/dist/scripts/_lib/rule_injection.js +67 -10
  364. package/dist/scripts/_lib/rule_law_section.js +122 -0
  365. package/dist/scripts/_lib/settings_removed_keys.js +168 -0
  366. package/dist/scripts/_lib/thin_rules.js +535 -0
  367. package/dist/scripts/_lib/windsurf_render.js +60 -0
  368. package/dist/scripts/condense.js +14 -26
  369. package/dist/scripts/project_thin_rules.js +14 -294
  370. package/dist/server/app.js +2 -1
  371. package/dist/server/gitKeysGate.js +105 -0
  372. package/dist/server/routes/settings.js +67 -8
  373. package/dist/server/routes/wizard.js +4 -0
  374. package/dist/server/schemas/settings.js +29 -81
  375. package/dist/shared/skillRanking.js +103 -16
  376. package/dist/ui/assets/{index-Cwq4d0hX.js → index-C3djEJah.js} +2 -2
  377. package/dist/ui/index.html +1 -1
  378. package/docs/MIGRATION.md +72 -1
  379. package/docs/contracts/settings-classes.md +39 -67
  380. package/docs/guidelines/agent-infra/active-remediation-mechanics.md +39 -0
  381. package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +1 -1
  382. package/docs/guidelines/agent-infra/cross-source-consistency-mechanics.md +8 -10
  383. package/docs/guidelines/agent-infra/frontier-reasoning-operating-profile.md +3 -2
  384. package/docs/guidelines/agent-infra/layered-settings.md +13 -1
  385. package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
  386. package/docs/guidelines/agent-infra/self-improvement-pipeline.md +10 -3
  387. package/docs/guidelines/agent-infra/size-and-scope.md +36 -0
  388. package/docs/guidelines/php/git.md +15 -2
  389. package/package.json +1 -1
  390. package/src/agent-src/scripts/archive_completed_roadmaps.ts +115 -20
  391. package/src/agent-src/scripts/deferral_carry.ts +339 -0
  392. package/src/agent-src/scripts/gate_budget.ts +47 -23
  393. package/src/agent-src/scripts/gate_execute.ts +12 -4
  394. package/src/agent-src/scripts/update_roadmap_progress.ts +4 -1
  395. package/src/agent-src/templates/AGENTS.md +1 -1
  396. package/src/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -6
  397. package/src/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +11 -7
  398. package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +48 -6
  399. package/src/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.ts +3 -2
  400. package/src/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.ts +2 -1
  401. package/src/agent-src/templates/scripts/work_engine/hooks/settings.ts +0 -6
  402. package/src/agent-src/templates/scripts/work_engine/scoring/decision_engine.ts +9 -12
  403. package/src/agent-src/templates/scripts/work_engine/scoring/memory_visibility.ts +2 -1
  404. package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
  405. package/src/config/agent-settings.template.yml +141 -334
  406. package/src/config/agents-paths.yml +16 -0
  407. package/src/config/assurance-capability-registry.json +7 -3
  408. package/src/config/ci-local-parity.yml +3 -0
  409. package/src/config/continuity-surface.json +10 -3
  410. package/src/config/discovery/packs.yml +17 -1
  411. package/src/config/evaluator-budgets.json +23 -10
  412. package/src/config/gate-coverage.yml +138 -3
  413. package/src/config/gate-violation-baselines.json +64 -16
  414. package/src/config/gitignore-block.txt +19 -0
  415. package/src/config/hook-bundle-budget.json +25 -0
  416. package/src/config/hook-token-budget.json +6 -1
  417. package/src/config/host-instruction-limits.json +33 -0
  418. package/src/config/release-gate-locality.yml +2 -1
  419. package/src/config/routing-coverage-seed.json +67 -4
  420. package/src/config/rule-activation-census.json +7 -3
  421. package/src/config/rule-consequence-class.json +161 -0
  422. package/src/config/rule-law-ceilings.json +105 -0
  423. package/src/config/rule-obligations.json +833 -0
  424. package/src/install/claudePathsPlan.ts +46 -4
  425. package/src/install/claudeRuleRewrite.ts +10 -1
  426. package/src/install/emit_host_rules_cli.ts +43 -34
  427. package/src/install/globalRuleScope.ts +109 -0
  428. package/src/install/host_rule_ownership.ts +170 -0
  429. package/src/install/installThinLayer.ts +378 -0
  430. package/src/install/installedRuleLinks.ts +308 -0
  431. package/src/install/wizard-plan.ts +24 -0
  432. package/src/scripts/_cli/cmd_analyze_session.ts +9 -15
  433. package/src/scripts/_cli/cmd_conformance.ts +13 -2
  434. package/src/scripts/_cli/cmd_doctor.ts +33 -81
  435. package/src/scripts/_cli/cmd_doctor_neighbours.ts +426 -0
  436. package/src/scripts/_cli/cmd_explain.ts +72 -14
  437. package/src/scripts/_cli/cmd_git_convention.ts +637 -0
  438. package/src/scripts/_cli/cmd_settings_check.ts +66 -8
  439. package/src/scripts/_cli/cmd_settings_get.ts +18 -3
  440. package/src/scripts/_cli/doctor_execution.ts +72 -1
  441. package/src/scripts/_dispatch.bash +53 -4
  442. package/src/scripts/_lib/agent_settings.ts +26 -124
  443. package/src/scripts/_lib/blocked_by_marker.ts +1 -1
  444. package/src/scripts/_lib/claude_settings_hooks.ts +10 -8
  445. package/src/scripts/_lib/compile_time_toggles.ts +12 -21
  446. package/src/scripts/_lib/dispatch_import_closure.ts +163 -0
  447. package/src/scripts/_lib/estate_offsets.ts +241 -0
  448. package/src/scripts/_lib/exemption_shape.ts +143 -0
  449. package/src/scripts/_lib/fnv.ts +23 -0
  450. package/src/scripts/_lib/foreign_scan.ts +106 -0
  451. package/src/scripts/_lib/git_base_ref.ts +92 -0
  452. package/src/scripts/_lib/git_convention.ts +291 -0
  453. package/src/scripts/_lib/git_convention_carrier.ts +389 -0
  454. package/src/scripts/_lib/git_convention_grammar.ts +246 -0
  455. package/src/scripts/_lib/git_convention_measure.ts +344 -0
  456. package/src/scripts/_lib/gitignore_block.ts +314 -0
  457. package/src/scripts/_lib/global_deploy_inventory.ts +106 -0
  458. package/src/scripts/_lib/graph_feeder_record.ts +437 -0
  459. package/src/scripts/_lib/hook_settings.ts +73 -0
  460. package/src/scripts/_lib/host_capability.ts +40 -19
  461. package/src/scripts/_lib/host_hook_merge.ts +165 -0
  462. package/src/scripts/_lib/installed_layer.ts +963 -0
  463. package/src/scripts/_lib/json_merge.ts +82 -0
  464. package/src/scripts/_lib/json_pointers.ts +93 -11
  465. package/src/scripts/_lib/knowledge_global.ts +14 -1
  466. package/src/scripts/_lib/lean_projection_mode.ts +275 -15
  467. package/src/scripts/_lib/machine_wake.ts +16 -3
  468. package/src/scripts/_lib/module_reach.ts +456 -0
  469. package/src/scripts/_lib/neighbour_census.ts +760 -0
  470. package/src/scripts/_lib/neighbour_contradictions.ts +236 -0
  471. package/src/scripts/_lib/neighbour_scan.ts +122 -0
  472. package/src/scripts/_lib/neighbour_tool_use.ts +187 -0
  473. package/src/scripts/_lib/prompt_shape.ts +46 -0
  474. package/src/scripts/_lib/ratification_artifact.ts +220 -1
  475. package/src/scripts/_lib/ratification_subject.ts +92 -0
  476. package/src/scripts/_lib/release_findings_ingest.ts +15 -7
  477. package/src/scripts/_lib/release_highlights.ts +5 -0
  478. package/src/scripts/_lib/release_migration_gate.ts +19 -3
  479. package/src/scripts/_lib/reserved_name_sweep.ts +73 -0
  480. package/src/scripts/_lib/review_coverage.ts +134 -0
  481. package/src/scripts/_lib/rule_consequence_class.ts +71 -0
  482. package/src/scripts/_lib/rule_injection.ts +130 -10
  483. package/src/scripts/_lib/rule_law_section.ts +147 -0
  484. package/src/scripts/_lib/rule_layer_overlap.ts +58 -0
  485. package/src/scripts/_lib/rule_obligations.ts +205 -0
  486. package/src/scripts/_lib/self_repair.ts +1 -1
  487. package/src/scripts/_lib/settings_removed_keys.ts +173 -0
  488. package/src/scripts/_lib/skill_origin.ts +254 -0
  489. package/src/scripts/_lib/structured_ask.ts +64 -21
  490. package/src/scripts/_lib/test_red_state.ts +5 -0
  491. package/src/scripts/_lib/thin_rules.ts +620 -0
  492. package/src/scripts/_lib/touched_file_quality.ts +570 -0
  493. package/src/scripts/_lib/turn_end_refusals.ts +77 -2
  494. package/src/scripts/_lib/windsurf_render.ts +63 -0
  495. package/src/scripts/_lib/worker_budget.ts +1 -1
  496. package/src/scripts/adr/regenerate_index.ts +16 -1
  497. package/src/scripts/ai_council/cli_call_budget.ts +13 -5
  498. package/src/scripts/ai_council/clients.ts +26 -57
  499. package/src/scripts/ai_council/config.ts +8 -8
  500. package/src/scripts/ai_council/modification_review.ts +100 -0
  501. package/src/scripts/ai_council/modification_review_questions.ts +90 -0
  502. package/src/scripts/ai_council/orchestrator.ts +5 -5
  503. package/src/scripts/ai_council/spend_gate.ts +18 -7
  504. package/src/scripts/ai_council/vendor_defaults.ts +45 -0
  505. package/src/scripts/ai_team/config.ts +11 -16
  506. package/src/scripts/audit_skill_overlap.ts +261 -0
  507. package/src/scripts/audit_user_type_axis.ts +20 -8
  508. package/src/scripts/before_complete_hook.ts +243 -12
  509. package/src/scripts/bench_ab_clone.ts +1 -2
  510. package/src/scripts/bench_concern_spawn_path.ts +129 -0
  511. package/src/scripts/bench_graph_feeder_latency.ts +584 -0
  512. package/src/scripts/bench_touched_file_quality.ts +238 -0
  513. package/src/scripts/check_agent_artifact_location.ts +36 -0
  514. package/src/scripts/check_branch_freshness.ts +147 -24
  515. package/src/scripts/check_enforcement_coverage.ts +130 -0
  516. package/src/scripts/check_enforcement_matrix.ts +377 -20
  517. package/src/scripts/check_estate_count.ts +130 -153
  518. package/src/scripts/check_evaluator_budgets.ts +4 -0
  519. package/src/scripts/check_finding_dispositions.ts +196 -21
  520. package/src/scripts/check_gate_coverage.ts +4 -3
  521. package/src/scripts/check_gate_reachability.ts +48 -1
  522. package/src/scripts/check_generator_sync.ts +48 -0
  523. package/src/scripts/check_hook_bundle_composition.ts +477 -0
  524. package/src/scripts/check_kernel_edit_ratified.ts +132 -14
  525. package/src/scripts/check_memory.ts +7 -1
  526. package/src/scripts/check_pack_size.ts +1 -1
  527. package/src/scripts/check_release_highlights.ts +10 -0
  528. package/src/scripts/check_release_manifest_content.ts +189 -0
  529. package/src/scripts/check_release_pr_shape.ts +38 -15
  530. package/src/scripts/check_standing_rule_delivery.ts +129 -13
  531. package/src/scripts/check_suppression_hygiene.ts +2 -5
  532. package/src/scripts/check_verify_expectation_delta.ts +521 -0
  533. package/src/scripts/ci_settle.ts +42 -5
  534. package/src/scripts/classify_merge_risk.ts +320 -0
  535. package/src/scripts/closure_scan.ts +91 -1
  536. package/src/scripts/code_graph/detect.ts +127 -7
  537. package/src/scripts/code_graph/foreign.ts +194 -0
  538. package/src/scripts/code_graph/query.ts +217 -4
  539. package/src/scripts/code_graph/types.ts +26 -2
  540. package/src/scripts/code_graph/validate.ts +3 -1
  541. package/src/scripts/code_graph/verbs.ts +103 -0
  542. package/src/scripts/command_suggester/settings.ts +8 -108
  543. package/src/scripts/command_suggester/types.ts +4 -5
  544. package/src/scripts/compile_hook_manifest.ts +33 -1
  545. package/src/scripts/condense.ts +14 -27
  546. package/src/scripts/consumer_matrix.ts +102 -0
  547. package/src/scripts/context_hygiene_hook.ts +13 -23
  548. package/src/scripts/cost/preflight.mjs +12 -1
  549. package/src/scripts/council_cli.ts +7 -7
  550. package/src/scripts/dispatch_r2_reviewer.ts +24 -11
  551. package/src/scripts/estate_exemption_shape.ts +202 -0
  552. package/src/scripts/explain_run.ts +8 -13
  553. package/src/scripts/generate_git_convention_grammar.ts +127 -0
  554. package/src/scripts/generate_host_cost_table.ts +21 -4
  555. package/src/scripts/handoff_context_hook.ts +86 -37
  556. package/src/scripts/hook_manifest.json +1 -1
  557. package/src/scripts/hook_manifest.yaml +175 -15
  558. package/src/scripts/hooks/block_config_weakening.ts +115 -7
  559. package/src/scripts/hooks/block_plumbing_writes.ts +37 -5
  560. package/src/scripts/hooks/code_graph_context_hook.ts +252 -23
  561. package/src/scripts/hooks/concern_failure_policy.ts +280 -0
  562. package/src/scripts/hooks/concern_registry.ts +2 -0
  563. package/src/scripts/hooks/delegation_nudge_hook.ts +2 -3
  564. package/src/scripts/hooks/dispatch_hook.ts +52 -52
  565. package/src/scripts/hooks/evidence_independence.ts +12 -4
  566. package/src/scripts/hooks/exit_codes.ts +2 -1
  567. package/src/scripts/hooks/host_lowering.json +1 -1
  568. package/src/scripts/hooks/host_lowering.ts +19 -1
  569. package/src/scripts/hooks/mcp_usage_observation_hook.ts +121 -0
  570. package/src/scripts/hooks/one_question_per_ask_hook.ts +41 -25
  571. package/src/scripts/hooks/payload_stub.ts +10 -1
  572. package/src/scripts/hooks/push_settle_hook.ts +4 -3
  573. package/src/scripts/hooks/rule_inject_hook.ts +795 -60
  574. package/src/scripts/hooks/state_io.ts +8 -4
  575. package/src/scripts/hooks/table_fingerprint.ts +21 -0
  576. package/src/scripts/hooks/telemetry_usage_hook.ts +24 -7
  577. package/src/scripts/hooks/turn_end_gate_hook.ts +85 -0
  578. package/src/scripts/hooks_status.ts +112 -0
  579. package/src/scripts/injection_scan_hook.ts +7 -0
  580. package/src/scripts/install-hooks.sh +42 -14
  581. package/src/scripts/install.ts +78 -215
  582. package/src/scripts/installed_layer_report.ts +103 -0
  583. package/src/scripts/language_mirror_hook.ts +15 -6
  584. package/src/scripts/learning_sidecar.ts +119 -8
  585. package/src/scripts/lint_blocker_citations.ts +198 -0
  586. package/src/scripts/lint_evidence_artifacts.ts +9 -0
  587. package/src/scripts/lint_hook_concern_budget.ts +10 -21
  588. package/src/scripts/lint_hook_manifest.ts +53 -0
  589. package/src/scripts/lint_major_migration_sections.ts +156 -26
  590. package/src/scripts/lint_pack_boundaries.ts +465 -29
  591. package/src/scripts/lint_roadmap_blockers.ts +282 -29
  592. package/src/scripts/lint_roadmap_complexity.ts +4 -2
  593. package/src/scripts/lint_rule_law_section.ts +647 -0
  594. package/src/scripts/lint_rule_skill_pack_reach.ts +17 -0
  595. package/src/scripts/lint_settings_classes.ts +1 -1
  596. package/src/scripts/lint_ticked_unmet_criteria.ts +165 -0
  597. package/src/scripts/lint_workflow_security.ts +173 -6
  598. package/src/scripts/mcp_server/consumer_tool_catalog.json +53 -0
  599. package/src/scripts/mcp_server/graph_tools.ts +72 -3
  600. package/src/scripts/measure_routing_signal.ts +54 -16
  601. package/src/scripts/measure_skill_ranker_baseline.ts +221 -8
  602. package/src/scripts/memory_learn_hook.ts +91 -6
  603. package/src/scripts/model_rule_injection.ts +55 -8
  604. package/src/scripts/onboarding_gate_hook.ts +7 -6
  605. package/src/scripts/print_required_checks.ts +15 -3
  606. package/src/scripts/probe_host_compliance.ts +33 -5
  607. package/src/scripts/probe_turnaround.ts +183 -3
  608. package/src/scripts/project_thin_rules.ts +34 -327
  609. package/src/scripts/ratification_header.ts +77 -0
  610. package/src/scripts/refusal_envelope.ts +138 -0
  611. package/src/scripts/release_publication.ts +29 -3
  612. package/src/scripts/report_dispatch_import_closure.ts +76 -0
  613. package/src/scripts/report_evidence_temperature.ts +657 -0
  614. package/src/scripts/report_installed_rule_links.ts +274 -0
  615. package/src/scripts/report_label_agreement.ts +233 -0
  616. package/src/scripts/report_module_reach.ts +212 -0
  617. package/src/scripts/report_obligation_mechanism.ts +228 -0
  618. package/src/scripts/report_parked_blockers.ts +222 -0
  619. package/src/scripts/report_required_checks_drift.ts +196 -0
  620. package/src/scripts/report_single_token_triggers.ts +277 -0
  621. package/src/scripts/report_skill_ranker_confusion.ts +543 -0
  622. package/src/scripts/report_standing_payload_by_host.ts +188 -15
  623. package/src/scripts/report_verification_record_coverage.ts +306 -0
  624. package/src/scripts/routing_doctor.ts +2 -2
  625. package/src/scripts/rule_activation_census.ts +5 -2
  626. package/src/scripts/rule_trigger_eval.ts +9 -9
  627. package/src/scripts/schemas/agent-settings.schema.json +17 -31
  628. package/src/scripts/schemas/command.schema.json +1 -1
  629. package/src/scripts/schemas/review-findings.schema.json +3 -2
  630. package/src/scripts/schemas/rule.schema.json +5 -0
  631. package/src/scripts/schemas/skill.schema.json +1 -1
  632. package/src/scripts/self_review_gate.ts +101 -9
  633. package/src/scripts/skill_tools/score_skill_relevance.ts +314 -40
  634. package/src/scripts/sweep_skill_ranker_signals.ts +129 -0
  635. package/src/scripts/sync_gitignore.ts +29 -235
  636. package/src/scripts/sync_pr_branch.ts +403 -132
  637. package/src/scripts/trigger_eval_grandfather.json +0 -21
  638. package/src/server/schemas/settings.ts +42 -176
  639. package/src/shared/skillRanking.ts +169 -14
  640. package/dist/cli-delegate/chunk-5R7HOLAF.js +0 -99
  641. package/dist/cli-delegate/chunk-JNMVLWLR.js +0 -4457
  642. package/dist/cli-delegate/chunk-YDPILCOL.js +0 -152
  643. package/src/scripts/_lib/config_chain.ts +0 -477
  644. package/src/scripts/_lib/conformance_report.ts +0 -403
  645. package/src/scripts/_lib/eval_discrimination.ts +0 -95
  646. package/src/scripts/_lib/evaluator_promotion.ts +0 -225
  647. package/src/scripts/_lib/file_slicer.ts +0 -117
  648. package/src/scripts/_lib/legacy_boundary_map.ts +0 -228
  649. package/src/scripts/_lib/minimality_tiebreak.ts +0 -168
  650. package/src/scripts/_lib/overbuild_lens_contract.ts +0 -196
  651. package/src/scripts/_lib/role_split.ts +0 -338
@@ -0,0 +1,543 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * report_skill_ranker_confusion — why the ranker misses, before anything changes.
4
+ *
5
+ * `road-to-a-ranker-that-routes` 1.3. The baseline measurement says the ranker
6
+ * is wrong on four prompts in five; it does not say in what WAY it is wrong, and
7
+ * a signal chosen without that is a guess dressed as a fix. This report is the
8
+ * read that has to come first, and it is deliberately READ-ONLY: it changes no
9
+ * default, flips no flag, and its only output is markdown on stdout.
10
+ *
11
+ * IT READS THE TUNING SLICE, NEVER THE SEALED ONE. The partition lives in
12
+ * `measure_skill_ranker_baseline.sliceForId`. A confusion class read off the
13
+ * sealed rows would make every later "lift on held-out data" claim circular —
14
+ * the rows would have been looked at while choosing what to change. The script
15
+ * therefore takes `--slice` but defaults to `tuning`, and prints the slice it
16
+ * read in the artifact's own header so a reader never has to assume.
17
+ *
18
+ * WHAT IT MEASURES, and each is one of 1.3's five asks:
19
+ *
20
+ * 1. per-pack top-1 — where the misses concentrate;
21
+ * 2. the most frequent (expected, ranked-first) pairs — WHICH skill the
22
+ * ranker reaches for instead, which is the only form of this number a
23
+ * candidate signal can be derived from;
24
+ * 3. mean reciprocal rank — whether a miss is a near miss or a rout;
25
+ * 4. the share of misses whose expected skill is outside the top ten —
26
+ * the same question asked as a cliff rather than as an average;
27
+ * 5. false activation on the deliberate empties — how often a prompt a seat
28
+ * judged to have NO skill answer draws a top score as confident as a
29
+ * genuine hit's.
30
+ *
31
+ * Usage:
32
+ * ./scripts-run src/scripts/report_skill_ranker_confusion > out.md
33
+ * ./scripts-run src/scripts/report_skill_ranker_confusion --slice sealed
34
+ * ./scripts-run src/scripts/report_skill_ranker_confusion --ranker keyword-v2
35
+ * ./scripts-run src/scripts/report_skill_ranker_confusion --date 2026-10-01
36
+ */
37
+
38
+ import * as path from 'node:path';
39
+ import { fileURLToPath } from 'node:url';
40
+
41
+ import { wilsonInterval } from './_lib/capture_rate.js';
42
+ import {
43
+ REPO,
44
+ SKILLS_DIR,
45
+ type LabelledPrompt,
46
+ type SliceName,
47
+ SLICE_NAMES,
48
+ packsForSkill,
49
+ parseFlagValue,
50
+ parseRanker,
51
+ partitionBySlice,
52
+ rankOptionsFor,
53
+ readMatrixCases,
54
+ readMatrixLabelledPrompts,
55
+ sliceForId,
56
+ sliceSizes,
57
+ } from './measure_skill_ranker_baseline.js';
58
+ import { _globSkillMd, rank, rankDetailed, type RankRow } from './skill_tools/score_skill_relevance.js';
59
+
60
+ /** How deep "outside the top ten" is. 1.3's own number, not a derived one. */
61
+ export const DEEP_MISS_DEPTH = 10;
62
+
63
+ /** How many confusion pairs the table carries. 1.3's own number. */
64
+ export const CONFUSION_PAIRS = 20;
65
+
66
+ function round3(n: number): number {
67
+ return Math.round(n * 1000) / 1000;
68
+ }
69
+
70
+ function pct(n: number, d: number): string {
71
+ return d === 0 ? 'n/a' : `${(100 * (n / d)).toFixed(1)} %`;
72
+ }
73
+
74
+ /**
75
+ * The 1-based position of the first expected skill, or 0 when the ranker never
76
+ * returns one at all.
77
+ *
78
+ * Zero rather than Infinity because the reciprocal of "absent" is 0, which is
79
+ * exactly what MRR wants, and because a sentinel that participates in
80
+ * arithmetic is how a rank-based metric quietly becomes a different metric.
81
+ */
82
+ export function firstExpectedRank(rows: readonly RankRow[], expected: readonly string[]): number {
83
+ for (let i = 0; i < rows.length; i += 1) {
84
+ if (expected.includes(rows[i]![0])) return i + 1;
85
+ }
86
+ return 0;
87
+ }
88
+
89
+ export interface RowReading {
90
+ id: string;
91
+ expected: string[];
92
+ rankedFirst: string | null;
93
+ topScore: number;
94
+ rankOfExpected: number;
95
+ /** An expected skill shares the winner's integer score (hit or miss). */
96
+ expectedInTopScoreBlock: boolean;
97
+ /** An expected skill shares the winner's whole ordering key and loses on name. */
98
+ lostOnTie: boolean;
99
+ }
100
+
101
+ /**
102
+ * The two tie readings for one ranking.
103
+ *
104
+ * `inBlock` asks whether an expected skill scored the winner's INTEGER — the
105
+ * block the alphabet orders under `keyword-v1`. `lostOnTie` asks whether the
106
+ * row was a top-1 miss that nothing but the name decided: the expected skill
107
+ * shares the winner's integer score and, under `tieBreakUnrounded`, its
108
+ * unrounded score too. Without the flag the two keys coincide, so `lostOnTie`
109
+ * is the evidence page's "scored exactly the winner's score and lost on its
110
+ * initial" class; with it, `lostOnTie` is what the unrounded score left.
111
+ */
112
+ export function tieReading(
113
+ rows: readonly RankRow[],
114
+ raw: ReadonlyMap<string, number>,
115
+ expected: readonly string[],
116
+ tieBreakUnrounded: boolean,
117
+ ): { inBlock: boolean; lostOnTie: boolean } {
118
+ const first = rows[0];
119
+ if (!first) return { inBlock: false, lostOnTie: false };
120
+ const block = rows.filter((r) => r[1] === first[1]);
121
+ const inBlock = block.some((r) => expected.includes(r[0]));
122
+ if (!inBlock || expected.includes(first[0])) return { inBlock, lostOnTie: false };
123
+ const lostOnTie = block.some(
124
+ (r) => expected.includes(r[0]) && (!tieBreakUnrounded || raw.get(r[0]) === raw.get(first[0])),
125
+ );
126
+ return { inBlock, lostOnTie };
127
+ }
128
+
129
+ export function readRows(
130
+ prompts: readonly LabelledPrompt[],
131
+ skillsDir: string,
132
+ ranker: string,
133
+ ): RowReading[] {
134
+ const opts = rankOptionsFor(ranker);
135
+ return prompts.map((p) => {
136
+ const { rows, raw } = rankDetailed(p.prompt, skillsDir, opts);
137
+ const tie = tieReading(rows, raw, p.expected, Boolean(opts.tieBreakUnrounded));
138
+ return {
139
+ id: p.id,
140
+ expected: p.expected,
141
+ rankedFirst: rows[0]?.[0] ?? null,
142
+ topScore: rows[0]?.[1] ?? 0,
143
+ rankOfExpected: firstExpectedRank(rows, p.expected),
144
+ expectedInTopScoreBlock: tie.inBlock,
145
+ lostOnTie: tie.lostOnTie,
146
+ };
147
+ });
148
+ }
149
+
150
+ export function meanReciprocalRank(readings: readonly RowReading[]): number {
151
+ if (readings.length === 0) return 0;
152
+ let sum = 0;
153
+ for (const r of readings) if (r.rankOfExpected > 0) sum += 1 / r.rankOfExpected;
154
+ return sum / readings.length;
155
+ }
156
+
157
+ export interface PackRow {
158
+ pack: string;
159
+ n: number;
160
+ top1: number;
161
+ }
162
+
163
+ export function perPackTop1(
164
+ readings: readonly RowReading[],
165
+ skillsDir: string,
166
+ ): PackRow[] {
167
+ const hit = new Map<string, number>();
168
+ const total = new Map<string, number>();
169
+ for (const r of readings) {
170
+ const packs = new Set<string>();
171
+ for (const s of r.expected) for (const p of packsForSkill(skillsDir, s)) packs.add(p);
172
+ const isHit = r.rankOfExpected === 1;
173
+ for (const p of packs) {
174
+ total.set(p, (total.get(p) ?? 0) + 1);
175
+ if (isHit) hit.set(p, (hit.get(p) ?? 0) + 1);
176
+ }
177
+ }
178
+ return [...total.keys()]
179
+ .map((pack) => ({
180
+ pack,
181
+ n: total.get(pack) ?? 0,
182
+ top1: round3((hit.get(pack) ?? 0) / Math.max(total.get(pack) ?? 1, 1)),
183
+ }))
184
+ // A TOTAL order, for the same reason `confusionPairs` below needs one:
185
+ // a comparator that never returns 0 leaves equal rows engine-ordered.
186
+ // Harmless here because `total` is a Map and its keys cannot collide —
187
+ // which is exactly why it would have stayed in place beside its own cure.
188
+ .sort((a, b) => a.top1 - b.top1 || b.n - a.n || (a.pack < b.pack ? -1 : a.pack > b.pack ? 1 : 0));
189
+ }
190
+
191
+ export interface ConfusionPair {
192
+ expected: string;
193
+ got: string;
194
+ count: number;
195
+ }
196
+
197
+ /**
198
+ * The (expected, ranked-first) pairs, most frequent first.
199
+ *
200
+ * Keyed on the label's FIRST skill — the seat wrote it best-fit-first, so it is
201
+ * the one the pair is a claim about. Counting every skill in a three-slot label
202
+ * would inflate a single row into three confusions and make the frequency column
203
+ * a count of label widths rather than of errors.
204
+ */
205
+ export function confusionPairs(readings: readonly RowReading[], limit = CONFUSION_PAIRS): ConfusionPair[] {
206
+ const counts = new Map<string, number>();
207
+ for (const r of readings) {
208
+ if (r.rankOfExpected === 1) continue;
209
+ const expected = r.expected[0] ?? '(none)';
210
+ const got = r.rankedFirst ?? '(nothing ranked)';
211
+ const key = `${expected}\u0000${got}`;
212
+ counts.set(key, (counts.get(key) ?? 0) + 1);
213
+ }
214
+ return (
215
+ [...counts.entries()]
216
+ .map(([key, count]) => {
217
+ const [expected, got] = key.split('\u0000');
218
+ return { expected: expected as string, got: got as string, count };
219
+ })
220
+ // A TOTAL order, so the table is reproducible. The earlier comparator
221
+ // tied on count and `expected` and then returned 1 for both argument
222
+ // orders — never 0 — which leaves equal rows in engine-defined order
223
+ // and quietly breaks the "regenerate every figure" claim this report
224
+ // opens with.
225
+ .sort(
226
+ (a, b) =>
227
+ b.count - a.count ||
228
+ (a.expected < b.expected ? -1 : a.expected > b.expected ? 1 : 0) ||
229
+ (a.got < b.got ? -1 : a.got > b.got ? 1 : 0),
230
+ )
231
+ .slice(0, limit)
232
+ );
233
+ }
234
+
235
+ /** The deliberate `expected_skills: []` rows, partitioned by the same seal. */
236
+ export function emptyRowIds(repo: string, slice: SliceName): { id: string; prompt: string }[] {
237
+ const out: { id: string; prompt: string }[] = [];
238
+ for (const c of readMatrixCases(repo)) {
239
+ if (c.expected?.length !== 0) continue;
240
+ const id = `${c.rule}#${c.section}[${String(c.ordinal)}]`;
241
+ if (slice !== 'all' && sliceForId(id) !== slice) continue;
242
+ out.push({ id, prompt: c.prompt });
243
+ }
244
+ return out;
245
+ }
246
+
247
+ export interface FalseActivation {
248
+ empties: number;
249
+ median_correct_hit_score: number;
250
+ at_or_above_median: number;
251
+ /** `null` when there is no threshold to compare against — see below. */
252
+ share: number | null;
253
+ correct_hits: number;
254
+ }
255
+
256
+ /**
257
+ * How often a prompt with no skill answer draws a score as confident as a hit.
258
+ *
259
+ * The comparison point is the MEDIAN top score among rows the ranker got right,
260
+ * which is the only threshold available that the ranker itself defines. A fixed
261
+ * cutoff would be a number chosen here, and the question 1.3 asks is whether the
262
+ * ranker's own confidence separates the two populations at all.
263
+ *
264
+ * WITH ZERO CORRECT HITS there is no such threshold, and the share is `null`
265
+ * rather than a number. Falling back to a median of 0 would count every empty as
266
+ * at-or-above it — every score is ≥ 0 — and print a 100 % false-activation rate
267
+ * indistinguishable from a measured one.
268
+ */
269
+ export function falseActivation(
270
+ labelled: readonly RowReading[],
271
+ emptyTopScores: readonly number[],
272
+ ): FalseActivation {
273
+ const hits = labelled
274
+ .filter((r) => r.rankOfExpected === 1)
275
+ .map((r) => r.topScore)
276
+ .sort((a, b) => a - b);
277
+ if (hits.length === 0) {
278
+ return {
279
+ empties: emptyTopScores.length,
280
+ median_correct_hit_score: 0,
281
+ at_or_above_median: 0,
282
+ share: null,
283
+ correct_hits: 0,
284
+ };
285
+ }
286
+ const median =
287
+ hits.length % 2 === 1
288
+ ? (hits[(hits.length - 1) / 2] as number)
289
+ : ((hits[hits.length / 2 - 1] as number) + (hits[hits.length / 2] as number)) / 2;
290
+ const over = emptyTopScores.filter((s) => s >= median).length;
291
+ return {
292
+ empties: emptyTopScores.length,
293
+ median_correct_hit_score: median,
294
+ at_or_above_median: over,
295
+ share: emptyTopScores.length ? round3(over / emptyTopScores.length) : null,
296
+ correct_hits: hits.length,
297
+ };
298
+ }
299
+
300
+ export interface AbstentionReading {
301
+ empties: number;
302
+ /** Empties whose top score is 0 — the ranker already abstains. */
303
+ noSkill: number;
304
+ threshold: number | null;
305
+ /** Empties whose top score is below `threshold`. */
306
+ abstainedEmpties: number;
307
+ correctHits: number;
308
+ /** Correct top-1 hits whose top score is below `threshold`. */
309
+ hitsLost: number;
310
+ }
311
+
312
+ /**
313
+ * What abstaining below one threshold buys on the empties and costs on the hits.
314
+ *
315
+ * A `null` threshold reads the no-skill rate only: with no correct hit there is
316
+ * no recall to cost, and inventing a cutoff would put a number chosen here
317
+ * beside a measured one.
318
+ */
319
+ export function abstentionReading(
320
+ labelled: readonly RowReading[],
321
+ emptyTopScores: readonly number[],
322
+ threshold: number | null,
323
+ ): AbstentionReading {
324
+ const hits = labelled.filter((r) => r.rankOfExpected === 1);
325
+ return {
326
+ empties: emptyTopScores.length,
327
+ noSkill: emptyTopScores.filter((s) => s === 0).length,
328
+ threshold,
329
+ abstainedEmpties: threshold === null ? 0 : emptyTopScores.filter((s) => s < threshold).length,
330
+ correctHits: hits.length,
331
+ hitsLost: threshold === null ? 0 : hits.filter((r) => r.topScore < threshold).length,
332
+ };
333
+ }
334
+
335
+ function interval(successes: number, trials: number): string {
336
+ const raw = wilsonInterval(successes, trials);
337
+ return `${round3(raw.lower).toFixed(3)} – ${round3(raw.upper).toFixed(3)}`;
338
+ }
339
+
340
+ export function renderReport(opts: {
341
+ repo: string;
342
+ skillsDir: string;
343
+ ranker: string;
344
+ slice: SliceName;
345
+ date: string;
346
+ }): string {
347
+ const whole = readMatrixLabelledPrompts(opts.repo);
348
+ const sizes = sliceSizes(whole);
349
+ const prompts = partitionBySlice(whole, opts.slice);
350
+ const readings = readRows(prompts, opts.skillsDir, opts.ranker);
351
+
352
+ const n = readings.length;
353
+ const top1 = readings.filter((r) => r.rankOfExpected === 1).length;
354
+ const top3 = readings.filter((r) => r.rankOfExpected >= 1 && r.rankOfExpected <= 3).length;
355
+ const unranked = readings.filter((r) => r.rankOfExpected === 0).length;
356
+ const misses = readings.filter((r) => r.rankOfExpected !== 1);
357
+ const deep = misses.filter((r) => r.rankOfExpected === 0 || r.rankOfExpected > DEEP_MISS_DEPTH).length;
358
+ const mrr = meanReciprocalRank(readings);
359
+ const tieLoss = readings.filter((r) => r.lostOnTie).length;
360
+ const inBlock = readings.filter((r) => r.expectedInTopScoreBlock).length;
361
+
362
+ const empties = emptyRowIds(opts.repo, opts.slice);
363
+ const rankOpts = rankOptionsFor(opts.ranker);
364
+ const emptyScores = empties.map((e) => rank(e.prompt, opts.skillsDir, rankOpts)[0]?.[1] ?? 0);
365
+ const fa = falseActivation(readings, emptyScores);
366
+
367
+ const packs = perPackTop1(readings, opts.skillsDir);
368
+ const pairs = confusionPairs(readings);
369
+
370
+ const L: string[] = [];
371
+ L.push(`# Skill-ranker confusion report — ${opts.ranker}, ${opts.slice} slice`);
372
+ L.push('');
373
+ L.push('<!-- evidence-type: analysis -->');
374
+ L.push('');
375
+ L.push(`Produced by \`road-to-a-ranker-that-routes\` 1.3 on ${opts.date}. Read-only: this`);
376
+ L.push('report changes no default and flips no flag. Regenerate every measured figure');
377
+ L.push('below with');
378
+ L.push('');
379
+ L.push('```bash');
380
+ L.push(`./scripts-run src/scripts/report_skill_ranker_confusion --ranker ${opts.ranker} --slice ${opts.slice}`);
381
+ L.push('```');
382
+ L.push('');
383
+ L.push('## What was read');
384
+ L.push('');
385
+ L.push('| | |');
386
+ L.push('|---|---:|');
387
+ L.push(`| labelled rows in the routing matrix | ${String(sizes.all)} |`);
388
+ L.push(`| …in the tuning slice | ${String(sizes.tuning)} |`);
389
+ L.push(`| …in the sealed slice | ${String(sizes.sealed)} |`);
390
+ L.push(`| rows this report read (\`${opts.slice}\`) | ${String(n)} |`);
391
+ L.push(`| deliberate \`expected_skills: []\` rows in the same slice | ${String(empties.length)} |`);
392
+ // The LOADER's own glob, not a second one written here. This count is
393
+ // published as the population behind the document-frequency denominator, so
394
+ // a reimplementation that diverged would print a count of something the
395
+ // ranker did not index — and this one did diverge: it used `existsSync`
396
+ // where the loader uses `statSync().isDirectory()` and swallows errors, and
397
+ // it threw on an absent directory where `rank()` returns [].
398
+ L.push(`| skills indexed | ${String(_globSkillMd(opts.skillsDir).length)} |`);
399
+ L.push('');
400
+ if (opts.slice === 'tuning') {
401
+ L.push('The sealed slice is **not** read here. A confusion class derived from rows a');
402
+ L.push('later lift is measured on would make that lift circular, which is the one');
403
+ L.push('failure a held-out partition exists to prevent.');
404
+ } else if (opts.slice === 'sealed') {
405
+ L.push('**This run READ the sealed slice.** That is legitimate for reporting a result');
406
+ L.push('on held-out rows and is NOT legitimate as an input to choosing what to change:');
407
+ L.push('a confusion class derived from these rows would make every later lift measured');
408
+ L.push('on them circular. Derive from the `tuning` run.');
409
+ } else {
410
+ L.push('**This run read BOTH slices.** A confusion class derived from it therefore');
411
+ L.push('includes the sealed rows, so it may not be used to choose what to change —');
412
+ L.push('that is the `tuning` run, and the seal only means something if the choosing');
413
+ L.push('never sees the other half.');
414
+ }
415
+ L.push('');
416
+ L.push('## The headline on this slice');
417
+ L.push('');
418
+ L.push('| measure | value | 95 % CI |');
419
+ L.push('|---|---:|---|');
420
+ L.push(`| top-1 | ${round3(top1 / Math.max(n, 1)).toFixed(3)} | ${interval(top1, n)} |`);
421
+ L.push(`| top-3 | ${round3(top3 / Math.max(n, 1)).toFixed(3)} | ${interval(top3, n)} |`);
422
+ L.push(`| mean reciprocal rank | ${round3(mrr).toFixed(3)} | — |`);
423
+ L.push('');
424
+ L.push('MRR is the average of 1 / (position of the first expected skill), counting a row');
425
+ L.push('where no expected skill appears anywhere in the ranking as 0. It is the figure');
426
+ L.push('that separates "the right answer was second" from "the right answer was never');
427
+ L.push('returned", and top-1 alone cannot.');
428
+ L.push('');
429
+ L.push('## How deep the misses are');
430
+ L.push('');
431
+ L.push('| | count | share of misses |');
432
+ L.push('|---|---:|---:|');
433
+ L.push(`| top-1 misses | ${String(misses.length)} | — |`);
434
+ L.push(`| …expected skill outside the top ${String(DEEP_MISS_DEPTH)} | ${String(deep)} | ${pct(deep, misses.length)} |`);
435
+ L.push(`| …expected skill not ranked at all (score 0) | ${String(unranked)} | ${pct(unranked, misses.length)} |`);
436
+ L.push('');
437
+ L.push('A miss inside the top ten is a ranking problem — the right skill is in the');
438
+ L.push('candidate set and something else outscored it. A miss outside it, and above all');
439
+ L.push('a row where the expected skill scores zero, is a RECALL problem: no re-weighting');
440
+ L.push('of the existing signal can recover a skill the formula never surfaces. The two');
441
+ L.push('take different fixes, which is why the split is reported rather than an average.');
442
+ L.push('');
443
+ L.push('## Ties');
444
+ L.push('');
445
+ L.push('| metric | rows | share of rows read |');
446
+ L.push('|---|---:|---:|');
447
+ L.push(`| \`top1_loss_due_to_tie\` | ${String(tieLoss)} | ${pct(tieLoss, n)} |`);
448
+ L.push(`| \`expected_in_top_score_block\` | ${String(inBlock)} | ${pct(inBlock, n)} |`);
449
+ L.push('');
450
+ L.push('`top1_loss_due_to_tie` counts top-1 misses where an expected skill shares the');
451
+ L.push('winner\'s whole ordering key and loses on the name alone — the integer score, and');
452
+ L.push('under `tieBreakUnrounded` the unrounded score as well. `expected_in_top_score_block`');
453
+ L.push('counts rows, hit or miss, whose expected skill scores the winner\'s integer.');
454
+ L.push('');
455
+ L.push('## False activation on the no-skill prompts');
456
+ L.push('');
457
+ L.push('| | |');
458
+ L.push('|---|---:|');
459
+ L.push(`| deliberate empties in this slice | ${String(fa.empties)} |`);
460
+ L.push(`| correct top-1 hits the median is taken over | ${String(fa.correct_hits)} |`);
461
+ L.push(`| median top score of a correct hit | ${String(fa.median_correct_hit_score)} |`);
462
+ L.push(`| empties whose top score reaches that median | ${String(fa.at_or_above_median)} |`);
463
+ // TWO causes produce a null share and they are not the same answer: no
464
+ // correct hit means there is no threshold to compare against, no empty row
465
+ // means there is nothing to compare. Printing one reason for both would
466
+ // state something the `correct_hits` row beside it contradicts.
467
+ const shareCell =
468
+ fa.share !== null
469
+ ? pct(fa.at_or_above_median, fa.empties)
470
+ : fa.correct_hits === 0
471
+ ? 'n/a — no correct top-1 hit, so no threshold'
472
+ : 'n/a — no deliberate empties in this slice, so no denominator';
473
+ L.push(`| share | ${shareCell} |`);
474
+ L.push('');
475
+ L.push('The threshold is the ranker\'s own median hit score rather than a cutoff chosen');
476
+ L.push('here, because the question is whether the ranker\'s confidence separates the two');
477
+ L.push('populations at all. A share near one half means it does not: a prompt a seat');
478
+ L.push('judged to have no skill answer is scored as confidently as a prompt it got right.');
479
+ L.push('');
480
+ const ab = abstentionReading(readings, emptyScores, fa.correct_hits > 0 ? fa.median_correct_hit_score : null);
481
+ L.push('## Abstention, beside its cost');
482
+ L.push('');
483
+ L.push('| | |');
484
+ L.push('|---|---:|');
485
+ L.push(`| empties the ranker already returns nothing for (no-skill rate) | ${String(ab.noSkill)} of ${String(ab.empties)} (${pct(ab.noSkill, ab.empties)}) |`);
486
+ if (ab.threshold === null) {
487
+ L.push('| abstention threshold | n/a — no correct top-1 hit, so no threshold |');
488
+ } else {
489
+ L.push(`| abstention threshold (abstain below the median correct-hit score) | ${String(ab.threshold)} |`);
490
+ L.push(`| empties that threshold abstains on | ${String(ab.abstainedEmpties)} of ${String(ab.empties)} (${pct(ab.abstainedEmpties, ab.empties)}) |`);
491
+ L.push(`| correct top-1 hits it would suppress (recall cost) | ${String(ab.hitsLost)} of ${String(ab.correctHits)} (${pct(ab.hitsLost, ab.correctHits)}) |`);
492
+ }
493
+ L.push('');
494
+ L.push('One threshold, the same median the false-activation table compares against, so');
495
+ L.push('the gain on the empties and the recall it costs are read off one number.');
496
+ L.push('');
497
+ L.push(`## Per-pack top-1, worst first`);
498
+ L.push('');
499
+ L.push('| pack | labelled rows | top-1 |');
500
+ L.push('|---|---:|---:|');
501
+ for (const p of packs) L.push(`| \`${p.pack}\` | ${String(p.n)} | ${p.top1.toFixed(3)} |`);
502
+ L.push('');
503
+ L.push('A row counts once per pack of each skill its label names, so the column sums');
504
+ L.push('above the row count — the same accounting the per-pack census uses.');
505
+ L.push('');
506
+ L.push(`## The ${String(CONFUSION_PAIRS)} most frequent (expected, ranked-first) pairs`);
507
+ L.push('');
508
+ L.push('| expected (label, best fit first) | ranked first instead | rows |');
509
+ L.push('|---|---|---:|');
510
+ for (const p of pairs) L.push(`| \`${p.expected}\` | \`${p.got}\` | ${String(p.count)} |`);
511
+ L.push('');
512
+ return `${L.join('\n')}\n`;
513
+ }
514
+
515
+ export function main(argv: readonly string[]): number {
516
+ let body: string;
517
+ try {
518
+ // Every flag through the shared parsers, inside one guard. A typo or a
519
+ // missing value must not reach the renderer: the label is printed in the
520
+ // report's own title and in the regenerate command beside it, and the
521
+ // date is printed in its header, so a swallowed next-flag would publish
522
+ // one configuration's number under another's name or stamp `--slice` as
523
+ // the date. `parseSlice` is not reused here only because this tool's
524
+ // default is `tuning` rather than `all`; the legal set is the one
525
+ // shared constant, so the two cannot disagree about what is valid.
526
+ const rawSlice = parseFlagValue(argv, '--slice', 'tuning');
527
+ if (!SLICE_NAMES.includes(rawSlice as SliceName)) {
528
+ throw new Error(`--slice expects one of ${SLICE_NAMES.join(' | ')}, got ${rawSlice}`);
529
+ }
530
+ const ranker = parseRanker(argv);
531
+ const date = parseFlagValue(argv, '--date', new Date().toISOString().slice(0, 10));
532
+ body = renderReport({ repo: REPO, skillsDir: SKILLS_DIR, ranker, slice: rawSlice as SliceName, date });
533
+ } catch (err) {
534
+ process.stderr.write(`${(err as Error).message}\n`);
535
+ return 2;
536
+ }
537
+ process.stdout.write(body);
538
+ return 0;
539
+ }
540
+
541
+ if (process.argv[1] && fileURLToPath(import.meta.url) === path.resolve(process.argv[1])) {
542
+ process.exit(main(process.argv.slice(2)));
543
+ }