@event4u/agent-config 16.1.0 → 16.3.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 (467) 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 +98 -257
  5. package/README.md +14 -12
  6. package/dist/agent-src/commands/analyze/inbox.md +1 -1
  7. package/dist/agent-src/commands/analyze/roadmap-repos.md +1 -1
  8. package/dist/agent-src/commands/bug/fix.md +17 -2
  9. package/dist/agent-src/commands/feature/plan.md +1 -1
  10. package/dist/agent-src/commands/feature/roadmap.md +1 -1
  11. package/dist/agent-src/commands/fix/ci.md +1 -1
  12. package/dist/agent-src/commands/implement-ticket.md +1 -1
  13. package/dist/agent-src/commands/jira-ticket.md +1 -1
  14. package/dist/agent-src/commands/roadmap/create.md +1 -1
  15. package/dist/agent-src/commands/roadmap/materialize.md +1 -1
  16. package/dist/agent-src/commands/roadmap/process-full.md +5 -5
  17. package/dist/agent-src/commands/roadmap/resolve-blockers.md +361 -0
  18. package/dist/agent-src/commands/roadmap/triage-parked.md +325 -0
  19. package/dist/agent-src/commands/roadmap.md +18 -4
  20. package/dist/agent-src/commands/tests/create.md +17 -3
  21. package/dist/agent-src/commands/tests/execute.md +22 -5
  22. package/dist/agent-src/commands/work.md +4 -0
  23. package/dist/agent-src/contexts/authority/decision-revisit-gate-enforcement.md +43 -0
  24. package/dist/agent-src/contexts/communication/rules-auto/design-fidelity-enforcement.md +24 -0
  25. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +6 -6
  26. package/dist/agent-src/contexts/execution/autonomy-mechanics.md +4 -8
  27. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +32 -2
  28. package/dist/agent-src/contexts/execution/session-canary-enforcement-history.md +67 -0
  29. package/dist/agent-src/contexts/execution/toolchain-resolver.md +101 -7
  30. package/dist/agent-src/rules/active-remediation.md +1 -1
  31. package/dist/agent-src/rules/autonomous-execution.md +1 -0
  32. package/dist/agent-src/rules/broken-access-control.md +1 -0
  33. package/dist/agent-src/rules/command-suggestion-policy.md +1 -0
  34. package/dist/agent-src/rules/context-hygiene.md +1 -1
  35. package/dist/agent-src/rules/decision-revisit-gate.md +16 -33
  36. package/dist/agent-src/rules/design-fidelity.md +13 -16
  37. package/dist/agent-src/rules/doc-screenshot-hygiene.md +1 -0
  38. package/dist/agent-src/rules/domain-safety-disclaimer.md +1 -0
  39. package/dist/agent-src/rules/domain-safety-pii.md +1 -0
  40. package/dist/agent-src/rules/domain-safety-retention.md +1 -0
  41. package/dist/agent-src/rules/engineering-safety-floor.md +1 -0
  42. package/dist/agent-src/rules/evaluator-independence.md +3 -2
  43. package/dist/agent-src/rules/fast-path-marker-visibility.md +1 -0
  44. package/dist/agent-src/rules/finance-safety-floor.md +1 -0
  45. package/dist/agent-src/rules/git-history-discipline.md +1 -0
  46. package/dist/agent-src/rules/image-likeness-and-rights.md +1 -0
  47. package/dist/agent-src/rules/legal-safety-floor.md +3 -2
  48. package/dist/agent-src/rules/lethal-trifecta-guard.md +1 -0
  49. package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +1 -0
  50. package/dist/agent-src/rules/media-governance-routing.md +14 -17
  51. package/dist/agent-src/rules/persona-governance.md +2 -2
  52. package/dist/agent-src/rules/provider-lifecycle-discipline.md +1 -1
  53. package/dist/agent-src/rules/question-not-instruction.md +1 -0
  54. package/dist/agent-src/rules/roadmap-progress-sync.md +1 -1
  55. package/dist/agent-src/rules/runtime-safety.md +1 -0
  56. package/dist/agent-src/rules/secret-vcs-guard.md +1 -0
  57. package/dist/agent-src/rules/security-sensitive-stop.md +3 -2
  58. package/dist/agent-src/rules/session-canary.md +8 -62
  59. package/dist/agent-src/rules/settings-ask-protocol.md +1 -0
  60. package/dist/agent-src/rules/source-confidentiality.md +1 -0
  61. package/dist/agent-src/rules/strategy-safety-floor.md +1 -0
  62. package/dist/agent-src/rules/tool-safety.md +1 -0
  63. package/dist/agent-src/rules/ui-audit-gate.md +1 -2
  64. package/dist/agent-src/rules/untrusted-input-defense.md +1 -0
  65. package/dist/agent-src/rules/user-interrupt-priority.md +1 -0
  66. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +115 -20
  67. package/dist/agent-src/scripts/deferral_carry.ts +339 -0
  68. package/dist/agent-src/scripts/update_roadmap_progress.ts +4 -1
  69. package/dist/agent-src/skills/accessibility-auditor/data/aria-patterns.csv +1 -1
  70. package/dist/agent-src/skills/accessibility-auditor/data/manifest.json +2 -2
  71. package/dist/agent-src/skills/api-design/data/manifest.json +2 -2
  72. package/dist/agent-src/skills/api-testing/SKILL.md +17 -0
  73. package/dist/agent-src/skills/code-intelligence/SKILL.md +14 -2
  74. package/dist/agent-src/skills/design-review/SKILL.md +30 -4
  75. package/dist/agent-src/skills/design-review/references/verification-automation.md +32 -0
  76. package/dist/agent-src/skills/design-system-capture/references/import-procedure.md +1 -1
  77. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +18 -3
  78. package/dist/agent-src/skills/existing-ui-audit/references/component-taxonomy-detection.md +56 -0
  79. package/dist/agent-src/skills/fe-design/SKILL.md +1 -1
  80. package/dist/agent-src/skills/iconography/SKILL.md +1 -1
  81. package/dist/agent-src/skills/js-library-packaging/SKILL.md +2 -2
  82. package/dist/agent-src/skills/markitdown/SKILL.md +4 -0
  83. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +1 -1
  84. package/dist/agent-src/skills/playwright-testing/SKILL.md +30 -6
  85. package/dist/agent-src/skills/quality-tools/SKILL.md +11 -1
  86. package/dist/agent-src/skills/quality-tools/references/go-tools.md +76 -0
  87. package/dist/agent-src/skills/quality-tools/references/python-tools.md +104 -0
  88. package/dist/agent-src/skills/review-routing/SKILL.md +2 -2
  89. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +1 -1
  90. package/dist/agent-src/skills/storybook-workshop/SKILL.md +3 -3
  91. package/dist/agent-src/skills/tailwind-engineer/SKILL.md +1 -1
  92. package/dist/agent-src/skills/test-case-discovery/SKILL.md +7 -0
  93. package/dist/agent-src/skills/test-driven-development/SKILL.md +17 -0
  94. package/dist/agent-src/skills/test-performance/SKILL.md +19 -1
  95. package/dist/agent-src/skills/ui-component-architect/SKILL.md +25 -2
  96. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  97. package/dist/agent-src/templates/roadmaps.md +30 -0
  98. package/dist/agent-src/templates/scripts/work_engine/directives/ui/app_spec.ts +10 -4
  99. package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +302 -21
  100. package/dist/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +22 -3
  101. package/dist/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +6 -1
  102. package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
  103. package/dist/agent-src/templates/scripts/work_engine/state.ts +57 -7
  104. package/dist/agent-src/templates/scripts/work_engine/taxonomy/detect.ts +500 -0
  105. package/dist/agent-src/templates/scripts/work_engine/taxonomy/place.ts +183 -0
  106. package/dist/cli/python/knowledge_ingest.js +1 -1
  107. package/dist/cli/python/workspace_drive.js +1 -1
  108. package/dist/cli/registry.js +1 -1
  109. package/dist/cli-delegate/archive_completed_roadmaps.js +92 -12
  110. package/dist/cli-delegate/check_update_banner.js +12 -1
  111. package/dist/cli-delegate/chunk-523HCFYO.js +90 -0
  112. package/dist/cli-delegate/{chunk-M2DPGFZ4.js → chunk-6V6TA25H.js} +22 -152
  113. package/dist/cli-delegate/chunk-7IQE3D5S.js +191 -0
  114. package/dist/cli-delegate/{chunk-6KFEC3G7.js → chunk-CQWX336L.js} +1 -1
  115. package/dist/cli-delegate/chunk-DEIV7XP7.js +108 -0
  116. package/dist/cli-delegate/chunk-EEHDXSYD.js +2040 -0
  117. package/dist/cli-delegate/{chunk-P6ZHP5W2.js → chunk-GKE7ZVFA.js} +4 -4
  118. package/dist/cli-delegate/chunk-JQOM7TTM.js +1201 -0
  119. package/dist/cli-delegate/{chunk-UNCRJBT3.js → chunk-JQVYKIZA.js} +41 -0
  120. package/dist/cli-delegate/{chunk-FC75PGJE.js → chunk-JY2I2DXV.js} +12 -1
  121. package/dist/cli-delegate/chunk-KB5FZ655.js +208 -0
  122. package/dist/cli-delegate/{chunk-YUM5KURG.js → chunk-KR6EM23A.js} +235 -1455
  123. package/dist/cli-delegate/{chunk-LTYVIY76.js → chunk-LIYTLH6O.js} +1 -1
  124. package/dist/cli-delegate/chunk-NQ7WT43P.js +2729 -0
  125. package/dist/cli-delegate/chunk-NXEILF2K.js +2160 -0
  126. package/dist/cli-delegate/{chunk-5R7HOLAF.js → chunk-NYX3L2PZ.js} +1 -1
  127. package/dist/cli-delegate/{chunk-4E2W63DA.js → chunk-OKJUIAPS.js} +62 -1
  128. package/dist/cli-delegate/{chunk-QAJS5YWY.js → chunk-PHD7OOLE.js} +2 -1
  129. package/dist/cli-delegate/{chunk-RGNIWTEA.js → chunk-QLDHIPWR.js} +1 -1
  130. package/dist/cli-delegate/{chunk-HDVVGPQW.js → chunk-RQNNW7IF.js} +1405 -567
  131. package/dist/cli-delegate/{chunk-S3VFXMTM.js → chunk-S4UMZNES.js} +1 -1
  132. package/dist/cli-delegate/{chunk-6KM6ORRY.js → chunk-S4YWNRKO.js} +24 -8
  133. package/dist/cli-delegate/{chunk-GJCBB2UG.js → chunk-TRI6DQZ6.js} +3054 -325
  134. package/dist/cli-delegate/chunk-ULQRUR23.js +208 -0
  135. package/dist/cli-delegate/{chunk-NUHLI2RX.js → chunk-YCU3TIXH.js} +2 -0
  136. package/dist/cli-delegate/chunk-ZBZV2G5R.js +210 -0
  137. package/dist/cli-delegate/{chunk-WGXTVKCQ.js → chunk-ZUZKZYCN.js} +5 -3
  138. package/dist/cli-delegate/cmd_analyze_session.js +1 -1
  139. package/dist/cli-delegate/cmd_brand_status.js +1 -1
  140. package/dist/cli-delegate/cmd_conformance.js +1862 -809
  141. package/dist/cli-delegate/cmd_doctor.js +13 -6
  142. package/dist/cli-delegate/cmd_doctor_neighbours.js +23 -0
  143. package/dist/cli-delegate/cmd_explain.js +5 -5
  144. package/dist/cli-delegate/cmd_export.js +11 -8
  145. package/dist/cli-delegate/cmd_fleet.js +3 -3
  146. package/dist/cli-delegate/cmd_handoff.js +10 -7
  147. package/dist/cli-delegate/cmd_mcp_available.js +1 -1
  148. package/dist/cli-delegate/cmd_memory_get.js +3 -1
  149. package/dist/cli-delegate/cmd_migrate.js +2 -2
  150. package/dist/cli-delegate/cmd_packs_active.js +3 -3
  151. package/dist/cli-delegate/cmd_preflight.js +6 -6
  152. package/dist/cli-delegate/cmd_prune.js +11 -8
  153. package/dist/cli-delegate/cmd_refresh.js +2 -1
  154. package/dist/cli-delegate/cmd_route_audit.js +8 -6
  155. package/dist/cli-delegate/cmd_route_explain.js +4 -4
  156. package/dist/cli-delegate/cmd_session_recycle.js +4 -3
  157. package/dist/cli-delegate/cmd_settings_get.js +1 -1
  158. package/dist/cli-delegate/cmd_settings_migrate.js +11 -8
  159. package/dist/cli-delegate/cmd_settings_set.js +4 -4
  160. package/dist/cli-delegate/cmd_sync.js +11 -8
  161. package/dist/cli-delegate/cmd_uninstall.js +11 -8
  162. package/dist/cli-delegate/cmd_update.js +1 -1
  163. package/dist/cli-delegate/cmd_upgrade.js +3 -2
  164. package/dist/cli-delegate/cmd_validate.js +11 -8
  165. package/dist/cli-delegate/cmd_versions.js +1 -1
  166. package/dist/cli-delegate/deferral_carry.js +16 -0
  167. package/dist/cli-delegate/gate_execute.js +2 -2
  168. package/dist/cli-delegate/roadmap_gates.js +5 -5
  169. package/dist/cli-delegate/update_roadmap_progress.js +1 -1
  170. package/dist/discovery/deprecation-report.md +1 -1
  171. package/dist/discovery/discovery-manifest.json +132 -80
  172. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  173. package/dist/discovery/discovery-manifest.summary.md +3 -3
  174. package/dist/discovery/dormancy-report.md +1 -1
  175. package/dist/discovery/orphan-report.md +1 -1
  176. package/dist/discovery/packs.json +7 -5
  177. package/dist/discovery/trust-report.md +2 -2
  178. package/dist/discovery/workspaces.json +6 -4
  179. package/dist/hooks/dispatch.js +7972 -5186
  180. package/dist/hooks/dispatch.sha256 +1 -0
  181. package/dist/install/claudePathsPlan.js +47 -6
  182. package/dist/install/claudeRuleRewrite.js +7 -0
  183. package/dist/install/emit_host_rules_cli.js +39 -36
  184. package/dist/install/globalRuleScope.js +87 -0
  185. package/dist/install/host_rule_ownership.js +160 -0
  186. package/dist/install/install.mjs +2226 -1055
  187. package/dist/install/installThinLayer.js +261 -0
  188. package/dist/install/installedRuleLinks.js +176 -0
  189. package/dist/install/wizard-plan.js +24 -0
  190. package/dist/mcp/registry-manifest.json +3 -3
  191. package/dist/mcp/server.json +2 -2
  192. package/dist/mcp/server.mjs +40913 -34865
  193. package/dist/scripts/_lib/agent_settings.js +11 -0
  194. package/dist/scripts/_lib/claude_settings_hooks.js +10 -8
  195. package/dist/scripts/_lib/installed_layer.js +378 -0
  196. package/dist/scripts/_lib/lean_projection_mode.js +218 -15
  197. package/dist/scripts/_lib/rule_consequence_class.js +45 -0
  198. package/dist/scripts/_lib/rule_injection.js +67 -10
  199. package/dist/scripts/_lib/rule_law_section.js +122 -0
  200. package/dist/scripts/_lib/thin_rules.js +458 -0
  201. package/dist/scripts/_lib/windsurf_render.js +60 -0
  202. package/dist/scripts/condense.js +14 -26
  203. package/dist/scripts/project_thin_rules.js +14 -294
  204. package/dist/server/schemas/settings.js +29 -0
  205. package/dist/shared/skillRanking.js +74 -13
  206. package/dist/ui/assets/index-Cwq4d0hX.js +23 -0
  207. package/dist/ui/assets/index-Cyjy8bWO.css +1 -0
  208. package/dist/ui/index.html +2 -2
  209. package/docs/contracts/settings-classes.md +10 -6
  210. package/package.json +4 -4
  211. package/src/agent-src/scripts/archive_completed_roadmaps.ts +115 -20
  212. package/src/agent-src/scripts/deferral_carry.ts +339 -0
  213. package/src/agent-src/scripts/update_roadmap_progress.ts +4 -1
  214. package/src/agent-src/templates/scripts/work_engine/directives/ui/app_spec.ts +10 -4
  215. package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +302 -21
  216. package/src/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +22 -3
  217. package/src/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +6 -1
  218. package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
  219. package/src/agent-src/templates/scripts/work_engine/state.ts +57 -7
  220. package/src/agent-src/templates/scripts/work_engine/taxonomy/detect.ts +500 -0
  221. package/src/agent-src/templates/scripts/work_engine/taxonomy/place.ts +183 -0
  222. package/src/config/agent-settings.template.yml +91 -22
  223. package/src/config/ci-local-parity.yml +18 -0
  224. package/src/config/continuity-surface.json +9 -2
  225. package/src/config/evaluator-budgets.json +4 -4
  226. package/src/config/gate-coverage.yml +327 -3
  227. package/src/config/gate-violation-baselines.json +21 -9
  228. package/src/config/hook-bundle-budget.json +25 -0
  229. package/src/config/hook-latency-budget.json +21 -0
  230. package/src/config/hook-token-budget.json +8 -3
  231. package/src/config/host-instruction-limits.json +33 -0
  232. package/src/config/metric-registry.yml +114 -0
  233. package/src/config/placeholder-drift-budget.json +10 -0
  234. package/src/config/routing-coverage-seed.json +38 -3
  235. package/src/config/rule-activation-census.json +7 -3
  236. package/src/config/rule-consequence-class.json +161 -0
  237. package/src/config/rule-law-ceilings.json +99 -0
  238. package/src/install/claudePathsPlan.ts +46 -4
  239. package/src/install/claudeRuleRewrite.ts +10 -1
  240. package/src/install/emit_host_rules_cli.ts +43 -34
  241. package/src/install/globalRuleScope.ts +109 -0
  242. package/src/install/host_rule_ownership.ts +170 -0
  243. package/src/install/installThinLayer.ts +312 -0
  244. package/src/install/installedRuleLinks.ts +220 -0
  245. package/src/install/wizard-plan.ts +24 -0
  246. package/src/scripts/_cli/cmd_doctor.ts +28 -90
  247. package/src/scripts/_cli/cmd_doctor_neighbours.ts +293 -0
  248. package/src/scripts/_cli/doctor_execution.ts +100 -17
  249. package/src/scripts/_cli/doctor_network_posture.ts +226 -0
  250. package/src/scripts/_dispatch.bash +16 -2
  251. package/src/scripts/_lib/agent_settings.ts +11 -0
  252. package/src/scripts/_lib/body_portable.ts +102 -0
  253. package/src/scripts/_lib/cc_transcript.ts +132 -1
  254. package/src/scripts/_lib/claude_settings_hooks.ts +10 -8
  255. package/src/scripts/_lib/concern_sla_window.ts +200 -0
  256. package/src/scripts/_lib/estate_offsets.ts +241 -0
  257. package/src/scripts/_lib/exemption_shape.ts +143 -0
  258. package/src/scripts/_lib/fnv.ts +23 -0
  259. package/src/scripts/_lib/foreign_scan.ts +106 -0
  260. package/src/scripts/_lib/forge_protection.ts +114 -0
  261. package/src/scripts/_lib/forge_reader.ts +558 -0
  262. package/src/scripts/_lib/gitignore_block.ts +314 -0
  263. package/src/scripts/_lib/global_deploy_inventory.ts +32 -0
  264. package/src/scripts/_lib/graph_feeder_record.ts +214 -0
  265. package/src/scripts/_lib/hook_settings.ts +73 -0
  266. package/src/scripts/_lib/host_capability.ts +40 -19
  267. package/src/scripts/_lib/host_env_write.ts +111 -0
  268. package/src/scripts/_lib/host_hook_merge.ts +165 -0
  269. package/src/scripts/_lib/installed_layer.ts +538 -0
  270. package/src/scripts/_lib/json_merge.ts +82 -0
  271. package/src/scripts/_lib/json_pointers.ts +93 -11
  272. package/src/scripts/_lib/lean_projection_mode.ts +275 -15
  273. package/src/scripts/_lib/llm_proposer_transport.ts +14 -4
  274. package/src/scripts/_lib/machine_wake.ts +16 -3
  275. package/src/scripts/_lib/neighbour_census.ts +760 -0
  276. package/src/scripts/_lib/neighbour_scan.ts +122 -0
  277. package/src/scripts/_lib/neighbour_tool_use.ts +189 -0
  278. package/src/scripts/_lib/obligations.ts +119 -8
  279. package/src/scripts/_lib/probe_inputs.ts +271 -0
  280. package/src/scripts/_lib/prompt_shape.ts +46 -0
  281. package/src/scripts/_lib/read_surface_scan.ts +322 -0
  282. package/src/scripts/_lib/release_highlights.ts +2 -1
  283. package/src/scripts/_lib/release_migration_gate.ts +19 -3
  284. package/src/scripts/_lib/reserved_name_sweep.ts +73 -0
  285. package/src/scripts/_lib/retrieval_sanitize.ts +77 -16
  286. package/src/scripts/_lib/review_coverage.ts +134 -0
  287. package/src/scripts/_lib/rule_consequence_class.ts +71 -0
  288. package/src/scripts/_lib/rule_injection.ts +130 -10
  289. package/src/scripts/_lib/rule_law_section.ts +147 -0
  290. package/src/scripts/_lib/rule_layer_overlap.ts +58 -0
  291. package/src/scripts/_lib/shell_write_shapes.ts +108 -0
  292. package/src/scripts/_lib/skill_origin.ts +254 -0
  293. package/src/scripts/_lib/structural_hiding.ts +622 -0
  294. package/src/scripts/_lib/structured_ask.ts +64 -21
  295. package/src/scripts/_lib/thin_rules.ts +540 -0
  296. package/src/scripts/_lib/touched_file_quality.ts +434 -0
  297. package/src/scripts/_lib/turn_end_refusals.ts +600 -4
  298. package/src/scripts/_lib/turn_end_transcript.ts +216 -0
  299. package/src/scripts/_lib/verification_command.ts +324 -0
  300. package/src/scripts/_lib/verification_evidence.ts +647 -0
  301. package/src/scripts/_lib/verify_clause.ts +280 -0
  302. package/src/scripts/_lib/windsurf_render.ts +63 -0
  303. package/src/scripts/ai_council/cli_call_budget.ts +13 -5
  304. package/src/scripts/ai_council/clients.ts +26 -57
  305. package/src/scripts/ai_council/config.ts +1 -1
  306. package/src/scripts/ai_council/vendor_defaults.ts +45 -0
  307. package/src/scripts/ai_team/team_dispatch.ts +4 -0
  308. package/src/scripts/audit_skill_overlap.ts +261 -0
  309. package/src/scripts/before_complete_hook.ts +573 -25
  310. package/src/scripts/bench_hook_latency.ts +412 -5
  311. package/src/scripts/bench_touched_file_quality.ts +238 -0
  312. package/src/scripts/cache_realization_report.ts +61 -1
  313. package/src/scripts/check_argument_hint.ts +287 -0
  314. package/src/scripts/check_claims.ts +125 -1
  315. package/src/scripts/check_enforcement_coverage.ts +38 -9
  316. package/src/scripts/check_enforcement_matrix.ts +621 -22
  317. package/src/scripts/check_estate_count.ts +130 -153
  318. package/src/scripts/check_finding_dispositions.ts +138 -7
  319. package/src/scripts/check_generator_sync.ts +71 -0
  320. package/src/scripts/check_hook_bundle_composition.ts +370 -0
  321. package/src/scripts/check_host_docs_digest.ts +786 -0
  322. package/src/scripts/check_host_format_column.ts +559 -0
  323. package/src/scripts/check_input_references.ts +228 -0
  324. package/src/scripts/check_inputs_parity.ts +235 -0
  325. package/src/scripts/check_kernel_edit_ratified.ts +89 -9
  326. package/src/scripts/check_kill_switch_table.ts +294 -0
  327. package/src/scripts/check_memory.ts +7 -1
  328. package/src/scripts/check_placeholder_drift.ts +221 -0
  329. package/src/scripts/check_read_surface_coverage.ts +515 -0
  330. package/src/scripts/check_release_highlights.ts +10 -0
  331. package/src/scripts/check_release_holds.ts +2 -1
  332. package/src/scripts/check_release_pr_shape.ts +38 -15
  333. package/src/scripts/check_routing_coverage.ts +378 -11
  334. package/src/scripts/check_standing_rule_delivery.ts +33 -13
  335. package/src/scripts/check_static_parity.ts +17 -0
  336. package/src/scripts/check_verify_expectation_delta.ts +521 -0
  337. package/src/scripts/ci_settle.ts +145 -19
  338. package/src/scripts/closure_scan.ts +115 -1
  339. package/src/scripts/code_graph/detect.ts +127 -7
  340. package/src/scripts/code_graph/foreign.ts +194 -0
  341. package/src/scripts/code_graph/query.ts +217 -4
  342. package/src/scripts/code_graph/types.ts +26 -2
  343. package/src/scripts/code_graph/validate.ts +3 -1
  344. package/src/scripts/code_graph/verbs.ts +103 -0
  345. package/src/scripts/compile_hook_manifest.ts +90 -14
  346. package/src/scripts/condense.ts +14 -27
  347. package/src/scripts/estate_exemption_shape.ts +202 -0
  348. package/src/scripts/external_sources_denylist.json +29 -4
  349. package/src/scripts/generate_host_cost_table.ts +1 -1
  350. package/src/scripts/hook_manifest.json +1 -1
  351. package/src/scripts/hook_manifest.yaml +192 -14
  352. package/src/scripts/hooks/block_config_weakening.ts +294 -4
  353. package/src/scripts/hooks/block_kernel_rule_writes.ts +9 -78
  354. package/src/scripts/hooks/block_plumbing_writes.ts +342 -0
  355. package/src/scripts/hooks/bundle_integrity.ts +291 -0
  356. package/src/scripts/hooks/chain_nudge_hook.ts +1 -2
  357. package/src/scripts/hooks/code_graph_context_hook.ts +253 -25
  358. package/src/scripts/hooks/comment_discipline_hook.ts +1 -3
  359. package/src/scripts/hooks/concern_failure_policy.ts +280 -0
  360. package/src/scripts/hooks/concern_registry.ts +2 -0
  361. package/src/scripts/hooks/concern_timings.ts +94 -0
  362. package/src/scripts/hooks/delegation_nudge_hook.ts +1 -2
  363. package/src/scripts/hooks/design_pass_hook.ts +100 -9
  364. package/src/scripts/hooks/design_slop_hook.ts +1 -2
  365. package/src/scripts/hooks/dispatch_hook.ts +77 -71
  366. package/src/scripts/hooks/edit_shape_hook.ts +1 -2
  367. package/src/scripts/hooks/end_review_nudge_hook.ts +1 -1
  368. package/src/scripts/hooks/evidence_independence.ts +1 -2
  369. package/src/scripts/hooks/exit_codes.ts +129 -0
  370. package/src/scripts/hooks/host_lowering.json +1 -0
  371. package/src/scripts/hooks/host_lowering.ts +146 -3
  372. package/src/scripts/hooks/host_lowering.yaml +262 -46
  373. package/src/scripts/hooks/host_semantics.ts +30 -2
  374. package/src/scripts/hooks/injection_budget.ts +9 -2
  375. package/src/scripts/hooks/interruption_ledger_hook.ts +1 -2
  376. package/src/scripts/hooks/journal_record_hook.ts +1 -2
  377. package/src/scripts/hooks/memory_recall_hook.ts +1 -2
  378. package/src/scripts/hooks/obligation_settle_hook.ts +151 -5
  379. package/src/scripts/hooks/one_question_per_ask_hook.ts +43 -6
  380. package/src/scripts/hooks/orchestration_record_hook.ts +1 -2
  381. package/src/scripts/hooks/payload_stub.ts +10 -1
  382. package/src/scripts/hooks/permission_gate.ts +1 -2
  383. package/src/scripts/hooks/push_settle_hook.ts +1 -3
  384. package/src/scripts/hooks/replay_hook.ts +2 -1
  385. package/src/scripts/hooks/reread_guard_hook.ts +1 -2
  386. package/src/scripts/hooks/review_baseline_hook.ts +1 -2
  387. package/src/scripts/hooks/rtk_wrap_hook.ts +1 -2
  388. package/src/scripts/hooks/rule_inject_hook.ts +765 -68
  389. package/src/scripts/hooks/run_continuation_hook.ts +13 -15
  390. package/src/scripts/hooks/skill_route_hook.ts +1 -2
  391. package/src/scripts/hooks/source_first_gate_hook.ts +1 -2
  392. package/src/scripts/hooks/spawn_guard_shadow_hook.ts +1 -2
  393. package/src/scripts/hooks/subagent_ledger_hook.ts +1 -2
  394. package/src/scripts/hooks/suggestion_capture_hook.ts +1 -1
  395. package/src/scripts/hooks/table_fingerprint.ts +70 -0
  396. package/src/scripts/hooks/telemetry_flush_hook.ts +1 -2
  397. package/src/scripts/hooks/telemetry_usage_hook.ts +65 -10
  398. package/src/scripts/hooks/tool_result_bytes_hook.ts +93 -9
  399. package/src/scripts/hooks/turn_end_gate_hook.ts +421 -324
  400. package/src/scripts/hooks/ui_route_nudge_hook.ts +1 -2
  401. package/src/scripts/hooks_status.ts +112 -0
  402. package/src/scripts/injection_scan_hook.ts +7 -0
  403. package/src/scripts/install.ts +75 -189
  404. package/src/scripts/installed_layer_report.ts +103 -0
  405. package/src/scripts/language_mirror_hook.ts +15 -6
  406. package/src/scripts/learning_sidecar.ts +119 -8
  407. package/src/scripts/lint_deny_text.ts +419 -0
  408. package/src/scripts/lint_exit_codes.ts +262 -0
  409. package/src/scripts/lint_hook_manifest.ts +108 -0
  410. package/src/scripts/lint_major_migration_sections.ts +156 -26
  411. package/src/scripts/lint_pack_boundaries.ts +63 -5
  412. package/src/scripts/lint_roadmap_blockers.ts +78 -12
  413. package/src/scripts/lint_rule_law_section.ts +517 -0
  414. package/src/scripts/lint_skill_descriptions.ts +1 -1
  415. package/src/scripts/lint_skill_scripts_readonly.ts +1 -1
  416. package/src/scripts/lint_workflow_security.ts +161 -5
  417. package/src/scripts/mcp_server/consumer_tool_catalog.json +53 -0
  418. package/src/scripts/mcp_server/graph_tools.ts +72 -3
  419. package/src/scripts/mcp_server/prompts.ts +142 -1
  420. package/src/scripts/measure_routing_signal.ts +54 -16
  421. package/src/scripts/measure_skill_ranker_baseline.ts +515 -53
  422. package/src/scripts/measure_turn_end_gate.ts +193 -0
  423. package/src/scripts/memory_learn_hook.ts +91 -6
  424. package/src/scripts/memory_lookup.ts +1 -1
  425. package/src/scripts/model_rule_injection.ts +52 -5
  426. package/src/scripts/prepack-check.mjs +53 -0
  427. package/src/scripts/project_thin_rules.ts +34 -327
  428. package/src/scripts/release_publication.ts +13 -1
  429. package/src/scripts/report_evidence_temperature.ts +657 -0
  430. package/src/scripts/report_installed_rule_links.ts +157 -0
  431. package/src/scripts/report_invocation_surface.ts +383 -0
  432. package/src/scripts/report_label_agreement.ts +233 -0
  433. package/src/scripts/report_obligation_carriers.ts +699 -0
  434. package/src/scripts/report_obligation_mechanism.ts +230 -0
  435. package/src/scripts/report_obligation_writer_split.ts +236 -0
  436. package/src/scripts/report_single_token_triggers.ts +277 -0
  437. package/src/scripts/report_skill_menu_census.ts +208 -0
  438. package/src/scripts/report_skill_ranker_confusion.ts +442 -0
  439. package/src/scripts/report_standing_payload_by_host.ts +188 -15
  440. package/src/scripts/report_verification_record_coverage.ts +306 -0
  441. package/src/scripts/roadmap_verify_share.ts +213 -0
  442. package/src/scripts/rule_activation_census.ts +5 -2
  443. package/src/scripts/rule_trigger_eval.ts +9 -9
  444. package/src/scripts/schemas/command.schema.json +44 -0
  445. package/src/scripts/schemas/review-findings.schema.json +7 -2
  446. package/src/scripts/schemas/rule.schema.json +5 -0
  447. package/src/scripts/schemas/skill.schema.json +44 -0
  448. package/src/scripts/self_review_gate.ts +421 -17
  449. package/src/scripts/semantic_parity_census.ts +314 -0
  450. package/src/scripts/session_eol_report.ts +54 -1
  451. package/src/scripts/skill_tools/score_skill_relevance.ts +290 -25
  452. package/src/scripts/sweep_dead_scan_roots.ts +1 -1
  453. package/src/scripts/sweep_skill_ranker_signals.ts +129 -0
  454. package/src/scripts/sync_gitignore.ts +29 -235
  455. package/src/scripts/trigger_eval_grandfather.json +0 -7
  456. package/src/scripts/trigger_eval_rotation.ts +122 -27
  457. package/src/scripts/ui_conformance_probe.ts +156 -4
  458. package/src/scripts/update_prices.ts +85 -3
  459. package/src/scripts/write_bundle_digest.mjs +74 -0
  460. package/src/server/schemas/settings.ts +41 -0
  461. package/src/shared/skillRanking.ts +117 -11
  462. package/src/templates/consumer-settings/ONBOARDING.md +1 -0
  463. package/dist/cli-delegate/chunk-FXYUYU4N.js +0 -4416
  464. package/dist/cli-delegate/chunk-QJWAUMJW.js +0 -1072
  465. package/dist/cli-delegate/chunk-YDPILCOL.js +0 -152
  466. package/dist/ui/assets/index-DH1xc62v.js +0 -29
  467. package/dist/ui/assets/index-jSfMW8_t.css +0 -1
@@ -0,0 +1,442 @@
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, 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
+ }
96
+
97
+ export function readRows(
98
+ prompts: readonly LabelledPrompt[],
99
+ skillsDir: string,
100
+ ranker: string,
101
+ ): RowReading[] {
102
+ const opts = rankOptionsFor(ranker);
103
+ return prompts.map((p) => {
104
+ const rows = rank(p.prompt, skillsDir, opts);
105
+ return {
106
+ id: p.id,
107
+ expected: p.expected,
108
+ rankedFirst: rows[0]?.[0] ?? null,
109
+ topScore: rows[0]?.[1] ?? 0,
110
+ rankOfExpected: firstExpectedRank(rows, p.expected),
111
+ };
112
+ });
113
+ }
114
+
115
+ export function meanReciprocalRank(readings: readonly RowReading[]): number {
116
+ if (readings.length === 0) return 0;
117
+ let sum = 0;
118
+ for (const r of readings) if (r.rankOfExpected > 0) sum += 1 / r.rankOfExpected;
119
+ return sum / readings.length;
120
+ }
121
+
122
+ export interface PackRow {
123
+ pack: string;
124
+ n: number;
125
+ top1: number;
126
+ }
127
+
128
+ export function perPackTop1(
129
+ readings: readonly RowReading[],
130
+ skillsDir: string,
131
+ ): PackRow[] {
132
+ const hit = new Map<string, number>();
133
+ const total = new Map<string, number>();
134
+ for (const r of readings) {
135
+ const packs = new Set<string>();
136
+ for (const s of r.expected) for (const p of packsForSkill(skillsDir, s)) packs.add(p);
137
+ const isHit = r.rankOfExpected === 1;
138
+ for (const p of packs) {
139
+ total.set(p, (total.get(p) ?? 0) + 1);
140
+ if (isHit) hit.set(p, (hit.get(p) ?? 0) + 1);
141
+ }
142
+ }
143
+ return [...total.keys()]
144
+ .map((pack) => ({
145
+ pack,
146
+ n: total.get(pack) ?? 0,
147
+ top1: round3((hit.get(pack) ?? 0) / Math.max(total.get(pack) ?? 1, 1)),
148
+ }))
149
+ // A TOTAL order, for the same reason `confusionPairs` below needs one:
150
+ // a comparator that never returns 0 leaves equal rows engine-ordered.
151
+ // Harmless here because `total` is a Map and its keys cannot collide —
152
+ // which is exactly why it would have stayed in place beside its own cure.
153
+ .sort((a, b) => a.top1 - b.top1 || b.n - a.n || (a.pack < b.pack ? -1 : a.pack > b.pack ? 1 : 0));
154
+ }
155
+
156
+ export interface ConfusionPair {
157
+ expected: string;
158
+ got: string;
159
+ count: number;
160
+ }
161
+
162
+ /**
163
+ * The (expected, ranked-first) pairs, most frequent first.
164
+ *
165
+ * Keyed on the label's FIRST skill — the seat wrote it best-fit-first, so it is
166
+ * the one the pair is a claim about. Counting every skill in a three-slot label
167
+ * would inflate a single row into three confusions and make the frequency column
168
+ * a count of label widths rather than of errors.
169
+ */
170
+ export function confusionPairs(readings: readonly RowReading[], limit = CONFUSION_PAIRS): ConfusionPair[] {
171
+ const counts = new Map<string, number>();
172
+ for (const r of readings) {
173
+ if (r.rankOfExpected === 1) continue;
174
+ const expected = r.expected[0] ?? '(none)';
175
+ const got = r.rankedFirst ?? '(nothing ranked)';
176
+ const key = `${expected}\u0000${got}`;
177
+ counts.set(key, (counts.get(key) ?? 0) + 1);
178
+ }
179
+ return (
180
+ [...counts.entries()]
181
+ .map(([key, count]) => {
182
+ const [expected, got] = key.split('\u0000');
183
+ return { expected: expected as string, got: got as string, count };
184
+ })
185
+ // A TOTAL order, so the table is reproducible. The earlier comparator
186
+ // tied on count and `expected` and then returned 1 for both argument
187
+ // orders — never 0 — which leaves equal rows in engine-defined order
188
+ // and quietly breaks the "regenerate every figure" claim this report
189
+ // opens with.
190
+ .sort(
191
+ (a, b) =>
192
+ b.count - a.count ||
193
+ (a.expected < b.expected ? -1 : a.expected > b.expected ? 1 : 0) ||
194
+ (a.got < b.got ? -1 : a.got > b.got ? 1 : 0),
195
+ )
196
+ .slice(0, limit)
197
+ );
198
+ }
199
+
200
+ /** The deliberate `expected_skills: []` rows, partitioned by the same seal. */
201
+ export function emptyRowIds(repo: string, slice: SliceName): { id: string; prompt: string }[] {
202
+ const out: { id: string; prompt: string }[] = [];
203
+ for (const c of readMatrixCases(repo)) {
204
+ if (c.expected?.length !== 0) continue;
205
+ const id = `${c.rule}#${c.section}[${String(c.ordinal)}]`;
206
+ if (slice !== 'all' && sliceForId(id) !== slice) continue;
207
+ out.push({ id, prompt: c.prompt });
208
+ }
209
+ return out;
210
+ }
211
+
212
+ export interface FalseActivation {
213
+ empties: number;
214
+ median_correct_hit_score: number;
215
+ at_or_above_median: number;
216
+ /** `null` when there is no threshold to compare against — see below. */
217
+ share: number | null;
218
+ correct_hits: number;
219
+ }
220
+
221
+ /**
222
+ * How often a prompt with no skill answer draws a score as confident as a hit.
223
+ *
224
+ * The comparison point is the MEDIAN top score among rows the ranker got right,
225
+ * which is the only threshold available that the ranker itself defines. A fixed
226
+ * cutoff would be a number chosen here, and the question 1.3 asks is whether the
227
+ * ranker's own confidence separates the two populations at all.
228
+ *
229
+ * WITH ZERO CORRECT HITS there is no such threshold, and the share is `null`
230
+ * rather than a number. Falling back to a median of 0 would count every empty as
231
+ * at-or-above it — every score is ≥ 0 — and print a 100 % false-activation rate
232
+ * indistinguishable from a measured one.
233
+ */
234
+ export function falseActivation(
235
+ labelled: readonly RowReading[],
236
+ emptyTopScores: readonly number[],
237
+ ): FalseActivation {
238
+ const hits = labelled
239
+ .filter((r) => r.rankOfExpected === 1)
240
+ .map((r) => r.topScore)
241
+ .sort((a, b) => a - b);
242
+ if (hits.length === 0) {
243
+ return {
244
+ empties: emptyTopScores.length,
245
+ median_correct_hit_score: 0,
246
+ at_or_above_median: 0,
247
+ share: null,
248
+ correct_hits: 0,
249
+ };
250
+ }
251
+ const median =
252
+ hits.length % 2 === 1
253
+ ? (hits[(hits.length - 1) / 2] as number)
254
+ : ((hits[hits.length / 2 - 1] as number) + (hits[hits.length / 2] as number)) / 2;
255
+ const over = emptyTopScores.filter((s) => s >= median).length;
256
+ return {
257
+ empties: emptyTopScores.length,
258
+ median_correct_hit_score: median,
259
+ at_or_above_median: over,
260
+ share: emptyTopScores.length ? round3(over / emptyTopScores.length) : null,
261
+ correct_hits: hits.length,
262
+ };
263
+ }
264
+
265
+ function interval(successes: number, trials: number): string {
266
+ const raw = wilsonInterval(successes, trials);
267
+ return `${round3(raw.lower).toFixed(3)} – ${round3(raw.upper).toFixed(3)}`;
268
+ }
269
+
270
+ export function renderReport(opts: {
271
+ repo: string;
272
+ skillsDir: string;
273
+ ranker: string;
274
+ slice: SliceName;
275
+ date: string;
276
+ }): string {
277
+ const whole = readMatrixLabelledPrompts(opts.repo);
278
+ const sizes = sliceSizes(whole);
279
+ const prompts = partitionBySlice(whole, opts.slice);
280
+ const readings = readRows(prompts, opts.skillsDir, opts.ranker);
281
+
282
+ const n = readings.length;
283
+ const top1 = readings.filter((r) => r.rankOfExpected === 1).length;
284
+ const top3 = readings.filter((r) => r.rankOfExpected >= 1 && r.rankOfExpected <= 3).length;
285
+ const unranked = readings.filter((r) => r.rankOfExpected === 0).length;
286
+ const misses = readings.filter((r) => r.rankOfExpected !== 1);
287
+ const deep = misses.filter((r) => r.rankOfExpected === 0 || r.rankOfExpected > DEEP_MISS_DEPTH).length;
288
+ const mrr = meanReciprocalRank(readings);
289
+
290
+ const empties = emptyRowIds(opts.repo, opts.slice);
291
+ const rankOpts = rankOptionsFor(opts.ranker);
292
+ const emptyScores = empties.map((e) => rank(e.prompt, opts.skillsDir, rankOpts)[0]?.[1] ?? 0);
293
+ const fa = falseActivation(readings, emptyScores);
294
+
295
+ const packs = perPackTop1(readings, opts.skillsDir);
296
+ const pairs = confusionPairs(readings);
297
+
298
+ const L: string[] = [];
299
+ L.push(`# Skill-ranker confusion report — ${opts.ranker}, ${opts.slice} slice`);
300
+ L.push('');
301
+ L.push('<!-- evidence-type: analysis -->');
302
+ L.push('');
303
+ L.push(`Produced by \`road-to-a-ranker-that-routes\` 1.3 on ${opts.date}. Read-only: this`);
304
+ L.push('report changes no default and flips no flag. Regenerate every measured figure');
305
+ L.push('below with');
306
+ L.push('');
307
+ L.push('```bash');
308
+ L.push(`./scripts-run src/scripts/report_skill_ranker_confusion --ranker ${opts.ranker} --slice ${opts.slice}`);
309
+ L.push('```');
310
+ L.push('');
311
+ L.push('## What was read');
312
+ L.push('');
313
+ L.push('| | |');
314
+ L.push('|---|---:|');
315
+ L.push(`| labelled rows in the routing matrix | ${String(sizes.all)} |`);
316
+ L.push(`| …in the tuning slice | ${String(sizes.tuning)} |`);
317
+ L.push(`| …in the sealed slice | ${String(sizes.sealed)} |`);
318
+ L.push(`| rows this report read (\`${opts.slice}\`) | ${String(n)} |`);
319
+ L.push(`| deliberate \`expected_skills: []\` rows in the same slice | ${String(empties.length)} |`);
320
+ // The LOADER's own glob, not a second one written here. This count is
321
+ // published as the population behind the document-frequency denominator, so
322
+ // a reimplementation that diverged would print a count of something the
323
+ // ranker did not index — and this one did diverge: it used `existsSync`
324
+ // where the loader uses `statSync().isDirectory()` and swallows errors, and
325
+ // it threw on an absent directory where `rank()` returns [].
326
+ L.push(`| skills indexed | ${String(_globSkillMd(opts.skillsDir).length)} |`);
327
+ L.push('');
328
+ if (opts.slice === 'tuning') {
329
+ L.push('The sealed slice is **not** read here. A confusion class derived from rows a');
330
+ L.push('later lift is measured on would make that lift circular, which is the one');
331
+ L.push('failure a held-out partition exists to prevent.');
332
+ } else if (opts.slice === 'sealed') {
333
+ L.push('**This run READ the sealed slice.** That is legitimate for reporting a result');
334
+ L.push('on held-out rows and is NOT legitimate as an input to choosing what to change:');
335
+ L.push('a confusion class derived from these rows would make every later lift measured');
336
+ L.push('on them circular. Derive from the `tuning` run.');
337
+ } else {
338
+ L.push('**This run read BOTH slices.** A confusion class derived from it therefore');
339
+ L.push('includes the sealed rows, so it may not be used to choose what to change —');
340
+ L.push('that is the `tuning` run, and the seal only means something if the choosing');
341
+ L.push('never sees the other half.');
342
+ }
343
+ L.push('');
344
+ L.push('## The headline on this slice');
345
+ L.push('');
346
+ L.push('| measure | value | 95 % CI |');
347
+ L.push('|---|---:|---|');
348
+ L.push(`| top-1 | ${round3(top1 / Math.max(n, 1)).toFixed(3)} | ${interval(top1, n)} |`);
349
+ L.push(`| top-3 | ${round3(top3 / Math.max(n, 1)).toFixed(3)} | ${interval(top3, n)} |`);
350
+ L.push(`| mean reciprocal rank | ${round3(mrr).toFixed(3)} | — |`);
351
+ L.push('');
352
+ L.push('MRR is the average of 1 / (position of the first expected skill), counting a row');
353
+ L.push('where no expected skill appears anywhere in the ranking as 0. It is the figure');
354
+ L.push('that separates "the right answer was second" from "the right answer was never');
355
+ L.push('returned", and top-1 alone cannot.');
356
+ L.push('');
357
+ L.push('## How deep the misses are');
358
+ L.push('');
359
+ L.push('| | count | share of misses |');
360
+ L.push('|---|---:|---:|');
361
+ L.push(`| top-1 misses | ${String(misses.length)} | — |`);
362
+ L.push(`| …expected skill outside the top ${String(DEEP_MISS_DEPTH)} | ${String(deep)} | ${pct(deep, misses.length)} |`);
363
+ L.push(`| …expected skill not ranked at all (score 0) | ${String(unranked)} | ${pct(unranked, misses.length)} |`);
364
+ L.push('');
365
+ L.push('A miss inside the top ten is a ranking problem — the right skill is in the');
366
+ L.push('candidate set and something else outscored it. A miss outside it, and above all');
367
+ L.push('a row where the expected skill scores zero, is a RECALL problem: no re-weighting');
368
+ L.push('of the existing signal can recover a skill the formula never surfaces. The two');
369
+ L.push('take different fixes, which is why the split is reported rather than an average.');
370
+ L.push('');
371
+ L.push('## False activation on the no-skill prompts');
372
+ L.push('');
373
+ L.push('| | |');
374
+ L.push('|---|---:|');
375
+ L.push(`| deliberate empties in this slice | ${String(fa.empties)} |`);
376
+ L.push(`| correct top-1 hits the median is taken over | ${String(fa.correct_hits)} |`);
377
+ L.push(`| median top score of a correct hit | ${String(fa.median_correct_hit_score)} |`);
378
+ L.push(`| empties whose top score reaches that median | ${String(fa.at_or_above_median)} |`);
379
+ // TWO causes produce a null share and they are not the same answer: no
380
+ // correct hit means there is no threshold to compare against, no empty row
381
+ // means there is nothing to compare. Printing one reason for both would
382
+ // state something the `correct_hits` row beside it contradicts.
383
+ const shareCell =
384
+ fa.share !== null
385
+ ? pct(fa.at_or_above_median, fa.empties)
386
+ : fa.correct_hits === 0
387
+ ? 'n/a — no correct top-1 hit, so no threshold'
388
+ : 'n/a — no deliberate empties in this slice, so no denominator';
389
+ L.push(`| share | ${shareCell} |`);
390
+ L.push('');
391
+ L.push('The threshold is the ranker\'s own median hit score rather than a cutoff chosen');
392
+ L.push('here, because the question is whether the ranker\'s confidence separates the two');
393
+ L.push('populations at all. A share near one half means it does not: a prompt a seat');
394
+ L.push('judged to have no skill answer is scored as confidently as a prompt it got right.');
395
+ L.push('');
396
+ L.push(`## Per-pack top-1, worst first`);
397
+ L.push('');
398
+ L.push('| pack | labelled rows | top-1 |');
399
+ L.push('|---|---:|---:|');
400
+ for (const p of packs) L.push(`| \`${p.pack}\` | ${String(p.n)} | ${p.top1.toFixed(3)} |`);
401
+ L.push('');
402
+ L.push('A row counts once per pack of each skill its label names, so the column sums');
403
+ L.push('above the row count — the same accounting the per-pack census uses.');
404
+ L.push('');
405
+ L.push(`## The ${String(CONFUSION_PAIRS)} most frequent (expected, ranked-first) pairs`);
406
+ L.push('');
407
+ L.push('| expected (label, best fit first) | ranked first instead | rows |');
408
+ L.push('|---|---|---:|');
409
+ for (const p of pairs) L.push(`| \`${p.expected}\` | \`${p.got}\` | ${String(p.count)} |`);
410
+ L.push('');
411
+ return `${L.join('\n')}\n`;
412
+ }
413
+
414
+ export function main(argv: readonly string[]): number {
415
+ let body: string;
416
+ try {
417
+ // Every flag through the shared parsers, inside one guard. A typo or a
418
+ // missing value must not reach the renderer: the label is printed in the
419
+ // report's own title and in the regenerate command beside it, and the
420
+ // date is printed in its header, so a swallowed next-flag would publish
421
+ // one configuration's number under another's name or stamp `--slice` as
422
+ // the date. `parseSlice` is not reused here only because this tool's
423
+ // default is `tuning` rather than `all`; the legal set is the one
424
+ // shared constant, so the two cannot disagree about what is valid.
425
+ const rawSlice = parseFlagValue(argv, '--slice', 'tuning');
426
+ if (!SLICE_NAMES.includes(rawSlice as SliceName)) {
427
+ throw new Error(`--slice expects one of ${SLICE_NAMES.join(' | ')}, got ${rawSlice}`);
428
+ }
429
+ const ranker = parseRanker(argv);
430
+ const date = parseFlagValue(argv, '--date', new Date().toISOString().slice(0, 10));
431
+ body = renderReport({ repo: REPO, skillsDir: SKILLS_DIR, ranker, slice: rawSlice as SliceName, date });
432
+ } catch (err) {
433
+ process.stderr.write(`${(err as Error).message}\n`);
434
+ return 2;
435
+ }
436
+ process.stdout.write(body);
437
+ return 0;
438
+ }
439
+
440
+ if (process.argv[1] && fileURLToPath(import.meta.url) === path.resolve(process.argv[1])) {
441
+ process.exit(main(process.argv.slice(2)));
442
+ }