@event4u/agent-config 16.2.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 (332) 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 +89 -237
  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 +4 -4
  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/contexts/authority/decision-revisit-gate-enforcement.md +43 -0
  23. package/dist/agent-src/contexts/communication/rules-auto/design-fidelity-enforcement.md +24 -0
  24. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +6 -6
  25. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +32 -2
  26. package/dist/agent-src/contexts/execution/session-canary-enforcement-history.md +67 -0
  27. package/dist/agent-src/contexts/execution/toolchain-resolver.md +101 -7
  28. package/dist/agent-src/rules/active-remediation.md +1 -1
  29. package/dist/agent-src/rules/autonomous-execution.md +1 -0
  30. package/dist/agent-src/rules/broken-access-control.md +1 -0
  31. package/dist/agent-src/rules/command-suggestion-policy.md +1 -0
  32. package/dist/agent-src/rules/context-hygiene.md +1 -1
  33. package/dist/agent-src/rules/decision-revisit-gate.md +16 -33
  34. package/dist/agent-src/rules/design-fidelity.md +13 -16
  35. package/dist/agent-src/rules/doc-screenshot-hygiene.md +1 -0
  36. package/dist/agent-src/rules/domain-safety-disclaimer.md +1 -0
  37. package/dist/agent-src/rules/domain-safety-pii.md +1 -0
  38. package/dist/agent-src/rules/domain-safety-retention.md +1 -0
  39. package/dist/agent-src/rules/engineering-safety-floor.md +1 -0
  40. package/dist/agent-src/rules/evaluator-independence.md +3 -2
  41. package/dist/agent-src/rules/fast-path-marker-visibility.md +1 -0
  42. package/dist/agent-src/rules/finance-safety-floor.md +1 -0
  43. package/dist/agent-src/rules/git-history-discipline.md +1 -0
  44. package/dist/agent-src/rules/image-likeness-and-rights.md +1 -0
  45. package/dist/agent-src/rules/legal-safety-floor.md +3 -2
  46. package/dist/agent-src/rules/lethal-trifecta-guard.md +1 -0
  47. package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +1 -0
  48. package/dist/agent-src/rules/media-governance-routing.md +14 -17
  49. package/dist/agent-src/rules/persona-governance.md +2 -2
  50. package/dist/agent-src/rules/provider-lifecycle-discipline.md +1 -1
  51. package/dist/agent-src/rules/question-not-instruction.md +1 -0
  52. package/dist/agent-src/rules/roadmap-progress-sync.md +1 -1
  53. package/dist/agent-src/rules/runtime-safety.md +1 -0
  54. package/dist/agent-src/rules/secret-vcs-guard.md +1 -0
  55. package/dist/agent-src/rules/security-sensitive-stop.md +3 -2
  56. package/dist/agent-src/rules/session-canary.md +8 -62
  57. package/dist/agent-src/rules/settings-ask-protocol.md +1 -0
  58. package/dist/agent-src/rules/source-confidentiality.md +1 -0
  59. package/dist/agent-src/rules/strategy-safety-floor.md +1 -0
  60. package/dist/agent-src/rules/tool-safety.md +1 -0
  61. package/dist/agent-src/rules/untrusted-input-defense.md +1 -0
  62. package/dist/agent-src/rules/user-interrupt-priority.md +1 -0
  63. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +115 -20
  64. package/dist/agent-src/scripts/deferral_carry.ts +339 -0
  65. package/dist/agent-src/scripts/update_roadmap_progress.ts +4 -1
  66. package/dist/agent-src/skills/api-design/data/manifest.json +2 -2
  67. package/dist/agent-src/skills/api-testing/SKILL.md +17 -0
  68. package/dist/agent-src/skills/code-intelligence/SKILL.md +14 -2
  69. package/dist/agent-src/skills/design-system-capture/references/import-procedure.md +1 -1
  70. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +2 -2
  71. package/dist/agent-src/skills/fe-design/SKILL.md +1 -1
  72. package/dist/agent-src/skills/iconography/SKILL.md +1 -1
  73. package/dist/agent-src/skills/js-library-packaging/SKILL.md +2 -2
  74. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +1 -1
  75. package/dist/agent-src/skills/quality-tools/SKILL.md +11 -1
  76. package/dist/agent-src/skills/quality-tools/references/go-tools.md +76 -0
  77. package/dist/agent-src/skills/quality-tools/references/python-tools.md +104 -0
  78. package/dist/agent-src/skills/review-routing/SKILL.md +2 -2
  79. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +1 -1
  80. package/dist/agent-src/skills/storybook-workshop/SKILL.md +3 -3
  81. package/dist/agent-src/skills/tailwind-engineer/SKILL.md +1 -1
  82. package/dist/agent-src/skills/test-case-discovery/SKILL.md +7 -0
  83. package/dist/agent-src/skills/test-driven-development/SKILL.md +17 -0
  84. package/dist/agent-src/skills/test-performance/SKILL.md +19 -1
  85. package/dist/agent-src/skills/ui-component-architect/SKILL.md +2 -2
  86. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  87. package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +48 -6
  88. package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
  89. package/dist/cli/registry.js +1 -1
  90. package/dist/cli-delegate/archive_completed_roadmaps.js +92 -12
  91. package/dist/cli-delegate/check_update_banner.js +12 -1
  92. package/dist/cli-delegate/chunk-523HCFYO.js +90 -0
  93. package/dist/cli-delegate/{chunk-M2DPGFZ4.js → chunk-6V6TA25H.js} +22 -152
  94. package/dist/cli-delegate/chunk-7IQE3D5S.js +191 -0
  95. package/dist/cli-delegate/{chunk-6KFEC3G7.js → chunk-CQWX336L.js} +1 -1
  96. package/dist/cli-delegate/chunk-DEIV7XP7.js +108 -0
  97. package/dist/cli-delegate/chunk-EEHDXSYD.js +2040 -0
  98. package/dist/cli-delegate/{chunk-P6ZHP5W2.js → chunk-GKE7ZVFA.js} +4 -4
  99. package/dist/cli-delegate/chunk-JQOM7TTM.js +1201 -0
  100. package/dist/cli-delegate/{chunk-IGD6ERX6.js → chunk-JQVYKIZA.js} +10 -0
  101. package/dist/cli-delegate/{chunk-FC75PGJE.js → chunk-JY2I2DXV.js} +12 -1
  102. package/dist/cli-delegate/chunk-KB5FZ655.js +208 -0
  103. package/dist/cli-delegate/{chunk-7RQP4UDH.js → chunk-KR6EM23A.js} +235 -1455
  104. package/dist/cli-delegate/{chunk-LTYVIY76.js → chunk-LIYTLH6O.js} +1 -1
  105. package/dist/cli-delegate/{chunk-YJ72UIAK.js → chunk-NQ7WT43P.js} +1186 -244
  106. package/dist/cli-delegate/chunk-NXEILF2K.js +2160 -0
  107. package/dist/cli-delegate/{chunk-5R7HOLAF.js → chunk-NYX3L2PZ.js} +1 -1
  108. package/dist/cli-delegate/{chunk-4E2W63DA.js → chunk-OKJUIAPS.js} +62 -1
  109. package/dist/cli-delegate/{chunk-QAJS5YWY.js → chunk-PHD7OOLE.js} +2 -1
  110. package/dist/cli-delegate/{chunk-RGNIWTEA.js → chunk-QLDHIPWR.js} +1 -1
  111. package/dist/cli-delegate/{chunk-7XGBX6ZH.js → chunk-RQNNW7IF.js} +1314 -560
  112. package/dist/cli-delegate/{chunk-4XFP2Y3E.js → chunk-S4UMZNES.js} +1 -1
  113. package/dist/cli-delegate/{chunk-6KM6ORRY.js → chunk-S4YWNRKO.js} +24 -8
  114. package/dist/cli-delegate/{chunk-FP36SWJD.js → chunk-TRI6DQZ6.js} +2781 -340
  115. package/dist/cli-delegate/chunk-ULQRUR23.js +208 -0
  116. package/dist/cli-delegate/{chunk-NUHLI2RX.js → chunk-YCU3TIXH.js} +2 -0
  117. package/dist/cli-delegate/chunk-ZBZV2G5R.js +210 -0
  118. package/dist/cli-delegate/{chunk-WGXTVKCQ.js → chunk-ZUZKZYCN.js} +5 -3
  119. package/dist/cli-delegate/cmd_analyze_session.js +1 -1
  120. package/dist/cli-delegate/cmd_brand_status.js +1 -1
  121. package/dist/cli-delegate/cmd_conformance.js +1167 -234
  122. package/dist/cli-delegate/cmd_doctor.js +13 -6
  123. package/dist/cli-delegate/cmd_doctor_neighbours.js +23 -0
  124. package/dist/cli-delegate/cmd_explain.js +5 -5
  125. package/dist/cli-delegate/cmd_export.js +11 -8
  126. package/dist/cli-delegate/cmd_fleet.js +3 -3
  127. package/dist/cli-delegate/cmd_handoff.js +10 -7
  128. package/dist/cli-delegate/cmd_mcp_available.js +1 -1
  129. package/dist/cli-delegate/cmd_memory_get.js +3 -1
  130. package/dist/cli-delegate/cmd_migrate.js +2 -2
  131. package/dist/cli-delegate/cmd_packs_active.js +3 -3
  132. package/dist/cli-delegate/cmd_preflight.js +6 -6
  133. package/dist/cli-delegate/cmd_prune.js +11 -8
  134. package/dist/cli-delegate/cmd_refresh.js +2 -1
  135. package/dist/cli-delegate/cmd_route_audit.js +8 -6
  136. package/dist/cli-delegate/cmd_route_explain.js +4 -4
  137. package/dist/cli-delegate/cmd_session_recycle.js +4 -3
  138. package/dist/cli-delegate/cmd_settings_get.js +1 -1
  139. package/dist/cli-delegate/cmd_settings_migrate.js +11 -8
  140. package/dist/cli-delegate/cmd_settings_set.js +4 -4
  141. package/dist/cli-delegate/cmd_sync.js +11 -8
  142. package/dist/cli-delegate/cmd_uninstall.js +11 -8
  143. package/dist/cli-delegate/cmd_update.js +1 -1
  144. package/dist/cli-delegate/cmd_upgrade.js +3 -2
  145. package/dist/cli-delegate/cmd_validate.js +11 -8
  146. package/dist/cli-delegate/cmd_versions.js +1 -1
  147. package/dist/cli-delegate/deferral_carry.js +16 -0
  148. package/dist/cli-delegate/gate_execute.js +2 -2
  149. package/dist/cli-delegate/roadmap_gates.js +5 -5
  150. package/dist/cli-delegate/update_roadmap_progress.js +1 -1
  151. package/dist/discovery/deprecation-report.md +1 -1
  152. package/dist/discovery/discovery-manifest.json +127 -75
  153. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  154. package/dist/discovery/discovery-manifest.summary.md +3 -3
  155. package/dist/discovery/dormancy-report.md +1 -1
  156. package/dist/discovery/orphan-report.md +1 -1
  157. package/dist/discovery/packs.json +7 -5
  158. package/dist/discovery/trust-report.md +2 -2
  159. package/dist/discovery/workspaces.json +6 -4
  160. package/dist/hooks/dispatch.js +5357 -6656
  161. package/dist/hooks/dispatch.sha256 +1 -1
  162. package/dist/install/claudePathsPlan.js +47 -6
  163. package/dist/install/claudeRuleRewrite.js +7 -0
  164. package/dist/install/emit_host_rules_cli.js +39 -36
  165. package/dist/install/globalRuleScope.js +87 -0
  166. package/dist/install/host_rule_ownership.js +160 -0
  167. package/dist/install/install.mjs +2080 -1024
  168. package/dist/install/installThinLayer.js +261 -0
  169. package/dist/install/installedRuleLinks.js +176 -0
  170. package/dist/install/wizard-plan.js +24 -0
  171. package/dist/mcp/registry-manifest.json +3 -3
  172. package/dist/mcp/server.json +2 -2
  173. package/dist/mcp/server.mjs +31965 -27154
  174. package/dist/scripts/_lib/agent_settings.js +11 -0
  175. package/dist/scripts/_lib/claude_settings_hooks.js +10 -8
  176. package/dist/scripts/_lib/installed_layer.js +378 -0
  177. package/dist/scripts/_lib/lean_projection_mode.js +218 -15
  178. package/dist/scripts/_lib/rule_consequence_class.js +45 -0
  179. package/dist/scripts/_lib/rule_injection.js +67 -10
  180. package/dist/scripts/_lib/rule_law_section.js +122 -0
  181. package/dist/scripts/_lib/thin_rules.js +458 -0
  182. package/dist/scripts/_lib/windsurf_render.js +60 -0
  183. package/dist/scripts/condense.js +14 -26
  184. package/dist/scripts/project_thin_rules.js +14 -294
  185. package/dist/server/schemas/settings.js +6 -0
  186. package/dist/shared/skillRanking.js +74 -13
  187. package/docs/contracts/settings-classes.md +7 -5
  188. package/package.json +1 -1
  189. package/src/agent-src/scripts/archive_completed_roadmaps.ts +115 -20
  190. package/src/agent-src/scripts/deferral_carry.ts +339 -0
  191. package/src/agent-src/scripts/update_roadmap_progress.ts +4 -1
  192. package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +48 -6
  193. package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
  194. package/src/config/agent-settings.template.yml +62 -22
  195. package/src/config/continuity-surface.json +7 -0
  196. package/src/config/evaluator-budgets.json +4 -4
  197. package/src/config/gate-coverage.yml +96 -3
  198. package/src/config/gate-violation-baselines.json +17 -9
  199. package/src/config/hook-bundle-budget.json +25 -0
  200. package/src/config/hook-token-budget.json +6 -1
  201. package/src/config/host-instruction-limits.json +33 -0
  202. package/src/config/routing-coverage-seed.json +24 -3
  203. package/src/config/rule-activation-census.json +7 -3
  204. package/src/config/rule-consequence-class.json +161 -0
  205. package/src/config/rule-law-ceilings.json +99 -0
  206. package/src/install/claudePathsPlan.ts +46 -4
  207. package/src/install/claudeRuleRewrite.ts +10 -1
  208. package/src/install/emit_host_rules_cli.ts +43 -34
  209. package/src/install/globalRuleScope.ts +109 -0
  210. package/src/install/host_rule_ownership.ts +170 -0
  211. package/src/install/installThinLayer.ts +312 -0
  212. package/src/install/installedRuleLinks.ts +220 -0
  213. package/src/install/wizard-plan.ts +24 -0
  214. package/src/scripts/_cli/cmd_doctor.ts +23 -71
  215. package/src/scripts/_cli/cmd_doctor_neighbours.ts +293 -0
  216. package/src/scripts/_dispatch.bash +16 -2
  217. package/src/scripts/_lib/agent_settings.ts +11 -0
  218. package/src/scripts/_lib/claude_settings_hooks.ts +10 -8
  219. package/src/scripts/_lib/estate_offsets.ts +241 -0
  220. package/src/scripts/_lib/exemption_shape.ts +143 -0
  221. package/src/scripts/_lib/fnv.ts +23 -0
  222. package/src/scripts/_lib/foreign_scan.ts +106 -0
  223. package/src/scripts/_lib/gitignore_block.ts +314 -0
  224. package/src/scripts/_lib/global_deploy_inventory.ts +32 -0
  225. package/src/scripts/_lib/graph_feeder_record.ts +214 -0
  226. package/src/scripts/_lib/hook_settings.ts +73 -0
  227. package/src/scripts/_lib/host_capability.ts +40 -19
  228. package/src/scripts/_lib/host_hook_merge.ts +165 -0
  229. package/src/scripts/_lib/installed_layer.ts +538 -0
  230. package/src/scripts/_lib/json_merge.ts +82 -0
  231. package/src/scripts/_lib/json_pointers.ts +93 -11
  232. package/src/scripts/_lib/lean_projection_mode.ts +275 -15
  233. package/src/scripts/_lib/machine_wake.ts +16 -3
  234. package/src/scripts/_lib/neighbour_census.ts +760 -0
  235. package/src/scripts/_lib/neighbour_scan.ts +122 -0
  236. package/src/scripts/_lib/neighbour_tool_use.ts +189 -0
  237. package/src/scripts/_lib/prompt_shape.ts +46 -0
  238. package/src/scripts/_lib/release_migration_gate.ts +19 -3
  239. package/src/scripts/_lib/reserved_name_sweep.ts +73 -0
  240. package/src/scripts/_lib/review_coverage.ts +134 -0
  241. package/src/scripts/_lib/rule_consequence_class.ts +71 -0
  242. package/src/scripts/_lib/rule_injection.ts +130 -10
  243. package/src/scripts/_lib/rule_law_section.ts +147 -0
  244. package/src/scripts/_lib/rule_layer_overlap.ts +58 -0
  245. package/src/scripts/_lib/skill_origin.ts +254 -0
  246. package/src/scripts/_lib/structured_ask.ts +64 -21
  247. package/src/scripts/_lib/thin_rules.ts +540 -0
  248. package/src/scripts/_lib/touched_file_quality.ts +434 -0
  249. package/src/scripts/_lib/turn_end_refusals.ts +77 -2
  250. package/src/scripts/_lib/windsurf_render.ts +63 -0
  251. package/src/scripts/ai_council/cli_call_budget.ts +13 -5
  252. package/src/scripts/ai_council/clients.ts +26 -57
  253. package/src/scripts/ai_council/config.ts +1 -1
  254. package/src/scripts/ai_council/vendor_defaults.ts +45 -0
  255. package/src/scripts/audit_skill_overlap.ts +261 -0
  256. package/src/scripts/before_complete_hook.ts +243 -12
  257. package/src/scripts/bench_touched_file_quality.ts +238 -0
  258. package/src/scripts/check_enforcement_matrix.ts +377 -20
  259. package/src/scripts/check_estate_count.ts +130 -153
  260. package/src/scripts/check_finding_dispositions.ts +116 -4
  261. package/src/scripts/check_hook_bundle_composition.ts +370 -0
  262. package/src/scripts/check_kernel_edit_ratified.ts +49 -11
  263. package/src/scripts/check_memory.ts +7 -1
  264. package/src/scripts/check_release_highlights.ts +10 -0
  265. package/src/scripts/check_release_pr_shape.ts +38 -15
  266. package/src/scripts/check_standing_rule_delivery.ts +33 -13
  267. package/src/scripts/check_verify_expectation_delta.ts +521 -0
  268. package/src/scripts/code_graph/detect.ts +127 -7
  269. package/src/scripts/code_graph/foreign.ts +194 -0
  270. package/src/scripts/code_graph/query.ts +217 -4
  271. package/src/scripts/code_graph/types.ts +26 -2
  272. package/src/scripts/code_graph/validate.ts +3 -1
  273. package/src/scripts/code_graph/verbs.ts +103 -0
  274. package/src/scripts/compile_hook_manifest.ts +33 -1
  275. package/src/scripts/condense.ts +14 -27
  276. package/src/scripts/estate_exemption_shape.ts +202 -0
  277. package/src/scripts/generate_host_cost_table.ts +1 -1
  278. package/src/scripts/hook_manifest.json +1 -1
  279. package/src/scripts/hook_manifest.yaml +150 -9
  280. package/src/scripts/hooks/block_config_weakening.ts +67 -2
  281. package/src/scripts/hooks/block_plumbing_writes.ts +29 -1
  282. package/src/scripts/hooks/code_graph_context_hook.ts +252 -23
  283. package/src/scripts/hooks/concern_failure_policy.ts +280 -0
  284. package/src/scripts/hooks/dispatch_hook.ts +52 -52
  285. package/src/scripts/hooks/exit_codes.ts +2 -1
  286. package/src/scripts/hooks/host_lowering.json +1 -1
  287. package/src/scripts/hooks/host_lowering.ts +19 -1
  288. package/src/scripts/hooks/one_question_per_ask_hook.ts +41 -25
  289. package/src/scripts/hooks/payload_stub.ts +10 -1
  290. package/src/scripts/hooks/rule_inject_hook.ts +757 -63
  291. package/src/scripts/hooks/table_fingerprint.ts +21 -0
  292. package/src/scripts/hooks/telemetry_usage_hook.ts +64 -8
  293. package/src/scripts/hooks/turn_end_gate_hook.ts +84 -0
  294. package/src/scripts/hooks_status.ts +112 -0
  295. package/src/scripts/injection_scan_hook.ts +7 -0
  296. package/src/scripts/install.ts +72 -185
  297. package/src/scripts/installed_layer_report.ts +103 -0
  298. package/src/scripts/language_mirror_hook.ts +15 -6
  299. package/src/scripts/learning_sidecar.ts +119 -8
  300. package/src/scripts/lint_hook_manifest.ts +53 -0
  301. package/src/scripts/lint_major_migration_sections.ts +156 -26
  302. package/src/scripts/lint_pack_boundaries.ts +63 -5
  303. package/src/scripts/lint_rule_law_section.ts +517 -0
  304. package/src/scripts/lint_workflow_security.ts +161 -5
  305. package/src/scripts/mcp_server/consumer_tool_catalog.json +53 -0
  306. package/src/scripts/mcp_server/graph_tools.ts +72 -3
  307. package/src/scripts/measure_routing_signal.ts +54 -16
  308. package/src/scripts/measure_skill_ranker_baseline.ts +216 -8
  309. package/src/scripts/memory_learn_hook.ts +91 -6
  310. package/src/scripts/model_rule_injection.ts +52 -5
  311. package/src/scripts/project_thin_rules.ts +34 -327
  312. package/src/scripts/report_evidence_temperature.ts +657 -0
  313. package/src/scripts/report_installed_rule_links.ts +157 -0
  314. package/src/scripts/report_label_agreement.ts +233 -0
  315. package/src/scripts/report_obligation_mechanism.ts +230 -0
  316. package/src/scripts/report_single_token_triggers.ts +277 -0
  317. package/src/scripts/report_skill_ranker_confusion.ts +442 -0
  318. package/src/scripts/report_standing_payload_by_host.ts +188 -15
  319. package/src/scripts/report_verification_record_coverage.ts +306 -0
  320. package/src/scripts/rule_activation_census.ts +5 -2
  321. package/src/scripts/rule_trigger_eval.ts +9 -9
  322. package/src/scripts/schemas/review-findings.schema.json +3 -2
  323. package/src/scripts/schemas/rule.schema.json +5 -0
  324. package/src/scripts/self_review_gate.ts +62 -7
  325. package/src/scripts/skill_tools/score_skill_relevance.ts +290 -25
  326. package/src/scripts/sweep_skill_ranker_signals.ts +129 -0
  327. package/src/scripts/sync_gitignore.ts +29 -235
  328. package/src/scripts/trigger_eval_grandfather.json +0 -5
  329. package/src/server/schemas/settings.ts +10 -0
  330. package/src/shared/skillRanking.ts +117 -11
  331. package/dist/cli-delegate/chunk-JNMVLWLR.js +0 -4457
  332. package/dist/cli-delegate/chunk-YDPILCOL.js +0 -152
@@ -31,243 +31,37 @@ import * as path from 'node:path';
31
31
  import process from 'node:process';
32
32
  import { fileURLToPath, pathToFileURL } from 'node:url';
33
33
 
34
- export const SECTION_HEADER = '# event4u/agent-config';
35
- export const SECTION_FOOTER = '# event4u/agent-config — END';
36
- export const DEFAULT_GITIGNORE = '.gitignore';
34
+ export {
35
+ SECTION_HEADER,
36
+ SECTION_FOOTER,
37
+ DEFAULT_GITIGNORE,
38
+ DEFAULT_TEMPLATE,
39
+ LEGACY_PATTERNS,
40
+ TemplateNotFoundError,
41
+ load_template,
42
+ find_block,
43
+ block_entries,
44
+ template_entries,
45
+ build_fresh_block,
46
+ sync_block,
47
+ cleanup_legacy,
48
+ format_file,
49
+ } from './_lib/gitignore_block.js';
50
+ import {
51
+ DEFAULT_GITIGNORE,
52
+ DEFAULT_TEMPLATE,
53
+ TemplateNotFoundError,
54
+ load_template,
55
+ cleanup_legacy,
56
+ format_file,
57
+ sync_block,
58
+ template_entries,
59
+ _isFile,
60
+ _splitlines,
61
+ _strip,
62
+ } from './_lib/gitignore_block.js';
37
63
 
38
64
  const _HERE = fileURLToPath(import.meta.url);
39
- // _HERE === <repo>/src/scripts/sync_gitignore.ts ; parents[2] of the .py file
40
- // is the repo root — two dirs up from src/scripts. the retired Python implementation derives
41
- // DEFAULT_TEMPLATE = <file>.parent.parent.parent / "src" / "config" /
42
- // "gitignore-block.txt".
43
- export const DEFAULT_TEMPLATE = path.join(
44
- path.dirname(_HERE),
45
- '..',
46
- '..',
47
- 'src',
48
- 'config',
49
- 'gitignore-block.txt',
50
- );
51
-
52
- // Legacy patterns that lived in older versions of src/config/gitignore-block.txt
53
- // before runtime artefacts moved under /agents/runtime/ (May 2026). They get
54
- // stripped wherever they appear in the consumer's .gitignore — inside the
55
- // managed block or outside (older installers / hand-edits). Current canonical
56
- // equivalents (e.g. /agents/runtime/.agent-prices.md) come from the template
57
- // and are NOT affected. Leading-slash variants are matched defensively.
58
- //
59
- // Authoritative source: src/config/agents-paths.yml entries with `legacy: true`.
60
- // Manual sync until the generation step from the manifest is implemented
61
- // (road-to-agents-dir-and-gitignore-hygiene Phase 3.2 follow-on).
62
- export const LEGACY_PATTERNS: readonly string[] = [
63
- '.agent-chat-history',
64
- '.agent-chat-history.bak',
65
- '.agent-chat-history.*.bak',
66
- '.agent-prices.md',
67
- '.council-tmp/',
68
- // 2.x intermediate: prices cache lived directly under agents/ before
69
- // consolidating under agents/runtime/.
70
- 'agents/.agent-prices.md',
71
- // Budget history JSONLs — previously listed explicitly at project
72
- // root or under agents/; now covered by the /agents/runtime/
73
- // catch-all in the managed block.
74
- '.augment-budget-history.jsonl',
75
- '.rule-budget-history.jsonl',
76
- 'agents/.augment-budget-history.jsonl',
77
- 'agents/.rule-budget-history.jsonl',
78
- ];
79
-
80
- function _strip(ln: string): string {
81
- // Python: ln.rstrip("\n").rstrip() — strip a trailing newline, then strip
82
- // all trailing whitespace.
83
- return ln.replace(/\n+$/, '').replace(/\s+$/, '');
84
- }
85
-
86
- function _is_entry(ln: string): boolean {
87
- // Non-empty, non-comment line = a path/pattern entry.
88
- const s = _strip(ln).replace(/^\s+/, '');
89
- return Boolean(s) && !s.startsWith('#');
90
- }
91
-
92
- /** Error raised when the template file is missing (→ exit 2 in main). */
93
- export class TemplateNotFoundError extends Error {
94
- constructor(p: string) {
95
- super(`template not found: ${p}`);
96
- this.name = 'TemplateNotFoundError';
97
- }
98
- }
99
-
100
- function _isFile(p: string): boolean {
101
- try {
102
- return fs.statSync(p).isFile();
103
- } catch {
104
- return false;
105
- }
106
- }
107
-
108
- /** Python str.splitlines() — split on universal newlines, no trailing empty. */
109
- function _splitlines(text: string): string[] {
110
- if (text === '') return [];
111
- // str.splitlines() splits on \n, \r, \r\n (and more) and does NOT keep a
112
- // trailing empty element. The targets here only ever contain \n / \r\n.
113
- const parts = text.split(/\r\n|\r|\n/);
114
- if (parts.length > 0 && parts[parts.length - 1] === '') parts.pop();
115
- return parts;
116
- }
117
-
118
- export function load_template(p: string): string[] {
119
- if (!_isFile(p)) {
120
- throw new TemplateNotFoundError(p);
121
- }
122
- const text = fs.readFileSync(p, 'utf-8');
123
- // Keep trailing newlines stripped; we splice explicit newlines.
124
- return _splitlines(text).map(_strip);
125
- }
126
-
127
- /**
128
- * Locate the managed block; return [start_idx, end_idx_exclusive] or null.
129
- *
130
- * `start_idx` points at the SECTION_HEADER line.
131
- * `end_idx_exclusive` points one past the last line of the block.
132
- * Honors explicit SECTION_FOOTER when present; otherwise treats the
133
- * block as extending to EOF or to the next non-managed section.
134
- */
135
- export function find_block(lines: readonly string[]): [number, number] | null {
136
- for (let i = 0; i < lines.length; i += 1) {
137
- if (_strip(lines[i] as string) === SECTION_HEADER) {
138
- const start = i;
139
- // Explicit footer?
140
- for (let j = i + 1; j < lines.length; j += 1) {
141
- if (_strip(lines[j] as string) === SECTION_FOOTER) {
142
- return [start, j + 1];
143
- }
144
- }
145
- // Legacy: extend to EOF or next non-managed section break.
146
- let end = lines.length;
147
- for (let j = i + 1; j < lines.length; j += 1) {
148
- const s = _strip(lines[j] as string).replace(/^\s+/, '');
149
- if (
150
- s.startsWith('#') &&
151
- !s.startsWith('# Agent config') &&
152
- s !== SECTION_HEADER
153
- ) {
154
- end = j;
155
- while (end > i + 1 && _strip(lines[end - 1] as string) === '') {
156
- end -= 1;
157
- }
158
- break;
159
- }
160
- }
161
- return [start, end];
162
- }
163
- }
164
- return null;
165
- }
166
-
167
- /** Return entries (paths/patterns) present in the given block. */
168
- export function block_entries(block_lines: readonly string[]): string[] {
169
- return block_lines
170
- .filter((ln) => _is_entry(ln))
171
- .map((ln) => _strip(ln).replace(/^\s+/, ''));
172
- }
173
-
174
- export function template_entries(template_lines: readonly string[]): string[] {
175
- return template_lines.filter((ln) => _is_entry(ln)).map((ln) => ln.replace(/^\s+/, ''));
176
- }
177
-
178
- /** Return a fresh, fully-managed block with START + body + END. */
179
- export function build_fresh_block(template_lines: readonly string[]): string[] {
180
- return [SECTION_HEADER, ...template_lines, SECTION_FOOTER];
181
- }
182
-
183
- /**
184
- * Return [new_lines, added_entries].
185
- *
186
- * - If block missing: append fresh block (preceded by a blank line if the
187
- * file's last line is not already empty).
188
- * - If block present and replace=true: rewrite block in full.
189
- * - If block present and replace=false: append any missing managed entries
190
- * before the END marker (adding END if absent). User-added lines inside the
191
- * block are preserved.
192
- */
193
- export function sync_block(
194
- existing_lines: readonly string[],
195
- template_lines: readonly string[],
196
- options: { replace?: boolean } = {},
197
- ): [string[], string[]] {
198
- const replace = options.replace ?? false;
199
- const loc = find_block(existing_lines);
200
- const fresh = build_fresh_block(template_lines);
201
-
202
- // Missing block → append with leading blank if needed.
203
- if (loc === null) {
204
- const newLines = [...existing_lines];
205
- if (newLines.length > 0 && _strip(newLines[newLines.length - 1] as string) !== '') {
206
- newLines.push('');
207
- }
208
- newLines.push(...fresh);
209
- return [newLines, template_entries(template_lines)];
210
- }
211
-
212
- const [start, end] = loc;
213
- const head = existing_lines.slice(0, start);
214
- let block = existing_lines.slice(start, end);
215
- const tail = existing_lines.slice(end);
216
-
217
- if (replace) {
218
- const existing = new Set(block_entries(block));
219
- const added = template_entries(template_lines).filter((e) => !existing.has(e));
220
- return [[...head, ...fresh, ...tail], added];
221
- }
222
-
223
- // Append-only mode.
224
- const existing_entries = new Set(block_entries(block));
225
- const missing = template_entries(template_lines).filter((e) => !existing_entries.has(e));
226
- if (missing.length === 0) {
227
- return [[...existing_lines], []];
228
- }
229
-
230
- // Ensure block ends with SECTION_FOOTER; insert missing entries right
231
- // before it.
232
- let insert_at: number;
233
- if (block.length > 0 && _strip(block[block.length - 1] as string) === SECTION_FOOTER) {
234
- insert_at = block.length - 1;
235
- } else {
236
- block = [...block, SECTION_FOOTER];
237
- insert_at = block.length - 1;
238
- }
239
- const new_block = [...block.slice(0, insert_at), ...missing, ...block.slice(insert_at)];
240
- return [[...head, ...new_block, ...tail], missing];
241
- }
242
-
243
- /**
244
- * Strip legacy entries from anywhere in the file.
245
- *
246
- * A line is legacy when its stripped, leading-whitespace-trimmed content
247
- * matches a `LEGACY_PATTERNS` entry — with or without a leading slash.
248
- * Comments and blank lines are untouched; current managed entries (e.g.
249
- * `/agents/.agent-chat-history`) are not in the legacy set and survive.
250
- */
251
- export function cleanup_legacy(lines: readonly string[]): [string[], string[]] {
252
- const legacy = new Set(LEGACY_PATTERNS);
253
- const kept: string[] = [];
254
- const removed: string[] = [];
255
- for (const ln of lines) {
256
- const s = _strip(ln).replace(/^\s+/, '');
257
- if (legacy.has(s) || (s.startsWith('/') && legacy.has(s.slice(1)))) {
258
- removed.push(s);
259
- continue;
260
- }
261
- kept.push(ln);
262
- }
263
- return [kept, removed];
264
- }
265
-
266
- /** Join lines with newlines and enforce exactly one trailing newline. */
267
- export function format_file(lines: readonly string[]): string {
268
- const text = lines.join('\n');
269
- return text.replace(/\n+$/, '') + '\n';
270
- }
271
65
 
272
66
  /** Python difflib.unified_diff(..., n=3) over keepends-split lines. */
273
67
  export function render_diff(old_text: string, new_text: string, p: string): string {
@@ -9,7 +9,6 @@
9
9
  "agent-docs-writing",
10
10
  "agents-md-thin-root",
11
11
  "ai-council",
12
- "api-design",
13
12
  "api-endpoint",
14
13
  "api-testing",
15
14
  "artisan-commands",
@@ -44,7 +43,6 @@
44
43
  "dependency-upgrade",
45
44
  "description-assist",
46
45
  "design-review",
47
- "design-system-capture",
48
46
  "devcontainer",
49
47
  "developer-like-execution",
50
48
  "discovery-interview",
@@ -153,7 +151,6 @@
153
151
  "repomix-packer",
154
152
  "requesting-code-review",
155
153
  "retention-loops",
156
- "review-routing",
157
154
  "rice-prioritization",
158
155
  "risk-officer",
159
156
  "roadmap-management",
@@ -169,7 +166,6 @@
169
166
  "security",
170
167
  "sentry-integration",
171
168
  "sequential-thinking",
172
- "skill-improvement-pipeline",
173
169
  "skill-management",
174
170
  "skill-reviewer",
175
171
  "song-to-script",
@@ -180,7 +176,6 @@
180
176
  "subagent-orchestration",
181
177
  "symfony-workflow",
182
178
  "systematic-debugging",
183
- "tailwind-engineer",
184
179
  "tech-debt-tracker",
185
180
  "technical-specification",
186
181
  "terraform",
@@ -323,6 +323,11 @@ export const settingsSchema = z.object({
323
323
  fidelity_mode: 'strict',
324
324
  approximation: { enabled: false, tolerance: { color: null, length: null } },
325
325
  }),
326
+ code_graph: z.object({
327
+ consumer_index_paths: z.array(z.string()).default([]).describe(
328
+ "Extra project-relative paths where THIS project keeps a code-graph index another tool wrote. The built-in list is deliberately vendor-neutral (graph.json, code-graph.json, .code-graph/graph.json) and names no tool, so a tool that writes its index elsewhere is named here rather than waited for. A graph found this way LOADS and answers query and explain with every edge tagged read-from-elsewhere; the gate verbs (impact, untested, dead) refuse a graph made only of such edges and say so, because an empty answer from a gate must not read as 'nothing found' when it means 'nothing trusted'. Absolute paths and paths escaping the project root are ignored.",
329
+ ),
330
+ }).default({}),
326
331
  consistency: z.object({
327
332
  cross_source: crossSourceMode.default('on').describe(
328
333
  'Consumed by the cross-source-consistency rule. When the agent works from multiple sources (ticket text, an attached image/mockup, the spec, the codebase) it checks them against each other and asks before proceeding on a discrepancy — instead of silently guessing. on (default) = surface every real cross-source contradiction / silent-scope-expansion as one question; auto = surface only high-confidence contradictions, state low-confidence as an assumption; off = no cross-source checking.',
@@ -590,6 +595,11 @@ export const settingsSchema = z.object({
590
595
  'When a hook exceeds hooks.concern_budget.max_per_event, fail the run (true) instead of warning and continuing (false, default). Turn on in CI when you want hook quality to gate merges.',
591
596
  ),
592
597
  }),
598
+ verify_before_complete: z.object({
599
+ touched_file_quality: z.enum(['off', 'shadow', 'warn']).default('off').describe(
600
+ "Stop-slot pass that runs the project's OWN quality commands — the ones resolve_toolchain() already reports — over the files this turn edited. Default off. `shadow` records a per-run result and emits nothing; `warn` adds ONE advisory line of at most 200 bytes. Never blocks and never counts as verification: a command recorded here never reaches _lib/verification_command.ts, so a clean eslint run cannot let a turn claim it verified anything. A writing command runs only in its check form (pint --test) or not at all, and a command with no per-file form is skipped rather than run project-wide at every stop.",
601
+ ),
602
+ }).default({}),
593
603
  injection_scan: z.object({
594
604
  enabled: z.boolean().default(false).describe(
595
605
  'PostToolUse prompt-injection scanner (road-to-security-pillar.md P3.2). Default off. When on, scans tool output (file reads, web fetches, MCP responses) for injection signatures and WARNS in context (never blocks). Runtime backstop on top of the always-on untrusted-input-defense rule; detection is probabilistic.',
@@ -24,10 +24,13 @@
24
24
  * `score_skill_relevance` CLI's argparse-parity suite is the check that the move
25
25
  * changed nothing.
26
26
  *
27
- * THE ONE ADDITION is `triggerTerms`, off by default. Phase 3.1 of the same
28
- * roadmap indexes `triggers.keyword` / `triggers.phrase` text; it is an opt-in
29
- * parameter rather than a second function so the two rankers can be measured
30
- * against each other on one corpus.
27
+ * THE ADDITIONS ARE ALL OFF BY DEFAULT and live in one {@link RankOptions}
28
+ * object: three that widen the indexed TERM SOURCE (trigger prose, the skill's
29
+ * own `## When to use` section, the body's headings) and one that changes the
30
+ * WEIGHTING (inverse document frequency over the catalogue). They are opt-in
31
+ * parameters rather than separate functions so two configurations can be
32
+ * measured against each other on one corpus without becoming two rankers. With
33
+ * every flag off the arithmetic is the ported one, unchanged.
31
34
  *
32
35
  * Pure — no imports, no I/O, no clock.
33
36
  */
@@ -115,36 +118,136 @@ export interface RankableSkill {
115
118
  personas?: readonly string[];
116
119
  /** `triggers[].keyword` / `triggers[].phrase` text. Indexed only on request. */
117
120
  triggerText?: readonly string[];
121
+ /** The skill's own `## When to use` prose. Indexed only on request. */
122
+ whenToUseText?: string;
123
+ /** The skill body's `##` / `###` heading lines. Indexed only on request. */
124
+ headingText?: readonly string[];
118
125
  }
119
126
 
127
+ /**
128
+ * The candidate signals, each off by default and each measurable alone.
129
+ *
130
+ * `road-to-a-ranker-that-routes` 2.2 requires exactly this shape: one flag per
131
+ * signal, default off, so a configuration is a named set of flags and two
132
+ * readings of "the ranker" are never two different rankers under one name. With
133
+ * every flag off the score is byte-identical to the Python-parity scorer, which
134
+ * is what the CLI parity suite pins.
135
+ */
120
136
  export interface RankOptions {
121
- /** Phase 3.1: fold `triggerText` into the indexed terms. Default false (keyword-v1). */
137
+ /** Fold `triggerText` into the indexed terms. Default false (keyword-v1). */
122
138
  includeTriggers?: boolean;
139
+ /** Fold the skill's own `## When to use` prose into the indexed terms. */
140
+ includeWhenToUse?: boolean;
141
+ /** Fold the body's section headings into the indexed terms. */
142
+ includeHeadings?: boolean;
143
+ /**
144
+ * Weight each matched term by its inverse document frequency over the
145
+ * catalogue, instead of counting every term alike.
146
+ *
147
+ * Needs {@link TermStats}. Setting it WITHOUT one throws, rather than
148
+ * quietly taking the unweighted branch: a weighting that falls back to
149
+ * unweighted on a missing input produces a baseline number under a
150
+ * configuration's name, which is the one failure the whole flag table
151
+ * exists to prevent.
152
+ */
153
+ idfWeighting?: boolean;
123
154
  }
124
155
 
125
156
  /** The indexed term set for one skill, under the given options. */
126
157
  export function skillTerms(skill: RankableSkill, opts: RankOptions = {}): Set<string> {
127
158
  const parts = [skill.name, skill.description];
128
159
  if (opts.includeTriggers && skill.triggerText) parts.push(...skill.triggerText);
160
+ if (opts.includeWhenToUse && skill.whenToUseText) parts.push(skill.whenToUseText);
161
+ if (opts.includeHeadings && skill.headingText) parts.push(...skill.headingText);
129
162
  return tokenize(parts.join(' '));
130
163
  }
131
164
 
165
+ /** True when `opts` turns on at least one term source beyond name + description. */
166
+ export function widensTermSource(opts: RankOptions): boolean {
167
+ return Boolean(opts.includeTriggers || opts.includeWhenToUse || opts.includeHeadings);
168
+ }
169
+
170
+ /**
171
+ * How many indexed skills carry each term, and how many skills there are.
172
+ *
173
+ * Derived from the catalogue under the SAME options the ranking uses — a
174
+ * document frequency computed over one term source and applied to another
175
+ * would weight terms by how rare they are somewhere they were never read.
176
+ */
177
+ export interface TermStats {
178
+ df: ReadonlyMap<string, number>;
179
+ skills: number;
180
+ }
181
+
182
+ /**
183
+ * @param termSets the per-skill term sets, in the same order as `skills`.
184
+ * Required rather than derived, so the catalogue is tokenized ONCE per call
185
+ * instead of once here and again at the scoring loop. Tokenizing ~300 skills
186
+ * twice per prompt is invisible next to re-reading them from disk, which is
187
+ * exactly why it would have stayed invisible.
188
+ */
189
+ export function buildTermStats(
190
+ skills: readonly RankableSkill[],
191
+ termSets: readonly ReadonlySet<string>[],
192
+ ): TermStats {
193
+ const df = new Map<string, number>();
194
+ for (const terms of termSets) {
195
+ for (const t of terms) df.set(t, (df.get(t) ?? 0) + 1);
196
+ }
197
+ return { df, skills: skills.length };
198
+ }
199
+
200
+ /**
201
+ * The weight one matched term carries.
202
+ *
203
+ * `ln(1 + skills / (1 + df))`, the smoothed textbook form: a term on every
204
+ * skill tends to zero, a term on one skill carries the most. Unknown terms are
205
+ * treated as df 0 — a task term no skill indexes cannot be matched anyway, so
206
+ * its weight only affects the denominator, where counting it fully is right:
207
+ * failing to cover a rare term should cost more than failing to cover a common
208
+ * one.
209
+ */
210
+ export function idf(term: string, stats: TermStats): number {
211
+ return Math.log(1 + stats.skills / (1 + (stats.df.get(term) ?? 0)));
212
+ }
213
+
132
214
  /**
133
215
  * The score. `taskTerms` is `tokenize(task)`; `terms` is `skillTerms(skill)`.
134
216
  *
135
217
  * Both are passed in rather than derived here so a caller ranking N skills
136
218
  * tokenizes the task once and each skill once, which is what makes this usable
137
- * on a per-prompt hook path.
219
+ * on a per-prompt hook path. `opts` and `stats` are optional and, with them
220
+ * absent or every flag off, the arithmetic is exactly the Python-parity one.
138
221
  */
139
222
  export function scoreSkill(
140
223
  taskTerms: ReadonlySet<string>,
141
224
  skill: RankableSkill,
142
225
  terms: ReadonlySet<string>,
226
+ opts: RankOptions = {},
227
+ stats?: TermStats,
143
228
  ): number {
229
+ if (opts.idfWeighting && !stats) {
230
+ throw new Error(
231
+ 'scoreSkill: idfWeighting is set but no TermStats was passed — scoring unweighted here ' +
232
+ 'would publish a baseline number under the idf label. Build stats with buildTermStats.',
233
+ );
234
+ }
144
235
  if (taskTerms.size === 0) return 0;
145
- let inter = 0;
146
- for (const t of taskTerms) if (terms.has(t)) inter++;
147
- const overlap = inter / Math.max(taskTerms.size, 1);
236
+ let overlap: number;
237
+ if (opts.idfWeighting && stats) {
238
+ let hit = 0;
239
+ let total = 0;
240
+ for (const t of taskTerms) {
241
+ const w = idf(t, stats);
242
+ total += w;
243
+ if (terms.has(t)) hit += w;
244
+ }
245
+ overlap = total > 0 ? hit / total : 0;
246
+ } else {
247
+ let inter = 0;
248
+ for (const t of taskTerms) if (terms.has(t)) inter++;
249
+ overlap = inter / Math.max(taskTerms.size, 1);
250
+ }
148
251
  let personaHit = 0;
149
252
  const taskLower = [...taskTerms].join(' ');
150
253
  for (const persona of skill.personas ?? []) {
@@ -173,9 +276,12 @@ export function rankSkills(
173
276
  opts: RankOptions = {},
174
277
  ): RankedSkill[] {
175
278
  const taskTerms = tokenize(task);
279
+ const termSets = skills.map((s) => skillTerms(s, opts));
280
+ const stats = opts.idfWeighting ? buildTermStats(skills, termSets) : undefined;
176
281
  const rows: RankedSkill[] = [];
177
- for (const skill of skills) {
178
- const score = scoreSkill(taskTerms, skill, skillTerms(skill, opts));
282
+ for (let i = 0; i < skills.length; i += 1) {
283
+ const skill = skills[i] as RankableSkill;
284
+ const score = scoreSkill(taskTerms, skill, termSets[i] as ReadonlySet<string>, opts, stats);
179
285
  if (score > 0) rows.push({ name: skill.name, score, personas: [...(skill.personas ?? [])] });
180
286
  }
181
287
  rows.sort((a, b) => (b.score - a.score) || (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));