@event4u/agent-config 16.3.0 → 16.5.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 (532) 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 +178 -78
  5. package/README.md +2 -2
  6. package/agents/templates/.ai-council.yml.example +26 -8
  7. package/dist/agent-src/commands/analyze/inbox.md +10 -7
  8. package/dist/agent-src/commands/bug/investigate.md +1 -1
  9. package/dist/agent-src/commands/commit/in-chunks.md +40 -31
  10. package/dist/agent-src/commands/commit.md +72 -33
  11. package/dist/agent-src/commands/condense.md +2 -8
  12. package/dist/agent-src/commands/council/debate.md +11 -7
  13. package/dist/agent-src/commands/council/default.md +10 -9
  14. package/dist/agent-src/commands/council.md +1 -1
  15. package/dist/agent-src/commands/design.md +1 -1
  16. package/dist/agent-src/commands/estimate-ticket.md +1 -1
  17. package/dist/agent-src/commands/feature/explore.md +3 -3
  18. package/dist/agent-src/commands/feature/plan.md +1 -1
  19. package/dist/agent-src/commands/fix/ci.md +17 -3
  20. package/dist/agent-src/commands/fix/commit-messages.md +48 -23
  21. package/dist/agent-src/commands/fix/pr-comments.md +3 -6
  22. package/dist/agent-src/commands/implement-ticket.md +3 -3
  23. package/dist/agent-src/commands/memory/add.md +4 -16
  24. package/dist/agent-src/commands/memory/load.md +5 -6
  25. package/dist/agent-src/commands/memory/promote.md +3 -16
  26. package/dist/agent-src/commands/mission/upgrade.md +3 -2
  27. package/dist/agent-src/commands/optimize/agents-dir.md +2 -2
  28. package/dist/agent-src/commands/optimize/deep.md +4 -2
  29. package/dist/agent-src/commands/optimize/rtk.md +4 -26
  30. package/dist/agent-src/commands/pr/create/description-only.md +18 -15
  31. package/dist/agent-src/commands/pr/create.md +42 -34
  32. package/dist/agent-src/commands/pr/merge.md +136 -9
  33. package/dist/agent-src/commands/prepare-for-review.md +13 -11
  34. package/dist/agent-src/commands/project/analyze.md +7 -35
  35. package/dist/agent-src/commands/refine-ticket.md +1 -1
  36. package/dist/agent-src/commands/review/changes.md +14 -19
  37. package/dist/agent-src/commands/roadmap/next.md +10 -1
  38. package/dist/agent-src/commands/roadmap/process-full.md +52 -38
  39. package/dist/agent-src/commands/roadmap/resolve-blockers.md +64 -14
  40. package/dist/agent-src/commands/worktree/create.md +7 -3
  41. package/dist/agent-src/commands/worktree/verify.md +2 -1
  42. package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +5 -3
  43. package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +7 -9
  44. package/dist/agent-src/contexts/contracts/command-suggestion-flow.md +8 -6
  45. package/dist/agent-src/contexts/contracts/frugality-charter.md +8 -5
  46. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +1 -1
  47. package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +0 -1
  48. package/dist/agent-src/contexts/execution/evidence-discipline.md +2 -2
  49. package/dist/agent-src/contexts/execution/non-interactive-contract.md +5 -8
  50. package/dist/agent-src/contexts/execution/rdp-gate.md +4 -4
  51. package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +9 -8
  52. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +67 -52
  53. package/dist/agent-src/contexts/execution/subagent-routing.md +8 -8
  54. package/dist/agent-src/contexts/execution/subagent-steering.md +6 -4
  55. package/dist/agent-src/contexts/execution/terminal-states.md +2 -2
  56. package/dist/agent-src/contexts/execution/toolchain-resolver.md +4 -10
  57. package/dist/agent-src/contexts/subagent-configuration.md +1 -1
  58. package/dist/agent-src/guidelines/agent-infra/active-remediation-mechanics.md +39 -0
  59. package/dist/agent-src/guidelines/agent-infra/context-hygiene-mechanics.md +1 -1
  60. package/dist/agent-src/guidelines/agent-infra/cross-source-consistency-mechanics.md +8 -10
  61. package/dist/agent-src/guidelines/agent-infra/frontier-reasoning-operating-profile.md +3 -2
  62. package/dist/agent-src/guidelines/agent-infra/layered-settings.md +13 -1
  63. package/dist/agent-src/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
  64. package/dist/agent-src/guidelines/agent-infra/self-improvement-pipeline.md +10 -3
  65. package/dist/agent-src/guidelines/agent-infra/size-and-scope.md +36 -0
  66. package/dist/agent-src/guidelines/design-antipatterns.md +1 -1
  67. package/dist/agent-src/guidelines/php/git.md +15 -2
  68. package/dist/agent-src/rules/active-remediation.md +0 -1
  69. package/dist/agent-src/rules/analysis-skill-routing.md +0 -1
  70. package/dist/agent-src/rules/architecture.md +0 -1
  71. package/dist/agent-src/rules/artifact-drafting-protocol.md +0 -1
  72. package/dist/agent-src/rules/artifact-engagement-recording.md +0 -1
  73. package/dist/agent-src/rules/augment-edit-discipline.md +0 -1
  74. package/dist/agent-src/rules/autonomous-execution.md +0 -1
  75. package/dist/agent-src/rules/brand-consistency.md +0 -1
  76. package/dist/agent-src/rules/brand-source-of-truth.md +0 -1
  77. package/dist/agent-src/rules/broken-access-control.md +0 -1
  78. package/dist/agent-src/rules/cli-output-handling.md +0 -1
  79. package/dist/agent-src/rules/code-comment-discipline.md +0 -1
  80. package/dist/agent-src/rules/code-provenance.md +0 -1
  81. package/dist/agent-src/rules/command-suggestion-policy.md +0 -1
  82. package/dist/agent-src/rules/commit-conventions.md +1 -2
  83. package/dist/agent-src/rules/communication-through-line.md +1 -2
  84. package/dist/agent-src/rules/content-quoting-floor.md +1 -2
  85. package/dist/agent-src/rules/context-hygiene.md +5 -5
  86. package/dist/agent-src/rules/copilot-routing.md +1 -2
  87. package/dist/agent-src/rules/council-availability.md +4 -4
  88. package/dist/agent-src/rules/cross-source-consistency.md +4 -6
  89. package/dist/agent-src/rules/decision-revisit-gate.md +2 -3
  90. package/dist/agent-src/rules/delegation-policy.md +2 -3
  91. package/dist/agent-src/rules/design-fidelity.md +0 -1
  92. package/dist/agent-src/rules/design-review-after-ui-write.md +3 -3
  93. package/dist/agent-src/rules/devcontainer-routing.md +1 -2
  94. package/dist/agent-src/rules/doc-screenshot-hygiene.md +0 -1
  95. package/dist/agent-src/rules/docker-commands.md +0 -1
  96. package/dist/agent-src/rules/domain-adoption-policy.md +0 -1
  97. package/dist/agent-src/rules/domain-safety-disclaimer.md +0 -1
  98. package/dist/agent-src/rules/domain-safety-pii.md +0 -1
  99. package/dist/agent-src/rules/domain-safety-retention.md +0 -1
  100. package/dist/agent-src/rules/downstream-changes.md +0 -1
  101. package/dist/agent-src/rules/engineering-safety-floor.md +0 -1
  102. package/dist/agent-src/rules/external-code-graph-interop.md +0 -1
  103. package/dist/agent-src/rules/external-reference-deep-dive.md +0 -1
  104. package/dist/agent-src/rules/fast-path-marker-visibility.md +1 -2
  105. package/dist/agent-src/rules/finance-safety-floor.md +0 -1
  106. package/dist/agent-src/rules/fix-what-you-see.md +6 -32
  107. package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +0 -1
  108. package/dist/agent-src/rules/git-history-discipline.md +1 -2
  109. package/dist/agent-src/rules/guidelines.md +0 -1
  110. package/dist/agent-src/rules/history-discipline.md +0 -1
  111. package/dist/agent-src/rules/icon-consistency.md +0 -1
  112. package/dist/agent-src/rules/image-likeness-and-rights.md +0 -1
  113. package/dist/agent-src/rules/improve-before-implement.md +0 -1
  114. package/dist/agent-src/rules/invite-challenge.md +0 -1
  115. package/dist/agent-src/rules/laravel-routing.md +1 -2
  116. package/dist/agent-src/rules/laravel-translations.md +0 -1
  117. package/dist/agent-src/rules/legal-safety-floor.md +0 -1
  118. package/dist/agent-src/rules/lethal-trifecta-guard.md +0 -1
  119. package/dist/agent-src/rules/linked-projects-onboarding-gate.md +0 -1
  120. package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +0 -1
  121. package/dist/agent-src/rules/markdown-safe-codeblocks.md +0 -1
  122. package/dist/agent-src/rules/media-governance-routing.md +1 -2
  123. package/dist/agent-src/rules/media-sync-ground-truth.md +0 -1
  124. package/dist/agent-src/rules/minimal-safe-diff.md +0 -1
  125. package/dist/agent-src/rules/missing-skill-recovery.md +0 -1
  126. package/dist/agent-src/rules/missing-tool-handling.md +0 -1
  127. package/dist/agent-src/rules/model-recommendation.md +0 -1
  128. package/dist/agent-src/rules/neighbour-precedence.md +64 -0
  129. package/dist/agent-src/rules/no-attribution-footers.md +0 -1
  130. package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +0 -1
  131. package/dist/agent-src/rules/no-pr-progress-comments.md +0 -1
  132. package/dist/agent-src/rules/no-roadmap-references.md +0 -1
  133. package/dist/agent-src/rules/notes-first-reasoning.md +0 -1
  134. package/dist/agent-src/rules/onboarding-gate.md +0 -1
  135. package/dist/agent-src/rules/output-discipline.md +0 -1
  136. package/dist/agent-src/rules/package-ci-checks.md +0 -1
  137. package/dist/agent-src/rules/persona-governance.md +2 -3
  138. package/dist/agent-src/rules/php-coding.md +0 -1
  139. package/dist/agent-src/rules/prefer-enums-over-literals.md +0 -1
  140. package/dist/agent-src/rules/preservation-guard.md +0 -1
  141. package/dist/agent-src/rules/provider-lifecycle-discipline.md +2 -3
  142. package/dist/agent-src/rules/question-not-instruction.md +0 -1
  143. package/dist/agent-src/rules/reviewer-awareness.md +0 -1
  144. package/dist/agent-src/rules/roadmap-ci-steps-policy.md +0 -1
  145. package/dist/agent-src/rules/roadmap-progress-sync.md +3 -6
  146. package/dist/agent-src/rules/role-mode-adherence.md +0 -1
  147. package/dist/agent-src/rules/rule-type-governance.md +0 -1
  148. package/dist/agent-src/rules/runtime-safety.md +0 -1
  149. package/dist/agent-src/rules/scale-discipline.md +0 -1
  150. package/dist/agent-src/rules/secret-vcs-guard.md +0 -1
  151. package/dist/agent-src/rules/security-sensitive-stop.md +0 -1
  152. package/dist/agent-src/rules/self-repair-loop.md +0 -1
  153. package/dist/agent-src/rules/senior-engineering-discipline.md +0 -1
  154. package/dist/agent-src/rules/session-canary.md +0 -1
  155. package/dist/agent-src/rules/settings-ask-protocol.md +5 -6
  156. package/dist/agent-src/rules/size-enforcement.md +0 -1
  157. package/dist/agent-src/rules/skill-improvement-trigger.md +2 -3
  158. package/dist/agent-src/rules/skill-quality.md +0 -1
  159. package/dist/agent-src/rules/slash-command-routing-policy.md +0 -1
  160. package/dist/agent-src/rules/source-confidentiality.md +0 -1
  161. package/dist/agent-src/rules/source-discovery-gate.md +0 -1
  162. package/dist/agent-src/rules/source-of-truth.md +0 -1
  163. package/dist/agent-src/rules/spreadsheet-source-quality.md +1 -2
  164. package/dist/agent-src/rules/strategy-safety-floor.md +0 -1
  165. package/dist/agent-src/rules/symfony-routing.md +1 -2
  166. package/dist/agent-src/rules/think-before-action.md +0 -1
  167. package/dist/agent-src/rules/token-budget-discipline.md +14 -48
  168. package/dist/agent-src/rules/token-efficiency.md +0 -1
  169. package/dist/agent-src/rules/token-optimizer-maintenance.md +0 -1
  170. package/dist/agent-src/rules/tool-safety.md +0 -1
  171. package/dist/agent-src/rules/ui-audit-gate.md +1 -2
  172. package/dist/agent-src/rules/untrusted-input-defense.md +0 -1
  173. package/dist/agent-src/rules/upstream-proposal.md +0 -1
  174. package/dist/agent-src/rules/user-interaction.md +0 -1
  175. package/dist/agent-src/rules/user-interrupt-priority.md +0 -1
  176. package/dist/agent-src/scripts/gate_budget.ts +47 -23
  177. package/dist/agent-src/scripts/gate_execute.ts +12 -4
  178. package/dist/agent-src/skills/accessibility-auditor/data/aria-patterns.csv +2 -0
  179. package/dist/agent-src/skills/accessibility-auditor/data/manifest.json +3 -3
  180. package/dist/agent-src/skills/ai-council/SKILL.md +7 -4
  181. package/dist/agent-src/skills/ai-council/references/cost-and-redaction.md +21 -11
  182. package/dist/agent-src/skills/ai-council/references/procedure.md +12 -6
  183. package/dist/agent-src/skills/analysis-autonomous-mode/SKILL.md +1 -1
  184. package/dist/agent-src/skills/bug-analyzer/SKILL.md +1 -1
  185. package/dist/agent-src/skills/canvas-design/SKILL.md +4 -2
  186. package/dist/agent-src/skills/command-routing/SKILL.md +3 -4
  187. package/dist/agent-src/skills/conventional-commits-writing/SKILL.md +127 -139
  188. package/dist/agent-src/skills/corpus-grounding/ATTRIBUTION.md +39 -0
  189. package/dist/agent-src/skills/corpus-grounding/SKILL.md +8 -2
  190. package/dist/agent-src/skills/database/data/manifest.json +2 -2
  191. package/dist/agent-src/skills/database/data/query-tuning.csv +13 -13
  192. package/dist/agent-src/skills/design-intelligence/references/integration-mapping.md +13 -10
  193. package/dist/agent-src/skills/design-system-capture/SKILL.md +0 -3
  194. package/dist/agent-src/skills/estimate-ticket/SKILL.md +1 -1
  195. package/dist/agent-src/skills/fe-design/references/design-patterns.md +49 -2
  196. package/dist/agent-src/skills/feature-planning/SKILL.md +1 -1
  197. package/dist/agent-src/skills/frontend-render-security/SKILL.md +9 -0
  198. package/dist/agent-src/skills/git-workflow/SKILL.md +44 -44
  199. package/dist/agent-src/skills/git-workflow/references/branch-update.md +312 -0
  200. package/dist/agent-src/skills/git-workflow/references/commit-subject.md +205 -0
  201. package/dist/agent-src/skills/iconography/SKILL.md +4 -2
  202. package/dist/agent-src/skills/image-provider-routing/SKILL.md +16 -5
  203. package/dist/agent-src/skills/jira-integration/SKILL.md +3 -3
  204. package/dist/agent-src/skills/logo-generation/SKILL.md +12 -8
  205. package/dist/agent-src/skills/merge-conflicts/SKILL.md +10 -4
  206. package/dist/agent-src/skills/po-discovery/SKILL.md +1 -1
  207. package/dist/agent-src/skills/refine-ticket/SKILL.md +4 -4
  208. package/dist/agent-src/skills/roadmap-writing/SKILL.md +2 -2
  209. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +4 -2
  210. package/dist/agent-src/skills/source-discovery/SKILL.md +1 -1
  211. package/dist/agent-src/skills/svg-authoring/SKILL.md +318 -0
  212. package/dist/agent-src/skills/tailwind-engineer/SKILL.md +3 -1
  213. package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
  214. package/dist/agent-src/skills/using-git-worktrees/SKILL.md +1 -1
  215. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +2 -2
  216. package/dist/agent-src/skills/wireframe/SKILL.md +5 -2
  217. package/dist/agent-src/templates/AGENTS.md +1 -1
  218. package/dist/agent-src/templates/agent-settings.md +46 -129
  219. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +3 -3
  220. package/dist/agent-src/templates/command.md +2 -2
  221. package/dist/agent-src/templates/roadmaps.md +6 -1
  222. package/dist/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -6
  223. package/dist/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +11 -7
  224. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.ts +3 -2
  225. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.ts +2 -1
  226. package/dist/agent-src/templates/scripts/work_engine/hooks/settings.ts +0 -6
  227. package/dist/agent-src/templates/scripts/work_engine/scoring/decision_engine.ts +9 -12
  228. package/dist/agent-src/templates/scripts/work_engine/scoring/memory_visibility.ts +2 -1
  229. package/dist/agent-src/templates/skill.md +1 -1
  230. package/dist/cli/commands/uiRender.js +201 -4
  231. package/dist/cli/commands/uiRenderAsset.js +1308 -0
  232. package/dist/cli/commands/uiRenderAssetCompare.js +752 -0
  233. package/dist/cli/commands/uiRenderAssetGrid.js +265 -0
  234. package/dist/cli/commands/uiRenderAssetGrounds.js +323 -0
  235. package/dist/cli/commands/uiRenderAssetIsolation.js +85 -0
  236. package/dist/cli/commands/uiRenderAssetTypes.js +145 -0
  237. package/dist/cli/main.js +47 -1
  238. package/dist/cli/registry.js +2 -1
  239. package/dist/cli-delegate/check_update_banner.js +195 -119
  240. package/dist/cli-delegate/{chunk-S4UMZNES.js → chunk-4DBG5K7M.js} +5 -5
  241. package/dist/cli-delegate/{chunk-TRI6DQZ6.js → chunk-5GPULQBE.js} +60 -42
  242. package/dist/cli-delegate/{chunk-JQVYKIZA.js → chunk-6SRJTYJS.js} +33 -177
  243. package/dist/cli-delegate/chunk-6V5FMA3P.js +186 -0
  244. package/dist/cli-delegate/chunk-6YQC2HLF.js +415 -0
  245. package/dist/cli-delegate/{chunk-E4XIZDIB.js → chunk-7HKRE54K.js} +1 -64
  246. package/dist/cli-delegate/{chunk-7HQ52DHU.js → chunk-AL3RZ22D.js} +1 -1
  247. package/dist/cli-delegate/{chunk-DBH4AHDK.js → chunk-ED7KCMLB.js} +9 -11
  248. package/dist/cli-delegate/{chunk-NXEILF2K.js → chunk-F3QDG2GT.js} +481 -72
  249. package/dist/cli-delegate/{chunk-CQWX336L.js → chunk-G5VVIZRC.js} +3 -3
  250. package/dist/cli-delegate/{chunk-JY2I2DXV.js → chunk-H76PHZBI.js} +137 -60
  251. package/dist/cli-delegate/chunk-IAYTIIQW.js +67 -0
  252. package/dist/cli-delegate/{chunk-LIYTLH6O.js → chunk-KXXWJTDO.js} +5 -10
  253. package/dist/cli-delegate/{chunk-T7L2QK3K.js → chunk-LQOCRFWT.js} +1 -1
  254. package/dist/cli-delegate/{chunk-S4YWNRKO.js → chunk-MDPPKQCQ.js} +34 -1
  255. package/dist/cli-delegate/chunk-OAFSJBHH.js +272 -0
  256. package/dist/cli-delegate/{chunk-GKE7ZVFA.js → chunk-PWX7CKMD.js} +1 -1
  257. package/dist/cli-delegate/{chunk-NDJLNC6Q.js → chunk-T6BP34WI.js} +1 -0
  258. package/dist/cli-delegate/{chunk-RQNNW7IF.js → chunk-T7XSJSUQ.js} +433 -632
  259. package/dist/cli-delegate/{chunk-NQ7WT43P.js → chunk-TMWYUOK4.js} +75 -12
  260. package/dist/cli-delegate/{chunk-EEHDXSYD.js → chunk-WQWXGIWB.js} +12 -273
  261. package/dist/cli-delegate/{chunk-QLDHIPWR.js → chunk-XQTPXKFA.js} +1 -1
  262. package/dist/cli-delegate/cmd_analyze_session.js +223 -43
  263. package/dist/cli-delegate/cmd_brand_status.js +3 -2
  264. package/dist/cli-delegate/cmd_conformance.js +489 -238
  265. package/dist/cli-delegate/cmd_converge.js +3 -3
  266. package/dist/cli-delegate/cmd_doctor.js +15 -12
  267. package/dist/cli-delegate/cmd_doctor_neighbours.js +11 -4
  268. package/dist/cli-delegate/cmd_explain.js +43 -19
  269. package/dist/cli-delegate/cmd_export.js +10 -10
  270. package/dist/cli-delegate/cmd_git_convention.js +1851 -0
  271. package/dist/cli-delegate/cmd_handoff.js +40 -21
  272. package/dist/cli-delegate/cmd_mcp_available.js +3 -2
  273. package/dist/cli-delegate/cmd_migrate.js +3 -3
  274. package/dist/cli-delegate/cmd_packs_active.js +4 -3
  275. package/dist/cli-delegate/cmd_prune.js +10 -10
  276. package/dist/cli-delegate/cmd_route_audit.js +7 -7
  277. package/dist/cli-delegate/cmd_route_explain.js +5 -5
  278. package/dist/cli-delegate/cmd_session_recycle.js +9 -7
  279. package/dist/cli-delegate/cmd_settings_check.js +54 -7
  280. package/dist/cli-delegate/cmd_settings_get.js +18 -8
  281. package/dist/cli-delegate/cmd_settings_migrate.js +10 -10
  282. package/dist/cli-delegate/cmd_settings_set.js +1 -1
  283. package/dist/cli-delegate/cmd_sync.js +10 -10
  284. package/dist/cli-delegate/cmd_uninstall.js +10 -10
  285. package/dist/cli-delegate/cmd_update.js +7 -7
  286. package/dist/cli-delegate/cmd_upgrade.js +7 -7
  287. package/dist/cli-delegate/cmd_validate.js +10 -10
  288. package/dist/cli-delegate/cmd_versions.js +5 -5
  289. package/dist/cli-delegate/gate_budget.js +1 -1
  290. package/dist/cli-delegate/gate_execute.js +2 -2
  291. package/dist/cli-delegate/roadmap_gates.js +2 -2
  292. package/dist/discovery/deprecation-report.md +1 -1
  293. package/dist/discovery/discovery-manifest.json +171 -107
  294. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  295. package/dist/discovery/discovery-manifest.summary.md +7 -7
  296. package/dist/discovery/dormancy-report.md +1 -1
  297. package/dist/discovery/orphan-report.md +1 -1
  298. package/dist/discovery/packs.json +41 -22
  299. package/dist/discovery/trust-report.md +3 -3
  300. package/dist/discovery/workspaces.json +16 -11
  301. package/dist/hooks/dispatch.js +2520 -1924
  302. package/dist/hooks/dispatch.sha256 +1 -1
  303. package/dist/hooks/svg_rules.chunk.cjs +1626 -0
  304. package/dist/hooks/svg_rules.chunk.cjs.sha256 +1 -0
  305. package/dist/install/install.mjs +462 -431
  306. package/dist/install/installThinLayer.js +40 -12
  307. package/dist/install/installedRuleLinks.js +105 -19
  308. package/dist/mcp/awesome-mcp-servers.row.md +1 -1
  309. package/dist/mcp/mcp-cloudflare-catalogue.json +2 -2
  310. package/dist/mcp/registry-manifest.json +5 -5
  311. package/dist/mcp/server.json +2 -2
  312. package/dist/mcp/server.mjs +3063 -2160
  313. package/dist/router.json +1 -1
  314. package/dist/scripts/_lib/agent_settings.js +15 -120
  315. package/dist/scripts/_lib/compile_time_toggles.js +12 -21
  316. package/dist/scripts/_lib/git_convention.js +232 -0
  317. package/dist/scripts/_lib/global_deploy_inventory.js +730 -0
  318. package/dist/scripts/_lib/installed_layer.js +344 -18
  319. package/dist/scripts/_lib/package_root.js +68 -0
  320. package/dist/scripts/_lib/rule_law_section.js +1 -1
  321. package/dist/scripts/_lib/scan_scope.js +105 -0
  322. package/dist/scripts/_lib/settings_removed_keys.js +168 -0
  323. package/dist/scripts/_lib/svg_dom.js +284 -0
  324. package/dist/scripts/_lib/svg_geometry.js +477 -0
  325. package/dist/scripts/_lib/svg_motion.js +179 -0
  326. package/dist/scripts/_lib/svg_rules.js +1337 -0
  327. package/dist/scripts/_lib/svg_urls.js +67 -0
  328. package/dist/scripts/_lib/thin_rules.js +80 -3
  329. package/dist/scripts/lint_svg_asset.js +324 -0
  330. package/dist/server/app.js +2 -1
  331. package/dist/server/gitKeysGate.js +105 -0
  332. package/dist/server/routes/settings.js +67 -8
  333. package/dist/server/routes/wizard.js +4 -0
  334. package/dist/server/schemas/settings.js +23 -81
  335. package/dist/shared/skillRanking.js +30 -4
  336. package/dist/ui/assets/{index-Cwq4d0hX.js → index-C3djEJah.js} +2 -2
  337. package/dist/ui/index.html +1 -1
  338. package/docs/MIGRATION.md +72 -1
  339. package/docs/contracts/settings-classes.md +35 -65
  340. package/docs/guidelines/agent-infra/active-remediation-mechanics.md +39 -0
  341. package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +1 -1
  342. package/docs/guidelines/agent-infra/cross-source-consistency-mechanics.md +8 -10
  343. package/docs/guidelines/agent-infra/frontier-reasoning-operating-profile.md +3 -2
  344. package/docs/guidelines/agent-infra/layered-settings.md +13 -1
  345. package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
  346. package/docs/guidelines/agent-infra/self-improvement-pipeline.md +10 -3
  347. package/docs/guidelines/agent-infra/size-and-scope.md +36 -0
  348. package/docs/guidelines/design-antipatterns.md +1 -1
  349. package/docs/guidelines/php/git.md +15 -2
  350. package/package.json +4 -3
  351. package/src/agent-src/scripts/gate_budget.ts +47 -23
  352. package/src/agent-src/scripts/gate_execute.ts +12 -4
  353. package/src/agent-src/templates/AGENTS.md +1 -1
  354. package/src/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -6
  355. package/src/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +11 -7
  356. package/src/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.ts +3 -2
  357. package/src/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.ts +2 -1
  358. package/src/agent-src/templates/scripts/work_engine/hooks/settings.ts +0 -6
  359. package/src/agent-src/templates/scripts/work_engine/scoring/decision_engine.ts +9 -12
  360. package/src/agent-src/templates/scripts/work_engine/scoring/memory_visibility.ts +2 -1
  361. package/src/config/agent-settings.template.yml +79 -312
  362. package/src/config/agents-paths.yml +16 -0
  363. package/src/config/assurance-capability-registry.json +7 -3
  364. package/src/config/ci-local-parity.yml +3 -0
  365. package/src/config/continuity-surface.json +3 -3
  366. package/src/config/discovery/packs.yml +17 -1
  367. package/src/config/evaluator-budgets.json +19 -6
  368. package/src/config/gate-coverage.yml +65 -23
  369. package/src/config/gate-violation-baselines.json +56 -16
  370. package/src/config/gitignore-block.txt +19 -0
  371. package/src/config/hook-bundle-budget.json +1 -1
  372. package/src/config/release-gate-locality.yml +2 -1
  373. package/src/config/routing-coverage-seed.json +55 -6
  374. package/src/config/rule-law-ceilings.json +12 -6
  375. package/src/config/rule-obligations.json +833 -0
  376. package/src/install/installThinLayer.ts +76 -10
  377. package/src/install/installedRuleLinks.ts +105 -17
  378. package/src/scripts/_cli/cmd_analyze_session.ts +9 -15
  379. package/src/scripts/_cli/cmd_conformance.ts +13 -2
  380. package/src/scripts/_cli/cmd_doctor.ts +10 -10
  381. package/src/scripts/_cli/cmd_doctor_neighbours.ts +133 -0
  382. package/src/scripts/_cli/cmd_explain.ts +72 -14
  383. package/src/scripts/_cli/cmd_git_convention.ts +637 -0
  384. package/src/scripts/_cli/cmd_settings_check.ts +66 -8
  385. package/src/scripts/_cli/cmd_settings_get.ts +18 -3
  386. package/src/scripts/_cli/doctor_execution.ts +72 -1
  387. package/src/scripts/_dispatch.bash +37 -2
  388. package/src/scripts/_lib/agent_settings.ts +15 -124
  389. package/src/scripts/_lib/blocked_by_marker.ts +1 -1
  390. package/src/scripts/_lib/compile_time_toggles.ts +12 -21
  391. package/src/scripts/_lib/dispatch_import_closure.ts +163 -0
  392. package/src/scripts/_lib/git_base_ref.ts +92 -0
  393. package/src/scripts/_lib/git_convention.ts +291 -0
  394. package/src/scripts/_lib/git_convention_carrier.ts +389 -0
  395. package/src/scripts/_lib/git_convention_grammar.ts +246 -0
  396. package/src/scripts/_lib/git_convention_measure.ts +344 -0
  397. package/src/scripts/_lib/global_deploy_inventory.ts +74 -0
  398. package/src/scripts/_lib/graph_feeder_record.ts +236 -13
  399. package/src/scripts/_lib/installed_layer.ts +448 -23
  400. package/src/scripts/_lib/knowledge_global.ts +14 -1
  401. package/src/scripts/_lib/module_reach.ts +456 -0
  402. package/src/scripts/_lib/neighbour_contradictions.ts +236 -0
  403. package/src/scripts/_lib/neighbour_tool_use.ts +8 -10
  404. package/src/scripts/_lib/ratification_artifact.ts +220 -1
  405. package/src/scripts/_lib/ratification_subject.ts +92 -0
  406. package/src/scripts/_lib/release_findings_ingest.ts +15 -7
  407. package/src/scripts/_lib/release_highlights.ts +5 -0
  408. package/src/scripts/_lib/rule_law_section.ts +1 -1
  409. package/src/scripts/_lib/rule_obligations.ts +205 -0
  410. package/src/scripts/_lib/self_repair.ts +1 -1
  411. package/src/scripts/_lib/settings_removed_keys.ts +173 -0
  412. package/src/scripts/_lib/svg_dom.ts +318 -0
  413. package/src/scripts/_lib/svg_geometry.ts +480 -0
  414. package/src/scripts/_lib/svg_motion.ts +208 -0
  415. package/src/scripts/_lib/svg_rules.ts +1453 -0
  416. package/src/scripts/_lib/svg_urls.ts +72 -0
  417. package/src/scripts/_lib/test_red_state.ts +5 -0
  418. package/src/scripts/_lib/thin_rules.ts +83 -3
  419. package/src/scripts/_lib/touched_file_quality.ts +142 -6
  420. package/src/scripts/_lib/verification_command.ts +59 -0
  421. package/src/scripts/_lib/verify_clause.ts +27 -17
  422. package/src/scripts/_lib/worker_budget.ts +1 -1
  423. package/src/scripts/adr/regenerate_index.ts +16 -1
  424. package/src/scripts/ai_council/config.ts +7 -7
  425. package/src/scripts/ai_council/modification_review.ts +100 -0
  426. package/src/scripts/ai_council/modification_review_questions.ts +90 -0
  427. package/src/scripts/ai_council/orchestrator.ts +5 -5
  428. package/src/scripts/ai_council/spend_gate.ts +18 -7
  429. package/src/scripts/ai_team/config.ts +11 -16
  430. package/src/scripts/audit_user_type_axis.ts +20 -8
  431. package/src/scripts/bench_ab_clone.ts +1 -2
  432. package/src/scripts/bench_concern_spawn_path.ts +129 -0
  433. package/src/scripts/bench_graph_feeder_latency.ts +584 -0
  434. package/src/scripts/check_agent_artifact_location.ts +36 -0
  435. package/src/scripts/check_branch_freshness.ts +147 -24
  436. package/src/scripts/check_enforcement_coverage.ts +130 -0
  437. package/src/scripts/check_evaluator_budgets.ts +4 -0
  438. package/src/scripts/check_finding_dispositions.ts +88 -25
  439. package/src/scripts/check_gate_coverage.ts +4 -3
  440. package/src/scripts/check_gate_reachability.ts +48 -1
  441. package/src/scripts/check_generator_sync.ts +48 -0
  442. package/src/scripts/check_hook_bundle_composition.ts +107 -0
  443. package/src/scripts/check_kernel_edit_ratified.ts +86 -6
  444. package/src/scripts/check_pack_size.ts +1 -1
  445. package/src/scripts/check_release_manifest_content.ts +189 -0
  446. package/src/scripts/check_standing_rule_delivery.ts +96 -0
  447. package/src/scripts/check_suppression_hygiene.ts +2 -5
  448. package/src/scripts/ci_settle.ts +42 -5
  449. package/src/scripts/classify_merge_risk.ts +320 -0
  450. package/src/scripts/closure_scan.ts +91 -1
  451. package/src/scripts/command_suggester/settings.ts +8 -108
  452. package/src/scripts/command_suggester/types.ts +4 -5
  453. package/src/scripts/consumer_matrix.ts +102 -0
  454. package/src/scripts/context_hygiene_hook.ts +13 -23
  455. package/src/scripts/cost/preflight.mjs +12 -1
  456. package/src/scripts/council_cli.ts +7 -7
  457. package/src/scripts/dispatch_r2_reviewer.ts +24 -11
  458. package/src/scripts/explain_run.ts +8 -13
  459. package/src/scripts/generate_git_convention_grammar.ts +127 -0
  460. package/src/scripts/generate_host_cost_table.ts +20 -3
  461. package/src/scripts/handoff_context_hook.ts +86 -37
  462. package/src/scripts/hook_manifest.json +1 -1
  463. package/src/scripts/hook_manifest.yaml +25 -6
  464. package/src/scripts/hooks/block_config_weakening.ts +48 -5
  465. package/src/scripts/hooks/block_plumbing_writes.ts +8 -4
  466. package/src/scripts/hooks/block_speaking_inbox_dir.ts +16 -1
  467. package/src/scripts/hooks/concern_registry.ts +2 -0
  468. package/src/scripts/hooks/delegation_nudge_hook.ts +2 -3
  469. package/src/scripts/hooks/design_pass_hook.ts +157 -3
  470. package/src/scripts/hooks/evidence_independence.ts +12 -4
  471. package/src/scripts/hooks/mcp_usage_observation_hook.ts +121 -0
  472. package/src/scripts/hooks/push_settle_hook.ts +4 -3
  473. package/src/scripts/hooks/rule_inject_hook.ts +44 -3
  474. package/src/scripts/hooks/state_io.ts +8 -4
  475. package/src/scripts/hooks/svg_obligation.ts +497 -0
  476. package/src/scripts/hooks/svg_rules_loader.ts +133 -0
  477. package/src/scripts/hooks/telemetry_usage_hook.ts +7 -46
  478. package/src/scripts/hooks/turn_end_gate_hook.ts +6 -3
  479. package/src/scripts/install-hooks.sh +42 -14
  480. package/src/scripts/install.ts +7 -31
  481. package/src/scripts/lint_blocker_citations.ts +198 -0
  482. package/src/scripts/lint_consolidation_lineage.ts +6 -3
  483. package/src/scripts/lint_design_quality.ts +60 -12
  484. package/src/scripts/lint_evidence_artifacts.ts +9 -0
  485. package/src/scripts/lint_hook_concern_budget.ts +10 -21
  486. package/src/scripts/lint_motion_authority_drift.ts +27 -0
  487. package/src/scripts/lint_pack_boundaries.ts +406 -28
  488. package/src/scripts/lint_roadmap_blockers.ts +282 -29
  489. package/src/scripts/lint_roadmap_complexity.ts +4 -2
  490. package/src/scripts/lint_rule_law_section.ts +151 -21
  491. package/src/scripts/lint_rule_skill_pack_reach.ts +17 -0
  492. package/src/scripts/lint_settings_classes.ts +1 -1
  493. package/src/scripts/lint_svg_asset.ts +365 -0
  494. package/src/scripts/lint_ticked_unmet_criteria.ts +165 -0
  495. package/src/scripts/lint_workflow_security.ts +12 -1
  496. package/src/scripts/measure_skill_ranker_baseline.ts +5 -0
  497. package/src/scripts/model_rule_injection.ts +3 -3
  498. package/src/scripts/onboarding_gate_hook.ts +7 -6
  499. package/src/scripts/print_required_checks.ts +15 -3
  500. package/src/scripts/probe_host_compliance.ts +33 -5
  501. package/src/scripts/probe_turnaround.ts +183 -3
  502. package/src/scripts/ratification_header.ts +77 -0
  503. package/src/scripts/refusal_envelope.ts +138 -0
  504. package/src/scripts/release_publication.ts +29 -3
  505. package/src/scripts/report_dispatch_import_closure.ts +76 -0
  506. package/src/scripts/report_installed_rule_links.ts +118 -1
  507. package/src/scripts/report_module_reach.ts +212 -0
  508. package/src/scripts/report_obligation_mechanism.ts +16 -18
  509. package/src/scripts/report_parked_blockers.ts +222 -0
  510. package/src/scripts/report_required_checks_drift.ts +196 -0
  511. package/src/scripts/report_skill_ranker_confusion.ts +103 -2
  512. package/src/scripts/report_standing_payload_by_host.ts +1 -1
  513. package/src/scripts/routing_doctor.ts +2 -2
  514. package/src/scripts/schemas/agent-settings.schema.json +17 -31
  515. package/src/scripts/schemas/command.schema.json +1 -1
  516. package/src/scripts/schemas/skill.schema.json +1 -1
  517. package/src/scripts/self_review_gate.ts +39 -2
  518. package/src/scripts/skill_tools/score_skill_relevance.ts +28 -19
  519. package/src/scripts/sync_pr_branch.ts +403 -132
  520. package/src/scripts/trigger_eval_grandfather.json +0 -16
  521. package/src/server/schemas/settings.ts +33 -177
  522. package/src/shared/skillRanking.ts +53 -4
  523. package/dist/cli-delegate/chunk-NYX3L2PZ.js +0 -99
  524. package/src/scripts/_lib/config_chain.ts +0 -477
  525. package/src/scripts/_lib/conformance_report.ts +0 -403
  526. package/src/scripts/_lib/eval_discrimination.ts +0 -95
  527. package/src/scripts/_lib/evaluator_promotion.ts +0 -225
  528. package/src/scripts/_lib/file_slicer.ts +0 -117
  529. package/src/scripts/_lib/legacy_boundary_map.ts +0 -228
  530. package/src/scripts/_lib/minimality_tiebreak.ts +0 -168
  531. package/src/scripts/_lib/overbuild_lens_contract.ts +0 -196
  532. package/src/scripts/_lib/role_split.ts +0 -338
@@ -6,10 +6,14 @@
6
6
  * Python module exactly (snake_case kept deliberately — fidelity over
7
7
  * TS idiom).
8
8
  *
9
- * Per `docs/contracts/hook-architecture-v1.md` § Concurrency, every concern
10
- * that writes under `agents/runtime/state/` MUST:
11
- *
12
- * 1. Acquire an exclusive lock on `agents/runtime/state/.dispatcher.lock`.
9
+ * Per `docs/contracts/hook-architecture-v1.md`, Concurrency, every concern
10
+ * that writes a state file under `agents/` MUST:
11
+ *
12
+ * 1. Acquire an exclusive lock on `<state_dir>/.dispatcher.lock` — the SAME
13
+ * directory the target file lives in, derived from the target's own
14
+ * path (`path.dirname`), never a single fixed location: one concern's
15
+ * target under `agents/runtime/state/` locks there, another's target
16
+ * under `agents/state/` locks there instead.
13
17
  * 2. Write to a sibling `<dest>.tmp.<pid>` file in the same directory.
14
18
  * 3. Rename(2) (atomic on the same filesystem) tmp → dest.
15
19
  * 4. Release the lock.
@@ -0,0 +1,497 @@
1
+ /**
2
+ * The open-SVG-obligation reading — step 2.1(b) of `road-to-svg-review-followups`.
3
+ *
4
+ * THE HOLE THIS CLOSES, which a review found and a reading confirmed. A turn
5
+ * that edits an `.svg` and then runs `ui:render --profile asset` looks, to the
6
+ * turn-end gate, like a turn that verified its work. It is not: on a machine
7
+ * with no Playwright that command rendered nothing, and until 2026-10-11 it
8
+ * also exited 0. Teaching `isVerificationCommand` the command would have made
9
+ * the hole worse rather than better — the transcript path never sees an exit
10
+ * code (`turn_end_gate_hook.ts:764` matches a command and stops), so a bare
11
+ * call would have discharged the obligation on both paths.
12
+ *
13
+ * So the detector reads the RENDER, never the call. An `.svg` the turn edited
14
+ * is discharged by exactly one of two records:
15
+ *
16
+ * 1. an asset manifest with `verification: "verified"` whose `asset.digest`
17
+ * equals the file's CURRENT digest; or
18
+ * 2. an asset manifest with `reason: "renderer-absent"` whose `static` block
19
+ * carries `errors: 0` on that same digest — reported as `static-only`.
20
+ *
21
+ * Path 2 is why a consumer without Playwright is not refused forever on a gate
22
+ * declared `blocking`. A `render-failed` manifest discharges NOTHING: a
23
+ * renderer that ran and failed is a real failure, not a capability fact.
24
+ *
25
+ * FOUR PRECISIONS, each from a third review and each closing a way the gate
26
+ * would otherwise refuse honest work or accept dishonest work:
27
+ *
28
+ * (ii) A planted fixture opens no obligation. `tests/design-artifacts/
29
+ * fixtures/**` and `tests/design-artifacts/scenarios/**` carry errors
30
+ * ON PURPOSE and can never reach `verified`, so without this every turn
31
+ * that touches one would be refused on a blocking gate. By PATH, not by
32
+ * an inline ignore marker — a marker would hide the planted error from
33
+ * the very test that has to find it.
34
+ * (iii) A manifest counts only where THIS turn ran a render NAMING THAT
35
+ * FILE after the edit. Otherwise an agent could write a manifest by
36
+ * hand, digest included, and discharge its own obligation.
37
+ *
38
+ * A turn that writes into the render directory by any other route —
39
+ * an edit tool, or a shell command naming the directory — voids every
40
+ * manifest for that turn, so a hand-written manifest plus a render that
41
+ * names the file (and failed) no longer discharges (16.5.0 release
42
+ * review).
43
+ *
44
+ * THE RESIDUAL, stated rather than implied. This is a check against an
45
+ * omission, not a tamper-proof attestation: a process that can run a
46
+ * shell can write a file by a route no transcript reading recognises.
47
+ * What is enforced is that a render naming the file ran and that the
48
+ * turn did not visibly write the render directory; what is not
49
+ * enforced is that the manifest on disk is the one that render produced. A manifest left by an
50
+ * EARLIER turn whose digest still matches therefore discharges — and
51
+ * that is defensible, because a matching digest means the bytes have
52
+ * not moved since it was taken, which is the whole claim a digest
53
+ * makes. It is recorded here because the first version of this
54
+ * paragraph promised more than the code did (finding 2 of this
55
+ * change's own completion review), and a gate whose documented
56
+ * assurance outruns its implementation is quoted as written.
57
+ * (iv) A deleted `.svg` opens no obligation — it has no current digest, so
58
+ * there is nothing a render could be bound to.
59
+ *
60
+ * Its own module rather than another 200 lines inside the gate: the gate ships
61
+ * in a byte-capped bundle AND sits two lines under the source-size ratchet, so
62
+ * a separate module is both the unit whose cost can be measured and the only
63
+ * place this could have gone.
64
+ *
65
+ * It is also why `openSvgObligation` returns a finding-shaped object rather
66
+ * than a reason the gate wraps: the gate's entry for it is ONE line, and the
67
+ * reasoning that would have been a comment there is the paragraph above.
68
+ *
69
+ * THE DETECTOR RUNS UNCONDITIONALLY, including while a subagent dispatch is
70
+ * open — nothing about a dispatch makes an unrendered graphic rendered.
71
+ */
72
+ import * as crypto from 'node:crypto';
73
+ import * as fs from 'node:fs';
74
+ import * as path from 'node:path';
75
+
76
+ import { isAssetRenderCommand } from '../_lib/verification_command.js';
77
+ import type { ToolCall } from '../_lib/turn_end_transcript.js';
78
+
79
+ /**
80
+ * Re-exported, not re-derived. Finding 3 of this change's SECOND completion
81
+ * review moved the predicate into `_lib/verification_command.ts`, because
82
+ * detector C needs it too and a `_lib` module may not import from `hooks/`.
83
+ * Two copies of a command-shape regex is how the two detectors come to
84
+ * disagree about what a render is.
85
+ */
86
+ export { isAssetRenderCommand };
87
+
88
+ /**
89
+ * Tools that WRITE. One copy, here rather than imported from the gate: the
90
+ * gate imports this module, so the dependency runs one way.
91
+ */
92
+ const EDIT_TOOLS = new Set(['Edit', 'Write', 'MultiEdit', 'NotebookEdit']);
93
+
94
+ /** Where `ui:render` writes. One copy of the path, shared with the CLI by value. */
95
+ export const RENDER_REL = path.join('agents', 'runtime', 'state', 'render');
96
+
97
+ /**
98
+ * Paths whose `.svg` files are planted on purpose. Precision (ii).
99
+ *
100
+ * Compared against a forward-slash form of the path so the list reads the same
101
+ * on every platform and a Windows-shaped tool call is not silently exempt.
102
+ */
103
+ export const PLANTED_PREFIXES: readonly string[] = [
104
+ 'tests/design-artifacts/fixtures/',
105
+ 'tests/design-artifacts/scenarios/',
106
+ ];
107
+
108
+ export type DischargeKind = 'verified' | 'static-only';
109
+
110
+ export interface SvgObligation {
111
+ /** Repo-relative, forward slashes — the evidence span a refusal quotes. */
112
+ file: string;
113
+ /** Why it is still open, in the words the refusal uses. */
114
+ reason: string;
115
+ }
116
+
117
+ export interface SvgDischarge {
118
+ file: string;
119
+ kind: DischargeKind;
120
+ }
121
+
122
+ export interface SvgObligationReading {
123
+ open: SvgObligation[];
124
+ discharged: SvgDischarge[];
125
+ }
126
+
127
+ /** The shape this reads out of a manifest. Deliberately partial. */
128
+ interface AssetManifestish {
129
+ profile?: unknown;
130
+ verification?: unknown;
131
+ reason?: unknown;
132
+ asset?: { digest?: unknown; findings?: unknown } | undefined;
133
+ static?: { errors?: unknown; digest?: unknown } | undefined;
134
+ }
135
+
136
+ /** Does a manifest's asset reading carry an error-severity finding? */
137
+ function hasErrorFinding(m: AssetManifestish): boolean {
138
+ const f = m.asset?.findings;
139
+ return Array.isArray(f) && f.some((x) => (x as { severity?: unknown })?.severity === 'error');
140
+ }
141
+
142
+ /**
143
+ * Repo-relative, forward slashes — whatever the host handed us.
144
+ *
145
+ * Finding 1 of this change's completion review, and it was a live gate risk
146
+ * rather than a tidiness point: this used to normalise separators only, so an
147
+ * ABSOLUTE tool-call path never started with `tests/design-artifacts/…` and the
148
+ * planted-fixture exemption silently missed. A blocking gate would then have
149
+ * refused every turn that edits one of the ~25 deliberately-broken fixtures
150
+ * this very change adds — and no test caught it, because every case passed a
151
+ * relative path. The function four lines down already treated an absolute path
152
+ * as expected input, which is the contradiction inside one file that made the
153
+ * finding decidable.
154
+ */
155
+ const rel = (root: string, p: string): string => {
156
+ const slashed = p.split(path.sep).join('/');
157
+ // Normalised, so `fixtures/../../../public/a.svg` is `public/a.svg` and not
158
+ // a planted fixture by prefix (16.5.0 re-cut review).
159
+ if (!path.isAbsolute(p)) return path.posix.normalize(slashed).replace(/^\.\//, '');
160
+ const inside = path.relative(root, p).split(path.sep).join('/');
161
+ // `path.relative` escaping the root with `..` means the path is NOT in this
162
+ // workspace; keep it as given rather than inventing a relation to it.
163
+ return inside === '' || inside.startsWith('../') ? slashed : inside;
164
+ };
165
+
166
+ export function isPlantedFixture(relPath: string, root = ''): boolean {
167
+ const norm = rel(root, relPath);
168
+ return PLANTED_PREFIXES.some((prefix) => norm.startsWith(prefix));
169
+ }
170
+
171
+ /** Every asset manifest currently under the render directory. */
172
+ export function readAssetManifests(root: string): AssetManifestish[] {
173
+ const dir = path.join(root, RENDER_REL);
174
+ let entries: string[];
175
+ try {
176
+ entries = fs.readdirSync(dir);
177
+ } catch {
178
+ return [];
179
+ }
180
+ const out: AssetManifestish[] = [];
181
+ for (const name of entries) {
182
+ let raw: string;
183
+ try {
184
+ raw = fs.readFileSync(path.join(dir, name, 'manifest.json'), 'utf8');
185
+ } catch {
186
+ continue;
187
+ }
188
+ try {
189
+ const parsed = JSON.parse(raw) as AssetManifestish;
190
+ if (parsed.profile === 'asset') out.push(parsed);
191
+ } catch {
192
+ // An unreadable manifest discharges nothing, which is the same
193
+ // verdict as an absent one and the safe direction for a gate.
194
+ }
195
+ }
196
+ return out;
197
+ }
198
+
199
+ /**
200
+ * How a digest is discharged by the manifests on disk, or `null`.
201
+ *
202
+ * `verified` wins over `static-only` when both exist: the stronger record is
203
+ * the one the report should name.
204
+ */
205
+ export function dischargeFor(manifests: readonly AssetManifestish[], digest: string): DischargeKind | null {
206
+ let staticOnly = false;
207
+ for (const m of manifests) {
208
+ // AN ERROR FLOOR ON BOTH PATHS. Finding 2 of the fifth completion
209
+ // review: `verification: 'verified'` is written unconditionally by the
210
+ // render — it means a digest-bound render HAPPENED, which is what the
211
+ // skill's status table says and what it should keep meaning — and this
212
+ // branch discharged on it with no look at what the render FOUND. So a
213
+ // file whose own reading carries an error findings discharged a
214
+ // blocking gate through the strong path, while the weaker
215
+ // `renderer-absent` path below refused at a single error. The rigour
216
+ // was inverted: the path that saw more of the file demanded less of it.
217
+ if (m.verification === 'verified' && m.asset?.digest === digest && !hasErrorFinding(m)) {
218
+ return 'verified';
219
+ }
220
+ if (m.reason === 'renderer-absent' && m.static?.digest === digest && m.static.errors === 0) {
221
+ staticOnly = true;
222
+ }
223
+ }
224
+ return staticOnly ? 'static-only' : null;
225
+ }
226
+
227
+ export interface SvgObligationInputs {
228
+ /**
229
+ * One entry per file the turn EDITED, in order, `.svg` and otherwise, each
230
+ * carrying the `ui:render --profile asset` command lines that ran after
231
+ * THAT file's last edit, verbatim.
232
+ *
233
+ * Precision (iii), and both halves of it were wrong once.
234
+ *
235
+ * The first round made it per file by NAME: a single boolean used to mean
236
+ * that any asset render anywhere unlocked every manifest on disk, so a
237
+ * hand-written manifest plus a decoy render on an unrelated file
238
+ * discharged the obligation. A command must NAME the file it discharges.
239
+ *
240
+ * The second round made it per file by TIME, which is finding 2 of that
241
+ * round. The render window was taken from the turn's LAST `.svg` edit
242
+ * globally while the obligation is per file, so the ordinary interleaved
243
+ * turn — edit a, render a, edit b, render b — hid render-a behind edit-b
244
+ * and refused a turn in which both files were rendered correctly after
245
+ * their own edits. Confirmed by running it before it was changed.
246
+ *
247
+ * Both windows are the same shape: a render counts for a file only if it
248
+ * names that file AND follows that file's own last edit.
249
+ */
250
+ edits: ReadonlyArray<{ path: string; rendered: readonly string[] }>;
251
+ /**
252
+ * True when this turn wrote into the render directory by some route other
253
+ * than an asset render — an edit tool, or a shell command naming the
254
+ * directory. The manifests on disk are then not evidence of a render, so
255
+ * none of them discharges anything (16.5.0 release review).
256
+ */
257
+ renderDirTampered?: boolean;
258
+ }
259
+
260
+ /**
261
+ * The reading. Pure apart from reading the files it is asked about, so the
262
+ * eight cases the roadmap names can be exercised without a hook run.
263
+ */
264
+ export function readSvgObligations(root: string, inputs: SvgObligationInputs): SvgObligationReading {
265
+ const open: SvgObligation[] = [];
266
+ const discharged: SvgDischarge[] = [];
267
+ const seen = new Set<string>();
268
+ let manifests: AssetManifestish[] | null = null;
269
+
270
+ for (const { path: raw, rendered } of inputs.edits) {
271
+ if (!/\.svg$/i.test(raw)) continue;
272
+ // Repo-relative FIRST, so `seen`, the planted exemption and the
273
+ // reported `file` all speak the same dialect — the doc on
274
+ // `SvgObligation.file` promises repo-relative and used to be false for
275
+ // an absolute tool call.
276
+ const relPath = rel(root, raw);
277
+ if (seen.has(relPath)) continue;
278
+ seen.add(relPath);
279
+ // (ii) planted fixtures carry errors on purpose.
280
+ if (isPlantedFixture(relPath, root)) continue;
281
+
282
+ // (iv) a deleted file has no current digest, so nothing could be bound
283
+ // to it and no render could ever discharge it.
284
+ const abs = path.isAbsolute(raw) ? raw : path.join(root, relPath);
285
+ // The BYTES, matching the render and the static witness. Finding 2 of
286
+ // the sixth completion review: this hashed the UTF-8 decoded string
287
+ // while the render hashed the raw buffer, so a file the decode is not
288
+ // byte-exact over could never have its obligation discharged.
289
+ let bytes: Buffer;
290
+ try {
291
+ bytes = fs.readFileSync(abs);
292
+ } catch {
293
+ continue;
294
+ }
295
+ const digest = crypto.createHash('sha256').update(bytes).digest('hex');
296
+
297
+ // (iii) The manifests are only consulted once a render was observed.
298
+ // Reading them first and then discarding the verdict would make the
299
+ // ordering look like a performance detail rather than the rule.
300
+ if (!renderNames(rendered, relPath)) {
301
+ open.push({
302
+ file: relPath,
303
+ reason:
304
+ 'no `ui:render --profile asset` naming this file ran after THIS file\'s last edit, so no ' +
305
+ 'manifest on ' +
306
+ 'disk can be attributed to it — a manifest written by any other route, and a render of ' +
307
+ 'some other file, both discharge nothing',
308
+ });
309
+ continue;
310
+ }
311
+ if (inputs.renderDirTampered) {
312
+ open.push({
313
+ file: relPath,
314
+ reason:
315
+ 'this turn wrote into the render directory by a route other than `ui:render`, so no manifest ' +
316
+ 'there is evidence of a render — re-run the render in a turn that does not touch it',
317
+ });
318
+ continue;
319
+ }
320
+ manifests ??= readAssetManifests(root);
321
+ const kind = dischargeFor(manifests, digest);
322
+ if (kind === null) {
323
+ open.push({
324
+ file: relPath,
325
+ reason:
326
+ 'no asset manifest matches this file\'s current digest — a render that is `verified`, or a ' +
327
+ '`renderer-absent` one whose static witness reports 0 errors on the same digest, discharges it',
328
+ });
329
+ continue;
330
+ }
331
+ discharged.push({ file: relPath, kind });
332
+ }
333
+ return { open, discharged };
334
+ }
335
+
336
+ /**
337
+ * Does one of the observed renders NAME this file?
338
+ *
339
+ * The render is a precondition for reading a manifest, never a discharge on
340
+ * its own — `isVerificationCommand` still does not match it, so the command's
341
+ * text cannot satisfy the obligation on the transcript path. Detector C reads
342
+ * `isVerificationAttempt` instead, which is a different question with a
343
+ * different right answer; both live in `_lib/verification_command.ts`, where
344
+ * the split is argued.
345
+ */
346
+ export function renderNames(commands: readonly string[], relPath: string): boolean {
347
+ const base = relPath.split('/').pop() ?? relPath;
348
+ return commands.some((c) => {
349
+ const slashed = c.split(path.sep).join('/');
350
+ // The path as written, or its basename — a caller may `cd` first, and a
351
+ // basename collision inside one turn is a narrower hole than the
352
+ // any-render-unlocks-everything it replaces.
353
+ //
354
+ // BOTH tests are anchored. Finding 3 of the fourth completion review:
355
+ // the path branch was a bare `includes`, so a render of
356
+ // `public/icon.svg` counted as naming `n.svg` and `on.svg` — any file
357
+ // whose path is a substring of another file's path was discharged by a
358
+ // render it had nothing to do with, which is the
359
+ // any-render-unlocks-everything hole this function replaced, reopened
360
+ // one character at a time. The boundary admits `/` before, so a path
361
+ // written `./public/icon.svg` still names `public/icon.svg`.
362
+ const bounded = (needle: string): boolean =>
363
+ new RegExp(`(^|[\\s/'"])${escapeRe(needle)}(\\s|$|['"])`).test(slashed);
364
+ return bounded(relPath) || bounded(base);
365
+ });
366
+ }
367
+
368
+ /**
369
+ * A render call standing alone — no second command chained to it and no
370
+ * redirect — so its text cannot also carry a write. A leading `cd <dir> &&`,
371
+ * piping its output to a read-only filter, and folding stderr into stdout are
372
+ * allowed.
373
+ */
374
+ export function isPureRender(command: string): boolean {
375
+ if (!isAssetRenderCommand(command)) return false;
376
+ const [head, ...pipes] = command.replace(/^\s*cd\s+[^;&|<>`$\n]+&&\s*/, '').replace(/\s\d?>&\d\b/g, ' ').replace(/\s2>\s*\/dev\/null\b/g, ' ').split('|');
377
+ if (/[;&<>`\n]|\$\(/.test(head ?? '')) return false;
378
+ return pipes.every((p) => /^\s*(tail|head|grep|jq|cat|less|wc)\b[^;&<>`|]*$/.test(p) && !/\$\(/.test(p));
379
+ }
380
+
381
+ /**
382
+ * Does a shell command (other than a pure render) write somewhere a render
383
+ * manifest could live? Read by shape: a write operator, together with the
384
+ * render directory, a `render/` path or a `manifest.json` — so `cd` into the
385
+ * state directory and a relative write is caught, and reading a manifest
386
+ * back is not.
387
+ */
388
+ export function writesRenderDir(command: string): boolean {
389
+ if (isPureRender(command)) return false;
390
+ const slashed = command.split(path.sep).join('/');
391
+ const names = /(^|[\s/'"])(render\/|manifest\.json\b)/.test(slashed) || slashed.includes('state/render');
392
+ // A LISTED interpreter in a command that names the directory counts as a
393
+ // write — inline flag, long option, `eval` or a program on stdin — because
394
+ // what it does with the path is not readable from the command line. A
395
+ // read-only script is caught too, on purpose: the cost is one re-render.
396
+ // An unlisted or indirected interpreter is not seen; see the header residual.
397
+ const writes = />(?!&)|\b(tee|sponge)\b|\b(cp|mv|ln|install|rsync|dd)\s|\bsed\s+-i|\bwriteFile|\b(python[\d.]*|perl|ruby|node|deno|bun|php|osascript)\b/.test(
398
+ slashed.replace(/\s\d?>&\d\b/g, ' ').replace(/\s2>\s*\/dev\/null\b/g, ' '),
399
+ );
400
+ return names && writes;
401
+ }
402
+
403
+ /** Escape a path component for use inside a RegExp. */
404
+ function escapeRe(s: string): string {
405
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
406
+ }
407
+
408
+
409
+
410
+ /**
411
+ * An `.svg` this turn edited that no render describes — step 2.1(b) of
412
+ * `road-to-svg-review-followups`.
413
+ *
414
+ * REPORTED UNDER `verification`, not under a new detector id, and that is a
415
+ * choice rather than a shortcut: this IS a verification finding — a file
416
+ * changed and nothing that can fail was run over it — and a seventh id would
417
+ * ripple through `DETECTOR_IDS`, the per-detector counters and the demotion
418
+ * contract for a distinction the operator never makes.
419
+ *
420
+ * IT RUNS EVEN WHEN `detectUnverifiedEdit` IS SATISFIED. That is the point:
421
+ * review claim C2 is about a turn that edits an `.svg` and then runs something
422
+ * — a test suite, a linter, a bare `ui:render` — which looks like verification
423
+ * and did not look at the graphic. An unrelated check discharges nothing here.
424
+ *
425
+ * The companion half is that `isVerificationCommand` learns NEITHER `ui:render`
426
+ * NOR `xmllint`. Teaching it either would discharge the obligation on the
427
+ * transcript path from the command text alone, which is the hole rather than
428
+ * the fix. `svg_obligation.ts` carries the two records that do discharge it.
429
+ */
430
+ export function openSvgObligation(
431
+ workspaceRoot: string,
432
+ toolCalls: readonly ToolCall[],
433
+ ): { detector: 'verification'; evidence: string; reason: string; mode: 'transcript' } | null {
434
+ // Precision (iii). The render has to come AFTER the edit it describes, on
435
+ // both evidence paths — `toolCalls` is assembled for both, so one rule
436
+ // covers them rather than two that can disagree.
437
+ //
438
+ // The window is per FILE, which finding 2 of the second review round is
439
+ // about: taking it from the turn's last `.svg` edit globally hid an
440
+ // earlier file's render behind a later file's edit, so the ordinary
441
+ // interleaved turn was refused although every file had been rendered after
442
+ // its own edit. The last edit of each path is the one that counts, because
443
+ // an earlier render describes bytes a later edit replaced.
444
+ const lastEditOf = new Map<string, number>();
445
+ for (let i = 0; i < toolCalls.length; i += 1) {
446
+ const c = toolCalls[i]!;
447
+ if (!EDIT_TOOLS.has(c.name) || c.path === undefined) continue;
448
+ lastEditOf.set(c.path, i);
449
+ }
450
+ if (lastEditOf.size === 0) return null;
451
+
452
+ const edits = [...lastEditOf].map(([p, at]) => {
453
+ const rendered: string[] = [];
454
+ for (let i = at + 1; i < toolCalls.length; i += 1) {
455
+ const c = toolCalls[i]!;
456
+ if (c.name === 'Bash' && c.command !== undefined && isPureRender(c.command)) {
457
+ rendered.push(c.command);
458
+ }
459
+ }
460
+ return { path: p, rendered };
461
+ });
462
+
463
+ const renderDir = RENDER_REL.split(path.sep).join('/');
464
+ const renderDirTampered = toolCalls.some((c) => {
465
+ if (EDIT_TOOLS.has(c.name) && c.path !== undefined) {
466
+ return rel(workspaceRoot, c.path).startsWith(`${renderDir}/`);
467
+ }
468
+ return c.name === 'Bash' && c.command !== undefined && writesRenderDir(c.command);
469
+ });
470
+
471
+ let reading: SvgObligationReading;
472
+ try {
473
+ reading = readSvgObligations(workspaceRoot, { edits, renderDirTampered });
474
+ } catch {
475
+ // A gate that crashed on its own instrument is a new failure mode on a
476
+ // path meant to be inert. An unreadable render directory is no finding.
477
+ return null;
478
+ }
479
+ const first = reading.open[0];
480
+ if (first === undefined) return null;
481
+
482
+ const more = reading.open.length > 1 ? ` (and ${String(reading.open.length - 1)} more)` : '';
483
+ return {
484
+ // Reported under `verification` rather than a seventh detector id: it
485
+ // IS a verification finding — a file changed and nothing that can fail
486
+ // ran over it — and a new id would ripple through DETECTOR_IDS, the
487
+ // per-detector counters and the demotion contract for a distinction the
488
+ // operator never makes.
489
+ detector: 'verification',
490
+ mode: 'transcript',
491
+ evidence: first.file,
492
+ reason:
493
+ `this turn edited an .svg and no render describes it${more} — ${first.reason}. ` +
494
+ 'A bare `ui:render --profile asset` that rendered nothing, and a test or lint run over other ' +
495
+ 'files, both discharge nothing: the gate reads the render, never the call.',
496
+ };
497
+ }
@@ -0,0 +1,133 @@
1
+ /**
2
+ * The conditional chunk — step 0.1 of `road-to-svg-rules-in-the-dispatch-path`.
3
+ *
4
+ * WHY A CHUNK AND NOT AN IMPORT. `src/scripts/_lib/svg_rules.ts` costs 30,924
5
+ * bytes when it is statically imported into `dist/hooks/dispatch.js`, the one
6
+ * bundle every hook event loads on every dispatch. An AI council of two
7
+ * providers refused a ceiling raise for it 2/2 on 2026-10-11 and both seats
8
+ * asked for this to be tried first: emit the rule set beside the bundle and
9
+ * load it only when the written path ends in `.svg`.
10
+ *
11
+ * WHY `require` AND NOT `await import`. `ConcernMain` is
12
+ * `(argv?) => number | undefined | void` — synchronous. A concern that returned
13
+ * a Promise would have its exit code read as an object, so the chunk has to be
14
+ * loadable without an `await`. It is therefore emitted as CJS and pulled with
15
+ * `createRequire`, which is synchronous. This is a constraint of the dispatch
16
+ * contract, not a style choice; making it `async` means making every concern
17
+ * async, which is a different change than this one.
18
+ *
19
+ * WHY THE SPECIFIER IS COMPUTED AT RUNTIME. A literal `import()` or `require()`
20
+ * argument is analyzable, and esbuild would inline the module — which is
21
+ * exactly the 30,924 bytes this avoids. Both branches build their specifier
22
+ * from `import.meta.url`, so neither is a static edge in the bundle's graph.
23
+ *
24
+ * THE TWO BRANCHES.
25
+ *
26
+ * bundled — `import.meta.url` is `dist/hooks/dispatch.js` (esbuild keeps
27
+ * `import.meta.url` in ESM output and the banner resolves the
28
+ * real path through a symlink), so the chunk is its sibling
29
+ * `dist/hooks/svg_rules.chunk.cjs`.
30
+ * unbundled — running from source under `tsx`, where `require` of a `.ts`
31
+ * file resolves through tsx's CJS hook. Measured working
32
+ * 2026-10-11; there is no chunk on this path and none is built.
33
+ *
34
+ * FAILURE IS NULL, NEVER A THROW. A missing chunk in a consumer install, a
35
+ * chunk packed to another path, or a module that throws on load all return
36
+ * `null` and the caller reports the rules as unavailable. The dispatch bundle
37
+ * handles every hook event in one process: a throw that escaped here would
38
+ * break events that never touched an `.svg`, which is the containment
39
+ * `design_pass_svg.test.ts` pins.
40
+ */
41
+ import { createRequire } from 'node:module';
42
+ import * as path from 'node:path';
43
+ import { fileURLToPath } from 'node:url';
44
+
45
+ import type { Finding as SvgFinding, ScanOptions } from '../_lib/svg_rules.js';
46
+ import { verifyBundle } from './bundle_integrity.js';
47
+
48
+ /** The signature `scanSvg` exports. Type-only, so no bytes reach the bundle. */
49
+ export type SvgScan = (text: string, file: string, opts?: ScanOptions) => SvgFinding[];
50
+
51
+ /** The emitted sibling's name. `build:hook-chunks` writes exactly this. */
52
+ export const CHUNK_BASENAME = 'svg_rules.chunk.cjs';
53
+
54
+ declare const __AGENT_CONFIG_BUNDLE__: boolean | undefined;
55
+
56
+ /** True when this code is running from `dist/hooks/dispatch.js`. */
57
+ export function isBundled(): boolean {
58
+ return typeof __AGENT_CONFIG_BUNDLE__ !== 'undefined' && __AGENT_CONFIG_BUNDLE__;
59
+ }
60
+
61
+ /**
62
+ * Where to load the rules from, given this module's own URL.
63
+ *
64
+ * Exported so a test can pin both branches without a bundle: the path algebra
65
+ * is the half that breaks silently in a consumer install, and a probe that can
66
+ * only run against a built bundle would not be run.
67
+ */
68
+ export function rulesSpecifier(selfUrl: string, bundled: boolean): string {
69
+ const selfPath = fileURLToPath(selfUrl);
70
+ const dir = path.dirname(selfPath);
71
+ if (bundled) return path.join(dir, CHUNK_BASENAME);
72
+ // From source: `.../src/scripts/hooks/` → `.../src/scripts/_lib/`. The
73
+ // extension follows this file's own, so a compiled-to-JS tree resolves too.
74
+ const ext = selfPath.endsWith('.ts') ? '.ts' : '.js';
75
+ return path.join(dir, '..', '_lib', `svg_rules${ext}`);
76
+ }
77
+
78
+ const cache = new Map<string, SvgScan | null>();
79
+
80
+ /**
81
+ * The rule set, or `null` when it could not be loaded.
82
+ *
83
+ * Cached including the failure: a consumer whose install is missing the chunk
84
+ * would otherwise pay a failed module resolution on every `.svg` write.
85
+ *
86
+ * Keyed BY `selfUrl`. Finding 13 of the third completion review: a single
87
+ * slot meant the first call's verdict answered every later call whatever url
88
+ * it passed, so the parameter was accepted and ignored — the shape this
89
+ * change's own review found three times under other names. It is one caller
90
+ * and one url on the hook path, so nothing observable changed; a cache whose
91
+ * key is not its input is wrong regardless of who currently calls it, and
92
+ * that is cheaper to fix than to remember.
93
+ */
94
+ export function loadSvgScan(selfUrl: string = import.meta.url): SvgScan | null {
95
+ const hit = cache.get(selfUrl);
96
+ if (hit !== undefined || cache.has(selfUrl)) return hit ?? null;
97
+ const scan = loadSvgScanUncached(selfUrl);
98
+ cache.set(selfUrl, scan);
99
+ return scan;
100
+ }
101
+
102
+ /**
103
+ * The uncached load. Separate so a test can exercise a failure and a success.
104
+ *
105
+ * `bundled` is an explicit override rather than always `isBundled()`: under a
106
+ * test runner the define is absent, so the bundled branch — the one that
107
+ * breaks silently in a consumer install — would otherwise be unreachable from
108
+ * any test that does not first build a bundle, and a probe that expensive does
109
+ * not get run. The hook path never passes it.
110
+ */
111
+ export function loadSvgScanUncached(
112
+ selfUrl: string = import.meta.url,
113
+ bundled: boolean = isBundled(),
114
+ ): SvgScan | null {
115
+ try {
116
+ const specifier = rulesSpecifier(selfUrl, bundled);
117
+ // The chunk runs inside the dispatch process, so it gets the bundle's
118
+ // own integrity check: a mismatch with its sidecar is not executed.
119
+ // No sidecar is `unverifiable` and allowed, as for `dispatch.js`.
120
+ if (bundled && verifyBundle(specifier).state === 'mismatch') return null;
121
+ const req = createRequire(selfUrl);
122
+ const mod = req(specifier) as Record<string, unknown>;
123
+ const scan = mod['scanSvg'];
124
+ return typeof scan === 'function' ? (scan as SvgScan) : null;
125
+ } catch {
126
+ return null;
127
+ }
128
+ }
129
+
130
+ /** Test seam: forget every cached verdict. Never called by the hook path. */
131
+ export function _resetSvgScanCache(): void {
132
+ cache.clear();
133
+ }