@event4u/agent-config 14.22.0 → 15.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 (557) 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 +333 -356
  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 +48 -39
  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 +1 -1
  60. package/dist/agent-src/commands/roadmap/materialize.md +2 -2
  61. package/dist/agent-src/commands/roadmap/next.md +9 -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 +1 -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 +13 -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 +36 -25
  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/scripts/archive_completed_roadmaps.ts +106 -4
  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-intelligence/SKILL.md +57 -1
  260. package/dist/agent-src/skills/code-refactoring/SKILL.md +3 -3
  261. package/dist/agent-src/skills/code-review/SKILL.md +3 -3
  262. package/dist/agent-src/skills/command-writing/SKILL.md +3 -3
  263. package/dist/agent-src/skills/comp-banding/SKILL.md +1 -1
  264. package/dist/agent-src/skills/competitive-moat-analysis/SKILL.md +1 -1
  265. package/dist/agent-src/skills/competitive-positioning/SKILL.md +2 -2
  266. package/dist/agent-src/skills/complexity-first-planning/SKILL.md +1 -1
  267. package/dist/agent-src/skills/condense-memory/SKILL.md +1 -1
  268. package/dist/agent-src/skills/content-funnel-design/SKILL.md +2 -2
  269. package/dist/agent-src/skills/contracts-cognition/SKILL.md +1 -1
  270. package/dist/agent-src/skills/copilot-agents-optimization/SKILL.md +2 -2
  271. package/dist/agent-src/skills/corpus-grounding/SKILL.md +2 -2
  272. package/dist/agent-src/skills/customer-research/SKILL.md +2 -2
  273. package/dist/agent-src/skills/dashboard-design/SKILL.md +1 -1
  274. package/dist/agent-src/skills/data-handling-judgment/SKILL.md +1 -1
  275. package/dist/agent-src/skills/deal-qualification-meddic/SKILL.md +2 -2
  276. package/dist/agent-src/skills/decision-record/SKILL.md +3 -3
  277. package/dist/agent-src/skills/decision-review/SKILL.md +8 -8
  278. package/dist/agent-src/skills/deep-reading-analyst/SKILL.md +22 -22
  279. package/dist/agent-src/skills/design-intelligence/SKILL.md +4 -4
  280. package/dist/agent-src/skills/design-intelligence/references/context-and-registers.md +2 -2
  281. package/dist/agent-src/skills/design-review/SKILL.md +4 -4
  282. package/dist/agent-src/skills/design-system-capture/references/design-system-json.md +20 -1
  283. package/dist/agent-src/skills/design-tokens/SKILL.md +17 -2
  284. package/dist/agent-src/skills/design-variations/SKILL.md +2 -2
  285. package/dist/agent-src/skills/developer-like-execution/SKILL.md +2 -2
  286. package/dist/agent-src/skills/discovery-interview/SKILL.md +2 -2
  287. package/dist/agent-src/skills/doc-coauthoring/SKILL.md +3 -3
  288. package/dist/agent-src/skills/editorial-calendar/SKILL.md +2 -2
  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/git-workflow/references/push-closes-its-loop.md +9 -0
  305. package/dist/agent-src/skills/gtm-launch/SKILL.md +2 -2
  306. package/dist/agent-src/skills/hiring-loop-design/SKILL.md +1 -1
  307. package/dist/agent-src/skills/html-deck/SKILL.md +5 -5
  308. package/dist/agent-src/skills/humanizer/SKILL.md +1 -1
  309. package/dist/agent-src/skills/humanizer/data/patterns.md +1 -1
  310. package/dist/agent-src/skills/iconography/SKILL.md +3 -3
  311. package/dist/agent-src/skills/judge-synthesis/SKILL.md +1 -1
  312. package/dist/agent-src/skills/laravel-api-endpoint/SKILL.md +2 -2
  313. package/dist/agent-src/skills/launch-readiness/SKILL.md +3 -3
  314. package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +6 -6
  315. package/dist/agent-src/skills/livewire/SKILL.md +1 -1
  316. package/dist/agent-src/skills/market-entry-analysis/SKILL.md +1 -1
  317. package/dist/agent-src/skills/mcp-builder/SKILL.md +1 -1
  318. package/dist/agent-src/skills/memory-consolidation/SKILL.md +3 -3
  319. package/dist/agent-src/skills/messaging-architecture/SKILL.md +2 -2
  320. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +1 -1
  321. package/dist/agent-src/skills/onboarding-design/SKILL.md +2 -2
  322. package/dist/agent-src/skills/onboarding-program/SKILL.md +1 -1
  323. package/dist/agent-src/skills/one-on-one-cadence/SKILL.md +1 -1
  324. package/dist/agent-src/skills/org-design/SKILL.md +1 -1
  325. package/dist/agent-src/skills/overbuild-review-lens/SKILL.md +3 -3
  326. package/dist/agent-src/skills/override-management/SKILL.md +1 -1
  327. package/dist/agent-src/skills/perf-feedback-craft/SKILL.md +1 -1
  328. package/dist/agent-src/skills/persona-writing/SKILL.md +1 -1
  329. package/dist/agent-src/skills/php-coder/SKILL.md +1 -1
  330. package/dist/agent-src/skills/pipeline-strategy/SKILL.md +2 -2
  331. package/dist/agent-src/skills/playwright-testing/SKILL.md +3 -3
  332. package/dist/agent-src/skills/po-discovery/SKILL.md +1 -1
  333. package/dist/agent-src/skills/positioning-strategy/SKILL.md +2 -2
  334. package/dist/agent-src/skills/privacy-review/SKILL.md +1 -1
  335. package/dist/agent-src/skills/prompt-optimizer/SKILL.md +3 -3
  336. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +1 -1
  337. package/dist/agent-src/skills/reasoning-orchestrator/SKILL.md +2 -2
  338. package/dist/agent-src/skills/receiving-code-review/SKILL.md +1 -1
  339. package/dist/agent-src/skills/refine-ticket/SKILL.md +2 -2
  340. package/dist/agent-src/skills/release-comms/SKILL.md +2 -2
  341. package/dist/agent-src/skills/retention-loops/SKILL.md +2 -2
  342. package/dist/agent-src/skills/review-routing/SKILL.md +2 -2
  343. package/dist/agent-src/skills/roadmap-management/SKILL.md +1 -1
  344. package/dist/agent-src/skills/roadmap-management/references/archival.md +1 -1
  345. package/dist/agent-src/skills/roadmap-writing/SKILL.md +5 -5
  346. package/dist/agent-src/skills/rule-writing/SKILL.md +6 -6
  347. package/dist/agent-src/skills/runway-cognition/SKILL.md +2 -2
  348. package/dist/agent-src/skills/scenario-modeling/SKILL.md +2 -2
  349. package/dist/agent-src/skills/skill-writing/SKILL.md +2 -2
  350. package/dist/agent-src/skills/skill-writing/references/procedure.md +1 -1
  351. package/dist/agent-src/skills/skill-writing/references/section-patterns.md +3 -3
  352. package/dist/agent-src/skills/spreadsheet-authoring/SKILL.md +1 -1
  353. package/dist/agent-src/skills/stakeholder-tradeoff/SKILL.md +3 -3
  354. package/dist/agent-src/skills/subagent-orchestration/SKILL.md +1 -1
  355. package/dist/agent-src/skills/supply-chain-intake/SKILL.md +1 -1
  356. package/dist/agent-src/skills/systematic-debugging/SKILL.md +2 -2
  357. package/dist/agent-src/skills/tailwind-engineer/SKILL.md +60 -4
  358. package/dist/agent-src/skills/throughput-vs-morale-tradeoff/SKILL.md +1 -1
  359. package/dist/agent-src/skills/token-optimizer/SKILL.md +1 -1
  360. package/dist/agent-src/skills/typography-system/SKILL.md +2 -2
  361. package/dist/agent-src/skills/ui-component-architect/SKILL.md +28 -8
  362. package/dist/agent-src/skills/unit-economics-modeling/SKILL.md +2 -2
  363. package/dist/agent-src/skills/upstream-contribute/SKILL.md +1 -1
  364. package/dist/agent-src/skills/validate-feature-fit/SKILL.md +2 -2
  365. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +2 -2
  366. package/dist/agent-src/skills/vision-articulation/SKILL.md +1 -1
  367. package/dist/agent-src/skills/voc-extract/SKILL.md +2 -2
  368. package/dist/agent-src/skills/voice-and-tone-design/SKILL.md +2 -2
  369. package/dist/agent-src/skills/wireframe/SKILL.md +1 -1
  370. package/dist/agent-src/skills/workspace-link/SKILL.md +1 -1
  371. package/dist/agent-src/templates/agent-settings.md +6 -6
  372. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  373. package/dist/agent-src/templates/contexts/knowledge-pages.md +2 -3
  374. package/dist/agent-src/templates/copilot-instructions.md +1 -1
  375. package/dist/agent-src/templates/roadmaps.md +1 -1
  376. package/dist/agent-src/templates/scripts/README.md +2 -2
  377. package/dist/agent-src/user-types/_template/user-type.md +1 -1
  378. package/dist/cli/registry.js +1 -1
  379. package/dist/cli-delegate/archive_completed_roadmaps.js +52 -4
  380. package/dist/cli-delegate/check_update_banner.js +12 -1
  381. package/dist/cli-delegate/{chunk-TGIPZBCW.js → chunk-2KKXJW25.js} +22 -8
  382. package/dist/cli-delegate/{chunk-NLP54U3J.js → chunk-2XY7ILBT.js} +13 -1
  383. package/dist/cli-delegate/{chunk-4FS4WRXP.js → chunk-3FKR64R5.js} +34 -6
  384. package/dist/cli-delegate/{chunk-J3RFNKG4.js → chunk-55ACLDUE.js} +2 -2
  385. package/dist/cli-delegate/{chunk-PKOBQADP.js → chunk-57PN4GYJ.js} +1 -1
  386. package/dist/cli-delegate/{chunk-BIXEDQPZ.js → chunk-AK6HODNQ.js} +4 -4
  387. package/dist/cli-delegate/{chunk-2FTMENJL.js → chunk-GYC3VRYN.js} +1 -1
  388. package/dist/cli-delegate/{chunk-LWTYTX6F.js → chunk-HZ52BRGG.js} +24 -18
  389. package/dist/cli-delegate/{chunk-6RJA2F5A.js → chunk-IVBPRCQO.js} +1 -1
  390. package/dist/cli-delegate/{chunk-I6RHFQEG.js → chunk-YUM5KURG.js} +17 -1
  391. package/dist/cli-delegate/cmd_analyze_session.js +1 -1
  392. package/dist/cli-delegate/cmd_brand_status.js +1 -1
  393. package/dist/cli-delegate/cmd_conformance.js +3 -3
  394. package/dist/cli-delegate/cmd_doctor.js +3 -3
  395. package/dist/cli-delegate/cmd_explain.js +2 -2
  396. package/dist/cli-delegate/cmd_export.js +4 -4
  397. package/dist/cli-delegate/cmd_handoff.js +24 -16
  398. package/dist/cli-delegate/cmd_mcp_available.js +1 -1
  399. package/dist/cli-delegate/cmd_memory_get.js +1 -1
  400. package/dist/cli-delegate/cmd_migrate.js +2 -2
  401. package/dist/cli-delegate/cmd_packs_active.js +2 -2
  402. package/dist/cli-delegate/cmd_prune.js +4 -4
  403. package/dist/cli-delegate/cmd_route_audit.js +3 -3
  404. package/dist/cli-delegate/cmd_route_explain.js +1 -1
  405. package/dist/cli-delegate/cmd_session_recycle.js +4 -14
  406. package/dist/cli-delegate/cmd_settings_get.js +15 -9
  407. package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
  408. package/dist/cli-delegate/cmd_settings_set.js +41 -11
  409. package/dist/cli-delegate/cmd_sync.js +4 -4
  410. package/dist/cli-delegate/cmd_uninstall.js +4 -4
  411. package/dist/cli-delegate/cmd_update.js +1 -1
  412. package/dist/cli-delegate/cmd_upgrade.js +1 -1
  413. package/dist/cli-delegate/cmd_validate.js +4 -4
  414. package/dist/cli-delegate/cmd_versions.js +1 -1
  415. package/dist/discovery/deprecation-report.md +1 -1
  416. package/dist/discovery/discovery-manifest.json +27 -80
  417. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  418. package/dist/discovery/discovery-manifest.summary.md +3 -3
  419. package/dist/discovery/dormancy-report.md +1 -1
  420. package/dist/discovery/orphan-report.md +1 -1
  421. package/dist/discovery/packs.json +5 -7
  422. package/dist/discovery/trust-report.md +2 -2
  423. package/dist/discovery/workspaces.json +4 -6
  424. package/dist/hooks/dispatch.js +9249 -8981
  425. package/dist/install/install.mjs +47 -8
  426. package/dist/mcp/registry-manifest.json +3 -3
  427. package/dist/mcp/server.json +2 -2
  428. package/dist/mcp/server.mjs +5496 -2400
  429. package/dist/router.json +1 -1
  430. package/dist/scripts/_lib/agent_settings.js +73 -0
  431. package/dist/scripts/_lib/agent_src.js +20 -0
  432. package/dist/scripts/_lib/guidelines_lane.js +158 -0
  433. package/dist/scripts/_lib/lean_projection_mode.js +108 -0
  434. package/dist/scripts/_lib/router_match.js +243 -0
  435. package/dist/scripts/_lib/rule_injection.js +216 -0
  436. package/dist/scripts/condense.js +22 -25
  437. package/dist/scripts/project_thin_rules.js +139 -19
  438. package/dist/server/io/yamlIO.js +125 -17
  439. package/dist/server/schemas/settings.js +32 -5
  440. package/dist/shared/settingsSurface.js +6 -1
  441. package/docs/MIGRATION.md +56 -0
  442. package/docs/contracts/settings-classes.md +48 -7
  443. package/docs/guidelines/abstraction-thresholds.md +35 -0
  444. package/docs/guidelines/agent-infra/active-remediation-mechanics.md +3 -3
  445. package/docs/guidelines/agent-infra/false-green.md +2 -2
  446. package/docs/guidelines/agent-infra/notes-horizon-mechanics.md +90 -0
  447. package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
  448. package/docs/guidelines/agent-infra/skill-quality-checklist.md +1 -1
  449. package/docs/guidelines/design-fidelity-mechanics.md +4 -0
  450. package/docs/guidelines/design-fidelity-routing.md +78 -0
  451. package/docs/guidelines/design-reconciliation.md +172 -0
  452. package/docs/guidelines/gtm-handoff.md +2 -2
  453. package/docs/guidelines/wing4-handoff.md +2 -2
  454. package/llms.txt +1 -1
  455. package/package.json +7 -3
  456. package/src/agent-src/scripts/archive_completed_roadmaps.ts +106 -4
  457. package/src/config/agent-settings.template.yml +94 -1
  458. package/src/config/ci-local-parity.yml +34 -0
  459. package/src/config/continuity-surface.json +8 -29
  460. package/src/config/evaluator-budgets.json +4 -4
  461. package/src/config/gate-coverage.yml +31 -8
  462. package/src/config/gate-reachability-exemptions.json +1 -0
  463. package/src/config/gate-violation-baselines.json +3 -3
  464. package/src/config/hook-token-budget.json +8 -7
  465. package/src/config/host-injection-effect.json +2 -2
  466. package/src/config/pack-size-budget.json +55 -4
  467. package/src/config/packed-binary-manifest.json +1 -1
  468. package/src/config/platform-anchor.json +47 -0
  469. package/src/config/preamble-payload-budget.json +2 -3
  470. package/src/config/publish-surface.json +4 -2
  471. package/src/config/ratification-policy.json +7 -0
  472. package/src/config/routing-coverage-seed.json +9 -2
  473. package/src/config/rule-stub-ceilings.json +16 -9
  474. package/src/scripts/_cli/cmd_session_recycle.ts +2 -25
  475. package/src/scripts/_cli/cmd_settings_get.ts +22 -7
  476. package/src/scripts/_cli/handoff_sessions.ts +14 -44
  477. package/src/scripts/_lib/agent_settings.ts +85 -0
  478. package/src/scripts/_lib/agent_src.ts +21 -0
  479. package/src/scripts/_lib/artifact_maturity.ts +242 -0
  480. package/src/scripts/_lib/conformance_report.ts +403 -0
  481. package/src/scripts/_lib/continuity_slot.ts +295 -0
  482. package/src/scripts/_lib/continuity_writer.ts +312 -0
  483. package/src/scripts/_lib/design_system_import.ts +20 -0
  484. package/src/scripts/_lib/design_tolerance.ts +281 -0
  485. package/src/scripts/_lib/guidelines_lane.ts +164 -0
  486. package/src/scripts/_lib/hook_settings.ts +85 -0
  487. package/src/scripts/_lib/lean_projection_mode.ts +127 -0
  488. package/src/scripts/_lib/obligation_frequency.ts +2 -3
  489. package/src/scripts/_lib/packed_binary_predicate.ts +37 -0
  490. package/src/scripts/_lib/platform_anchor.ts +1053 -0
  491. package/src/scripts/_lib/ratification_artifact.ts +278 -0
  492. package/src/scripts/_lib/recycle_envelope_paths.ts +109 -21
  493. package/src/scripts/_lib/regression_neighbourhood.ts +159 -22
  494. package/src/scripts/_lib/security_lint.ts +23 -2
  495. package/src/scripts/_lib/self_repair.ts +21 -0
  496. package/src/scripts/_lib/session_eol.ts +44 -0
  497. package/src/scripts/_lib/session_index_trust.ts +387 -0
  498. package/src/scripts/_lib/standing_bound_ratchet.ts +220 -0
  499. package/src/scripts/_lib/tolerance_shadow.ts +177 -0
  500. package/src/scripts/_lib/vendored_grammar_upstream.ts +280 -0
  501. package/src/scripts/ai_council/redact_low_impact_entry.ts +8 -0
  502. package/src/scripts/audit_mcp_tools.ts +69 -25
  503. package/src/scripts/autonomy_friction_traffic.ts +379 -0
  504. package/src/scripts/build_mcp_catalog.ts +24 -1
  505. package/src/scripts/check_host_tree_parity.ts +291 -0
  506. package/src/scripts/check_kernel_edit_ratified.ts +462 -0
  507. package/src/scripts/check_loss_class_declared.ts +793 -46
  508. package/src/scripts/check_platform_anchor.ts +390 -0
  509. package/src/scripts/check_preamble_payload_budget.ts +424 -7
  510. package/src/scripts/check_projected_rule_routes.ts +395 -0
  511. package/src/scripts/check_rule_projection_integrity.ts +102 -2
  512. package/src/scripts/ci_settle.ts +205 -5
  513. package/src/scripts/code_graph/build.ts +79 -0
  514. package/src/scripts/code_graph/cli.ts +264 -7
  515. package/src/scripts/code_graph/detect.ts +38 -0
  516. package/src/scripts/code_graph/query.ts +25 -2
  517. package/src/scripts/code_graph/sqlite_store.ts +16 -1
  518. package/src/scripts/code_graph/types.ts +52 -3
  519. package/src/scripts/code_graph/validate.ts +3 -1
  520. package/src/scripts/code_graph/verbs.ts +590 -0
  521. package/src/scripts/condense.ts +22 -26
  522. package/src/scripts/generate_host_cost_table.ts +354 -0
  523. package/src/scripts/handoff_context_hook.ts +39 -1
  524. package/src/scripts/hook_manifest.json +1 -1
  525. package/src/scripts/hook_manifest.yaml +59 -28
  526. package/src/scripts/hooks/block_speaking_inbox_dir.ts +182 -16
  527. package/src/scripts/hooks/category_a.ts +1 -1
  528. package/src/scripts/hooks/chain_nudge_hook.ts +311 -25
  529. package/src/scripts/hooks/code_graph_context_hook.ts +7 -18
  530. package/src/scripts/hooks/push_settle_hook.ts +3 -2
  531. package/src/scripts/hooks/rule_inject_hook.ts +107 -20
  532. package/src/scripts/hooks/session_eol_hook.ts +177 -145
  533. package/src/scripts/hooks/source_first_gate_hook.ts +12 -0
  534. package/src/scripts/hooks/ui_route_nudge_hook.ts +52 -15
  535. package/src/scripts/hot_context_hook.ts +103 -408
  536. package/src/scripts/lint_evidence_artifacts.ts +1 -0
  537. package/src/scripts/lint_knowledge_scale.ts +0 -26
  538. package/src/scripts/lint_roadmap_blockers.ts +164 -1
  539. package/src/scripts/mcp_server/consumer_tool_catalog.json +152 -2
  540. package/src/scripts/mcp_server/graph_tools.ts +294 -0
  541. package/src/scripts/mcp_server/path_util.ts +31 -0
  542. package/src/scripts/mcp_server/tool_catalog_source.ts +7 -1
  543. package/src/scripts/mcp_server/tools.ts +3 -13
  544. package/src/scripts/memory_lookup.ts +9 -9
  545. package/src/scripts/model_rule_injection.ts +61 -4
  546. package/src/scripts/project_thin_rules.ts +149 -16
  547. package/src/scripts/report_standing_payload_by_host.ts +650 -0
  548. package/src/scripts/schemas/agent-settings.schema.json +7 -1
  549. package/src/scripts/session_memory_index.ts +86 -8
  550. package/src/scripts/sync_agent_settings.ts +270 -10
  551. package/src/server/io/yamlIO.ts +127 -17
  552. package/src/server/schemas/settings.ts +45 -6
  553. package/src/shared/settingsSurface.ts +13 -2
  554. package/src/templates/compact-instructions.md +8 -3
  555. package/src/vendor/grammars/README.md +27 -2
  556. package/dist/agent-src/commands/chat-history/import.md +0 -170
  557. package/dist/agent-src/commands/chat-history.md +0 -63
@@ -19,7 +19,7 @@
19
19
  * `.augment/` projections.
20
20
  *
21
21
  * NOTE (faithful literal): the thin-entry pointer keeps the verbatim
22
- * `Body: [`{rule_id}`](../../.agent-src.uncondensed/rules/{rule_id}.md)`
22
+ * `Body: [`{rule_id}`](../../dist/agent-src/rules/{rule_id}.md)`
23
23
  * Markdown link from the retired Python implementation. The same-basename `.py` twin
24
24
  * carries that literal, so the ADR-051 legacy-path guard exempts this `.ts`
25
25
  * file by twin-parity.
@@ -34,6 +34,7 @@ import * as fs from 'node:fs';
34
34
  import * as path from 'node:path';
35
35
  import process from 'node:process';
36
36
  import { fileURLToPath, pathToFileURL } from 'node:url';
37
+ import { pathOnlyRuleIds, triggerlessRuleIds, } from './_lib/rule_injection.js';
37
38
  import * as token_count from './_lib/token_count.js';
38
39
  const _HERE = fileURLToPath(import.meta.url);
39
40
  // REPO_ROOT = Path(__file__).resolve().parent.parent.parent — three dirs up
@@ -72,21 +73,85 @@ export function kernel_ids() {
72
73
  * visible instead of being absorbed into the pointer count
73
74
  * (road-to-trigger-delivered-rule-bodies 1.3).
74
75
  */
76
+ /**
77
+ * Rules whose ONLY triggers are path-shaped — reachable from `pre_tool_use`
78
+ * and from no other slot (road-to-delivery-for-every-host 3.2).
79
+ *
80
+ * They must never be thinned while the delivery concern is NOT bound on
81
+ * `pre_tool_use`, because a stub plus a slot nobody listens on is a rule that
82
+ * reaches the model at no scope at all. This is the same failure the
83
+ * `no_trigger_ids` exemption prevents, one step out: there the rule has nothing
84
+ * to match on, here it has nothing to match ON.
85
+ *
86
+ * Stated as a PROPERTY rather than a list of ids. If the concern is ever bound
87
+ * on `pre_tool_use` again, this exemption is what should be reconsidered — not
88
+ * three names someone has to remember.
89
+ *
90
+ * WHAT THIS EXEMPTION DOES **NOT** COVER — recorded 2026-09-08, R2 finding 1,
91
+ * because the silence read as coverage. The predicate is `every` trigger
92
+ * path-shaped. A rule with BOTH path and non-path triggers is therefore THINNED,
93
+ * and its path-shaped half then has no carrier at all: the stub carries no
94
+ * frontmatter (`condense.ts` writes it with `_writeText`, bypassing
95
+ * `_emit_claude_rule`'s host-native `paths:` key), `pre_tool_use` lost the
96
+ * binding under owner ruling E2, and `user_prompt_submit` never populates
97
+ * `openFiles`. Measured over the current `dist/router.json`: **18 such rules**,
98
+ * all non-kernel and all thinned — augment-edit-discipline, design-fidelity,
99
+ * doc-screenshot-hygiene, domain-adoption-policy,
100
+ * framework-neutrality-in-generic-skills, image-likeness-and-rights,
101
+ * laravel-translations, lethal-trifecta-guard, linked-projects-onboarding-gate,
102
+ * low-impact-corpus-privacy-floor, markdown-safe-codeblocks, onboarding-gate,
103
+ * persona-governance, php-coding, provider-lifecycle-discipline,
104
+ * roadmap-ci-steps-policy, roadmap-progress-sync, settings-ask-protocol.
105
+ *
106
+ * They do NOT reach the model at no scope: every non-path route
107
+ * (keyword / phrase / command) still delivers the body through the concern, and
108
+ * on `claude-code` they never had a separate host-native path route to lose —
109
+ * `_claude_paths_plan` emits no `paths:` for a mixed-trigger rule on purpose, so
110
+ * under `eager-all` they loaded UNCONDITIONALLY. What is lost is the difference
111
+ * between unconditional and prompt-triggered: a session that touches a matching
112
+ * file and says nothing that matches gets nothing.
113
+ *
114
+ * The labelled corpus cannot see this and the endpoint says so rather than
115
+ * implying otherwise — `model_rule_injection --endpoints` (b) now publishes the
116
+ * shipped `user_prompt_submit` reach beside the pre-registered reading, and
117
+ * every one of these 18 has at least one prompt-matching positive, so none
118
+ * appears in its "reachable only via a path trigger" column.
119
+ *
120
+ * WHY THIS IS NOT WIDENED TO `some` HERE. Measured: exempting all 18 moves the
121
+ * thin rule layer 23,592 -> 39,921 GPT tok (+16,329, +69 %), which is a budget
122
+ * move of a magnitude no agent may take, and it would erase most of the saving
123
+ * the flip is licensed on. Restoring a path route needs either that exemption
124
+ * under a re-anchored baseline or a `pre_tool_use` binding under a raised slot
125
+ * cap — both owner-reserved, so the closure is tracked rather than taken here.
126
+ * ADR-267's Consequences section names the receiver.
127
+ */
128
+ /**
129
+ * ONE spelling of the router-derived sets, shared with the injector (R2
130
+ * finding 11).
131
+ *
132
+ * `path_only_ids` and `no_trigger_ids` were each a second, hand-rolled
133
+ * implementation of `_lib/rule_injection.ts::pathOnlyRuleIds` /
134
+ * `triggerlessRuleIds` — verified identical over the current router at the time
135
+ * (symmetric difference empty), so drift risk rather than a live defect. It is
136
+ * exactly the hazard `THIN_ENTRY_MARKER`'s own comment argues against one
137
+ * screen below ("a gate that re-spelled this string would drift from the writer
138
+ * silently"), and the two consumers here are the PROJECTOR's exemption set and
139
+ * the INJECTOR's reachability set: they must not be able to disagree about which
140
+ * rules the delivery path can reach.
141
+ *
142
+ * The finding named `path_only_ids`. The defect-pattern sweep found the SECOND
143
+ * instance one function down — `no_trigger_ids` against `triggerlessRuleIds` —
144
+ * and it is delegated in the same change. Count: 2 of 2 duplicated
145
+ * router-derived sets in this file, 0 remaining.
146
+ */
147
+ function _router() {
148
+ return JSON.parse(fs.readFileSync(ROUTER, 'utf-8'));
149
+ }
150
+ export function path_only_ids() {
151
+ return pathOnlyRuleIds(_router());
152
+ }
75
153
  export function no_trigger_ids() {
76
- const data = JSON.parse(fs.readFileSync(ROUTER, 'utf-8'));
77
- const out = new Set();
78
- for (const tier of ['tier_1', 'tier_2']) {
79
- const entries = data[tier];
80
- if (!Array.isArray(entries))
81
- continue;
82
- for (const e of entries) {
83
- const obj = e;
84
- const t = obj.triggers;
85
- if (!Array.isArray(t) || t.length === 0)
86
- out.add(String(obj.id));
87
- }
88
- }
89
- return out;
154
+ return new Set(triggerlessRuleIds(_router()));
90
155
  }
91
156
  /**
92
157
  * id → workspaces for every non-kernel router entry (router.json schema v2,
@@ -179,6 +244,42 @@ function _trigger_hint(fm) {
179
244
  function _title(s) {
180
245
  return s.replace(/[A-Za-z]+/g, (w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase());
181
246
  }
247
+ /**
248
+ * The marker that makes a projected entry recognisable as a stub.
249
+ *
250
+ * Exported so the WRITER and every DETECTOR share one definition. A gate that
251
+ * re-spelled this string would drift from the writer silently, and the failure
252
+ * would be invisible in exactly the direction that matters: a stub the gate
253
+ * fails to recognise reads as a complete rule body.
254
+ */
255
+ export const THIN_ENTRY_MARKER = '> Routed rule — load the body on trigger-match.';
256
+ /** Is this projected entry a pointer stub rather than a rule body? */
257
+ export function is_thin_entry(text) {
258
+ return text.includes(THIN_ENTRY_MARKER);
259
+ }
260
+ /**
261
+ * Where a stub tells a reader the body actually is.
262
+ *
263
+ * FIXED 2026-09-07: this pointed into the uncondensed source tree ADR-051
264
+ * retired — the literal path is deliberately NOT reproduced here, because
265
+ * `check_no_uncondensed_refs` matches the string and cannot tell a repair
266
+ * record from a live reference; `git log -S` on this file finds the old value.
267
+ * It exists in no checkout, so EVERY stub's fallback pointer
268
+ * resolved to nothing — invisible under `delivery`, where the hook loads the
269
+ * body from `dist/agent-src/rules` and never follows this link, and total under
270
+ * `thin`, where the pointer is the only path to the body there is.
271
+ *
272
+ * KNOWN LIMIT, stated rather than discovered later: one relative prefix cannot
273
+ * be right for every tree, because they sit at different depths — `.claude/rules`
274
+ * and `.cursor/rules` are two levels below the repo root and `.clinerules` is
275
+ * one. `../../` is correct for the first two, which are the only trees the
276
+ * shipped `lean_projection.hosts` default can thin. A stub in `.clinerules`
277
+ * needs an operator to have added `cline` to that list, and its pointer is off
278
+ * by one level. That is strictly better than the previous state, where the
279
+ * pointer was dead in all three, and it is recorded here so the remaining case
280
+ * is a known limit rather than a surprise.
281
+ */
282
+ const BODY_LINK_PREFIX = '../../dist/agent-src/rules/';
182
283
  /** Build the minimal progressive-disclosure pointer for a non-kernel rule. */
183
284
  export function thin_entry(rule_id, text) {
184
285
  const [fm] = split_frontmatter(text);
@@ -187,13 +288,25 @@ export function thin_entry(rule_id, text) {
187
288
  const title = _title(rule_id.replace(/-/g, ' '));
188
289
  const fires = hint ? ` Fires on: ${hint}.` : '';
189
290
  return (`## ${title}\n` +
190
- `> Routed rule — load the body on trigger-match.${fires} ${desc} ` +
191
- `Body: [\`${rule_id}\`](../../.agent-src.uncondensed/rules/${rule_id}.md)\n`);
291
+ `${THIN_ENTRY_MARKER}${fires} ${desc} ` +
292
+ `Body: [\`${rule_id}\`](${BODY_LINK_PREFIX}${rule_id}.md)\n`);
192
293
  }
193
294
  /** Map {filename: thin_or_full_text} for every rule. Kernel stays full. */
194
- export function build_thin(rules_dir = RULES_SOURCE, scope = null) {
295
+ export function build_thin(rules_dir = RULES_SOURCE, scope = null,
296
+ /**
297
+ * Optional sink for the D3 diagnostic
298
+ * (road-to-delivery-for-every-host 2.2).
299
+ *
300
+ * An `auto` rule the router gives NO trigger is already kept full-bodied by
301
+ * `noTrigger` below, which is the substantive protection and predates this
302
+ * roadmap. What did not exist is any way to SEE it happen: the rule is
303
+ * silently exempted, so an author who removes a rule's last trigger gets a
304
+ * silently eager rule and no signal. The line makes the exemption audible.
305
+ */
306
+ announce = null) {
195
307
  const kernel = kernel_ids();
196
308
  const noTrigger = no_trigger_ids();
309
+ const pathOnly = path_only_ids();
197
310
  const wsMap = scope !== null ? rule_workspaces_map() : new Map();
198
311
  const out = new Map();
199
312
  for (const p of _globSortedMd(rules_dir)) {
@@ -202,7 +315,14 @@ export function build_thin(rules_dir = RULES_SOURCE, scope = null) {
202
315
  if (!id_in_scope(stem, scope, kernel, wsMap, fm_workspaces(text))) {
203
316
  continue; // out of workspace scope — no body, no pointer line
204
317
  }
205
- const full = kernel.has(stem) || noTrigger.has(stem);
318
+ const full = kernel.has(stem) || noTrigger.has(stem) || pathOnly.has(stem);
319
+ if (announce !== null && noTrigger.has(stem) && !kernel.has(stem)) {
320
+ announce(`D3: trigger-less auto rule ${path.basename(p)} — kept full-bodied, never thinned`);
321
+ }
322
+ if (announce !== null && pathOnly.has(stem) && !kernel.has(stem) && !noTrigger.has(stem)) {
323
+ announce(`E2: path-only auto rule ${path.basename(p)} — kept full-bodied; its only triggers ` +
324
+ `are path-shaped and the delivery concern is not bound on pre_tool_use`);
325
+ }
206
326
  out.set(path.basename(p), full ? text : thin_entry(stem, text));
207
327
  }
208
328
  return out;
@@ -33,6 +33,24 @@ function formatScalar(value) {
33
33
  // Arrays / nested objects: dump inline. Form keeps depth ≤ 2 so this is rare.
34
34
  return yamlDump(value, { lineWidth: -1, flowLevel: 0 }).replace(/\n$/, '').trim();
35
35
  }
36
+ /**
37
+ * A NESTED mapping key, as both the presence probe and the insertion walk read
38
+ * one. Shared so the writer and its own existence-probe cannot drift apart —
39
+ * that drift is the shape this file has now hit four times.
40
+ *
41
+ * `-` is in the class because a dashed key is ordinary YAML (`first-name`,
42
+ * `dry-run`, `retry-count`) and `detectIndentWidth` already accepted one.
43
+ * While this pattern did not, `findScalarLine` could never find such a key:
44
+ * `mergeIntoTemplate` then wrote a bogus top-level `x.first-principles:` line
45
+ * beside the real nested one and the intended value was never written — a save
46
+ * that silently did nothing — and `upsertScalar` appended another child line on
47
+ * EVERY call, growing without bound until the file stopped parsing.
48
+ *
49
+ * `.` stays OUT, deliberately. A dotted key is the FLAT form, which
50
+ * `replaceFlatDottedKey` owns; letting this pattern match `a.b:` would make the
51
+ * nested probe claim a line that is one key literally named "a.b".
52
+ */
53
+ const NESTED_KEY_RE = /^([A-Za-z_][A-Za-z0-9_-]*)\s*:/;
36
54
  function flatten(value, prefix = []) {
37
55
  if (value === null || typeof value !== 'object' || Array.isArray(value)) {
38
56
  return [{ path: prefix, value }];
@@ -55,6 +73,25 @@ export function replaceScalar(template, dottedPath, value) {
55
73
  const sections = dottedPath.slice(0, -1);
56
74
  const key = dottedPath[dottedPath.length - 1];
57
75
  const lines = template.split('\n');
76
+ const at = findScalarLine(lines, sections, key);
77
+ if (at === -1)
78
+ return template;
79
+ const width = detectIndentWidth(lines);
80
+ lines[at] = `${' '.repeat(width * sections.length)}${key}: ${formatScalar(value)}`;
81
+ return lines.join('\n');
82
+ }
83
+ /**
84
+ * Index of the line holding the scalar at `sections`/`key`, or -1.
85
+ *
86
+ * Split out of `replaceScalar` so that "is this path present?" is answerable
87
+ * WITHOUT writing. `mergeIntoTemplate` used to infer presence from
88
+ * `replaceScalar` returning a changed string, which conflates "absent" with
89
+ * "present and already equal to the value being written" — under that test a
90
+ * no-op write reads as a miss and the caller appends a duplicate mapping key.
91
+ * A presence question answered by a mutation's side effect is the shape to
92
+ * look for here; the file already carries two earlier rounds of it.
93
+ */
94
+ function findScalarLine(lines, sections, key) {
58
95
  // The document's own width, the same read `upsertScalar` performs.
59
96
  //
60
97
  // R2 round 5, finding 1, and it is the second half of round 4's finding 7.
@@ -71,9 +108,7 @@ export function replaceScalar(template, dottedPath, value) {
71
108
  // A writer and its own existence-probe disagreeing about the format is the
72
109
  // shape to look for whenever one of a pair is taught something new.
73
110
  const width = detectIndentWidth(lines);
74
- const targetIndent = ' '.repeat(width * sections.length);
75
111
  const currentPath = new Array(sections.length).fill(null);
76
- const formatted = formatScalar(value);
77
112
  for (let i = 0; i < lines.length; i++) {
78
113
  const line = lines[i];
79
114
  if (line === undefined)
@@ -87,7 +122,7 @@ export function replaceScalar(template, dottedPath, value) {
87
122
  const level = indentLen / width;
88
123
  if (level > sections.length)
89
124
  continue;
90
- const m = /^([A-Za-z_][A-Za-z0-9_]*)\s*:/.exec(stripped);
125
+ const m = NESTED_KEY_RE.exec(stripped);
91
126
  if (!m)
92
127
  continue;
93
128
  const lineKey = m[1];
@@ -110,10 +145,9 @@ export function replaceScalar(template, dottedPath, value) {
110
145
  continue;
111
146
  if (lineKey !== key)
112
147
  continue;
113
- lines[i] = `${targetIndent}${key}: ${formatted}`;
114
- return lines.join('\n');
148
+ return i;
115
149
  }
116
- return template;
150
+ return -1;
117
151
  }
118
152
  /**
119
153
  * The indent width this document actually uses, or 2 when it has no nesting.
@@ -181,11 +215,19 @@ export function detectIndentWidth(lines) {
181
215
  export function upsertScalar(template, dottedPath, value) {
182
216
  if (dottedPath.length === 0)
183
217
  return template;
184
- const replaced = replaceScalar(template, dottedPath, value);
185
- if (replaced !== template)
186
- return replaced;
187
218
  const sections = dottedPath.slice(0, -1);
188
219
  const key = dottedPath[dottedPath.length - 1];
220
+ // Presence is asked, never inferred from the write changing the text. The
221
+ // string compare that used to stand here read "key already holds this
222
+ // value" as "key absent" and fell through to the append below — so saving
223
+ // the wizard's council page twice WITHOUT changing a toggle wrote a second
224
+ // `api_on_quota:` into the same block, over two `{ok: true}` responses, and
225
+ // left `.ai-council.yml` rejected by a strict parser. Third instance of one
226
+ // shape in this file; `findScalarLine` exists to end it, and a fix that
227
+ // taught only `mergeIntoTemplate` would have left the live path here.
228
+ if (findScalarLine(template.split('\n'), sections, key) !== -1) {
229
+ return replaceScalar(template, dottedPath, value);
230
+ }
189
231
  const formatted = formatScalar(value);
190
232
  const lines = template.split('\n');
191
233
  // The document's OWN indent width, not an assumed two.
@@ -229,7 +271,7 @@ export function upsertScalar(template, dottedPath, value) {
229
271
  const indentLen = line.length - line.trimStart().length;
230
272
  if (indentLen !== indent.length)
231
273
  continue;
232
- const m = /^([A-Za-z_][A-Za-z0-9_]*)\s*:/.exec(line.trim());
274
+ const m = NESTED_KEY_RE.exec(line.trim());
233
275
  if (m !== null && m[1] === want) {
234
276
  found = i;
235
277
  break;
@@ -271,23 +313,89 @@ export function upsertScalar(template, dottedPath, value) {
271
313
  lines.splice(insertAt, 0, ...block);
272
314
  return lines.join('\n');
273
315
  }
316
+ /**
317
+ * Rewrite an existing top-level `a.b.c: value` line — the FLAT form
318
+ * `mergeIntoTemplate` itself appends when a path has no template entry.
319
+ * Returns the template unchanged when no such line exists.
320
+ *
321
+ * `replaceScalar` cannot see this line: its key pattern is
322
+ * `[A-Za-z_][A-Za-z0-9_]*`, with no dot, so a path this module appended on
323
+ * one pass is invisible to the probe on the next and `mergeIntoTemplate`
324
+ * appends a SECOND copy. Two wizard saves therefore produce a file carrying
325
+ * duplicate mapping keys — a strict parser rejects it outright, which is what
326
+ * wedged `task release`: its `sync` step exits 2 with "Map keys must be
327
+ * unique" before the release does any git work.
328
+ *
329
+ * A pre-existing duplicate run is COLLAPSED, not merely updated: the first
330
+ * occurrence keeps its position and takes the new value, every later one is
331
+ * dropped. Collapsing is value-neutral — a lenient reader already resolved
332
+ * such a run last-wins — and it is the only way a file corrupted by the old
333
+ * behaviour becomes parseable again through the ordinary write path.
334
+ *
335
+ * Deliberately NOT folded into `replaceScalar`: `upsertScalar` calls that
336
+ * probe and documents the flat form as the WRONG shape for a nested key (a
337
+ * reader sees one key literally named "a.b"). Teaching the shared probe to
338
+ * match it would make `upsertScalar` write into that broken line instead of
339
+ * creating the nesting. The flat form is legitimate only here, where this
340
+ * function is the one that wrote it.
341
+ */
342
+ function replaceFlatDottedKey(template, dottedPath, value) {
343
+ if (dottedPath.length < 2)
344
+ return { found: false, body: template };
345
+ const flat = dottedPath.join('.');
346
+ const lines = template.split('\n');
347
+ const hits = [];
348
+ for (let i = 0; i < lines.length; i++) {
349
+ const line = lines[i];
350
+ if (line === undefined)
351
+ continue;
352
+ // Top level only — an indented `a.b:` is somebody else's child key.
353
+ if (line.length !== line.trimStart().length)
354
+ continue;
355
+ const m = /^([A-Za-z_][A-Za-z0-9_.-]*)\s*:/.exec(line);
356
+ if (m === null || m[1] !== flat)
357
+ continue;
358
+ hits.push(i);
359
+ }
360
+ if (hits.length === 0)
361
+ return { found: false, body: template };
362
+ lines[hits[0]] = `${flat}: ${formatScalar(value)}`;
363
+ // Drop the later copies back-to-front so the earlier indices stay valid.
364
+ for (let i = hits.length - 1; i >= 1; i--)
365
+ lines.splice(hits[i], 1);
366
+ return { found: true, body: lines.join('\n') };
367
+ }
274
368
  /**
275
369
  * Apply every leaf change from `newValues` to `templateBody`. Paths that
276
370
  * are not present in the template are appended at the end. Comments are
277
371
  * preserved for every key that already exists in the template.
372
+ *
373
+ * Idempotent: applying the same values twice yields the same document, so a
374
+ * second wizard save re-writes the flat block instead of duplicating it.
278
375
  */
279
376
  export function mergeIntoTemplate(templateBody, newValues) {
280
377
  let body = templateBody;
281
378
  const appended = [];
282
379
  for (const entry of flatten(newValues)) {
283
- const before = body;
284
- body = replaceScalar(body, entry.path, entry.value);
285
- if (body === before) {
286
- // Path is not in the template — append a flat key=value at EOF.
287
- // Form coverage is asserted by parity test, so this branch only
288
- // fires on hand-edited templates.
289
- appended.push(`${entry.path.join('.')}: ${formatScalar(entry.value)}`);
380
+ const sections = entry.path.slice(0, -1);
381
+ const leaf = entry.path[entry.path.length - 1];
382
+ // Presence is asked, never inferred from the write changing the text —
383
+ // see `findScalarLine`. Writing the value it already holds is a hit.
384
+ if (findScalarLine(body.split('\n'), sections, leaf) !== -1) {
385
+ body = replaceScalar(body, entry.path, entry.value);
386
+ continue;
387
+ }
388
+ // Not in the template's nested form. It may still be here as a flat
389
+ // dotted line this function appended on an earlier pass.
390
+ const flat = replaceFlatDottedKey(body, entry.path, entry.value);
391
+ if (flat.found) {
392
+ body = flat.body;
393
+ continue;
290
394
  }
395
+ // Genuinely absent — append a flat key=value at EOF. Form coverage is
396
+ // asserted by parity test, so this branch only fires on hand-edited
397
+ // templates.
398
+ appended.push(`${entry.path.join('.')}: ${formatScalar(entry.value)}`);
291
399
  }
292
400
  if (appended.length > 0) {
293
401
  if (!body.endsWith('\n'))
@@ -29,7 +29,8 @@ const confidenceBand = z.enum(['off', 'low', 'medium', 'high']);
29
29
  const onBlock = z.enum(['stop', 'ask', 'warn']);
30
30
  const onBlockFallback = z.enum(['stop', 'warn']);
31
31
  const modelAutoSwitch = z.enum(['auto', 'suggest', 'off']);
32
- const leanProjectionMode = z.enum(['eager-all', 'thin']);
32
+ const leanProjectionMode = z.enum(['eager-all', 'thin', 'delivery']);
33
+ const leanProjectionHost = z.enum(['claude-code', 'cursor', 'cline']);
33
34
  const projectionMode = z.enum(['legacy-all', 'scoped']);
34
35
  const memoryCadence = z.enum(['auto', 'always', 'never']);
35
36
  const projectAudience = z.enum(['self', 'internal', 'client', 'public']);
@@ -46,8 +47,16 @@ export const settingsSchema = z.object({
46
47
  rule_loading_tier: ruleLoadingTier.default('balanced').describe('Master switch for which rule tiers load and how cautiously the agent spends tokens. minimal = only the 9 kernel rules (cheapest, fewest guardrails). balanced = kernel + tier-1 (recommended default). full = kernel + tier-1 + tier-2 (most guardrails, highest token cost). custom = roll your own in agents/overrides/. LEGACY: superseded by discipline_profile — when that key is set it wins (mapping: minimal→off, balanced→essential, full→full).'),
47
48
  discipline_profile: disciplineProfile.optional().describe('The ONE runtime knob for the discipline-rule tier (successor of rule_loading_tier; council 2026-07-07). off = kernel only (~1x tokens). essential = kernel + the measured lift-carrying rules (~3.3x, keeps the weak-host discipline lift). full = everything (~11.7x, EXPERIMENTAL — residual lift over essential not established). auto = resolve per session against the evidence-gated NULL-lift disable-list in src/config/host-capabilities.yml (measured-null host → off, otherwise → essential). Optional and opt-in until the P1/P2 evidence gates pass (agents/roadmaps/road-to-discipline-profile-tiering.md); absent = legacy rule_loading_tier applies.'),
48
49
  lean_projection: z.object({
49
- mode: leanProjectionMode.default('eager-all').describe('How the per-tool projector emits the rule layer. eager-all = every rule body inlined into every projection (default, safe). thin = kernel rules full-bodied + non-kernel rules as router-resolved pointers (~45k GPT-tok lighter per session). EXPERIMENTAL: validate with the live A/B before flipping; one-flip revert to eager-all.'),
50
- }).default({ mode: 'eager-all' }),
50
+ mode: leanProjectionMode.default('eager-all').describe('How the per-tool projector emits the rule layer. eager-all = every rule body inlined into every projection (safe; what an ABSENT key still resolves to, per ADR-267 decision point 4). thin = kernel rules full-bodied + non-kernel rules as router-resolved pointers (~45k GPT-tok lighter per session), with no delivery mechanism. delivery = thin stubs PLUS the rule-inject hook concern, which delivers a body back on a trigger match; this is the value the SHIPPED TEMPLATE carries for Claude Code since ADR-267, and the activation charge for it is paid in src/config/hook-token-budget.json (user_prompt_submit slot sum 4,096 -> 16,384).'),
51
+ hosts: z.array(leanProjectionHost).default(['claude-code']).describe('Which hosts a thinning mode may thin (ADR-267). Absent resolves to [claude-code]. '
52
+ + 'Only the three hosts with a per-rule rule tree are accepted, and this enum is the '
53
+ + 'AUTHORING layer: an id outside it is a hard validation FAILURE here and under '
54
+ + 'validate_agent_settings, never a warning. resolveLeanProjectionHosts is the '
55
+ + 'READ-TIME backstop for a hand-edited .agent-settings.yml that passed neither, and '
56
+ + 'THERE the id is dropped with a warning (R2 finding 6 — the two layers answer '
57
+ + 'differently and neither said so). Every host outside this list receives exactly '
58
+ + 'what eager-all writes, asserted byte-for-byte by check_host_tree_parity.'),
59
+ }).default({ mode: 'eager-all', hosts: ['claude-code'] }),
51
60
  cost: z.object({
52
61
  budgets: z.object({
53
62
  daily: z.number().min(0).default(0).describe('Daily USD ceiling across all model calls. The agent warns at 50% / 75% / 90% and either stops or warns at 100% depending on cost.enforcement. Set 0 to disable the daily budget entirely.'),
@@ -92,7 +101,7 @@ export const settingsSchema = z.object({
92
101
  access_style: accessStyle.default('getters_setters').describe('How the agent writes Laravel Eloquent property access. getters_setters = explicit getName() / setName() methods (most refactor-safe). get_attribute = $model->getAttribute("name") (verbose but explicit). magic_properties = $model->name (idiomatic but harder to grep).'),
93
102
  }),
94
103
  chat_history: z.object({
95
- enabled: z.boolean().default(true).describe('Persist a structured log of every chat turn to .agent-config/chat-history/ so /chat-history:show, :import, and :learn can replay sessions. Turn off if you never want chat transcripts on disk.'),
104
+ enabled: z.boolean().default(true).describe('Persist a structured log of every chat turn to agents/runtime/.agent-chat-history (JSONL). Recording only — no command in this package replays a session from the file; it is a record on disk that a human or a later tool can read. Turn off if you never want chat transcripts on disk.'),
96
105
  frequency: chatFreq.default('per_turn').describe('How often the chat-history writer flushes to disk. per_turn = after every user / agent exchange (default, lowest data loss on crash). per_phase = at phase boundaries (cheaper I/O). per_tool = after every tool call (highest fidelity, noisiest log).'),
97
106
  text_limits: z.object({
98
107
  user: z.number().int().min(0).default(0).describe('Per-message character cap for user inputs in the chat-history log. 0 = log verbatim (default). Raise above 0 only if your prompts contain large pasted artefacts you do not want stored.'),
@@ -131,7 +140,21 @@ export const settingsSchema = z.object({
131
140
  }),
132
141
  design: z.object({
133
142
  fidelity_mode: fidelityMode.default('strict').describe('How strictly the agent must follow a user-provided prototype / mockup / design system (consumed by the design-fidelity rule). strict = build 1:1, every visible deviation needs confirmation; structural = structure locked, silent gaps fillable with a stated assumption; hard-floor = any deviation is never autonomous.'),
134
- }).default({ fidelity_mode: 'strict' }),
143
+ approximation: z
144
+ .object({
145
+ enabled: z.boolean().default(false).describe('Whether a value INSIDE the configured tolerance may be replaced by the project\'s own token without a per-value confirmation. Ships false. The distance from the artifact\'s value to the nearest project token is computed and REPORTED on every value row regardless of this switch — what it decides is whether the agent may act on it without asking. Turning it on for a whole install is a consumer-facing default flip and is owner-reserved (agents/roadmaps/stubs/road-to-frontend-power-default-flip.md); design.fidelity_mode: hard-floor overrides it to off.'),
146
+ tolerance: z
147
+ .object({
148
+ color: z.number().nullable().default(null).describe('Colour distance below which a value may be reconciled, in OKLab ΔEOK. Ships null, and null means "preserve and report" rather than "reconcile freely". No number is set because none is supported: zero of seven design-to-code benchmarks in the evidence set score token conformance, and a number in a config file — even flagged unmeasured — shapes behavior and acquires the authority of a default. Not an RGB channel delta: RGB distance is not perceptually uniform.'),
149
+ length: z.number().nullable().default(null).describe('Length distance below which a value may be reconciled, in absolute CSS pixels. Ships null, same reasoning as color. GitHub Primer\'s ±1px spacing widening is recorded as an externally observed candidate in src/scripts/_lib/design_tolerance.ts and is deliberately not the shipped value; max(1px, 2%) was rejected for growing more permissive at large dimensions with no evidence that this is wanted.'),
150
+ })
151
+ .default({ color: null, length: null }),
152
+ })
153
+ .default({ enabled: false, tolerance: { color: null, length: null } }),
154
+ }).default({
155
+ fidelity_mode: 'strict',
156
+ approximation: { enabled: false, tolerance: { color: null, length: null } },
157
+ }),
135
158
  consistency: z.object({
136
159
  cross_source: crossSourceMode.default('on').describe('Consumed by the cross-source-consistency rule. When the agent works from multiple sources (ticket text, an attached image/mockup, the spec, the codebase) it checks them against each other and asks before proceeding on a discrepancy — instead of silently guessing. on (default) = surface every real cross-source contradiction / silent-scope-expansion as one question; auto = surface only high-confidence contradictions, state low-confidence as an assumption; off = no cross-source checking.'),
137
160
  }).default({ cross_source: 'on' }),
@@ -229,6 +252,10 @@ export const settingsSchema = z.object({
229
252
  api_paths: z.array(z.string()).default([]).describe('Optional glob list that makes API-endpoint detection explicit instead of heuristic (e.g. ["app/Http/Controllers/Api/**", "src/pages/api/**"]). Empty (default) = a light path/extension heuristic that fails open.'),
230
253
  }),
231
254
  }),
255
+ continuity: z.object({
256
+ auto_record: z.enum(['on', 'off']).default('on').describe('Deterministic continuity-record writer at session end (road-to-continuity-writer-activation Phase 1). on (default since 2026-09-10) = the session-eol concern writes the continuity_record capsule variant on Stop for a substantive session that has claimed a roadmap; every field is computed from on-disk state, with no model spend and no subprocess. off = no automatic record, and only the explicit agent-config session:recycle writes one. The default flipped once the parity evidence landed, so the normal path carries an automatic writer rather than a remembered command; session:recycle is retained because the automatic writer skips a session that claimed no roadmap and omits the git-status anchors.'),
257
+ run_checkpoints: z.enum(['on', 'off']).default('on').describe('Deterministic run-checkpoint production at session end (road-to-continuity-writer-activation Phase 1.4). on (default) = a session above the recycle threshold and inside a running roadmap contract leaves agents/runtime/state/checkpoints/<run>.json, so a killed run resumes from a derived checkpoint rather than from bookkeeping. off = no checkpoint; continuity writing, the recycle advisory and the context-fill surface are unaffected. Default ON because it is the behavior the tree already had — the switch exists to make the three session-end handlers independently disableable, not to change what ships.'),
258
+ }),
232
259
  memory: z.object({
233
260
  cadence: memoryCadence.default('always').describe('Cadence of the 🧠 memory-visibility line after a memory-consulting step. always (default) = show whenever a memory type was asked; auto = show only when 3+ types were consulted (less noise); never = suppress. Distinct from rule_loading_tier — owns its own key since the 2026-06-01 untangle.'),
234
261
  review_threshold: z.number().int().min(0).default(10).describe('Maximum number of memory entries /memory:load surfaces inline before falling back to a summary view. Default 10 keeps the chat readable. Raise to see more candidates, lower to keep the context tight.'),
@@ -77,7 +77,12 @@ export function computeSurfaceDelta(oldS, newS) {
77
77
  continue;
78
78
  }
79
79
  const o = oldS.entries[key];
80
- if (o.type !== n.type) {
80
+ // `sameJson`, not `!==`: `type` is an array for a nullable key, and two
81
+ // structurally equal arrays are never `===`. Left as a strict compare
82
+ // it reported `type_changed` on EVERY version bump for every nullable
83
+ // key, forever — caught by the identical-surface test the moment the
84
+ // first one shipped (`design.approximation.tolerance.*`).
85
+ if (!sameJson(o.type, n.type)) {
81
86
  changes.push({ key, kind: 'type_changed', old: o, new: n });
82
87
  }
83
88
  if (!sameJson(o.default, n.default)) {
package/docs/MIGRATION.md CHANGED
@@ -42,6 +42,62 @@ reason, which no arithmetic can.
42
42
  or that promises a future breaking removal, gets a row here in the same commit
43
43
  that makes the promise. A promise with no row is not tracked and will be missed.
44
44
 
45
+ ## 14.22.x — the code-graph engine gets readers, and the MCP install hint changes
46
+
47
+ 💡 advisory · 🔄 automatic — **one exception, below.**
48
+
49
+ The 14.21.x entry above shipped the engine to consumers. This one ships the
50
+ things that read it (`road-to-a-graph-that-is-shipped`, Phases 3 and 4).
51
+
52
+ ### Additive — nothing to do
53
+
54
+ - **Four new `code-graph` subcommands**, all answering questions about a DIFF
55
+ rather than a symbol: `impact --diff <rev>`, `tests-for <symbol>`,
56
+ `untested --diff <rev>`, `dead`. Each prints the resolution mechanisms it
57
+ accepted, the mechanisms it refused, and the graph's three-state staleness.
58
+ No existing subcommand changed, and no new top-level verb was added.
59
+ - **Five new MCP tools** on the existing stdio server — `graph_impact`,
60
+ `graph_tests_for`, `graph_dead`, `graph_query`, `graph_path` — taking the
61
+ catalogue from 31 tools to 36. Four are read-only; `graph_impact` runs
62
+ `git diff --name-only` to resolve its rev and declares `side_effect: shell`
63
+ for that reason.
64
+ - **A new `tests` edge relation**, derived in the build pass from a test file's
65
+ imports. `SCHEMA_VERSION` 3 → 4 and `GRAPH_STORE_VERSION` 3 → 4, so an
66
+ existing cache and its SQLite twin are refused and rebuilt on the next
67
+ `code-graph build`. The cache is derived and disposable
68
+ (ADR-129) — there is nothing to migrate, and a rebuild takes seconds.
69
+
70
+ ### The one thing to check — `dead` refuses by default
71
+
72
+ `agent-config code-graph dead` exits **1** with an empty list unless you either
73
+ supply an entry-point list (`--entry-points <file>`) or accept the gap
74
+ (`--accept-missing-exports`). That is deliberate: this engine records no
75
+ exportedness, so without a supplied list an exported-but-not-yet-imported public
76
+ symbol is indistinguishable from a dead one, and a confident false "dead" invites
77
+ a deletion the graph cannot justify. If you wire `dead` into a script, handle the
78
+ refusal — an exit 1 here is not a crash, and treating it as an empty dead list
79
+ is the false negative the refusal exists to prevent.
80
+
81
+ ### One consumer-visible string changed
82
+
83
+ `install_hint_stdio` in the published MCP tool catalogue was
84
+ `npx -y @event4u/agent-config mcp-server` and is now **`agent-config mcp-server`**
85
+ — the installed-binary form the setup docs already lead with. It resolves no
86
+ dist-tag, so the server you run is the version you installed rather than
87
+ whatever the registry served most recently. **It assumes `agent-config` is on
88
+ PATH.** If you read that field programmatically and rely on `npx`, keep using
89
+ the pinned form from [`mcp-server.md`](mcp-server.md) —
90
+ `npx -y @event4u/agent-config@<version> mcp-server` — which is unchanged and
91
+ still the documented client configuration.
92
+
93
+ ### Standing context cost
94
+
95
+ Registering the stdio MCP server now costs **4,876 tokens** of standing context
96
+ per session, up from 3,886 — the five graph tools measure 993 between them. It
97
+ remains roughly 4x under the ~20,000-token Tool Search deferral threshold at a
98
+ 200k window, so the surface still loads upfront. Measured, with the prior reading
99
+ kept: `agents/evidence/metrics/mcp-tool-standing-cost.jsonl`.
100
+
45
101
  ## 14.21.x — the code-graph engine ships to consumers
46
102
 
47
103
  💡 advisory · 🔄 automatic — no action required.