@event4u/agent-config 14.23.0 → 16.0.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 (541) 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 +144 -152
  5. package/README.md +1 -1
  6. package/dist/agent-src/commands/agent-handoff.md +8 -7
  7. package/dist/agent-src/commands/agents/init.md +1 -1
  8. package/dist/agent-src/commands/agents/user/accept.md +4 -4
  9. package/dist/agent-src/commands/agents/user/delete.md +2 -2
  10. package/dist/agent-src/commands/agents/user/init.md +3 -3
  11. package/dist/agent-src/commands/agents/user/review.md +3 -3
  12. package/dist/agent-src/commands/agents/user/show.md +3 -3
  13. package/dist/agent-src/commands/agents/user/update.md +2 -2
  14. package/dist/agent-src/commands/agents/user.md +6 -6
  15. package/dist/agent-src/commands/analytics/prune.md +1 -1
  16. package/dist/agent-src/commands/analytics/show.md +2 -2
  17. package/dist/agent-src/commands/analyze/decision.md +2 -2
  18. package/dist/agent-src/commands/analyze/inbox.md +5 -5
  19. package/dist/agent-src/commands/analyze/incident.md +3 -3
  20. package/dist/agent-src/commands/analyze/near-miss.md +3 -3
  21. package/dist/agent-src/commands/analyze/postmortem.md +4 -4
  22. package/dist/agent-src/commands/analyze/premortem.md +2 -2
  23. package/dist/agent-src/commands/analyze.md +2 -2
  24. package/dist/agent-src/commands/bug/fix.md +1 -1
  25. package/dist/agent-src/commands/bug/investigate.md +2 -2
  26. package/dist/agent-src/commands/cost/profile.md +3 -3
  27. package/dist/agent-src/commands/design.md +1 -1
  28. package/dist/agent-src/commands/feature/explore.md +1 -1
  29. package/dist/agent-src/commands/feature/plan.md +2 -2
  30. package/dist/agent-src/commands/feature/roadmap.md +2 -2
  31. package/dist/agent-src/commands/ghostwriter/fetch.md +4 -4
  32. package/dist/agent-src/commands/ghostwriter/list.md +1 -1
  33. package/dist/agent-src/commands/ghostwriter/show.md +1 -1
  34. package/dist/agent-src/commands/ghostwriter/write.md +9 -9
  35. package/dist/agent-src/commands/humanize.md +6 -6
  36. package/dist/agent-src/commands/jira-ticket.md +1 -1
  37. package/dist/agent-src/commands/judge/solo.md +1 -1
  38. package/dist/agent-src/commands/judge.md +1 -1
  39. package/dist/agent-src/commands/knowledge/cross-repo.md +1 -1
  40. package/dist/agent-src/commands/knowledge/forget.md +1 -1
  41. package/dist/agent-src/commands/knowledge/ingest.md +2 -2
  42. package/dist/agent-src/commands/knowledge/list.md +1 -1
  43. package/dist/agent-src/commands/memory/add.md +3 -3
  44. package/dist/agent-src/commands/memory/load.md +4 -4
  45. package/dist/agent-src/commands/memory/mine-session.md +1 -1
  46. package/dist/agent-src/commands/memory/promote.md +4 -4
  47. package/dist/agent-src/commands/memory/propose.md +2 -2
  48. package/dist/agent-src/commands/mode.md +5 -5
  49. package/dist/agent-src/commands/post-as/ghostwriter.md +3 -3
  50. package/dist/agent-src/commands/post-as/me.md +7 -7
  51. package/dist/agent-src/commands/pr/create.md +1 -1
  52. package/dist/agent-src/commands/pr/merge.md +1 -1
  53. package/dist/agent-src/commands/profile/activate.md +1 -1
  54. package/dist/agent-src/commands/profile/show.md +1 -1
  55. package/dist/agent-src/commands/research/deep.md +2 -2
  56. package/dist/agent-src/commands/research/report.md +2 -2
  57. package/dist/agent-src/commands/review/changes.md +1 -1
  58. package/dist/agent-src/commands/review/routing.md +1 -1
  59. package/dist/agent-src/commands/roadmap/create.md +4 -3
  60. package/dist/agent-src/commands/roadmap/materialize.md +2 -2
  61. package/dist/agent-src/commands/roadmap/next.md +1 -1
  62. package/dist/agent-src/commands/roadmap/process-full.md +2 -2
  63. package/dist/agent-src/commands/security-audit-config.md +3 -3
  64. package/dist/agent-src/commands/skill/preview.md +1 -1
  65. package/dist/agent-src/commands/skills/discover.md +1 -1
  66. package/dist/agent-src/commands/sync/agent-settings.md +2 -2
  67. package/dist/agent-src/commands/sync/gitignore/fix.md +1 -1
  68. package/dist/agent-src/commands/tests/create.md +1 -1
  69. package/dist/agent-src/commands/tests/e2e-heal.md +1 -1
  70. package/dist/agent-src/commands/tests/e2e-plan.md +1 -1
  71. package/dist/agent-src/contexts/authority/kernel-rule-edits.md +6 -6
  72. package/dist/agent-src/contexts/communication/rules-auto/slash-command-routing-policy-mechanics.md +1 -2
  73. package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +2 -2
  74. package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +88 -1
  75. package/dist/agent-src/contexts/communication/rules-auto/user-interaction-mechanics.md +51 -1
  76. package/dist/agent-src/contexts/contracts/frugality-charter.md +1 -1
  77. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +1 -1
  78. package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +1 -1
  79. package/dist/agent-src/contexts/execution/autonomy-mechanics.md +1 -1
  80. package/dist/agent-src/contexts/execution/cheap-question-mechanics.md +1 -1
  81. package/dist/agent-src/contexts/execution/contract-decision-sheet.md +3 -3
  82. package/dist/agent-src/contexts/execution/mandated-lines.md +1 -1
  83. package/dist/agent-src/contexts/execution/non-interactive-contract.md +1 -1
  84. package/dist/agent-src/contexts/execution/orchestration-telemetry.md +1 -1
  85. package/dist/agent-src/contexts/execution/plan-confidence-gate.md +5 -5
  86. package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +1 -1
  87. package/dist/agent-src/contexts/execution/subagent-modes-detail.md +1 -1
  88. package/dist/agent-src/contexts/execution/subagent-routing.md +2 -2
  89. package/dist/agent-src/contexts/execution/subagent-spawn-contract.md +1 -1
  90. package/dist/agent-src/contexts/execution/user-memory-channels.md +3 -3
  91. package/dist/agent-src/contexts/execution/verification-mechanics.md +1 -1
  92. package/dist/agent-src/contexts/judges/persona-voice-rubric.md +2 -2
  93. package/dist/agent-src/guidelines/abstraction-thresholds.md +88 -0
  94. package/dist/agent-src/guidelines/agent-infra/5w2h-analysis.md +260 -0
  95. package/dist/agent-src/guidelines/agent-infra/active-remediation-mechanics.md +99 -0
  96. package/dist/agent-src/guidelines/agent-infra/agent-interaction-and-decision-quality.md +325 -0
  97. package/dist/agent-src/guidelines/agent-infra/api-cost-levers.md +177 -0
  98. package/dist/agent-src/guidelines/agent-infra/artifact-drafting-protocol-mechanics.md +222 -0
  99. package/dist/agent-src/guidelines/agent-infra/ask-when-uncertain-demos.md +134 -0
  100. package/dist/agent-src/guidelines/agent-infra/asking-and-brevity-examples.md +198 -0
  101. package/dist/agent-src/guidelines/agent-infra/break-glass-usage.md +113 -0
  102. package/dist/agent-src/guidelines/agent-infra/carve-out-predicates.md +17 -0
  103. package/dist/agent-src/guidelines/agent-infra/comparison-matrix.md +179 -0
  104. package/dist/agent-src/guidelines/agent-infra/context-hygiene-mechanics.md +165 -0
  105. package/dist/agent-src/guidelines/agent-infra/corpus-grounding-authoring.md +91 -0
  106. package/dist/agent-src/guidelines/agent-infra/critical-thinking.md +156 -0
  107. package/dist/agent-src/guidelines/agent-infra/cross-source-consistency-mechanics.md +109 -0
  108. package/dist/agent-src/guidelines/agent-infra/developer-judgment.md +82 -0
  109. package/dist/agent-src/guidelines/agent-infra/direct-answers-demos.md +142 -0
  110. package/dist/agent-src/guidelines/agent-infra/domain-adoption-gates.md +112 -0
  111. package/dist/agent-src/guidelines/agent-infra/domain-eval-anti-pattern.md +53 -0
  112. package/dist/agent-src/guidelines/agent-infra/domain-pack-architecture.md +56 -0
  113. package/dist/agent-src/guidelines/agent-infra/downstream-changes-mechanics.md +91 -0
  114. package/dist/agent-src/guidelines/agent-infra/emphasis-budget.md +45 -0
  115. package/dist/agent-src/guidelines/agent-infra/engineering-memory-data-format.md +210 -0
  116. package/dist/agent-src/guidelines/agent-infra/evaluator-independence-mechanics.md +92 -0
  117. package/dist/agent-src/guidelines/agent-infra/existence-question-verdicts.md +80 -0
  118. package/dist/agent-src/guidelines/agent-infra/failure-signatures.md +70 -0
  119. package/dist/agent-src/guidelines/agent-infra/false-green.md +233 -0
  120. package/dist/agent-src/guidelines/agent-infra/first-principles.md +192 -0
  121. package/dist/agent-src/guidelines/agent-infra/framework-neutrality-patterns.md +66 -0
  122. package/dist/agent-src/guidelines/agent-infra/frontier-reasoning-operating-profile.md +169 -0
  123. package/dist/agent-src/guidelines/agent-infra/gate-authoring.md +177 -0
  124. package/dist/agent-src/guidelines/agent-infra/guarded-baseline.md +39 -0
  125. package/dist/agent-src/guidelines/agent-infra/installed-tools-manifest.md +142 -0
  126. package/dist/agent-src/guidelines/agent-infra/inversion-thinking.md +388 -0
  127. package/dist/agent-src/guidelines/agent-infra/ios-simulator-guide.md +378 -0
  128. package/dist/agent-src/guidelines/agent-infra/language-and-tone-examples.md +141 -0
  129. package/dist/agent-src/guidelines/agent-infra/layered-settings.md +317 -0
  130. package/dist/agent-src/guidelines/agent-infra/linked-projects-onboarding-gate.md +80 -0
  131. package/dist/agent-src/guidelines/agent-infra/mcp-request-signing.md +197 -0
  132. package/dist/agent-src/guidelines/agent-infra/memory-access.md +149 -0
  133. package/dist/agent-src/guidelines/agent-infra/mental-models.md +314 -0
  134. package/dist/agent-src/guidelines/agent-infra/minimal-safe-diff-mechanics.md +241 -0
  135. package/dist/agent-src/guidelines/agent-infra/missing-tool-handling.md +66 -0
  136. package/dist/agent-src/guidelines/agent-infra/model-recommendation.md +101 -0
  137. package/dist/agent-src/guidelines/agent-infra/naming.md +69 -0
  138. package/dist/agent-src/guidelines/agent-infra/notes-horizon-mechanics.md +90 -0
  139. package/dist/agent-src/guidelines/agent-infra/output-patterns.md +117 -0
  140. package/dist/agent-src/guidelines/agent-infra/recurring-criticism-mechanics.md +96 -0
  141. package/dist/agent-src/guidelines/agent-infra/reuse-verdict-mechanics.md +71 -0
  142. package/dist/agent-src/guidelines/agent-infra/review-routing-data-format.md +143 -0
  143. package/dist/agent-src/guidelines/agent-infra/roadmap-deferred-resolution-provenance.md +54 -0
  144. package/dist/agent-src/guidelines/agent-infra/roadmap-progress-mechanics.md +274 -0
  145. package/dist/agent-src/guidelines/agent-infra/role-contracts.md +209 -0
  146. package/dist/agent-src/guidelines/agent-infra/role-mode-router.md +89 -0
  147. package/dist/agent-src/guidelines/agent-infra/rule-body-migration-inventory.md +241 -0
  148. package/dist/agent-src/guidelines/agent-infra/rule-type-governance.md +73 -0
  149. package/dist/agent-src/guidelines/agent-infra/runtime-layer.md +89 -0
  150. package/dist/agent-src/guidelines/agent-infra/scqa-framework.md +526 -0
  151. package/dist/agent-src/guidelines/agent-infra/security-lint-containment.md +121 -0
  152. package/dist/agent-src/guidelines/agent-infra/self-improvement-pipeline.md +134 -0
  153. package/dist/agent-src/guidelines/agent-infra/simplicity-and-goal-demos.md +211 -0
  154. package/dist/agent-src/guidelines/agent-infra/six-hats.md +353 -0
  155. package/dist/agent-src/guidelines/agent-infra/size-and-scope.md +229 -0
  156. package/dist/agent-src/guidelines/agent-infra/skill-quality-checklist.md +157 -0
  157. package/dist/agent-src/guidelines/agent-infra/source-confidentiality-mechanics.md +109 -0
  158. package/dist/agent-src/guidelines/agent-infra/symptom-driven-harvest-loop.md +104 -0
  159. package/dist/agent-src/guidelines/agent-infra/systems-thinking.md +220 -0
  160. package/dist/agent-src/guidelines/agent-infra/tool-description-as-policy.md +35 -0
  161. package/dist/agent-src/guidelines/agent-infra/tool-integration.md +73 -0
  162. package/dist/agent-src/guidelines/agent-infra/traceability-field-mechanics.md +50 -0
  163. package/dist/agent-src/guidelines/agent-infra/untrusted-input-spotlighting.md +166 -0
  164. package/dist/agent-src/guidelines/agent-infra/verify-before-complete-demos.md +128 -0
  165. package/dist/agent-src/guidelines/augment-portability-patterns.md +70 -0
  166. package/dist/agent-src/guidelines/code-clarity.md +350 -0
  167. package/dist/agent-src/guidelines/component-oriented-and-oop-development.md +189 -0
  168. package/dist/agent-src/guidelines/cross-role-handoff.md +127 -0
  169. package/dist/agent-src/guidelines/design-antipatterns-triggers.json +18 -0
  170. package/dist/agent-src/guidelines/design-antipatterns.md +327 -0
  171. package/dist/agent-src/guidelines/design-asset-discipline.md +38 -0
  172. package/dist/agent-src/guidelines/design-canon.md +63 -0
  173. package/dist/agent-src/guidelines/design-fidelity-mechanics.md +293 -0
  174. package/dist/agent-src/guidelines/design-fidelity-routing.md +78 -0
  175. package/dist/agent-src/guidelines/design-handover-extraction.md +117 -0
  176. package/dist/agent-src/guidelines/design-modes.md +143 -0
  177. package/dist/agent-src/guidelines/design-reconciliation.md +172 -0
  178. package/dist/agent-src/guidelines/docs/readme-size-and-splitting.md +209 -0
  179. package/dist/agent-src/guidelines/e2e/playwright.md +363 -0
  180. package/dist/agent-src/guidelines/gtm-handoff.md +114 -0
  181. package/dist/agent-src/guidelines/monorepo-antipatterns.md +141 -0
  182. package/dist/agent-src/guidelines/php/api-design.md +115 -0
  183. package/dist/agent-src/guidelines/php/artisan-commands.md +81 -0
  184. package/dist/agent-src/guidelines/php/blade-ui.md +78 -0
  185. package/dist/agent-src/guidelines/php/controllers.md +90 -0
  186. package/dist/agent-src/guidelines/php/database.md +194 -0
  187. package/dist/agent-src/guidelines/php/eloquent.md +208 -0
  188. package/dist/agent-src/guidelines/php/flux.md +80 -0
  189. package/dist/agent-src/guidelines/php/general.md +207 -0
  190. package/dist/agent-src/guidelines/php/git.md +164 -0
  191. package/dist/agent-src/guidelines/php/jobs.md +111 -0
  192. package/dist/agent-src/guidelines/php/livewire.md +71 -0
  193. package/dist/agent-src/guidelines/php/logging.md +79 -0
  194. package/dist/agent-src/guidelines/php/naming.md +89 -0
  195. package/dist/agent-src/guidelines/php/patterns/dependency-injection.md +57 -0
  196. package/dist/agent-src/guidelines/php/patterns/dtos.md +199 -0
  197. package/dist/agent-src/guidelines/php/patterns/events.md +67 -0
  198. package/dist/agent-src/guidelines/php/patterns/factory.md +53 -0
  199. package/dist/agent-src/guidelines/php/patterns/pipelines.md +66 -0
  200. package/dist/agent-src/guidelines/php/patterns/policies.md +66 -0
  201. package/dist/agent-src/guidelines/php/patterns/repositories.md +122 -0
  202. package/dist/agent-src/guidelines/php/patterns/service-layer.md +64 -0
  203. package/dist/agent-src/guidelines/php/patterns/strategy.md +247 -0
  204. package/dist/agent-src/guidelines/php/patterns.md +28 -0
  205. package/dist/agent-src/guidelines/php/performance.md +92 -0
  206. package/dist/agent-src/guidelines/php/php-coding-patterns.md +80 -0
  207. package/dist/agent-src/guidelines/php/resources.md +100 -0
  208. package/dist/agent-src/guidelines/php/security.md +110 -0
  209. package/dist/agent-src/guidelines/php/sql.md +97 -0
  210. package/dist/agent-src/guidelines/php/validations.md +119 -0
  211. package/dist/agent-src/guidelines/php/websocket.md +100 -0
  212. package/dist/agent-src/guidelines/prompt-templates.md +189 -0
  213. package/dist/agent-src/guidelines/redundancy-taxonomy.md +208 -0
  214. package/dist/agent-src/guidelines/wing4-handoff.md +127 -0
  215. package/dist/agent-src/personas/README.md +1 -1
  216. package/dist/agent-src/personas/_template-specialist/persona.md +1 -1
  217. package/dist/agent-src/personas/product-owner.md +1 -1
  218. package/dist/agent-src/rules/active-remediation.md +1 -1
  219. package/dist/agent-src/rules/architecture.md +2 -2
  220. package/dist/agent-src/rules/artifact-drafting-protocol.md +1 -1
  221. package/dist/agent-src/rules/ask-when-uncertain.md +2 -2
  222. package/dist/agent-src/rules/brand-source-of-truth.md +9 -7
  223. package/dist/agent-src/rules/code-comment-discipline.md +2 -2
  224. package/dist/agent-src/rules/code-provenance.md +1 -1
  225. package/dist/agent-src/rules/content-quoting-floor.md +1 -1
  226. package/dist/agent-src/rules/context-hygiene.md +5 -5
  227. package/dist/agent-src/rules/cross-source-consistency.md +1 -1
  228. package/dist/agent-src/rules/design-fidelity.md +36 -46
  229. package/dist/agent-src/rules/direct-answers.md +2 -2
  230. package/dist/agent-src/rules/domain-adoption-policy.md +1 -1
  231. package/dist/agent-src/rules/evaluator-independence.md +1 -1
  232. package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +1 -1
  233. package/dist/agent-src/rules/icon-consistency.md +5 -1
  234. package/dist/agent-src/rules/improve-before-implement.md +1 -1
  235. package/dist/agent-src/rules/language-and-tone.md +3 -3
  236. package/dist/agent-src/rules/minimal-safe-diff.md +1 -1
  237. package/dist/agent-src/rules/notes-first-reasoning.md +2 -2
  238. package/dist/agent-src/rules/recurring-criticism.md +1 -1
  239. package/dist/agent-src/rules/roadmap-progress-sync.md +1 -1
  240. package/dist/agent-src/rules/role-mode-adherence.md +2 -2
  241. package/dist/agent-src/rules/security-sensitive-stop.md +1 -1
  242. package/dist/agent-src/rules/size-enforcement.md +1 -1
  243. package/dist/agent-src/rules/source-confidentiality.md +2 -2
  244. package/dist/agent-src/rules/think-before-action.md +1 -1
  245. package/dist/agent-src/rules/token-efficiency.md +7 -5
  246. package/dist/agent-src/rules/ui-audit-gate.md +3 -2
  247. package/dist/agent-src/rules/untrusted-input-defense.md +3 -3
  248. package/dist/agent-src/rules/user-interaction.md +31 -30
  249. package/dist/agent-src/skills/activation-design/SKILL.md +2 -2
  250. package/dist/agent-src/skills/adr-create/SKILL.md +5 -5
  251. package/dist/agent-src/skills/ai-council/SKILL.md +1 -1
  252. package/dist/agent-src/skills/ai-council/references/advanced-modes.md +1 -1
  253. package/dist/agent-src/skills/blade-ui/SKILL.md +1 -1
  254. package/dist/agent-src/skills/blast-radius-analyzer/SKILL.md +1 -1
  255. package/dist/agent-src/skills/brand-to-tokens/SKILL.md +24 -3
  256. package/dist/agent-src/skills/bug-analyzer/SKILL.md +1 -1
  257. package/dist/agent-src/skills/build-buy-partner/SKILL.md +1 -1
  258. package/dist/agent-src/skills/churn-prevention/SKILL.md +2 -2
  259. package/dist/agent-src/skills/code-refactoring/SKILL.md +3 -3
  260. package/dist/agent-src/skills/code-review/SKILL.md +3 -3
  261. package/dist/agent-src/skills/command-writing/SKILL.md +3 -3
  262. package/dist/agent-src/skills/comp-banding/SKILL.md +1 -1
  263. package/dist/agent-src/skills/competitive-moat-analysis/SKILL.md +1 -1
  264. package/dist/agent-src/skills/competitive-positioning/SKILL.md +2 -2
  265. package/dist/agent-src/skills/complexity-first-planning/SKILL.md +1 -1
  266. package/dist/agent-src/skills/condense-memory/SKILL.md +1 -1
  267. package/dist/agent-src/skills/content-funnel-design/SKILL.md +2 -2
  268. package/dist/agent-src/skills/contracts-cognition/SKILL.md +1 -1
  269. package/dist/agent-src/skills/copilot-agents-optimization/SKILL.md +2 -2
  270. package/dist/agent-src/skills/corpus-grounding/SKILL.md +2 -2
  271. package/dist/agent-src/skills/customer-research/SKILL.md +2 -2
  272. package/dist/agent-src/skills/dashboard-design/SKILL.md +1 -1
  273. package/dist/agent-src/skills/data-handling-judgment/SKILL.md +1 -1
  274. package/dist/agent-src/skills/deal-qualification-meddic/SKILL.md +2 -2
  275. package/dist/agent-src/skills/decision-record/SKILL.md +3 -3
  276. package/dist/agent-src/skills/decision-review/SKILL.md +8 -8
  277. package/dist/agent-src/skills/deep-reading-analyst/SKILL.md +22 -22
  278. package/dist/agent-src/skills/design-intelligence/SKILL.md +4 -4
  279. package/dist/agent-src/skills/design-intelligence/references/context-and-registers.md +2 -2
  280. package/dist/agent-src/skills/design-review/SKILL.md +4 -4
  281. package/dist/agent-src/skills/design-system-capture/references/design-system-json.md +20 -1
  282. package/dist/agent-src/skills/design-tokens/SKILL.md +17 -2
  283. package/dist/agent-src/skills/design-variations/SKILL.md +2 -2
  284. package/dist/agent-src/skills/developer-like-execution/SKILL.md +2 -2
  285. package/dist/agent-src/skills/discovery-interview/SKILL.md +2 -2
  286. package/dist/agent-src/skills/doc-coauthoring/SKILL.md +3 -3
  287. package/dist/agent-src/skills/editorial-calendar/SKILL.md +2 -2
  288. package/dist/agent-src/skills/error-handling-patterns/SKILL.md +9 -0
  289. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +44 -1
  290. package/dist/agent-src/skills/existing-ui-audit/references/anti-slop-cross-reference.md +2 -2
  291. package/dist/agent-src/skills/expansion-playbook/SKILL.md +2 -2
  292. package/dist/agent-src/skills/experiment-loop/SKILL.md +1 -1
  293. package/dist/agent-src/skills/experiment-loop/references/protocol.md +1 -1
  294. package/dist/agent-src/skills/fe-design/SKILL.md +3 -3
  295. package/dist/agent-src/skills/fe-design/references/design-patterns.md +1 -1
  296. package/dist/agent-src/skills/fe-design/references/design-read-and-memory.md +3 -3
  297. package/dist/agent-src/skills/fe-design/references/source-led-port.md +1 -1
  298. package/dist/agent-src/skills/feature-planning/SKILL.md +1 -1
  299. package/dist/agent-src/skills/flux/SKILL.md +1 -1
  300. package/dist/agent-src/skills/forecast-accuracy/SKILL.md +2 -2
  301. package/dist/agent-src/skills/forecasting/SKILL.md +2 -2
  302. package/dist/agent-src/skills/fundraising-narrative/SKILL.md +2 -2
  303. package/dist/agent-src/skills/funnel-analysis/SKILL.md +2 -2
  304. package/dist/agent-src/skills/gtm-launch/SKILL.md +2 -2
  305. package/dist/agent-src/skills/hiring-loop-design/SKILL.md +1 -1
  306. package/dist/agent-src/skills/html-deck/SKILL.md +5 -5
  307. package/dist/agent-src/skills/humanizer/SKILL.md +1 -1
  308. package/dist/agent-src/skills/humanizer/data/patterns.md +1 -1
  309. package/dist/agent-src/skills/iconography/SKILL.md +3 -3
  310. package/dist/agent-src/skills/judge-synthesis/SKILL.md +1 -1
  311. package/dist/agent-src/skills/laravel-api-endpoint/SKILL.md +2 -2
  312. package/dist/agent-src/skills/launch-readiness/SKILL.md +3 -3
  313. package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +6 -6
  314. package/dist/agent-src/skills/livewire/SKILL.md +1 -1
  315. package/dist/agent-src/skills/market-entry-analysis/SKILL.md +1 -1
  316. package/dist/agent-src/skills/mcp-builder/SKILL.md +1 -1
  317. package/dist/agent-src/skills/memory-consolidation/SKILL.md +3 -3
  318. package/dist/agent-src/skills/messaging-architecture/SKILL.md +2 -2
  319. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +1 -1
  320. package/dist/agent-src/skills/onboarding-design/SKILL.md +2 -2
  321. package/dist/agent-src/skills/onboarding-program/SKILL.md +1 -1
  322. package/dist/agent-src/skills/one-on-one-cadence/SKILL.md +1 -1
  323. package/dist/agent-src/skills/org-design/SKILL.md +1 -1
  324. package/dist/agent-src/skills/overbuild-review-lens/SKILL.md +3 -3
  325. package/dist/agent-src/skills/override-management/SKILL.md +1 -1
  326. package/dist/agent-src/skills/perf-feedback-craft/SKILL.md +1 -1
  327. package/dist/agent-src/skills/persona-writing/SKILL.md +1 -1
  328. package/dist/agent-src/skills/php-coder/SKILL.md +1 -1
  329. package/dist/agent-src/skills/pipeline-strategy/SKILL.md +2 -2
  330. package/dist/agent-src/skills/playwright-testing/SKILL.md +3 -3
  331. package/dist/agent-src/skills/po-discovery/SKILL.md +1 -1
  332. package/dist/agent-src/skills/positioning-strategy/SKILL.md +2 -2
  333. package/dist/agent-src/skills/privacy-review/SKILL.md +1 -1
  334. package/dist/agent-src/skills/prompt-optimizer/SKILL.md +3 -3
  335. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +1 -1
  336. package/dist/agent-src/skills/reasoning-orchestrator/SKILL.md +2 -2
  337. package/dist/agent-src/skills/receiving-code-review/SKILL.md +1 -1
  338. package/dist/agent-src/skills/refine-ticket/SKILL.md +2 -2
  339. package/dist/agent-src/skills/release-comms/SKILL.md +2 -2
  340. package/dist/agent-src/skills/retention-loops/SKILL.md +2 -2
  341. package/dist/agent-src/skills/review-routing/SKILL.md +2 -2
  342. package/dist/agent-src/skills/roadmap-management/SKILL.md +1 -1
  343. package/dist/agent-src/skills/roadmap-management/references/archival.md +1 -1
  344. package/dist/agent-src/skills/roadmap-writing/SKILL.md +5 -5
  345. package/dist/agent-src/skills/rule-writing/SKILL.md +6 -6
  346. package/dist/agent-src/skills/runway-cognition/SKILL.md +2 -2
  347. package/dist/agent-src/skills/scenario-modeling/SKILL.md +2 -2
  348. package/dist/agent-src/skills/skill-writing/SKILL.md +2 -2
  349. package/dist/agent-src/skills/skill-writing/references/procedure.md +1 -1
  350. package/dist/agent-src/skills/skill-writing/references/section-patterns.md +3 -3
  351. package/dist/agent-src/skills/spreadsheet-authoring/SKILL.md +1 -1
  352. package/dist/agent-src/skills/stakeholder-tradeoff/SKILL.md +3 -3
  353. package/dist/agent-src/skills/subagent-orchestration/SKILL.md +1 -1
  354. package/dist/agent-src/skills/supply-chain-intake/SKILL.md +1 -1
  355. package/dist/agent-src/skills/systematic-debugging/SKILL.md +2 -2
  356. package/dist/agent-src/skills/tailwind-engineer/SKILL.md +11 -5
  357. package/dist/agent-src/skills/throughput-vs-morale-tradeoff/SKILL.md +1 -1
  358. package/dist/agent-src/skills/token-optimizer/SKILL.md +1 -1
  359. package/dist/agent-src/skills/typography-system/SKILL.md +2 -2
  360. package/dist/agent-src/skills/ui-component-architect/SKILL.md +28 -8
  361. package/dist/agent-src/skills/unit-economics-modeling/SKILL.md +2 -2
  362. package/dist/agent-src/skills/upstream-contribute/SKILL.md +1 -1
  363. package/dist/agent-src/skills/validate-feature-fit/SKILL.md +2 -2
  364. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +2 -2
  365. package/dist/agent-src/skills/vision-articulation/SKILL.md +1 -1
  366. package/dist/agent-src/skills/voc-extract/SKILL.md +2 -2
  367. package/dist/agent-src/skills/voice-and-tone-design/SKILL.md +2 -2
  368. package/dist/agent-src/skills/wireframe/SKILL.md +1 -1
  369. package/dist/agent-src/skills/workspace-link/SKILL.md +1 -1
  370. package/dist/agent-src/templates/agent-settings.md +6 -6
  371. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  372. package/dist/agent-src/templates/contexts/knowledge-pages.md +2 -3
  373. package/dist/agent-src/templates/copilot-instructions.md +1 -1
  374. package/dist/agent-src/templates/roadmaps.md +1 -1
  375. package/dist/agent-src/templates/scripts/README.md +2 -2
  376. package/dist/agent-src/user-types/_template/user-type.md +1 -1
  377. package/dist/cli-delegate/check_update_banner.js +12 -1
  378. package/dist/cli-delegate/{chunk-NLP54U3J.js → chunk-2XY7ILBT.js} +13 -1
  379. package/dist/cli-delegate/{chunk-IAI3XL43.js → chunk-3FKR64R5.js} +22 -6
  380. package/dist/cli-delegate/{chunk-J3RFNKG4.js → chunk-55ACLDUE.js} +2 -2
  381. package/dist/cli-delegate/{chunk-PKOBQADP.js → chunk-57PN4GYJ.js} +1 -1
  382. package/dist/cli-delegate/{chunk-KCNTUSPI.js → chunk-AK6HODNQ.js} +4 -4
  383. package/dist/cli-delegate/{chunk-2FTMENJL.js → chunk-GYC3VRYN.js} +1 -1
  384. package/dist/cli-delegate/{chunk-LWTYTX6F.js → chunk-H32DGUJH.js} +15 -84
  385. package/dist/cli-delegate/{chunk-6RJA2F5A.js → chunk-IVBPRCQO.js} +1 -1
  386. package/dist/cli-delegate/chunk-NUHLI2RX.js +80 -0
  387. package/dist/cli-delegate/{chunk-TYSY33MD.js → chunk-QJWAUMJW.js} +12 -2
  388. package/dist/cli-delegate/{chunk-2KKXJW25.js → chunk-S3VFXMTM.js} +1 -1
  389. package/dist/cli-delegate/{chunk-I6RHFQEG.js → chunk-YUM5KURG.js} +17 -1
  390. package/dist/cli-delegate/cmd_analyze_session.js +1 -1
  391. package/dist/cli-delegate/cmd_brand_status.js +1 -1
  392. package/dist/cli-delegate/cmd_conformance.js +834 -275
  393. package/dist/cli-delegate/cmd_doctor.js +3 -3
  394. package/dist/cli-delegate/cmd_explain.js +5 -3
  395. package/dist/cli-delegate/cmd_export.js +4 -4
  396. package/dist/cli-delegate/cmd_handoff.js +6 -6
  397. package/dist/cli-delegate/cmd_mcp_available.js +1 -1
  398. package/dist/cli-delegate/cmd_memory_get.js +1 -1
  399. package/dist/cli-delegate/cmd_migrate.js +2 -2
  400. package/dist/cli-delegate/cmd_packs_active.js +3 -2
  401. package/dist/cli-delegate/cmd_prune.js +4 -4
  402. package/dist/cli-delegate/cmd_route_audit.js +3 -3
  403. package/dist/cli-delegate/cmd_route_explain.js +1 -1
  404. package/dist/cli-delegate/cmd_session_recycle.js +3 -3
  405. package/dist/cli-delegate/cmd_settings_get.js +15 -9
  406. package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
  407. package/dist/cli-delegate/cmd_settings_set.js +54 -11
  408. package/dist/cli-delegate/cmd_sync.js +4 -4
  409. package/dist/cli-delegate/cmd_uninstall.js +4 -4
  410. package/dist/cli-delegate/cmd_update.js +1 -1
  411. package/dist/cli-delegate/cmd_upgrade.js +1 -1
  412. package/dist/cli-delegate/cmd_validate.js +4 -4
  413. package/dist/cli-delegate/cmd_versions.js +1 -1
  414. package/dist/discovery/deprecation-report.md +1 -1
  415. package/dist/discovery/discovery-manifest.json +25 -78
  416. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  417. package/dist/discovery/discovery-manifest.summary.md +3 -3
  418. package/dist/discovery/dormancy-report.md +1 -1
  419. package/dist/discovery/orphan-report.md +1 -1
  420. package/dist/discovery/packs.json +5 -7
  421. package/dist/discovery/trust-report.md +2 -2
  422. package/dist/discovery/workspaces.json +4 -6
  423. package/dist/hooks/dispatch.js +9684 -9304
  424. package/dist/install/install.mjs +36 -8
  425. package/dist/mcp/registry-manifest.json +3 -3
  426. package/dist/mcp/server.json +2 -2
  427. package/dist/mcp/server.mjs +2147 -1470
  428. package/dist/router.json +1 -1
  429. package/dist/scripts/_lib/agent_settings.js +73 -0
  430. package/dist/scripts/_lib/agent_src.js +20 -0
  431. package/dist/scripts/_lib/guidelines_lane.js +158 -0
  432. package/dist/scripts/_lib/installed_lock.js +1 -1
  433. package/dist/scripts/condense.js +2 -5
  434. package/dist/server/io/yamlIO.js +175 -17
  435. package/dist/server/schemas/settings.js +18 -4
  436. package/dist/shared/settingsSurface.js +6 -1
  437. package/docs/contracts/settings-classes.md +18 -9
  438. package/docs/guidelines/abstraction-thresholds.md +35 -0
  439. package/docs/guidelines/agent-infra/active-remediation-mechanics.md +3 -3
  440. package/docs/guidelines/agent-infra/false-green.md +2 -2
  441. package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
  442. package/docs/guidelines/agent-infra/skill-quality-checklist.md +1 -1
  443. package/docs/guidelines/design-fidelity-mechanics.md +4 -0
  444. package/docs/guidelines/design-fidelity-routing.md +78 -0
  445. package/docs/guidelines/design-reconciliation.md +172 -0
  446. package/docs/guidelines/gtm-handoff.md +2 -2
  447. package/docs/guidelines/wing4-handoff.md +2 -2
  448. package/package.json +7 -3
  449. package/src/config/agent-settings.template.yml +55 -8
  450. package/src/config/ci-local-parity.yml +34 -0
  451. package/src/config/continuity-surface.json +11 -32
  452. package/src/config/gate-coverage.yml +31 -8
  453. package/src/config/gate-reachability-exemptions.json +1 -0
  454. package/src/config/gate-violation-baselines.json +3 -3
  455. package/src/config/hook-token-budget.json +1 -1
  456. package/src/config/host-injection-effect.json +2 -2
  457. package/src/config/pack-size-budget.json +55 -4
  458. package/src/config/platform-anchor.json +47 -0
  459. package/src/config/preamble-payload-budget.json +12 -8
  460. package/src/config/preamble-payload-exceptions.json +28 -0
  461. package/src/config/publish-surface.json +4 -2
  462. package/src/config/ratification-policy.json +7 -0
  463. package/src/config/rule-stub-ceilings.json +16 -9
  464. package/src/scripts/_cli/cmd_settings_get.ts +22 -7
  465. package/src/scripts/_dispatch.bash +3 -1
  466. package/src/scripts/_lib/agent_settings.ts +85 -0
  467. package/src/scripts/_lib/agent_src.ts +21 -0
  468. package/src/scripts/_lib/artifact_maturity.ts +242 -0
  469. package/src/scripts/_lib/base_ref_payload.ts +315 -0
  470. package/src/scripts/_lib/conformance_report.ts +403 -0
  471. package/src/scripts/_lib/continuity_writer.ts +72 -13
  472. package/src/scripts/_lib/design_system_import.ts +20 -0
  473. package/src/scripts/_lib/design_tolerance.ts +281 -0
  474. package/src/scripts/_lib/dropped_decision.ts +142 -0
  475. package/src/scripts/_lib/guidelines_lane.ts +164 -0
  476. package/src/scripts/_lib/installed_lock.ts +1 -1
  477. package/src/scripts/_lib/measured_payload_ceiling.ts +424 -0
  478. package/src/scripts/_lib/obligation_frequency.ts +2 -3
  479. package/src/scripts/_lib/payload_catalogue_completeness.ts +211 -0
  480. package/src/scripts/_lib/platform_anchor.ts +1053 -0
  481. package/src/scripts/_lib/ratification_artifact.ts +278 -0
  482. package/src/scripts/_lib/release_findings_ingest.ts +324 -0
  483. package/src/scripts/_lib/release_tag_dispatch.ts +63 -0
  484. package/src/scripts/_lib/review_baseline.ts +254 -0
  485. package/src/scripts/_lib/review_skipped_record.ts +61 -1
  486. package/src/scripts/_lib/security_lint.ts +23 -2
  487. package/src/scripts/_lib/self_repair.ts +21 -0
  488. package/src/scripts/_lib/session_index_trust.ts +42 -1
  489. package/src/scripts/_lib/standing_bound_ratchet.ts +267 -88
  490. package/src/scripts/_lib/tolerance_shadow.ts +177 -0
  491. package/src/scripts/_lib/turn_end_refusals.ts +51 -4
  492. package/src/scripts/ai_council/redact_low_impact_entry.ts +8 -0
  493. package/src/scripts/autonomy_friction_traffic.ts +379 -0
  494. package/src/scripts/check_beta_review_markers.ts +35 -4
  495. package/src/scripts/check_finding_dispositions.ts +167 -16
  496. package/src/scripts/check_held_object_arrivals.ts +381 -0
  497. package/src/scripts/check_kernel_edit_ratified.ts +462 -0
  498. package/src/scripts/check_loss_class_declared.ts +793 -46
  499. package/src/scripts/check_platform_anchor.ts +390 -0
  500. package/src/scripts/check_preamble_payload_budget.ts +672 -107
  501. package/src/scripts/check_projected_rule_routes.ts +395 -0
  502. package/src/scripts/check_release_published.ts +1 -1
  503. package/src/scripts/check_reply_consistency.ts +86 -17
  504. package/src/scripts/code_graph/cli.ts +6 -0
  505. package/src/scripts/condense.ts +2 -6
  506. package/src/scripts/generate_host_cost_table.ts +354 -0
  507. package/src/scripts/hook_manifest.json +1 -1
  508. package/src/scripts/hook_manifest.yaml +74 -30
  509. package/src/scripts/hooks/block_kernel_rule_writes.ts +12 -2
  510. package/src/scripts/hooks/category_a.ts +1 -1
  511. package/src/scripts/hooks/chain_nudge_hook.ts +311 -25
  512. package/src/scripts/hooks/concern_registry.ts +2 -0
  513. package/src/scripts/hooks/end_review_nudge_hook.ts +101 -21
  514. package/src/scripts/hooks/review_baseline_hook.ts +130 -0
  515. package/src/scripts/hooks/session_eol_hook.ts +68 -154
  516. package/src/scripts/hooks/source_first_gate_hook.ts +12 -0
  517. package/src/scripts/hooks/turn_end_gate_hook.ts +232 -14
  518. package/src/scripts/hooks/ui_route_nudge_hook.ts +52 -15
  519. package/src/scripts/hooks_doctor.ts +4 -1
  520. package/src/scripts/hot_context_hook.ts +41 -401
  521. package/src/scripts/install.ts +1 -1
  522. package/src/scripts/interruption_report.ts +8 -2
  523. package/src/scripts/janitor.ts +8 -1
  524. package/src/scripts/lint_evidence_artifacts.ts +1 -0
  525. package/src/scripts/lint_knowledge_scale.ts +0 -26
  526. package/src/scripts/measure_turn_end_gate.ts +302 -5
  527. package/src/scripts/memory_lookup.ts +9 -9
  528. package/src/scripts/release.ts +52 -64
  529. package/src/scripts/release_drill.ts +193 -14
  530. package/src/scripts/release_env.ts +1 -1
  531. package/src/scripts/release_publication.ts +1 -1
  532. package/src/scripts/report_held_object_arrivals.ts +456 -0
  533. package/src/scripts/report_standing_payload_by_host.ts +7 -7
  534. package/src/scripts/session_memory_index.ts +5 -0
  535. package/src/scripts/sync_agent_settings.ts +394 -12
  536. package/src/server/io/yamlIO.ts +175 -17
  537. package/src/server/schemas/settings.ts +25 -5
  538. package/src/shared/settingsSurface.ts +13 -2
  539. package/src/templates/compact-instructions.md +8 -3
  540. package/dist/agent-src/commands/chat-history/import.md +0 -170
  541. package/dist/agent-src/commands/chat-history.md +0 -63
@@ -44,14 +44,13 @@ concerns:
44
44
  fail_closed: false
45
45
  severity: advisory
46
46
  needs_payload_bodies: [result]
47
- # Hot-context working-memory cache (road-to-second-brain Phase 1).
48
- # stop: deterministic, redacted 400-word overwrite of
49
- # agents/runtime/state/hot-context.md from the chat-history JSONL.
50
- # session_start: staleness-checked restore; the dispatcher forwards the
51
- # returned `context` block to its own stdout (Claude Code SessionStart
52
- # injection; on Claude, source=compact re-injects after compaction).
53
- # Runs AFTER chat-history in both slots so the stop-write sees the final
54
- # session entries. Never blocks.
47
+ # Restore persisted memory session index (road-to-memory-retrieval-economy
48
+ # P5). session_start only: the dispatcher forwards the returned `context`
49
+ # block to its own stdout (Claude Code SessionStart injection).
50
+ # The working-memory CACHE this concern used to write on stop / session_end /
51
+ # pre_compact was retired in road-to-continuity-writer-activation step 3.1;
52
+ # the id is kept deliberately, so the restore stays a tagged concern rather
53
+ # than untagged running code. Never blocks.
55
54
  hot-context:
56
55
  script: src/scripts/hot_context_hook.ts
57
56
  args: []
@@ -62,7 +61,7 @@ concerns:
62
61
  # agents/runtime/state/handoff-context.md, inject it as spotlighted DATA
63
62
  # and DELETE the file (consume-once; a >48h stamp discards instead).
64
63
  # Runs directly AFTER hot-context so the handoff lands after the generic
65
- # cache. Never blocks.
64
+ # session-index block. Never blocks.
66
65
  handoff-context:
67
66
  script: src/scripts/handoff_context_hook.ts
68
67
  args: []
@@ -416,8 +415,25 @@ concerns:
416
415
  # and 5,037 of those were a leading `VAR=…` assignment — a shape no allowlist
417
416
  # pattern can express. It shrinks only by not being written.
418
417
  #
419
- # Warn-only, once per session, ON by default with `hooks.chain_nudge.enabled:
420
- # false` as the opt-out. The inverted default is deliberate and differs from
418
+ # SECOND SHAPE CLASS (2026-09-10). A Bash command that fills a file — `sed
419
+ # -i`, `cat > f`, `tee f`, `perl -i`, a `python3 -c` opening a path for
420
+ # writing — costs a confirmation no allowlist entry removes: the host's own
421
+ # permission documentation records a permanent saved rule for a read-only
422
+ # command and a session-lifetime one for a write-shaped command, so the same
423
+ # shape is confirmed again next session. Edit and Write carry no such expiry
424
+ # inside the working directory. Measured 2026-09-10 over 7,569 distinct real
425
+ # Bash calls in 39 transcripts: 306 (4.0 %) wrote a file through the shell,
426
+ # 216 of them `cat >` — a FLOOR, since the rules are a positive list of five
427
+ # commands rather than a redirect scanner. Re-measure with
428
+ # `./scripts-run src/scripts/autonomy_friction_traffic`.
429
+ #
430
+ # Warn-only, once per SHAPE CLASS per session, ON by default with
431
+ # `hooks.chain_nudge.enabled: false` as the opt-out. Per class, not per
432
+ # call: the anti-nagging decision this concern was written under refuses
433
+ # repeating a line every call, and a single boolean latch would have let
434
+ # whichever shape came first silence the other for the rest of the session.
435
+ #
436
+ # The inverted default is deliberate and differs from
421
437
  # `code-graph-context` below: that one gates on a project capability that may
422
438
  # be absent, while the fact this one carries is a property of the HOST's
423
439
  # permission matcher and therefore holds in every consumer.
@@ -903,13 +919,49 @@ concerns:
903
919
  # about it. The saving is the module load rather than a large read, which is
904
920
  # the smaller of the two flags below it and is stated as such.
905
921
  skip_on_refusal_retry: true
922
+ # road-to-a-question-that-survives-the-turn Phase 2 — the session baseline
923
+ # `end-review-nudge` subtracts. CAPTURE ONLY: one small JSON file per session
924
+ # under agents/runtime/state/review-baseline/ (gitignored), holding HEAD and
925
+ # the count of non-doc lines already dirty when the session began. It emits no
926
+ # context, never warns, and always exits 0.
927
+ #
928
+ # WHY. `end_review_nudge_hook`'s own header records that a dirty tree
929
+ # predating the session is charged to the session, and names the reason it was
930
+ # left: "no such baseline exists anywhere a `stop` concern can read it". That
931
+ # was true of a one-concern phase and stale by the time it mattered —
932
+ # session_start is bound on seven hosts here. Measured cost of leaving it: on
933
+ # an accumulator branch the nudge read 1,771 lines of two crashed sessions'
934
+ # uncommitted work and fired every turn.
935
+ #
936
+ # The counting function is IMPORTED from the nudge, so the baseline and the
937
+ # measurement cannot drift on what a non-doc mutated line is.
938
+ #
939
+ # BOUND ON `claude` ALONE, and narrowly on purpose. Seven hosts carry
940
+ # session_start, but `end-review-nudge` — the only reader — is bound on
941
+ # claude's stop slot and nowhere else (cowork refuses it explicitly). Binding
942
+ # the writer everywhere would spend ~91 ms of git per session start on six
943
+ # hosts to produce a file nothing opens. It is dropped for the `worker` role
944
+ # alongside its reader, for the same reason. Where the baseline is absent the
945
+ # nudge reads `absent` and degrades to exactly its previous behaviour,
946
+ # recorded in its telemetry row rather than inferred. fail_closed: false.
947
+ review-baseline:
948
+ script: src/scripts/hooks/review_baseline_hook.ts
949
+ args: []
950
+ fail_closed: false
951
+ severity: advisory
906
952
  # road-to-conformance-round5 Phase 3 — the FIRST concern that can refuse a
907
953
  # turn-END. Round 5 measured the reason: both blocking carriers reached zero
908
954
  # violations, neither advisory carrier did, and 19 language violations
909
955
  # survived a pin that had fired 26-35 seconds earlier. Refusal-capable
910
956
  # intercepts enforce; context injection requests.
911
957
  #
912
- # Two detectors on one guard — promissory closing (20 measured) and language
958
+ # FIVE detectors on one guard — promissory closing, language mismatch,
959
+ # unverified edit, unsettled completion claim, and a decision the turn asked
960
+ # and then dropped. This said "Two" and named the first pair, which was true
961
+ # of the concern on the day it was registered and of nothing since; the
962
+ # authority is `DetectorId` in the hook, and the demotion contract carries the
963
+ # per-detector bars. Original note, kept because its reason still holds:
964
+ # promissory closing (20 measured) and language
913
965
  # mismatch (19 measured) — because building the unsafe part twice is how a
914
966
  # second detector becomes a second outage.
915
967
  #
@@ -1256,20 +1308,20 @@ roles:
1256
1308
  # contacts, so a worker turn that ends in a question to its orchestrator
1257
1309
  # would be recorded as a contact that never reached a human, inflating the
1258
1310
  # exact baseline Phase 0 pre-registers.
1259
- drop: [delegation-nudge, skill-route, end-review-nudge, council-availability, team-review-gate, self-repair, session-eol, interruption-ledger]
1311
+ drop: [delegation-nudge, skill-route, end-review-nudge, review-baseline, council-availability, team-review-gate, self-repair, session-eol, interruption-ledger]
1260
1312
 
1261
1313
  platforms:
1262
1314
  augment:
1263
1315
  session_start: [chat-history, hot-context, handoff-context, session-canary, council-availability, telemetry-disclosure, first-run-gate, onboarding-gate, verify-before-complete, minimal-safe-diff, profile-staleness, wrapper-freshness, surface-probe, session-register]
1264
1316
  session_end: [chat-history, memory-learn, session-register, roadmap-progress, telemetry-flush]
1265
- stop: [chat-history, hot-context, verify-before-complete, self-repair, session-register, roadmap-progress, design-pass-stop]
1317
+ stop: [chat-history, verify-before-complete, self-repair, session-register, roadmap-progress, design-pass-stop]
1266
1318
  pre_tool_use: [block-no-verify, evidence-independence, block-kernel-rule-writes, block-config-weakening, block-speaking-inbox-dir, rtk-wrap, design-slop, ui-route-nudge, code-graph-context, chain-nudge, ship-diff-volume, reread-guard]
1267
1319
  post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder, push-settle, orchestration-record, telemetry-usage, tool-result-bytes, edit-shape, comment-discipline, design-pass]
1268
1320
 
1269
1321
  claude:
1270
- session_start: [chat-history, hot-context, handoff-context, session-canary, council-availability, telemetry-disclosure, first-run-gate, onboarding-gate, verify-before-complete, minimal-safe-diff, profile-staleness, wrapper-freshness, surface-probe, session-register, journal-record]
1322
+ session_start: [chat-history, hot-context, handoff-context, session-canary, council-availability, telemetry-disclosure, first-run-gate, onboarding-gate, verify-before-complete, minimal-safe-diff, profile-staleness, wrapper-freshness, surface-probe, session-register, review-baseline, journal-record]
1271
1323
  session_end: [chat-history, memory-learn, session-register, roadmap-progress, telemetry-flush, journal-record]
1272
- stop: [chat-history, hot-context, verify-before-complete, team-review-gate, end-review-nudge, turn-end-gate, self-repair, session-register, session-eol, interruption-ledger, roadmap-progress, design-pass-stop, suggestion-capture, journal-record, run-continuation]
1324
+ stop: [chat-history, verify-before-complete, team-review-gate, end-review-nudge, turn-end-gate, self-repair, session-register, session-eol, interruption-ledger, roadmap-progress, design-pass-stop, suggestion-capture, journal-record, run-continuation]
1273
1325
  user_prompt_submit: [chat-history, verify-before-complete, minimal-safe-diff, language-mirror, delegation-nudge, skill-route, git-authorization, session-canary, self-repair, session-register, rule-inject, suggestion-capture, journal-record]
1274
1326
  # `rule-inject` was bound here and is not any more
1275
1327
  # (road-to-delivery-for-every-host 3.2, owner ruling E2). E2's strategy is
@@ -1304,15 +1356,7 @@ platforms:
1304
1356
  # Claude Code transcript fact. (It was the ONLY binding on this slot until
1305
1357
  # the entry below; that sentence is retired rather than left to rot.)
1306
1358
  #
1307
- # `hot-context` — road-to-inbox-harvest-2026-08-d-context-ledger Step 2.1.
1308
- # This is the one slot that fires WHILE state is being destroyed, and it
1309
- # carried no WRITER at all: the cache a post-compaction `session_start`
1310
- # restores was written at the last `stop`, so everything the session did
1311
- # between that stop and the compaction was lost with it. The concern is
1312
- # already bound on `stop` and `session_start`; this adds the write at the
1313
- # moment the loss actually happens. Deterministic rebuild, emits nothing
1314
- # here — the 4,096-byte row it carries is for its session_start restore.
1315
- pre_compact: [language-mirror, hot-context, rule-inject, journal-record]
1359
+ pre_compact: [language-mirror, rule-inject, journal-record]
1316
1360
  # road-to-subagent-lifecycle-integrity Phase 1 Step 1. `claude` is the only
1317
1361
  # platform where both native events were measured present on the installed
1318
1362
  # binary (2.1.229 — see the evidence page cited on the alias rows below).
@@ -1346,7 +1390,7 @@ platforms:
1346
1390
  # is later verified to forward it. Binding them here would be dead
1347
1391
  # weight: the concern still runs (git diff, transcript scan, classifier),
1348
1392
  # still costs the dispatch, and its entire output is thrown away.
1349
- stop: [chat-history, hot-context, verify-before-complete, self-repair, session-register, roadmap-progress, design-pass-stop]
1393
+ stop: [chat-history, verify-before-complete, self-repair, session-register, roadmap-progress, design-pass-stop]
1350
1394
  user_prompt_submit: [chat-history, verify-before-complete, minimal-safe-diff, language-mirror, git-authorization, session-canary, self-repair, session-register]
1351
1395
  pre_tool_use: [block-no-verify, evidence-independence, block-kernel-rule-writes, block-config-weakening, block-speaking-inbox-dir, rtk-wrap, design-slop, ui-route-nudge, code-graph-context, chain-nudge, ship-diff-volume, reread-guard, spawn-guard-shadow, source-first-gate]
1352
1396
  post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder, push-settle, orchestration-record, telemetry-usage, tool-result-bytes, edit-shape, comment-discipline, design-pass]
@@ -1371,7 +1415,7 @@ platforms:
1371
1415
  cursor:
1372
1416
  session_start: [chat-history, hot-context, handoff-context, session-canary, council-availability, telemetry-disclosure, first-run-gate, onboarding-gate, verify-before-complete, minimal-safe-diff, profile-staleness, wrapper-freshness, surface-probe, session-register]
1373
1417
  session_end: [chat-history, memory-learn, session-register, roadmap-progress, telemetry-flush]
1374
- stop: [chat-history, hot-context, verify-before-complete, self-repair, session-register, roadmap-progress, design-pass-stop]
1418
+ stop: [chat-history, verify-before-complete, self-repair, session-register, roadmap-progress, design-pass-stop]
1375
1419
  user_prompt_submit: [chat-history, verify-before-complete, minimal-safe-diff, language-mirror, git-authorization, session-canary, self-repair, session-register]
1376
1420
  post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder, push-settle, orchestration-record, telemetry-usage, tool-result-bytes, edit-shape, comment-discipline, design-pass]
1377
1421
 
@@ -1386,7 +1430,7 @@ platforms:
1386
1430
  cline:
1387
1431
  session_start: [chat-history, hot-context, handoff-context, session-canary, council-availability, telemetry-disclosure, first-run-gate, onboarding-gate, verify-before-complete, minimal-safe-diff, profile-staleness, wrapper-freshness, surface-probe, session-register]
1388
1432
  session_end: [chat-history, memory-learn, session-register, roadmap-progress, telemetry-flush]
1389
- stop: [chat-history, hot-context, verify-before-complete, self-repair, session-register, roadmap-progress, design-pass-stop]
1433
+ stop: [chat-history, verify-before-complete, self-repair, session-register, roadmap-progress, design-pass-stop]
1390
1434
  user_prompt_submit: [chat-history, verify-before-complete, minimal-safe-diff, language-mirror, git-authorization, session-canary, self-repair, session-register]
1391
1435
  post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder, push-settle, orchestration-record, telemetry-usage, tool-result-bytes, edit-shape, comment-discipline, design-pass]
1392
1436
 
@@ -1404,7 +1448,7 @@ platforms:
1404
1448
  # minimal-safe-diff is omitted entirely on Windsurf for the same reason.
1405
1449
  windsurf:
1406
1450
  session_start: [chat-history, hot-context, handoff-context, session-canary, council-availability, telemetry-disclosure, first-run-gate, onboarding-gate, verify-before-complete, profile-staleness, wrapper-freshness, surface-probe, session-register]
1407
- stop: [chat-history, hot-context, verify-before-complete, self-repair, session-register, design-pass-stop]
1451
+ stop: [chat-history, verify-before-complete, self-repair, session-register, design-pass-stop]
1408
1452
  # language-mirror IS bound here: unlike minimal-safe-diff it needs only the
1409
1453
  # user_prompt_submit slot, which Windsurf has.
1410
1454
  user_prompt_submit: [chat-history, verify-before-complete, language-mirror, git-authorization, session-canary, self-repair, session-register]
@@ -1422,7 +1466,7 @@ platforms:
1422
1466
  gemini:
1423
1467
  session_start: [chat-history, hot-context, handoff-context, session-canary, council-availability, telemetry-disclosure, first-run-gate, onboarding-gate, verify-before-complete, minimal-safe-diff, profile-staleness, wrapper-freshness, surface-probe, session-register]
1424
1468
  session_end: [chat-history, memory-learn, session-register, roadmap-progress, telemetry-flush]
1425
- stop: [chat-history, hot-context, verify-before-complete, self-repair, session-register, roadmap-progress, design-pass-stop]
1469
+ stop: [chat-history, verify-before-complete, self-repair, session-register, roadmap-progress, design-pass-stop]
1426
1470
  user_prompt_submit: [chat-history, verify-before-complete, minimal-safe-diff, language-mirror, git-authorization, session-canary, self-repair, session-register]
1427
1471
  post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder, push-settle, orchestration-record, telemetry-usage, tool-result-bytes, edit-shape, comment-discipline, design-pass]
1428
1472
 
@@ -26,8 +26,18 @@
26
26
  * exported pure functions, and reports via the same stderr-block-message +
27
27
  * exit-code shape (0 allow · 1 block). `fail_closed: true` in the manifest —
28
28
  * ADR-127 permits more than one blocking hook; this is the second (after
29
- * block-no-verify). No agent-accessible override: the sole legitimate bypass
30
- * is the human-owned exception registry the deny message points to.
29
+ * block-no-verify).
30
+ *
31
+ * Coverage is limited to edit-tool envelopes whose explicit target is a
32
+ * kernel rule, and to the literal shell-argument write shapes recognized by
33
+ * `check_envelope`. Indirect or dynamically resolved writes may not be
34
+ * detected; this guard is not a sandbox and does not provide complete write
35
+ * mediation. The human-owned exception registry named in the denial message
36
+ * is the only LEGITIMATE bypass; it is not the only reachable one.
37
+ *
38
+ * The boundary is stated as an abstraction, without an inventory of concrete
39
+ * evasion families. `check_envelope` is the authoritative inspection point
40
+ * for exact behaviour.
31
41
  *
32
42
  * Exit codes (docs/contracts/hook-architecture-v1.md):
33
43
  * 0 — allow
@@ -57,7 +57,7 @@ const PATH_KEYS: readonly string[] = [
57
57
  * tries to parse past them is a shell parser with a security boundary attached.
58
58
  * Refusing the whole shape is both smaller and correct.
59
59
  */
60
- const SHELL_METACHARACTERS = /[;&|`$><\n\r(){}\\]/;
60
+ export const SHELL_METACHARACTERS = /[;&|`$><\n\r(){}\\]/;
61
61
 
62
62
  /**
63
63
  * Words naming a consequence operation, matched as whole tokens anywhere in
@@ -18,11 +18,37 @@
18
18
  * a shape that cannot be written as an allowlist pattern at all. That class
19
19
  * shrinks only by not writing it.
20
20
  *
21
+ * THE SECOND CLASS, AND WHY IT BELONGS HERE. A Bash command that writes a
22
+ * file — `sed -i`, `cat > f`, `tee f`, `perl -i`, a `python3 -c` that opens a
23
+ * path for writing — costs a confirmation for a reason no allowlist entry
24
+ * fixes: a write-shaped Bash grant does NOT persist. The host's own
25
+ * permission documentation records that "don't ask again" saves a permanent
26
+ * rule for read-only and pre-approved commands and that write-shaped ones
27
+ * last until session end, so the same shape is confirmed again next session.
28
+ * The Edit and Write tools carry no such expiry for a path inside the working
29
+ * directory. That makes the substitution a strictly cheaper primitive rather
30
+ * than a style preference, which is why the concern that already reads
31
+ * `tool_input.command` carries it instead of a second concern reading the
32
+ * same field. Measured on 2026-09-10 over 7,569 distinct real Bash calls in
33
+ * 39 transcripts on the maintainer's machine: 306 (4.0 %) wrote a file
34
+ * through the shell — 216 `cat >`, 66 `sed -i`, 16 `python3 -c` with a
35
+ * write-mode `open`, 7 `perl -i`, 1 `tee`. Recompute with
36
+ * `./scripts-run src/scripts/autonomy_friction_traffic`, which shares these
37
+ * detectors; every figure in this change comes from that one run.
38
+ *
39
+ * THE COUNT IS A FLOOR, and the five rules are why. `echo >`, `printf >`,
40
+ * `jq >`, `awk >`, `git show >` and `cp` all fill a file and none is matched:
41
+ * the list is positive by design, and a generic redirect scanner would fire on
42
+ * `grep x f > out.txt`, where the shell is not the thing doing the writing.
43
+ * A heredoc whose BODY performs the write is invisible for the same reason the
44
+ * body is stripped at all. Read 4.0 % as "at least".
45
+ *
21
46
  * WHAT IT DOES NOT FLAG, DELIBERATELY. A pipe of ordinary filters
22
47
  * (`grep foo file | head`) is one command with a filter, not two work steps.
23
- * A redirect has its target checked against the file rules on its own. A
24
- * heredoc is a command with input. Flagging any of those would make the
25
- * nudge noise, and a nudge that fires on correct usage is worse than none.
48
+ * A redirect whose target is not a file the shell is filling with content —
49
+ * `2>&1`, `> /dev/null` — is not a write. A heredoc is a command with input.
50
+ * Flagging any of those would make the nudge noise, and a nudge that fires on
51
+ * correct usage is worse than none.
26
52
  *
27
53
  * NEVER BLOCKS. The dispatcher contract is 0 allow · 2 warn, and a warn on
28
54
  * `pre_tool_use` with `severity: advisory` is an injection, not a deny — the
@@ -30,10 +56,23 @@
30
56
  * failure path returns allow: unreadable stdin, malformed JSON, unwritable
31
57
  * latch. A token optimisation must never break a tool call.
32
58
  *
33
- * ONCE PER SESSION. A latch keyed by session id, in the state directory
34
- * `code-graph-nudge.json` already occupies. The rule body reaches the model
35
- * once, early, on the first chained call — repeating it every call would be
36
- * the nagging this codebase refuses elsewhere.
59
+ * ONCE PER SHAPE CLASS PER SESSION. A latch keyed by session id, in the state
60
+ * directory `code-graph-nudge.json` already occupies. Each class reaches the
61
+ * model once, early, on the first call carrying it — so a session sees at most
62
+ * two lines, never one line for two different mistakes.
63
+ *
64
+ * That is a per-CLASS latch, not a per-CALL one, and the distinction is the
65
+ * whole reason it is allowed to change: the recorded decision this file
66
+ * carried refuses "repeating it every call", which is the nagging this
67
+ * codebase refuses elsewhere, and a second class firing once is a different
68
+ * mechanism from a first class firing twice. The single-boolean latch was
69
+ * written when there was one class; with two, it would have let whichever
70
+ * shape came first silence the other for the rest of the session.
71
+ *
72
+ * A latch file written by the single-class version holds `true` rather than an
73
+ * object. That is read as "the chain class has fired", which is what it meant,
74
+ * so an in-flight session upgrades without losing its latch and without
75
+ * replaying a line it already showed.
37
76
  *
38
77
  * ON BY DEFAULT, WITH AN OPT-OUT. Unlike `code-graph-nudge`, which gates on a
39
78
  * project capability that may not exist, the fact this nudge carries is a
@@ -137,14 +176,208 @@ export function stripLiterals(cmd: string): string {
137
176
  return out;
138
177
  }
139
178
 
179
+ /**
180
+ * Heredoc BODIES removed, the command line they sit on kept.
181
+ *
182
+ * `stripLiterals` runs from `<<` to the closing tag and so deletes the redirect
183
+ * that shares the command line; leaving the body in instead let a heredoc that
184
+ * merely MENTIONS a write shape fire the nudge and spend the session's one
185
+ * write line. Neither view is right for the write rules, so this is the third:
186
+ * the marker and the rest of the command line survive, the body does not.
187
+ *
188
+ * Consequence, stated because it is a real false negative: a heredoc whose BODY
189
+ * performs the write — `python3 - <<PY` opening a path — is invisible here. The
190
+ * class is a floor, and this is one of the reasons.
191
+ */
192
+ export function stripHeredocBodies(cmd: string): string {
193
+ const marker = /<<-?\s*(['"]?)([A-Za-z_][A-Za-z0-9_]*)\1/g;
194
+ let out = '';
195
+ let cursor = 0;
196
+ let m: RegExpExecArray | null;
197
+ while ((m = marker.exec(cmd)) !== null) {
198
+ const tag = m[2] as string;
199
+ const nl = cmd.indexOf('\n', m.index + m[0].length);
200
+ if (nl === -1) break;
201
+ const close = cmd.indexOf(`\n${tag}`, nl);
202
+ const end = close === -1 ? cmd.length : close + tag.length + 1;
203
+ out += cmd.slice(cursor, m.index) + '<<' + cmd.slice(m.index + m[0].length, nl);
204
+ cursor = end;
205
+ marker.lastIndex = end;
206
+ }
207
+ return out + cmd.slice(cursor);
208
+ }
209
+
210
+ /**
211
+ * Quoted spans removed, heredoc bodies LEFT IN PLACE.
212
+ *
213
+ * The sibling of `stripLiterals` for the write rules. That one must consume a
214
+ * heredoc, because an operator in its body is not chaining; this one must not,
215
+ * because the heredoc marker and the redirect share a command line and
216
+ * consuming to the closing tag takes the redirect with it.
217
+ */
218
+ export function stripQuoted(cmd: string): string {
219
+ let out = '';
220
+ let i = 0;
221
+ let quote: string | null = null;
222
+ while (i < cmd.length) {
223
+ const c = cmd[i] as string;
224
+ if (quote) {
225
+ if (c === '\\' && quote === '"') {
226
+ i += 2;
227
+ continue;
228
+ }
229
+ if (c === quote) quote = null;
230
+ i += 1;
231
+ continue;
232
+ }
233
+ if (c === '\\') {
234
+ i += 2;
235
+ continue;
236
+ }
237
+ if (c === '"' || c === "'") {
238
+ quote = c;
239
+ i += 1;
240
+ continue;
241
+ }
242
+ out += c;
243
+ i += 1;
244
+ }
245
+ return out;
246
+ }
247
+
140
248
  /** What the nudge saw, or null when the command is not chained work. */
141
249
  export function detectChaining(command: string): string | null {
142
- const bare = stripLiterals(command);
250
+ return _detectChaining(stripLiterals(command));
251
+ }
252
+
253
+ function _detectChaining(bare: string): string | null {
143
254
  if (/^\s*[A-Za-z_][A-Za-z0-9_]*=/.test(bare) && /[;\n]/.test(bare)) {
144
255
  return 'a leading `VAR=…` assignment carrying state into a later segment';
145
256
  }
146
257
  if (/&&|\|\|/.test(bare)) return 'work steps chained with `&&` / `||`';
147
258
  if (/;\s*\S/.test(bare)) return 'work steps chained with `;`';
259
+ // The header names newlines among the host's split points and this rule did
260
+ // not read them, so `git status\ngit diff` — two work steps by any reading —
261
+ // was silent. Heredoc bodies are already gone from this view, so a
262
+ // multi-line heredoc command does not reach here.
263
+ if (/\n\s*\S/.test(bare)) return 'work steps separated by a newline';
264
+ return null;
265
+ }
266
+
267
+ /**
268
+ * The five shapes that fill a file's content from the shell, each matched on
269
+ * the literal-stripped command so a quoted mention cannot fire it.
270
+ *
271
+ * A positive list, not a redirect scan: `>` alone is a redirect and the header
272
+ * says a redirect is not flagged. What is flagged is a command whose named
273
+ * operation IS "put this content in that path", which is the operation Edit
274
+ * and Write perform without an expiring grant. `/dev/null` and an fd
275
+ * duplication (`2>&1`) are excluded because neither names a file being filled.
276
+ */
277
+ const EDIT_BY_SHELL: ReadonlyArray<{ re: RegExp; seen: string }> = [
278
+ // `-i` may ride inside a flag cluster (`-ri`, `-Ei`) or carry a backup
279
+ // suffix (`-i.bak`), so the letter is matched inside the cluster rather
280
+ // than as a token. `sed -n 2,8p` and `sed -e s/a/b/ f` have no `i` in any
281
+ // flag and stay silent; `--expression=…` cannot match because the class
282
+ // admits letters only after the single leading dash.
283
+ {
284
+ re: /(^|[\s;&|(])sed\s+(?:-\S+\s+)*-(?:i|[nersuzE]*i[nersuzE]*|-in-place)(?:\.\S+)?(?=\s|$)/,
285
+ seen: '`sed -i` edits a file in place',
286
+ },
287
+ // The letter set is closed on purpose. Matching an `i` ANYWHERE in a flag
288
+ // cluster made `perl -Mstrict`, `perl -MList::Util` and `perl -Ilib` all
289
+ // report an in-place edit — the letters after `-M` and `-I` are a module
290
+ // name and a directory, not switches. Only perl's own one-letter switches
291
+ // may share the cluster with `i`.
292
+ {
293
+ re: /(^|[\s;&|(])perl\s+(?:-\S+\s+)*-(?:i|[pnlaw]*i[pnlaw]*)(?:\.\S+)?(?=\s|$)/,
294
+ seen: '`perl -i` edits a file in place',
295
+ },
296
+ // `[^\n]*` between the head and the redirect, so `cat <<'EOF' > out.txt`
297
+ // and `cat a b > merged` both land, while `> /dev/null` and an fd
298
+ // duplication (`2>&1`) are excluded by the lookahead at every position the
299
+ // engine tries.
300
+ // `[^\n|;&]*` — the redirect must belong to the SAME simple command. With
301
+ // `[^\n]*` this rule was a general redirect scanner for any cat-headed
302
+ // pipeline, so `cat f | grep x > out.txt` fired while the identical
303
+ // `grep x f > out.txt` stayed silent, which its own "positive list, not a
304
+ // redirect scan" comment forbids.
305
+ { re: /(^|[\s;&|(])cat\b[^\n|;&]*>{1,2}\s*(?!&|\/dev\/null)\S/, seen: '`cat >` fills a file from the shell' },
306
+ // A flag cluster before the path is normal (`tee -a out.txt`), and the path
307
+ // is REQUIRED. Dropping the original `(?!-)` lookahead to admit the flagged
308
+ // form turned a false negative into a false-positive class: `tee -a`,
309
+ // `foo | tee | wc -l`, `foo | tee -` and `tee -a /dev/null` all fired. The
310
+ // path token is therefore matched explicitly — not a flag, not a shell
311
+ // operator, not the null device.
312
+ {
313
+ re: /(^|[\s;&|(])tee\s+(?:-[A-Za-z]+\s+)*(?!\/dev\/null)[^-\s;&|<>][^\s;&|<>]*/,
314
+ seen: '`tee` writes its input to a file',
315
+ },
316
+ ];
317
+
318
+ /** The interpreter form, split across the two views for the reason below. */
319
+ const PY_AT_COMMAND_POSITION = /(^|[\s;&|(])python3?\s+-c\b/;
320
+ const PY_OPENS_FOR_WRITING = /\bopen\s*\([^)]*['"][wax]\+?['"]/;
321
+
322
+ /**
323
+ * What the write-shaped detector saw, or null when the call writes no file.
324
+ *
325
+ * `stripQuoted` rather than `stripLiterals` for the redirect rules: the
326
+ * heredoc branch of `stripLiterals` runs to the closing tag and swallows the
327
+ * command line with it, so `cat <<'EOF' > out.txt` lost its own redirect and
328
+ * the largest measured write shape went undetected in its most common spelling.
329
+ *
330
+ * The interpreter rule reads BOTH views, and needs to. Its program is a quoted
331
+ * argument, so the write mode is only visible in the raw string; but matching
332
+ * the raw string alone fires on any command that merely QUOTES the shape —
333
+ * `git commit -m "use python3 -c open(p,'w')"` did, and this change ships that
334
+ * exact string in a substitution table. So the interpreter must sit at a
335
+ * command position in the STRIPPED text, where a quoted mention has already
336
+ * been removed, and the write mode must be named in the RAW text.
337
+ */
338
+ export function detectEditByShell(command: string): string | null {
339
+ return _detectEditByShell(command, writeView(command));
340
+ }
341
+
342
+ /** The view the write rules read: no heredoc bodies, no quoted spans. */
343
+ export function writeView(command: string): string {
344
+ return stripQuoted(stripHeredocBodies(command));
345
+ }
346
+
347
+ function _detectEditByShell(command: string, quotesStripped: string): string | null {
348
+ for (const shape of EDIT_BY_SHELL) {
349
+ if (shape.re.test(quotesStripped)) return shape.seen;
350
+ }
351
+ if (PY_AT_COMMAND_POSITION.test(quotesStripped) && PY_OPENS_FOR_WRITING.test(command)) {
352
+ return 'a `python3 -c` one-liner opens a path for writing';
353
+ }
354
+ return null;
355
+ }
356
+
357
+ /** The two shape classes this concern carries. */
358
+ export type NudgeClass = 'edit-by-shell' | 'chain';
359
+
360
+ /** One finding: which class fired, and what it saw. */
361
+ export interface NudgeFinding {
362
+ klass: NudgeClass;
363
+ seen: string;
364
+ }
365
+
366
+ /**
367
+ * The finding for this command, or null.
368
+ *
369
+ * `edit-by-shell` is tested first, and on a call that is both — `cd d && sed
370
+ * -i … f` is — it wins: its line names a primitive that costs no confirmation
371
+ * at all, while the chain line only explains why this one did.
372
+ */
373
+ export function detectShape(command: string): NudgeFinding | null {
374
+ // Each view is built once. This runs on every shell tool call and the
375
+ // header documents 26 ms p95 as load-bearing, so calling the two exported
376
+ // wrappers here would strip the same string twice per call for nothing.
377
+ const write = _detectEditByShell(command, writeView(command));
378
+ if (write) return { klass: 'edit-by-shell', seen: write };
379
+ const chained = _detectChaining(stripLiterals(command));
380
+ if (chained) return { klass: 'chain', seen: chained };
148
381
  return null;
149
382
  }
150
383
 
@@ -190,25 +423,59 @@ function latchFile(root: string): string {
190
423
  return path.join(root, 'agents', 'runtime', 'state', 'chain-nudge.json');
191
424
  }
192
425
 
193
- function alreadyNudged(root: string, session: string): boolean {
426
+ /** One session's latch: the object form, or the pre-two-class `true`. */
427
+ type LatchEntry = boolean | Record<string, boolean>;
428
+
429
+ /**
430
+ * Has `klass` already fired for this session?
431
+ *
432
+ * A legacy `true` is read as the chain class having fired, which is what the
433
+ * single-class version wrote it to mean. The write class is then unlatched in
434
+ * that session and gets its first line — correct, because it never had one.
435
+ */
436
+ export function classAlreadyNudged(entry: LatchEntry | undefined, klass: NudgeClass): boolean {
437
+ if (entry === true) return klass === 'chain';
438
+ if (isObject(entry)) return entry[klass] === true;
439
+ return false;
440
+ }
441
+
442
+ /** `klass` recorded on top of whatever the entry already held. */
443
+ export function withClassLatched(entry: LatchEntry | undefined, klass: NudgeClass): Record<string, boolean> {
444
+ const next: Record<string, boolean> = entry === true ? { chain: true } : isObject(entry) ? { ...(entry as Record<string, boolean>) } : {};
445
+ next[klass] = true;
446
+ return next;
447
+ }
448
+
449
+ /**
450
+ * The latch state, or `{}` for anything that is not a JSON object.
451
+ *
452
+ * The shape check is not decoration. `JSON.parse` returns `null` for a latch
453
+ * file holding `null` and a number for one holding `7`, neither of which throws
454
+ * — so the try/catch alone let a corrupted file reach the caller as a non-object
455
+ * and crash the property read. The helper this replaced guarded that by reading
456
+ * the property inside its own try; consolidating the read dropped the guard, and
457
+ * the header's "every failure path returns allow" stopped being true.
458
+ */
459
+ function readLatch(root: string): Record<string, LatchEntry> {
194
460
  try {
195
- const state = JSON.parse(fs.readFileSync(latchFile(root), 'utf-8')) as Record<string, boolean>;
196
- return state[session] === true;
461
+ const parsed: unknown = JSON.parse(fs.readFileSync(latchFile(root), 'utf-8'));
462
+ return isObject(parsed as JsonValue) ? (parsed as Record<string, LatchEntry>) : {};
197
463
  } catch {
198
- return false;
464
+ return {};
199
465
  }
200
466
  }
201
467
 
202
- function latch(root: string, session: string): void {
468
+ /**
469
+ * Record `klass` into an ALREADY-READ state and persist it.
470
+ *
471
+ * The state is passed in rather than re-read: the caller has just consulted it
472
+ * to decide whether to fire, and reading the same file twice per firing call is
473
+ * the kind of hot-path waste this file's own ordering comment exists to avoid.
474
+ */
475
+ function latch(root: string, session: string, klass: NudgeClass, state: Record<string, LatchEntry>): void {
203
476
  try {
204
477
  const p = latchFile(root);
205
- let state: Record<string, boolean> = {};
206
- try {
207
- state = JSON.parse(fs.readFileSync(p, 'utf-8')) as Record<string, boolean>;
208
- } catch {
209
- /* fresh */
210
- }
211
- state[session] = true;
478
+ state[session] = withClassLatched(state[session], klass);
212
479
  fs.mkdirSync(path.dirname(p), { recursive: true });
213
480
  fs.writeFileSync(p, JSON.stringify(state));
214
481
  } catch {
@@ -216,6 +483,24 @@ function latch(root: string, session: string): void {
216
483
  }
217
484
  }
218
485
 
486
+ /** The write-shape line — names the expiry, then the primitive without one. */
487
+ export function editByShellReason(seen: string): string {
488
+ return (
489
+ `This Bash call writes a file through the shell: ${seen}. A write-shaped ` +
490
+ 'Bash grant does not persist — the host saves a permanent rule for ' +
491
+ 'read-only commands, while a write-shaped one lasts until session end, so ' +
492
+ 'this same shape costs another confirmation next session. Edit and Write ' +
493
+ 'carry no such expiry inside the working directory: Edit for a targeted ' +
494
+ 'change, Write for a new file, the shell for reads. ' +
495
+ 'See `token-efficiency` § One command per Bash call.'
496
+ );
497
+ }
498
+
499
+ /** The line for a finding, dispatched on its class. */
500
+ export function reasonFor(finding: NudgeFinding): string {
501
+ return finding.klass === 'edit-by-shell' ? editByShellReason(finding.seen) : nudgeReason(finding.seen);
502
+ }
503
+
219
504
  /** The nudge line — one line, names what was seen and what to do instead. */
220
505
  export function nudgeReason(seen: string): string {
221
506
  return (
@@ -247,8 +532,8 @@ export function main(): number {
247
532
  const command = bashCommand(envelope);
248
533
  if (!command) return EXIT_ALLOW;
249
534
 
250
- const seen = detectChaining(command);
251
- if (!seen) return EXIT_ALLOW;
535
+ const finding = detectShape(command);
536
+ if (!finding) return EXIT_ALLOW;
252
537
 
253
538
  const cwd = envelope['cwd'];
254
539
  const pr = envelope['workspace_root'] ?? envelope['project_root'];
@@ -256,10 +541,11 @@ export function main(): number {
256
541
  if (!enabled(root)) return EXIT_ALLOW;
257
542
 
258
543
  const session = sessionId(envelope);
259
- if (alreadyNudged(root, session)) return EXIT_ALLOW;
544
+ const state = readLatch(root);
545
+ if (classAlreadyNudged(state[session], finding.klass)) return EXIT_ALLOW;
260
546
 
261
- latch(root, session);
262
- process.stdout.write(`${JSON.stringify({ decision: 'warn', reason: nudgeReason(seen) })}\n`);
547
+ latch(root, session, finding.klass, state);
548
+ process.stdout.write(`${JSON.stringify({ decision: 'warn', reason: reasonFor(finding) })}\n`);
263
549
  return EXIT_WARN;
264
550
  }
265
551
 
@@ -69,6 +69,7 @@ import { main as delegationNudgeMain } from './delegation_nudge_hook.js';
69
69
  import { main as skillRouteMain } from './skill_route_hook.js';
70
70
  import { main as ruleInjectMain } from './rule_inject_hook.js';
71
71
  import { main as endReviewNudgeMain } from './end_review_nudge_hook.js';
72
+ import { main as reviewBaselineMain } from './review_baseline_hook.js';
72
73
  import { main as turnEndGateMain } from './turn_end_gate_hook.js';
73
74
  import { main as editShapeMain } from './edit_shape_hook.js';
74
75
  import { main as commentDisciplineMain } from './comment_discipline_hook.js';
@@ -132,6 +133,7 @@ export const CONCERN_REGISTRY: Readonly<Record<string, ConcernMain>> = {
132
133
  'src/scripts/hooks/skill_route_hook.ts': skillRouteMain as ConcernMain,
133
134
  'src/scripts/hooks/rule_inject_hook.ts': ruleInjectMain as ConcernMain,
134
135
  'src/scripts/hooks/end_review_nudge_hook.ts': endReviewNudgeMain as ConcernMain,
136
+ 'src/scripts/hooks/review_baseline_hook.ts': reviewBaselineMain as ConcernMain,
135
137
  'src/scripts/hooks/turn_end_gate_hook.ts': turnEndGateMain as ConcernMain,
136
138
  'src/scripts/hooks/edit_shape_hook.ts': editShapeMain as ConcernMain,
137
139
  'src/scripts/hooks/comment_discipline_hook.ts': commentDisciplineMain as ConcernMain,