@event4u/agent-config 9.9.0 → 9.10.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 (384) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +153 -194
  3. package/README.md +1 -1
  4. package/dist/agent-src/commands/agent-status.md +12 -11
  5. package/dist/agent-src/commands/agents/user/accept.md +115 -30
  6. package/dist/agent-src/commands/agents/user/delete.md +147 -0
  7. package/dist/agent-src/commands/agents/user/review.md +65 -28
  8. package/dist/agent-src/commands/agents/user/show.md +82 -29
  9. package/dist/agent-src/commands/agents/user/update.md +2 -2
  10. package/dist/agent-src/commands/agents/user.md +16 -3
  11. package/dist/agent-src/commands/check-current-md.md +0 -10
  12. package/dist/agent-src/commands/condense.md +28 -97
  13. package/dist/agent-src/commands/cost/report.md +7 -0
  14. package/dist/agent-src/commands/fix/portability.md +0 -8
  15. package/dist/agent-src/commands/fix/refs.md +0 -8
  16. package/dist/agent-src/commands/humanize.md +2 -2
  17. package/dist/agent-src/commands/jira-ticket.md +1 -1
  18. package/dist/agent-src/commands/memory/load.md +11 -0
  19. package/dist/agent-src/commands/optimize/skills.md +1 -1
  20. package/dist/agent-src/commands/pr/create.md +4 -4
  21. package/dist/agent-src/commands/profile/show.md +3 -3
  22. package/dist/agent-src/commands/rule-compliance-audit.md +5 -4
  23. package/dist/agent-src/commands/security-audit-config.md +1 -1
  24. package/dist/agent-src/commands/sync/gitignore/fix.md +1 -1
  25. package/dist/agent-src/commands/tdd.md +21 -0
  26. package/dist/agent-src/commands/team/delegate.md +2 -2
  27. package/dist/agent-src/commands/team-knowledge/bootstrap.md +9 -8
  28. package/dist/agent-src/commands/team-knowledge/consolidate.md +8 -7
  29. package/dist/agent-src/commands/team.md +4 -1
  30. package/dist/agent-src/commands/upstream-contribute.md +0 -1
  31. package/dist/agent-src/contexts/authority/commit-mechanics.md +7 -0
  32. package/dist/agent-src/contexts/authority/destructive-mechanics.md +16 -0
  33. package/dist/agent-src/contexts/authority/scope-mechanics.md +61 -0
  34. package/dist/agent-src/contexts/communication/rules-auto/reply-close-mechanics.md +20 -18
  35. package/dist/agent-src/contexts/communication/rules-auto/skill-quality-mechanics.md +1 -1
  36. package/dist/agent-src/contexts/communication/rules-auto/slash-command-routing-policy-mechanics.md +1 -1
  37. package/dist/agent-src/contexts/communication/rules-auto/source-of-truth-mechanics.md +9 -10
  38. package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +1 -1
  39. package/dist/agent-src/contexts/communication/rules-auto/user-interaction-mechanics.md +11 -0
  40. package/dist/agent-src/contexts/contracts/artifact-engagement-flow.md +26 -15
  41. package/dist/agent-src/contexts/contracts/command-suggestion-flow.md +3 -0
  42. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +67 -37
  43. package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +1 -1
  44. package/dist/agent-src/contexts/execution/autonomy-examples.md +1 -1
  45. package/dist/agent-src/contexts/execution/autonomy-mechanics.md +7 -6
  46. package/dist/agent-src/contexts/execution/evidence-discipline.md +92 -77
  47. package/dist/agent-src/contexts/execution/orchestration-benchmark-gate.md +22 -21
  48. package/dist/agent-src/contexts/execution/orchestration-telemetry.md +24 -0
  49. package/dist/agent-src/contexts/execution/project-intelligence.md +122 -103
  50. package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +23 -21
  51. package/dist/agent-src/contexts/execution/subagent-response-contract.md +5 -5
  52. package/dist/agent-src/contexts/execution/subagent-routing.md +11 -0
  53. package/dist/agent-src/contexts/execution/subagent-spawn-contract.md +13 -13
  54. package/dist/agent-src/contexts/execution/subagent-steering.md +36 -34
  55. package/dist/agent-src/contexts/execution/toolchain-resolver.md +1 -1
  56. package/dist/agent-src/contexts/execution/user-memory-channels.md +189 -0
  57. package/dist/agent-src/contexts/execution/verification-mechanics.md +9 -0
  58. package/dist/agent-src/contexts/model-recommendations.md +3 -2
  59. package/dist/agent-src/contexts/subagent-configuration.md +3 -3
  60. package/dist/agent-src/ghostwriter/README.md +2 -2
  61. package/dist/agent-src/packs/README.md +1 -1
  62. package/dist/agent-src/personas/README.md +5 -5
  63. package/dist/agent-src/personas/_template-specialist/persona.md +3 -3
  64. package/dist/agent-src/personas/backend-architect.md +24 -23
  65. package/dist/agent-src/personas/eloquent-tamer.md +30 -30
  66. package/dist/agent-src/personas/frontend-engineer.md +30 -30
  67. package/dist/agent-src/personas/product-owner.md +41 -38
  68. package/dist/agent-src/personas/qa.md +13 -13
  69. package/dist/agent-src/personas/security-engineer.md +22 -22
  70. package/dist/agent-src/presets/README.md +3 -3
  71. package/dist/agent-src/profiles/README.md +3 -3
  72. package/dist/agent-src/rules/active-remediation.md +2 -2
  73. package/dist/agent-src/rules/artifact-engagement-recording.md +4 -4
  74. package/dist/agent-src/rules/ask-when-uncertain.md +0 -4
  75. package/dist/agent-src/rules/augment-edit-discipline.md +1 -1
  76. package/dist/agent-src/rules/broken-access-control.md +4 -4
  77. package/dist/agent-src/rules/code-comment-discipline.md +1 -1
  78. package/dist/agent-src/rules/code-provenance.md +2 -2
  79. package/dist/agent-src/rules/commit-policy.md +4 -9
  80. package/dist/agent-src/rules/communication-through-line.md +5 -5
  81. package/dist/agent-src/rules/decision-revisit-gate.md +1 -1
  82. package/dist/agent-src/rules/doc-screenshot-hygiene.md +1 -1
  83. package/dist/agent-src/rules/domain-adoption-policy.md +1 -1
  84. package/dist/agent-src/rules/domain-safety-pii.md +1 -1
  85. package/dist/agent-src/rules/external-code-graph-interop.md +1 -1
  86. package/dist/agent-src/rules/fast-path-marker-visibility.md +43 -7
  87. package/dist/agent-src/rules/finance-safety-floor.md +1 -1
  88. package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +3 -3
  89. package/dist/agent-src/rules/history-discipline.md +1 -1
  90. package/dist/agent-src/rules/legal-safety-floor.md +1 -1
  91. package/dist/agent-src/rules/lethal-trifecta-guard.md +5 -5
  92. package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +10 -8
  93. package/dist/agent-src/rules/media-governance-routing.md +13 -13
  94. package/dist/agent-src/rules/media-sync-ground-truth.md +29 -11
  95. package/dist/agent-src/rules/no-cheap-questions.md +7 -7
  96. package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +29 -18
  97. package/dist/agent-src/rules/non-destructive-by-default.md +5 -23
  98. package/dist/agent-src/rules/onboarding-gate.md +14 -4
  99. package/dist/agent-src/rules/persona-governance.md +2 -2
  100. package/dist/agent-src/rules/prefer-enums-over-literals.md +9 -9
  101. package/dist/agent-src/rules/preservation-guard.md +10 -2
  102. package/dist/agent-src/rules/question-not-instruction.md +1 -1
  103. package/dist/agent-src/rules/roadmap-progress-sync.md +6 -6
  104. package/dist/agent-src/rules/rule-type-governance.md +1 -1
  105. package/dist/agent-src/rules/scale-discipline.md +1 -1
  106. package/dist/agent-src/rules/scope-control.md +1 -1
  107. package/dist/agent-src/rules/secret-vcs-guard.md +1 -1
  108. package/dist/agent-src/rules/security-sensitive-stop.md +17 -11
  109. package/dist/agent-src/rules/senior-engineering-discipline.md +17 -17
  110. package/dist/agent-src/rules/session-canary.md +1 -1
  111. package/dist/agent-src/rules/skill-quality.md +1 -1
  112. package/dist/agent-src/rules/source-confidentiality.md +21 -19
  113. package/dist/agent-src/rules/source-of-truth.md +6 -5
  114. package/dist/agent-src/rules/spreadsheet-source-quality.md +2 -2
  115. package/dist/agent-src/rules/strategy-safety-floor.md +1 -1
  116. package/dist/agent-src/rules/think-before-action.md +5 -5
  117. package/dist/agent-src/rules/token-budget-discipline.md +5 -3
  118. package/dist/agent-src/rules/token-efficiency.md +2 -2
  119. package/dist/agent-src/rules/untrusted-input-defense.md +4 -4
  120. package/dist/agent-src/rules/user-interaction.md +12 -0
  121. package/dist/agent-src/rules/verify-before-complete.md +4 -24
  122. package/dist/agent-src/skills/adversarial-review/SKILL.md +2 -2
  123. package/dist/agent-src/skills/agent-security-review/SKILL.md +52 -45
  124. package/dist/agent-src/skills/agents-md-thin-root/SKILL.md +2 -2
  125. package/dist/agent-src/skills/ai-code-blindspots/SKILL.md +20 -20
  126. package/dist/agent-src/skills/ai-council/SKILL.md +185 -128
  127. package/dist/agent-src/skills/analysis-skill-router/SKILL.md +3 -3
  128. package/dist/agent-src/skills/api-endpoint/SKILL.md +2 -2
  129. package/dist/agent-src/skills/artisan-commands/SKILL.md +2 -2
  130. package/dist/agent-src/skills/async-python-patterns/SKILL.md +8 -7
  131. package/dist/agent-src/skills/authz-review/SKILL.md +16 -15
  132. package/dist/agent-src/skills/aws-infrastructure/SKILL.md +5 -5
  133. package/dist/agent-src/skills/blade-ui/SKILL.md +1 -1
  134. package/dist/agent-src/skills/bug-analyzer/SKILL.md +30 -12
  135. package/dist/agent-src/skills/code-intelligence/SKILL.md +0 -1
  136. package/dist/agent-src/skills/code-intelligence/evals/triggers.json +52 -0
  137. package/dist/agent-src/skills/code-review/SKILL.md +6 -6
  138. package/dist/agent-src/skills/command-routing/SKILL.md +5 -4
  139. package/dist/agent-src/skills/composer-packages/SKILL.md +2 -2
  140. package/dist/agent-src/skills/condense-memory/SKILL.md +43 -41
  141. package/dist/agent-src/skills/context-document/SKILL.md +23 -21
  142. package/dist/agent-src/skills/copilot-config/SKILL.md +6 -1
  143. package/dist/agent-src/skills/decision-record/SKILL.md +20 -18
  144. package/dist/agent-src/skills/design-intelligence/SKILL.md +4 -4
  145. package/dist/agent-src/skills/design-review/SKILL.md +15 -14
  146. package/dist/agent-src/skills/design-system-capture/reference/design-system-json.md +28 -25
  147. package/dist/agent-src/skills/devcontainer/SKILL.md +2 -2
  148. package/dist/agent-src/skills/docker/SKILL.md +1 -1
  149. package/dist/agent-src/skills/docx-authoring/evals/triggers.json +52 -0
  150. package/dist/agent-src/skills/emit-tickets/SKILL.md +2 -2
  151. package/dist/agent-src/skills/error-handling-patterns/SKILL.md +1 -1
  152. package/dist/agent-src/skills/estimate-ticket/SKILL.md +2 -2
  153. package/dist/agent-src/skills/evaluate-llm-feature/SKILL.md +0 -1
  154. package/dist/agent-src/skills/evaluate-llm-feature/evals/triggers.json +52 -0
  155. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +6 -5
  156. package/dist/agent-src/skills/feature-planning/SKILL.md +2 -2
  157. package/dist/agent-src/skills/finishing-a-development-branch/SKILL.md +3 -3
  158. package/dist/agent-src/skills/flux/SKILL.md +1 -1
  159. package/dist/agent-src/skills/frontend-render-security/SKILL.md +13 -13
  160. package/dist/agent-src/skills/git-workflow/SKILL.md +33 -33
  161. package/dist/agent-src/skills/grafana/SKILL.md +5 -0
  162. package/dist/agent-src/skills/humanizer/SKILL.md +83 -66
  163. package/dist/agent-src/skills/humanizer/data/patterns.md +14 -14
  164. package/dist/agent-src/skills/humanizer/references/anti-aiisms.md +4 -4
  165. package/dist/agent-src/skills/judge-artifact-completeness/SKILL.md +82 -37
  166. package/dist/agent-src/skills/judge-bug-hunter/SKILL.md +17 -5
  167. package/dist/agent-src/skills/judge-injection-defense/SKILL.md +63 -25
  168. package/dist/agent-src/skills/judge-security-auditor/SKILL.md +2 -0
  169. package/dist/agent-src/skills/judge-synthesis/SKILL.md +72 -28
  170. package/dist/agent-src/skills/laravel-horizon/SKILL.md +5 -0
  171. package/dist/agent-src/skills/laravel-mail/SKILL.md +5 -4
  172. package/dist/agent-src/skills/laravel-middleware/SKILL.md +5 -4
  173. package/dist/agent-src/skills/laravel-notifications/SKILL.md +10 -9
  174. package/dist/agent-src/skills/laravel-pennant/SKILL.md +1 -1
  175. package/dist/agent-src/skills/laravel-pulse/SKILL.md +9 -8
  176. package/dist/agent-src/skills/laravel-reverb/SKILL.md +6 -5
  177. package/dist/agent-src/skills/laravel-scheduling/SKILL.md +6 -1
  178. package/dist/agent-src/skills/laravel-validation/SKILL.md +12 -0
  179. package/dist/agent-src/skills/launch-readiness/SKILL.md +1 -1
  180. package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +7 -7
  181. package/dist/agent-src/skills/learning-tutor/SKILL.md +44 -43
  182. package/dist/agent-src/skills/learning-tutor/evals/triggers.json +52 -0
  183. package/dist/agent-src/skills/license-compliance-audit/SKILL.md +7 -7
  184. package/dist/agent-src/skills/license-compliance-borrow-check/SKILL.md +3 -3
  185. package/dist/agent-src/skills/license-compliance-credits/SKILL.md +4 -4
  186. package/dist/agent-src/skills/llm-provider-knowledge/SKILL.md +0 -1
  187. package/dist/agent-src/skills/memory-consolidation/SKILL.md +69 -64
  188. package/dist/agent-src/skills/motion-choreographer/SKILL.md +6 -6
  189. package/dist/agent-src/skills/pdf-tools/evals/triggers.json +52 -0
  190. package/dist/agent-src/skills/performance-analysis/SKILL.md +7 -3
  191. package/dist/agent-src/skills/persona-improvement/SKILL.md +0 -2
  192. package/dist/agent-src/skills/persona-improvement/evals/triggers.json +52 -0
  193. package/dist/agent-src/skills/php-coder/SKILL.md +10 -0
  194. package/dist/agent-src/skills/prediction-pool-optimizer/SKILL.md +129 -120
  195. package/dist/agent-src/skills/prediction-pool-optimizer/reference/ev-fixtures.md +36 -35
  196. package/dist/agent-src/skills/prediction-pool-optimizer/reference/odds-and-bonus.md +45 -41
  197. package/dist/agent-src/skills/project-analysis-core/SKILL.md +4 -4
  198. package/dist/agent-src/skills/project-analysis-hypothesis-driven/SKILL.md +3 -3
  199. package/dist/agent-src/skills/project-analysis-react/SKILL.md +1 -1
  200. package/dist/agent-src/skills/project-analysis-symfony/SKILL.md +1 -1
  201. package/dist/agent-src/skills/project-analysis-zend-laminas/SKILL.md +2 -2
  202. package/dist/agent-src/skills/prompt-engineering-patterns/SKILL.md +1 -1
  203. package/dist/agent-src/skills/prompt-validator/SKILL.md +39 -39
  204. package/dist/agent-src/skills/quality-tools/SKILL.md +15 -15
  205. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +55 -19
  206. package/dist/agent-src/skills/react-shadcn-ui/reference/registry.md +29 -27
  207. package/dist/agent-src/skills/readme-writing-package/SKILL.md +2 -2
  208. package/dist/agent-src/skills/reasoning-orchestrator/SKILL.md +25 -25
  209. package/dist/agent-src/skills/recursive-verification/SKILL.md +6 -5
  210. package/dist/agent-src/skills/refine-prompt/SKILL.md +1 -1
  211. package/dist/agent-src/skills/refine-ticket/SKILL.md +20 -2
  212. package/dist/agent-src/skills/repomix-packer/SKILL.md +1 -1
  213. package/dist/agent-src/skills/requesting-code-review/SKILL.md +2 -2
  214. package/dist/agent-src/skills/roadmap-management/SKILL.md +80 -66
  215. package/dist/agent-src/skills/roadmap-writing/SKILL.md +84 -77
  216. package/dist/agent-src/skills/rule-refactor/SKILL.md +1 -1
  217. package/dist/agent-src/skills/screenshot-hygiene/evals/triggers.json +52 -0
  218. package/dist/agent-src/skills/security-audit/SKILL.md +26 -9
  219. package/dist/agent-src/skills/security-maturity-assessment/SKILL.md +38 -16
  220. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +14 -11
  221. package/dist/agent-src/skills/skill-writing/SKILL.md +9 -8
  222. package/dist/agent-src/skills/song-to-script/SKILL.md +93 -85
  223. package/dist/agent-src/skills/sql-writing/SKILL.md +2 -2
  224. package/dist/agent-src/skills/stakeholder-tradeoff/SKILL.md +4 -3
  225. package/dist/agent-src/skills/standards-from-config/SKILL.md +61 -43
  226. package/dist/agent-src/skills/subagent-orchestration/SKILL.md +22 -8
  227. package/dist/agent-src/skills/subagent-orchestration/prompts/README.md +28 -2
  228. package/dist/agent-src/skills/supply-chain-intake/SKILL.md +13 -13
  229. package/dist/agent-src/skills/systematic-debugging/SKILL.md +22 -21
  230. package/dist/agent-src/skills/tailwind-engineer/SKILL.md +1 -1
  231. package/dist/agent-src/skills/technical-specification/SKILL.md +5 -0
  232. package/dist/agent-src/skills/terraform/SKILL.md +2 -2
  233. package/dist/agent-src/skills/terragrunt/SKILL.md +8 -8
  234. package/dist/agent-src/skills/testing-anti-patterns/process-anti-patterns.md +1 -1
  235. package/dist/agent-src/skills/threat-modeling/SKILL.md +19 -13
  236. package/dist/agent-src/skills/universal-project-analysis/SKILL.md +1 -1
  237. package/dist/agent-src/skills/upstream-contribute/SKILL.md +0 -1
  238. package/dist/agent-src/skills/using-git-worktrees/SKILL.md +9 -9
  239. package/dist/agent-src/skills/validate-feature-fit/SKILL.md +3 -1
  240. package/dist/agent-src/skills/verify-completion-evidence/SKILL.md +4 -6
  241. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +67 -61
  242. package/dist/agent-src/skills/video-director/SKILL.md +7 -7
  243. package/dist/agent-src/skills/worktree-lifecycle/SKILL.md +3 -3
  244. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  245. package/dist/agent-src/templates/contexts/knowledge-pages.md +47 -45
  246. package/dist/agent-src/templates/contexts/lesson-card.md +2 -2
  247. package/dist/agent-src/templates/contexts/tenant-boundaries.md +2 -2
  248. package/dist/agent-src/templates/contexts.md +1 -1
  249. package/dist/agent-src/templates/features.md +1 -1
  250. package/dist/agent-src/templates/roadmaps.md +125 -116
  251. package/dist/agent-src/templates/rule.md +2 -1
  252. package/dist/agent-src/templates/scripts/pr_risk_review.ts +0 -0
  253. package/dist/agent-src/templates/scripts/telemetry/aggregator.ts +0 -0
  254. package/dist/agent-src/templates/scripts/tier_usage_report.ts +2 -2
  255. package/dist/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +2 -2
  256. package/dist/agent-src/templates/scripts/work_engine/directives/ui/review.ts +1 -1
  257. package/dist/agent-src/user-types/README.md +8 -8
  258. package/dist/agent-src/user-types/galabau-field-crew.md +34 -33
  259. package/dist/agent-src/user-types/metalworking-shop.md +35 -34
  260. package/dist/agent-src/user-types/truck-driver.md +22 -20
  261. package/dist/cli/python/workspace_roles.js +2 -2
  262. package/dist/cli/python/workspace_roles.js.map +1 -1
  263. package/dist/discovery/deprecation-report.md +1 -1
  264. package/dist/discovery/discovery-manifest.json +88 -62
  265. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  266. package/dist/discovery/discovery-manifest.summary.md +3 -3
  267. package/dist/discovery/orphan-report.md +1 -1
  268. package/dist/discovery/packs.json +6 -5
  269. package/dist/discovery/trust-report.md +2 -2
  270. package/dist/discovery/workspaces.json +5 -4
  271. package/dist/hooks/dispatch.js +186 -12
  272. package/dist/install/install.mjs +8 -0
  273. package/dist/mcp/registry-manifest.json +3 -3
  274. package/dist/mcp/server.json +2 -2
  275. package/dist/mcp/server.mjs +1199 -857
  276. package/dist/router.json +1 -1
  277. package/dist/scripts/_lib/compile_time_toggles.js +48 -0
  278. package/dist/scripts/_lib/compile_time_toggles.js.map +1 -0
  279. package/dist/scripts/condense.js +234 -217
  280. package/dist/scripts/condense.js.map +1 -1
  281. package/dist/server/schemas/settings.js +4 -0
  282. package/dist/server/schemas/settings.js.map +1 -1
  283. package/dist/shared/userMd/utils.js +30 -0
  284. package/dist/shared/userMd/utils.js.map +1 -1
  285. package/dist/ui/assets/index-BpSQt5vm.js.map +1 -1
  286. package/docs/guidelines/agent-infra/api-cost-levers.md +56 -5
  287. package/docs/guidelines/agent-infra/simplicity-and-goal-demos.md +93 -33
  288. package/package.json +1 -1
  289. package/src/agent-src/templates/scripts/pr_risk_review.ts +0 -0
  290. package/src/agent-src/templates/scripts/telemetry/aggregator.ts +0 -0
  291. package/src/agent-src/templates/scripts/tier_usage_report.ts +2 -2
  292. package/src/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +2 -2
  293. package/src/agent-src/templates/scripts/work_engine/directives/ui/review.ts +1 -1
  294. package/src/config/agent-settings.template.yml +32 -2
  295. package/src/config/ci-local-parity.yml +142 -0
  296. package/src/config/gate-coverage.yml +127 -0
  297. package/src/config/preamble-payload-budget.json +44 -0
  298. package/src/scripts/_cli/cmd_doctor.ts +78 -2
  299. package/src/scripts/_lib/agent_user_profile.ts +381 -0
  300. package/src/scripts/_lib/agents_overlay.ts +9 -0
  301. package/src/scripts/_lib/anchor_eval.ts +311 -0
  302. package/src/scripts/_lib/cc_transcript.ts +316 -0
  303. package/src/scripts/_lib/compile_time_toggles.ts +79 -0
  304. package/src/scripts/_lib/confusables.ts +101 -0
  305. package/src/scripts/_lib/duplicate_scope_census.ts +77 -0
  306. package/src/scripts/_lib/managed_agents_folder.ts +181 -0
  307. package/src/scripts/_lib/payload_hash_drift.ts +126 -0
  308. package/src/scripts/_lib/preservation_migration.ts +291 -0
  309. package/src/scripts/_lib/retrieval_sanitize.ts +166 -2
  310. package/src/scripts/_lib/scan_scope.ts +115 -0
  311. package/src/scripts/_lib/user_global_memory_audit.ts +187 -0
  312. package/src/scripts/_lib/user_global_observations.ts +830 -0
  313. package/src/scripts/_lib/user_global_revocations.ts +110 -0
  314. package/src/scripts/_lib/user_memory_gate_counters.ts +291 -0
  315. package/src/scripts/ai_council/blind_review.ts +0 -0
  316. package/src/scripts/ai_council/budget_guard.ts +90 -11
  317. package/src/scripts/ai_council/bundler.ts +2 -2
  318. package/src/scripts/ai_council/clients.ts +59 -3
  319. package/src/scripts/ai_council/config.ts +38 -0
  320. package/src/scripts/ai_council/orchestrator.ts +54 -9
  321. package/src/scripts/ai_team/team_dispatch.ts +17 -6
  322. package/src/scripts/anchor_eval_falsify.ts +198 -0
  323. package/src/scripts/anchor_scoring_run.ts +239 -0
  324. package/src/scripts/annotate_discovery.ts +1 -65
  325. package/src/scripts/bench_quality_run.ts +168 -4
  326. package/src/scripts/cache_realization_report.ts +782 -0
  327. package/src/scripts/check_artefact_count_messaging.ts +5 -1
  328. package/src/scripts/check_augment_description_cap.ts +15 -4
  329. package/src/scripts/check_ci_local_parity.ts +317 -0
  330. package/src/scripts/check_condensation.ts +96 -191
  331. package/src/scripts/check_context_paths.ts +38 -9
  332. package/src/scripts/check_gate_coverage.ts +299 -0
  333. package/src/scripts/check_iron_law_prominence.ts +22 -1
  334. package/src/scripts/check_kernel_prefix_stability.ts +0 -0
  335. package/src/scripts/check_no_new_legacy_path.ts +16 -6
  336. package/src/scripts/check_no_roadmap_refs.ts +22 -9
  337. package/src/scripts/check_originality_freshness.ts +167 -0
  338. package/src/scripts/check_preamble_payload_budget.ts +130 -0
  339. package/src/scripts/check_proposal.ts +0 -0
  340. package/src/scripts/check_references.ts +0 -1
  341. package/src/scripts/check_safety_floor_untouched.ts +171 -24
  342. package/src/scripts/check_site_links.ts +62 -3
  343. package/src/scripts/ci_status.ts +0 -0
  344. package/src/scripts/cluster_near_miss_patterns.ts +0 -0
  345. package/src/scripts/code_graph/build.ts +0 -0
  346. package/src/scripts/command_suggester/types.ts +0 -0
  347. package/src/scripts/compile_router.ts +10 -14
  348. package/src/scripts/condense.sh +3 -4
  349. package/src/scripts/condense.ts +247 -228
  350. package/src/scripts/cost/track.mjs +168 -33
  351. package/src/scripts/cost_summary.ts +33 -1
  352. package/src/scripts/council_cli.ts +45 -3
  353. package/src/scripts/discovery_graph.ts +0 -0
  354. package/src/scripts/encoding_corpus.ts +500 -0
  355. package/src/scripts/encoding_corpus_report.ts +216 -0
  356. package/src/scripts/generate_index.ts +19 -2
  357. package/src/scripts/install-hooks.sh +2 -2
  358. package/src/scripts/learning_sidecar.ts +0 -0
  359. package/src/scripts/lint_confusables.ts +10 -72
  360. package/src/scripts/lint_featured_skills.ts +0 -0
  361. package/src/scripts/lint_hidden_unicode.ts +208 -0
  362. package/src/scripts/lint_load_context.ts +17 -5
  363. package/src/scripts/lint_new_skill_gate.ts +9 -3
  364. package/src/scripts/lint_no_python_twin_rationale.ts +17 -2
  365. package/src/scripts/lint_originality.ts +1 -1
  366. package/src/scripts/lint_skill_originality.ts +1 -1
  367. package/src/scripts/lint_ticket_buildable.ts +1 -1
  368. package/src/scripts/mcp_server/tools.ts +4 -4
  369. package/src/scripts/measure_scope_dedup.ts +224 -0
  370. package/src/scripts/memory_lookup.ts +0 -0
  371. package/src/scripts/mine_session.ts +98 -0
  372. package/src/scripts/orchestration_payload_hash_drift.ts +145 -0
  373. package/src/scripts/preamble_byte_census.ts +574 -0
  374. package/src/scripts/probe_skill_registration.ts +2 -2
  375. package/src/scripts/redact_hook_capture.ts +13 -0
  376. package/src/scripts/release.ts +65 -10
  377. package/src/scripts/router_telemetry.ts +1 -1
  378. package/src/scripts/second_brain_retrieval.ts +14 -4
  379. package/src/scripts/skill_linter.ts +5 -0
  380. package/src/scripts/surface-tiers.yml +2 -0
  381. package/src/scripts/validate_pack_yaml.ts +0 -0
  382. package/src/server/schemas/settings.ts +8 -0
  383. package/src/shared/userMd/utils.ts +31 -0
  384. package/dist/agent-src/rules/telegraph-speak.md +0 -87
@@ -0,0 +1,299 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * Meta-gate: verify that the repo's gates actually inspect something.
4
+ *
5
+ * A gate that scans nothing exits 0 and certifies coverage that does not exist.
6
+ * That is strictly worse than having no gate, because the green is believed. On
7
+ * 2026-07-29 a sweep found three such gates in CI, each pointing at a tree
8
+ * emptied by the ADR-051 flat-`src/` migration; one of them printed the literal
9
+ * count `0` in its own output for as long as it was broken.
10
+ *
11
+ * This guard reads `src/config/gate-coverage.yml`, runs each listed gate with the
12
+ * CI-identical arguments declared there, reads the `scanned: <N>` line the gate
13
+ * emits, and fails when N falls below the declared floor.
14
+ *
15
+ * Three design rules, each traceable to a concrete failure — see the manifest
16
+ * header for the full rationale:
17
+ * 1. Gates emit a machine-readable count; the guard never parses human output.
18
+ * 2. Invocations mirror CI exactly (a bare probe produced a false alarm during
19
+ * the sweep).
20
+ * 3. The check is a baseline floor, not `> 0` (428 → 3 is also a collapse).
21
+ *
22
+ * Self-honesty: this guard must not become the thing it catches. It fails when
23
+ * the manifest is empty or unreadable, and it REPORTS `pending` gates (listed but
24
+ * not yet emitting a count) instead of skipping them silently.
25
+ *
26
+ * CLI:
27
+ * ./scripts-run src/scripts/check_gate_coverage # enforce
28
+ * ./scripts-run src/scripts/check_gate_coverage --list # show the manifest
29
+ * ./scripts-run src/scripts/check_gate_coverage --format json
30
+ *
31
+ * Exit codes: 0 all enforced gates cleared their floor · 1 a gate is blind,
32
+ * collapsed, or silent · 2 the manifest itself is missing/empty/malformed.
33
+ */
34
+ import { spawnSync } from 'node:child_process';
35
+ import * as fs from 'node:fs';
36
+ import * as path from 'node:path';
37
+ import process from 'node:process';
38
+ import { fileURLToPath, pathToFileURL } from 'node:url';
39
+
40
+ import yaml from 'js-yaml';
41
+
42
+ const _HERE = fileURLToPath(import.meta.url);
43
+ const REPO_ROOT = path.resolve(path.dirname(_HERE), '..', '..');
44
+ const MANIFEST = path.join(REPO_ROOT, 'src/config/gate-coverage.yml');
45
+
46
+ /** The one line a gate must emit. Deliberately narrow: no format guessing. */
47
+ const SCANNED_RE = /^\s*scanned:\s*(\d+)\s*$/m;
48
+
49
+ export interface GateSpec {
50
+ id: string;
51
+ argv: string[];
52
+ min_scanned: number;
53
+ corpus: string;
54
+ status: 'enforced' | 'pending';
55
+ /**
56
+ * Exit code meaning "my prerequisite is absent, so I inspected nothing" — e.g.
57
+ * check_site_links exits 2 when the site is unbuilt or stale. Without this the
58
+ * guard reads that as `silent` and fails, which would make it red on every machine
59
+ * lacking a build artefact: a gate that blocks for an environmental reason teaches
60
+ * people to ignore it, which is worse than no gate. Reported as `unavailable`
61
+ * rather than skipped, so the partial coverage stays visible — the same reason
62
+ * `pending` is reported instead of hidden.
63
+ */
64
+ unavailable_exit?: number;
65
+ note?: string;
66
+ }
67
+
68
+ export type Verdict = 'ok' | 'below_floor' | 'silent' | 'crashed' | 'pending' | 'unavailable';
69
+
70
+ export interface GateResult {
71
+ id: string;
72
+ status: GateSpec['status'];
73
+ verdict: Verdict;
74
+ scanned: number | null;
75
+ min_scanned: number;
76
+ message: string;
77
+ }
78
+
79
+ function _require_int(v: unknown, id: string, i: number): number {
80
+ const n = Number(v);
81
+ if (!Number.isInteger(n)) {
82
+ throw new Error(`gates[${String(i)}] (${id}): unavailable_exit must be an integer exit code`);
83
+ }
84
+ return n;
85
+ }
86
+
87
+ /** Parse + validate the manifest. Throws on anything that would make the guard
88
+ * silently vacuous — an empty gate list is a hard error, not an empty pass. */
89
+ export function load_manifest(file = MANIFEST): GateSpec[] {
90
+ if (!fs.existsSync(file)) {
91
+ throw new Error(`manifest not found: ${path.relative(REPO_ROOT, file)}`);
92
+ }
93
+ const doc = yaml.load(fs.readFileSync(file, 'utf-8')) as { gates?: unknown[] };
94
+ const raw = Array.isArray(doc?.gates) ? doc.gates : [];
95
+ if (raw.length === 0) {
96
+ throw new Error('manifest declares zero gates — a coverage guard over an empty set is vacuous');
97
+ }
98
+ return raw.map((entry, i) => {
99
+ const e = entry as Record<string, unknown>;
100
+ const id = String(e['id'] ?? '');
101
+ if (id === '') throw new Error(`gates[${i}]: missing id`);
102
+ const min = Number(e['min_scanned']);
103
+ if (!Number.isInteger(min) || min < 0) {
104
+ throw new Error(`gates[${i}] (${id}): min_scanned must be a non-negative integer`);
105
+ }
106
+ const status = String(e['status'] ?? 'enforced');
107
+ if (status !== 'enforced' && status !== 'pending') {
108
+ throw new Error(`gates[${i}] (${id}): status must be 'enforced' or 'pending'`);
109
+ }
110
+ return {
111
+ id,
112
+ argv: Array.isArray(e['argv']) ? e['argv'].map(String) : [],
113
+ min_scanned: min,
114
+ corpus: String(e['corpus'] ?? ''),
115
+ status,
116
+ ...(e['unavailable_exit'] === undefined
117
+ ? {}
118
+ : { unavailable_exit: _require_int(e['unavailable_exit'], id, i) }),
119
+ ...(e['note'] === undefined ? {} : { note: String(e['note']) }),
120
+ };
121
+ });
122
+ }
123
+
124
+ /** Extract the contract line. Returns null when the gate emitted no count. */
125
+ export function parse_scanned(output: string): number | null {
126
+ const m = SCANNED_RE.exec(output);
127
+ return m === null ? null : Number(m[1]);
128
+ }
129
+
130
+ /** Classify one gate's run against its declared floor. Pure — testable without
131
+ * spawning anything. */
132
+ export function classify(
133
+ spec: GateSpec,
134
+ scanned: number | null,
135
+ crashed: boolean,
136
+ exit_code?: number | null,
137
+ ): GateResult {
138
+ const base = { id: spec.id, status: spec.status, scanned, min_scanned: spec.min_scanned };
139
+ if (spec.status === 'pending') {
140
+ return {
141
+ ...base,
142
+ verdict: 'pending',
143
+ message:
144
+ scanned === null
145
+ ? `not yet emitting 'scanned:' — listed as pending, NOT enforced (coverage gap is visible, not hidden)`
146
+ : `reports ${String(scanned)}; floor ${String(spec.min_scanned)} not enforced while pending`,
147
+ };
148
+ }
149
+ if (crashed) {
150
+ return { ...base, verdict: 'crashed', message: 'gate could not be executed' };
151
+ }
152
+ if (
153
+ spec.unavailable_exit !== undefined &&
154
+ exit_code !== undefined &&
155
+ exit_code !== null &&
156
+ exit_code === spec.unavailable_exit
157
+ ) {
158
+ return {
159
+ ...base,
160
+ verdict: 'unavailable',
161
+ message:
162
+ `exited ${String(exit_code)} — prerequisite absent, nothing inspected. ` +
163
+ `Coverage unverified here; CI is where this gate has its inputs`,
164
+ };
165
+ }
166
+ if (scanned === null) {
167
+ return {
168
+ ...base,
169
+ verdict: 'silent',
170
+ message: `emitted no 'scanned: <N>' line — an enforced gate must report what it inspected`,
171
+ };
172
+ }
173
+ if (scanned < spec.min_scanned) {
174
+ return {
175
+ ...base,
176
+ verdict: 'below_floor',
177
+ message:
178
+ `scanned ${String(scanned)}, floor ${String(spec.min_scanned)} (${spec.corpus}) — ` +
179
+ `a gate inspecting this little cannot certify the corpus`,
180
+ };
181
+ }
182
+ return { ...base, verdict: 'ok', message: `scanned ${String(scanned)} ≥ ${String(spec.min_scanned)}` };
183
+ }
184
+
185
+ function run_gate(spec: GateSpec): { scanned: number | null; crashed: boolean; exit_code: number | null } {
186
+ const runner = path.join(REPO_ROOT, 'scripts-run');
187
+ const r = spawnSync(runner, [`src/scripts/${spec.id}`, ...spec.argv], {
188
+ cwd: REPO_ROOT,
189
+ encoding: 'utf8',
190
+ });
191
+ if (r.error !== undefined || r.status === null) return { scanned: null, crashed: true, exit_code: null };
192
+ // A gate may legitimately exit non-zero (it found real violations) and still
193
+ // have scanned plenty — coverage and verdict are different questions.
194
+ return { scanned: parse_scanned(`${r.stdout}\n${r.stderr}`), crashed: false, exit_code: r.status };
195
+ }
196
+
197
+ const ICON: Record<Verdict, string> = {
198
+ ok: '✅',
199
+ below_floor: '❌',
200
+ silent: '❌',
201
+ crashed: '❌',
202
+ pending: '⚠️',
203
+ unavailable: '⚠️',
204
+ };
205
+
206
+ export function main(argv: readonly string[]): number {
207
+ const wantJson = argv.includes('--format') && argv[argv.indexOf('--format') + 1] === 'json';
208
+ const listOnly = argv.includes('--list');
209
+
210
+ let specs: GateSpec[];
211
+ try {
212
+ specs = load_manifest();
213
+ } catch (e) {
214
+ process.stderr.write(`❌ gate-coverage manifest: ${(e as Error).message}\n`);
215
+ return 2;
216
+ }
217
+
218
+ if (listOnly) {
219
+ for (const s of specs) {
220
+ process.stdout.write(
221
+ ` ${s.status === 'enforced' ? '[enforced]' : '[pending] '} ${s.id} ` +
222
+ `argv=[${s.argv.join(' ')}] floor=${String(s.min_scanned)}\n`,
223
+ );
224
+ }
225
+ process.stdout.write(`scanned: ${String(specs.length)}\n`);
226
+ return 0;
227
+ }
228
+
229
+ const results = specs.map((s) => {
230
+ if (spec_is_pending(s)) {
231
+ const { scanned, crashed } = probe_pending(s);
232
+ return classify(s, scanned, crashed);
233
+ }
234
+ const { scanned, crashed, exit_code } = run_gate(s);
235
+ return classify(s, scanned, crashed, exit_code);
236
+ });
237
+
238
+ if (wantJson) {
239
+ process.stdout.write(`${JSON.stringify({ generated_by: 'check_gate_coverage', results }, null, 2)}\n`);
240
+ } else {
241
+ for (const r of results) {
242
+ process.stdout.write(` ${ICON[r.verdict]} ${r.id}: ${r.message}\n`);
243
+ }
244
+ }
245
+
246
+ const failed = results.filter((r) => r.verdict === 'below_floor' || r.verdict === 'silent' || r.verdict === 'crashed');
247
+ const pending = results.filter((r) => r.verdict === 'pending');
248
+ const unavailable = results.filter((r) => r.verdict === 'unavailable');
249
+
250
+ // The guard reports its OWN coverage. Hiding a pending gate behind a green
251
+ // summary is exactly the failure mode this file exists to prevent.
252
+ process.stdout.write(
253
+ `\nscanned: ${String(results.length)}\n` +
254
+ ` enforced ${String(results.length - pending.length)} · pending ${String(pending.length)} · ` +
255
+ `unavailable ${String(unavailable.length)} · failing ${String(failed.length)}\n`,
256
+ );
257
+ if (unavailable.length > 0) {
258
+ process.stdout.write(
259
+ `⚠️ ${String(unavailable.length)} gate(s) could not run here (prerequisite absent) — ` +
260
+ `their coverage is unverified locally, not proven.\n`,
261
+ );
262
+ }
263
+ if (pending.length > 0) {
264
+ process.stdout.write(
265
+ `⚠️ ${String(pending.length)} gate(s) are listed but NOT enforced — this guard's coverage is partial by declaration.\n`,
266
+ );
267
+ }
268
+ if (failed.length > 0) {
269
+ process.stdout.write(`❌ ${String(failed.length)} gate(s) failed the coverage floor.\n`);
270
+ return 1;
271
+ }
272
+ process.stdout.write('✅ every enforced gate cleared its coverage floor.\n');
273
+ return 0;
274
+ }
275
+
276
+ function spec_is_pending(s: GateSpec): boolean {
277
+ return s.status === 'pending';
278
+ }
279
+
280
+ /** Pending gates are still probed (so the report shows what they currently do),
281
+ * but their count never fails the build. */
282
+ function probe_pending(s: GateSpec): { scanned: number | null; crashed: boolean } {
283
+ return run_gate(s);
284
+ }
285
+
286
+ function _isCliEntry(): boolean {
287
+ if (process.argv[1] === undefined) return false;
288
+ const argvUrl = pathToFileURL(path.resolve(process.argv[1])).href;
289
+ if (argvUrl === import.meta.url) return true;
290
+ try {
291
+ return pathToFileURL(fs.realpathSync(path.resolve(process.argv[1]))).href === import.meta.url;
292
+ } catch {
293
+ return false;
294
+ }
295
+ }
296
+
297
+ if (_isCliEntry()) {
298
+ process.exit(main(process.argv.slice(2)));
299
+ }
@@ -28,6 +28,8 @@ import * as fs from 'node:fs';
28
28
  import * as path from 'node:path';
29
29
  import { fileURLToPath, pathToFileURL } from 'node:url';
30
30
 
31
+ import { assertScanned } from './_lib/scan_scope.js';
32
+
31
33
  const HEADING_RE = /^(#{1,6})\s+(.+?)\s*$/;
32
34
  const IRON_LAW_RE = /\biron\s+laws?\b/i;
33
35
  const FENCE_RE = /^\s*```/;
@@ -247,7 +249,11 @@ function parse_args(argv: readonly string[]): Args {
247
249
  i++;
248
250
  }
249
251
  return {
250
- paths: paths.length ? paths : ['.agent-src.uncondensed/rules'],
252
+ // ADR-051 moved rule authoring to `src/rules`. Until 2026-07-29 this
253
+ // default still named the retired container, so both CI call sites
254
+ // (consistency.yml + ci-fast.yml) resolved 0 targets and printed
255
+ // "✅ Iron Law prominence clean (0 file(s) scanned)" forever.
256
+ paths: paths.length ? paths : ['src/rules'],
251
257
  format,
252
258
  quiet,
253
259
  };
@@ -257,6 +263,21 @@ export function main(argv?: readonly string[]): number {
257
263
  const args = parse_args(argv ?? process.argv.slice(2));
258
264
 
259
265
  const targets = _resolve_targets(args.paths);
266
+
267
+ // Scope assertion: 0 targets means the root moved, not that the tree is
268
+ // clean. Without this the gate reported success while reading nothing.
269
+ try {
270
+ assertScanned({
271
+ gate: 'check_iron_law_prominence',
272
+ scanned: targets.length,
273
+ units: 'rule file(s)',
274
+ roots: args.paths,
275
+ });
276
+ } catch (exc) {
277
+ process.stderr.write(`❌ ${exc instanceof Error ? exc.message : String(exc)}\n`);
278
+ return 2;
279
+ }
280
+
260
281
  const all_violations: Violation[] = [];
261
282
  for (const p of targets) {
262
283
  if (!_exists(p)) {
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env tsx
2
2
  /**
3
- * Regression guard: no NEW `.agent-src.uncondensed/` references in `src/`.
3
+ * Regression guard: no NEW dead-root references in `src/` or `tests/`.
4
4
  *
5
5
  * Ported from the retired Python `src/scripts/check_no_new_legacy_path.py` (ADR-200,
6
6
  * Phase 4 / Wave 4c). The CLI contract is pinned — `--base`
@@ -104,12 +104,22 @@ function find_offenders(diffText: string, twinCheck: TwinCheck = _is_faithful_tw
104
104
  continue;
105
105
  }
106
106
  if (line.startsWith('+') && !line.startsWith('+++')) {
107
- // src/-scoped: a full diff (e.g. `gh pr diff`) carries every path;
108
- // only added lines under src/ (minus the exempt detectors and
109
- // faithful TS twins) count.
107
+ // Scoped to src/ + tests/: a full diff (e.g. `gh pr diff`) carries
108
+ // every path; only added lines under those roots (minus the exempt
109
+ // detectors and faithful TS twins) count.
110
+ //
111
+ // tests/ added 2026-07-29. Four separate tests were found pinning the
112
+ // dead root — two via fixture paths, one via a `resolve_entry`
113
+ // expectation, one asserting that a missing root exits 0 — and each
114
+ // kept a gate's blindness green because test and implementation agreed
115
+ // on a tree reality had abandoned. A FULL-tree lint over tests/ is the
116
+ // wrong shape (44 files / 213 hits, most of them legitimate: the
117
+ // legacy detectors' own tests, validator_ignore substrings, and
118
+ // synthetic fixtures under tmpdir()). Diff-scoping is what makes this
119
+ // tractable — existing debt stays, growth stops, no allowlist.
110
120
  if (
111
121
  curFile &&
112
- curFile.startsWith('src/') &&
122
+ (curFile.startsWith('src/') || curFile.startsWith('tests/')) &&
113
123
  !EXEMPT.has(curFile) &&
114
124
  line.includes(LEGACY) &&
115
125
  !twinCheck(curFile)
@@ -135,7 +145,7 @@ function main(): number {
135
145
  // additions (robust locally and where the working tree is the branch tip).
136
146
  let proc: ReturnType<typeof spawnSync>;
137
147
  try {
138
- proc = spawnSync('git', ['diff', base, '--', 'src/'], {
148
+ proc = spawnSync('git', ['diff', base, '--', 'src/', 'tests/'], {
139
149
  encoding: 'utf-8',
140
150
  });
141
151
  } catch (exc) {
@@ -18,7 +18,7 @@
18
18
  * `agents/roadmaps/skipped/`). Forbidden: specific `*.md` files inside those
19
19
  * directories.
20
20
  *
21
- * Contract: .agent-src.uncondensed/rules/no-roadmap-references.md
21
+ * Contract: src/rules/no-roadmap-references.md
22
22
  *
23
23
  * Exit codes: 0 = clean, 1 = violations, 3 = internal error.
24
24
  */
@@ -34,13 +34,20 @@ const ROOT = path.resolve(path.dirname(_HERE), '..', '..');
34
34
 
35
35
  // Stable artefact trees — every `*.md` below MUST be free of roadmap-file
36
36
  // citations. Directory mentions stay allowed (the regex below excludes them).
37
+ // Retargeted 2026-07-29: these six pointed at the pre-relocation source tree,
38
+ // emptied by the ADR-051 flat-`src/` migration. The gate kept enforcing the rule
39
+ // for `docs/` while the rule + skill layer — the layer `no-roadmap-references` is
40
+ // actually about — went unscanned, and reported green. No violation had slipped
41
+ // through yet (verified), so this closes a latent gap rather than a live breach.
42
+ // (Phrased without the dead path literal on purpose: `check_no_new_legacy_path`
43
+ // guards against those accumulating, and this comment tripped it.)
37
44
  const STABLE_TREES = [
38
- '.agent-src.uncondensed/rules',
39
- '.agent-src.uncondensed/skills',
40
- '.agent-src.uncondensed/commands',
41
- '.agent-src.uncondensed/contexts',
42
- '.agent-src.uncondensed/templates',
43
- '.agent-src.uncondensed/personas',
45
+ 'src/rules',
46
+ 'src/skills',
47
+ 'src/agent-src/commands',
48
+ 'src/agent-src/contexts',
49
+ 'src/agent-src/templates',
50
+ 'src/agent-src/personas',
44
51
  'agents/settings/contexts',
45
52
  'docs/guidelines',
46
53
  'docs/contracts',
@@ -69,7 +76,7 @@ const ROADMAP_FILE_RE =
69
76
  // documentation purposes — the rule itself, the companion CI script docs,
70
77
  // and the contract doc that names the rule.
71
78
  const SELF_DOCUMENTING_ALLOWLIST: ReadonlySet<string> = new Set([
72
- '.agent-src.uncondensed/rules/no-roadmap-references.md',
79
+ 'src/rules/no-roadmap-references.md',
73
80
  'docs/guidelines/agent-infra/no-roadmap-references.md',
74
81
  ]);
75
82
 
@@ -172,9 +179,15 @@ function _collect_targets(root: string): string[] {
172
179
 
173
180
  function scan(root: string): Violation[] {
174
181
  const out: Violation[] = [];
182
+ let scanned = 0;
175
183
  for (const p of _collect_targets(root)) {
184
+ scanned += 1;
176
185
  out.push(..._scan_file(p, root));
177
186
  }
187
+ // Gate-coverage contract (src/config/gate-coverage.yml): report what was
188
+ // actually inspected, so a future dead root fails `check_gate_coverage`
189
+ // instead of printing a green "no violations" over an empty set.
190
+ process.stdout.write(`scanned: ${String(scanned)}\n`);
178
191
  return out;
179
192
  }
180
193
 
@@ -190,7 +203,7 @@ function format_text(violations: Violation[]): string {
190
203
  }
191
204
  lines.push(
192
205
  '\nPromote the durable conclusion to agents/settings/contexts/ and cite that ' +
193
- 'instead. See .agent-src.uncondensed/rules/no-roadmap-references.md.',
206
+ 'instead. See src/rules/no-roadmap-references.md.',
194
207
  );
195
208
  return lines.join('\n');
196
209
  }
@@ -0,0 +1,167 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * Freshness check for the committed originality report.
4
+ *
5
+ * `agents/reports/originality.{json,md}` is a committed artefact that nothing
6
+ * regenerates on a schedule, and the report itself "blocks NOTHING on its own" —
7
+ * so it can drift silently. It did: on 2026-07-31 the committed copy read 507
8
+ * artifacts while the identical corpus produced 508, meaning it predated an
9
+ * artefact and nobody noticed.
10
+ *
11
+ * This check regenerates the report, compares it against the committed bytes,
12
+ * restores the committed bytes either way, and **always exits 0**. Warning, not
13
+ * a gate — the report's non-blocking character is deliberate, and turning a
14
+ * stale doc into a red build would be a worse trade than a visible warning.
15
+ *
16
+ * Restoring is what keeps it safe to run inside a pipeline: the working tree is
17
+ * byte-identical afterwards, so no later step sees a spurious diff.
18
+ */
19
+ import * as fs from 'node:fs';
20
+ import * as path from 'node:path';
21
+
22
+ import { main as runOriginality } from './lint_originality.js';
23
+
24
+ const REPO_ROOT = path.resolve(path.dirname(new URL(import.meta.url).pathname), '..', '..');
25
+ export const REPORTS = [
26
+ path.join(REPO_ROOT, 'agents', 'reports', 'originality.json'),
27
+ path.join(REPO_ROOT, 'agents', 'reports', 'originality.md'),
28
+ ];
29
+
30
+ /** `null` for a report that is not committed yet — absence is not drift. */
31
+ function snapshot(files: readonly string[]): Map<string, Buffer | null> {
32
+ const out = new Map<string, Buffer | null>();
33
+ for (const f of files) {
34
+ try {
35
+ out.set(f, fs.readFileSync(f));
36
+ } catch {
37
+ out.set(f, null);
38
+ }
39
+ }
40
+ return out;
41
+ }
42
+
43
+ /**
44
+ * Put the committed bytes back. Best-effort per file and never throwing: this
45
+ * check runs inside pipelines, so a restore failure (read-only mount, a
46
+ * concurrent writer) must not become the exception that fails the build for an
47
+ * advisory. A file it could not restore is named loudly instead — that is the
48
+ * one case where the tree is left dirty, and the reader has to know.
49
+ */
50
+ function restore(before: Map<string, Buffer | null>): void {
51
+ for (const [f, buf] of before) {
52
+ try {
53
+ if (buf === null) {
54
+ fs.rmSync(f, { force: true });
55
+ } else {
56
+ fs.writeFileSync(f, buf);
57
+ }
58
+ } catch (err) {
59
+ const why = err instanceof Error ? err.message : String(err);
60
+ process.stdout.write(
61
+ `⚠️ could not restore ${f} after the freshness sweep: ${why}\n` +
62
+ ' The working tree now holds a REGENERATED report. Restore it with\n' +
63
+ ` \`git checkout -- ${f}\` if that was not intended.\n`,
64
+ );
65
+ }
66
+ }
67
+ }
68
+
69
+ /** Default regeneration: the real sweep, which writes into `REPORTS`. */
70
+ function regenerateReports(): void {
71
+ runOriginality(['--quiet']);
72
+ }
73
+
74
+ /**
75
+ * `regenerate` is injectable for one reason: a test that exercised the drift
76
+ * path against the real reports would have to write a stale version into a
77
+ * TRACKED file, and vitest runs suites in parallel — any sibling test asserting
78
+ * "the working tree is clean" would see that transient write and fail. (It did:
79
+ * `backfill_model_tier`'s dry-run purity check caught exactly that.) With the
80
+ * hook, drift and restore behaviour is provable entirely in temp space, and the
81
+ * real wiring stays covered by the fresh-path test, which is tree-neutral
82
+ * because rewriting identical bytes is invisible to git.
83
+ */
84
+ export function checkFreshness(
85
+ files: readonly string[] = REPORTS,
86
+ regenerate: () => void = regenerateReports,
87
+ ): {
88
+ drifted: string[];
89
+ missing: string[];
90
+ } {
91
+ const before = snapshot(files);
92
+ try {
93
+ regenerate();
94
+ } catch {
95
+ // A sweep that cannot run is not a drift signal; leave the tree as found.
96
+ restore(before);
97
+ return { drifted: [], missing: [] };
98
+ }
99
+ const drifted: string[] = [];
100
+ const missing: string[] = [];
101
+ for (const [f, buf] of before) {
102
+ let now: Buffer | null;
103
+ try {
104
+ now = fs.readFileSync(f);
105
+ } catch {
106
+ now = null;
107
+ }
108
+ if (buf === null) {
109
+ if (now !== null) missing.push(f);
110
+ continue;
111
+ }
112
+ if (now === null || !now.equals(buf)) drifted.push(f);
113
+ }
114
+ restore(before);
115
+ return { drifted, missing };
116
+ }
117
+
118
+ /**
119
+ * LOCAL-ONLY, established empirically. On a CI runner the sweep produced
120
+ * different bytes than the committed report even with a byte-identical corpus
121
+ * (verified: 508 members on both this branch and `main`, report fresh locally,
122
+ * both files reported stale in `Node Tests`). Something in the CI environment
123
+ * moves the output, and chasing it would mean designing a reproducibility gate
124
+ * for a report that "blocks nothing on its own" — a bad trade for a warning.
125
+ *
126
+ * So this stays a developer-side surface. A freshness warning that fires on
127
+ * every PR regardless of staleness is exactly the never-turns-off warning this
128
+ * check was written to remove.
129
+ */
130
+ export function main(): number {
131
+ if (process.env['CI'] !== undefined && process.env['CI'] !== '') {
132
+ process.stdout.write(
133
+ 'ℹ️ originality freshness: skipped on CI — the sweep is not byte-reproducible\n' +
134
+ ' across environments, so a CI warning here would fire regardless of\n' +
135
+ ' staleness. Run it locally before quoting the report numbers.\n',
136
+ );
137
+ return 0;
138
+ }
139
+ const { drifted, missing } = checkFreshness();
140
+ const rel = (f: string): string => path.relative(REPO_ROOT, f);
141
+
142
+ if (missing.length > 0) {
143
+ process.stdout.write(
144
+ `⚠️ originality report is not committed yet: ${missing.map(rel).join(', ')}\n` +
145
+ ' Run `./scripts-run src/scripts/lint_originality` and commit the result.\n',
146
+ );
147
+ }
148
+ if (drifted.length === 0 && missing.length === 0) {
149
+ process.stdout.write('✅ originality report is fresh.\n');
150
+ return 0;
151
+ }
152
+ if (drifted.length > 0) {
153
+ process.stdout.write(
154
+ `⚠️ originality report is STALE: ${drifted.map(rel).join(', ')}\n` +
155
+ ' Regenerating from the current corpus produces different bytes, so the\n' +
156
+ ' committed numbers describe an older corpus. Not a build failure — this\n' +
157
+ ' report blocks nothing on its own — but the counts should not be quoted\n' +
158
+ ' until refreshed: `./scripts-run src/scripts/lint_originality`.\n',
159
+ );
160
+ }
161
+ // Always 0: this is a warning surface by design.
162
+ return 0;
163
+ }
164
+
165
+ if (process.argv[1] !== undefined && import.meta.url === `file://${process.argv[1]}`) {
166
+ process.exit(main());
167
+ }