@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,79 @@
1
+ /**
2
+ * Compile-time rule toggles — the single definition, shared by the router compiler
3
+ * and the projector.
4
+ *
5
+ * WHY THIS FILE EXISTS
6
+ * --------------------
7
+ * The map used to live only in `compile_router.ts`, which meant a disabled rule was
8
+ * dropped from `dist/router.json` while its **body still shipped** as a file in
9
+ * `dist/agent-src/rules/` (and through the `.claude/rules/` symlink). ADR
10
+ * `telegraph/0002` originally claimed that flipping the toggle gave "zero-cost
11
+ * dormancy". That was measured and found half wrong on 2026-07-29: the router entry
12
+ * governs *trigger-routing*; **file existence governs always-loaded injection**, and
13
+ * the host reads the file — a maintainer session's context listed the body verbatim
14
+ * as "project instructions", never having consulted the router.
15
+ *
16
+ * Two surfaces, one switch. Sharing the definition is what lets the projector honour
17
+ * it, so `speak: false` means what the ADR assumed instead of the ADR being weakened
18
+ * to match a partial implementation.
19
+ */
20
+
21
+ /**
22
+ * HOW A RULE GETS HERE — the dormancy routing (road-to-cache-economy Phase 3)
23
+ * --------------------------------------------------------------------------
24
+ * A rule body is re-written on EVERY subagent spawn, so an always-loaded rule
25
+ * that is not earning its keep is paid per spawn, not once. That makes "should
26
+ * this rule be dormant?" a real question — and this map is the ONLY place the
27
+ * answer may land. The route, in order:
28
+ *
29
+ * 1. **Candidate** — `preamble_byte_census` ranks always-loaded rules by
30
+ * per-spawn token cost (`--top`). A candidate is a number, never an
31
+ * impression: telegraph-speak was ~982 tokens.
32
+ * 2. **Evidence** — the same bar telegraph-speak had to clear: an output-side
33
+ * bench showing the rule does not pay for itself, judged against the
34
+ * kill-criterion, BEFORE dormancy. A preference is not evidence, and
35
+ * "it looks verbose" is not a measurement.
36
+ * 3. **Landing** — a new entry in the map below, keyed on a real setting the
37
+ * consumer can flip back. Never a fifth toggle axis: this predicate already
38
+ * has four consumers (the router compiler, the dist writer, `check_sync`,
39
+ * and the per-tool symlink generator), and a rule wired into three of four
40
+ * is how the last attempt blocked its own push.
41
+ *
42
+ * What is explicitly NOT this route: dropping a rule from the router while its
43
+ * body still ships (that was the measured half-truth this file exists to fix),
44
+ * and gating bodies behind triggers wholesale — that is thin projection, which
45
+ * failed a 48% quality floor at 36.2% and stays disabled.
46
+ */
47
+
48
+ /** Loose settings shape — the toggles only ever read nested plain objects. */
49
+ export type ToggleSettings = Record<string, unknown>;
50
+
51
+ /** rule-id → predicate. A rule is emitted (router AND projection) only when its
52
+ * predicate returns true. A rule absent from this map is always emitted. */
53
+ export const COMPILE_TIME_TOGGLES: Record<string, (s: ToggleSettings) => boolean> = {
54
+ // `speak` defaults FALSE (dormant) per docs/adrs/telegraph/0002 — the absent-key
55
+ // fallback used to be `true`, which silently contradicted ADR 0001 (accepted,
56
+ // "default off until bench"). Measured basis: median vs_terse −9.27% (API) /
57
+ // −5.47% (exact cl100k_base) — telegraph emits MORE than a plain "be terse".
58
+ // Opt back in with an explicit `telegraph.speak: true` once an output-side bench
59
+ // clears the kill-criterion bar. `enabled` keeps its true default: it is the
60
+ // family master switch, and flipping it would silence sibling telegraph settings
61
+ // that were never measured negative.
62
+ //
63
+ // This predicate deliberately does NOT read `speak_scope`. That key disables the
64
+ // rule's *behaviour* and never removed its token cost — the trap the measurement
65
+ // exposed.
66
+ 'telegraph-speak': (s: ToggleSettings): boolean => {
67
+ const tg = (s['telegraph'] as ToggleSettings | undefined) ?? {};
68
+ const enabled = tg['enabled'] === undefined ? true : tg['enabled'];
69
+ const speak = tg['speak'] === undefined ? false : tg['speak'];
70
+ return Boolean(enabled) && Boolean(speak);
71
+ },
72
+ };
73
+
74
+ /** True when the rule may be emitted. Unknown ids are always emitted — the map is an
75
+ * opt-in list of gated rules, never an allowlist of permitted ones. */
76
+ export function rule_is_compile_enabled(rule_id: string, settings: ToggleSettings): boolean {
77
+ const predicate = COMPILE_TIME_TOGGLES[rule_id];
78
+ return predicate === undefined ? true : predicate(settings);
79
+ }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Visible mixed-script confusable signature — the ONE definition in the tree.
3
+ *
4
+ * Extracted from `lint_confusables.ts` so the authoring-time linter and the
5
+ * runtime encoding scanner share one table and one decision rule
6
+ * (road-to-runtime-encoding-hardening Phase 3). Two copies of a confusable set
7
+ * is exactly the drift this extraction prevents: a codepoint added to one and
8
+ * not the other means the two surfaces disagree about what a homoglyph is.
9
+ *
10
+ * The dependency direction matters. This module imports NOTHING — no `fs`, no
11
+ * lint framework — so the runtime retrieval path can use it without pulling the
12
+ * authoring-time lint infrastructure into a request.
13
+ */
14
+
15
+ /** A token needs this many letters before the signature can fire. */
16
+ export const MIN_LETTERS = 3;
17
+
18
+ // Unicode-script classifiers via property escapes (requires the `u` flag).
19
+ const _LATIN = /\p{Script=Latin}/u;
20
+ const _CYRILLIC = /\p{Script=Cyrillic}/u;
21
+ const _GREEK = /\p{Script=Greek}/u;
22
+ const _LETTER = /\p{L}/u;
23
+
24
+ /** A "token" is a maximal run of letters / combining marks / decimal digits. */
25
+ export const TOKEN_RE = /[\p{L}\p{M}\p{Nd}]+/gu;
26
+
27
+ /**
28
+ * Cyrillic + Greek codepoints that have a basic-Latin lookalike (Unicode TR39
29
+ * confusables, common subset). A foreign letter only counts toward the
30
+ * confusable signal when it is in this set — Greek math operators with no Latin
31
+ * twin (Δ Σ Π Ω Φ Θ Λ Ξ Ψ Γ δ π ω …) are deliberately excluded so legit
32
+ * notation does not false-positive.
33
+ */
34
+ export const CONFUSABLE_FOREIGN: ReadonlySet<number> = new Set([
35
+ // Cyrillic lowercase ↔ Latin
36
+ 0x0430 /*а→a*/, 0x0435 /*е→e*/, 0x043e /*о→o*/, 0x0440 /*р→p*/, 0x0441 /*с→c*/,
37
+ 0x0443 /*у→y*/, 0x0445 /*х→x*/, 0x0455 /*ѕ→s*/, 0x0456 /*і→i*/, 0x0458 /*ј→j*/,
38
+ 0x04bb /*һ→h*/, 0x0501 /*ԁ→d*/, 0x051b /*ԛ→q*/, 0x0577 /*no*/,
39
+ // Cyrillic uppercase ↔ Latin
40
+ 0x0410 /*А→A*/, 0x0412 /*В→B*/, 0x0415 /*Е→E*/, 0x041a /*К→K*/, 0x041c /*М→M*/,
41
+ 0x041d /*Н→H*/, 0x041e /*О→O*/, 0x0420 /*Р→P*/, 0x0421 /*С→C*/, 0x0422 /*Т→T*/,
42
+ 0x0423 /*У→Y*/, 0x0425 /*Х→X*/, 0x0405 /*Ѕ→S*/, 0x0406 /*І→I*/, 0x0408 /*Ј→J*/,
43
+ // Greek lowercase ↔ Latin
44
+ 0x03b1 /*α→a*/, 0x03b5 /*ε→e*/, 0x03bf /*ο→o*/, 0x03bd /*ν→v*/, 0x03c1 /*ρ→p*/,
45
+ 0x03c5 /*υ→u*/, 0x03c7 /*χ→x*/, 0x03ba /*κ→k*/,
46
+ // Greek uppercase ↔ Latin (only those with a real Latin twin)
47
+ 0x0391 /*Α→A*/, 0x0392 /*Β→B*/, 0x0395 /*Ε→E*/, 0x0396 /*Ζ→Z*/, 0x0397 /*Η→H*/,
48
+ 0x0399 /*Ι→I*/, 0x039a /*Κ→K*/, 0x039c /*Μ→M*/, 0x039d /*Ν→N*/, 0x039f /*Ο→O*/,
49
+ 0x03a1 /*Ρ→P*/, 0x03a4 /*Τ→T*/, 0x03a5 /*Υ→Y*/, 0x03a7 /*Χ→X*/, 0x0392 /*Β→B*/,
50
+ ]);
51
+
52
+ type ScriptName = 'latin' | 'cyrillic' | 'greek' | 'other';
53
+
54
+ function _script_of(ch: string): ScriptName {
55
+ if (_LATIN.test(ch)) return 'latin';
56
+ if (_CYRILLIC.test(ch)) return 'cyrillic';
57
+ if (_GREEK.test(ch)) return 'greek';
58
+ return 'other';
59
+ }
60
+
61
+ /**
62
+ * Classify a single token. Returns the offending mixed-script descriptor when
63
+ * the token matches the homoglyph signature, else null.
64
+ *
65
+ * The containment rules are the load-bearing part, and they are why this is one
66
+ * shared function rather than two similar ones: a Latin-majority token with at
67
+ * least one TR39-confusable foreign letter is the signal; a single-script token
68
+ * (a genuine Cyrillic or Greek word) is not; and a token whose foreign letters
69
+ * outnumber its Latin ones is a foreign word, not an attack.
70
+ */
71
+ export function classifyToken(token: string): string | null {
72
+ let latin = 0;
73
+ let cyrillic = 0;
74
+ let greek = 0;
75
+ let letters = 0;
76
+ for (const ch of token) {
77
+ if (!_LETTER.test(ch)) continue; // skip combining marks / digits for script vote
78
+ letters += 1;
79
+ const script = _script_of(ch);
80
+ if (script === 'latin') {
81
+ latin += 1;
82
+ } else if (script === 'cyrillic' || script === 'greek') {
83
+ // Only confusable foreign letters (TR39) count — math operators with
84
+ // no Latin twin are ignored, so legit notation never trips.
85
+ if (CONFUSABLE_FOREIGN.has(ch.codePointAt(0) as number)) {
86
+ if (script === 'cyrillic') cyrillic += 1;
87
+ else greek += 1;
88
+ }
89
+ }
90
+ }
91
+ if (letters < MIN_LETTERS) return null;
92
+ const foreign = cyrillic + greek;
93
+ if (latin === 0 || foreign === 0) return null; // single-script (or no Latin) → legit
94
+ if (latin <= foreign) return null; // majority must be Latin (foreign word ≠ attack)
95
+ const which = cyrillic > 0 && greek > 0
96
+ ? 'cyrillic+greek'
97
+ : cyrillic > 0
98
+ ? 'cyrillic'
99
+ : 'greek';
100
+ return `latin+${which} (${latin} latin / ${foreign} foreign-confusable)`;
101
+ }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Duplicate-scope rule census — the shared byte-comparison primitive behind
3
+ * both C-2 (`cache_realization_report.ts`'s `computeDuplicateScope`, which
4
+ * turns this into a share of subagent write volume) and the `doctor`
5
+ * `duplicate-scope-rules` health check (`_cli/cmd_doctor.ts`), so the two
6
+ * surfaces can never drift on what counts as "shared" or how a redundant
7
+ * copy's size is estimated.
8
+ *
9
+ * `road-to-cache-economy.md` Phase 3: the same 110 rule
10
+ * filenames observed at both `~/.claude/rules` (user scope) and
11
+ * `dist/agent-src/rules` (project scope) on this maintainer's own checkout —
12
+ * C-2 confirmed at 38.5% of subagent write volume. This module answers only
13
+ * "which filenames are shared, and how many redundant bytes do they cost" —
14
+ * the write-volume share and the doctor warning are each computed by their
15
+ * own caller from this raw census.
16
+ *
17
+ * Detection only. Never deletes, never rewrites a user's file — see
18
+ * `non-destructive-by-default`.
19
+ */
20
+ import * as fs from 'node:fs';
21
+ import * as path from 'node:path';
22
+
23
+ export interface DuplicateScopeCensus {
24
+ evaluable: boolean;
25
+ reason?: string | undefined;
26
+ /** `.md` basenames present in BOTH directories, sorted. */
27
+ shared_filenames: string[];
28
+ /** Σ min(userBytes, projectBytes) over shared filenames — the conservative
29
+ * estimate of the redundant copy (the roadmap's byte census found the two
30
+ * scopes near-identical in size, so the min/max choice rarely matters). */
31
+ duplicate_chars: number;
32
+ }
33
+
34
+ /**
35
+ * For every `.md` filename present in BOTH `userRulesDir` and
36
+ * `projectRulesDir`, the redundant copy is estimated as the SMALLER of the
37
+ * two files' byte sizes, summed across all shared filenames.
38
+ */
39
+ export function censusDuplicateScope(userRulesDir: string, projectRulesDir: string): DuplicateScopeCensus {
40
+ if (!fs.existsSync(userRulesDir) || !fs.existsSync(projectRulesDir)) {
41
+ return {
42
+ evaluable: false,
43
+ reason: `one or both rule directories are missing (user: ${userRulesDir}, project: ${projectRulesDir})`,
44
+ shared_filenames: [],
45
+ duplicate_chars: 0,
46
+ };
47
+ }
48
+
49
+ const userFiles = new Set(fs.readdirSync(userRulesDir).filter((f) => f.endsWith('.md')));
50
+ const projectFiles = fs.readdirSync(projectRulesDir).filter((f) => f.endsWith('.md'));
51
+
52
+ const shared: string[] = [];
53
+ let duplicateChars = 0;
54
+ for (const f of projectFiles) {
55
+ if (!userFiles.has(f)) continue;
56
+ shared.push(f);
57
+ const a = fs.statSync(path.join(userRulesDir, f)).size;
58
+ const b = fs.statSync(path.join(projectRulesDir, f)).size;
59
+ duplicateChars += Math.min(a, b);
60
+ }
61
+ shared.sort();
62
+
63
+ if (shared.length === 0) {
64
+ return {
65
+ evaluable: false,
66
+ reason: 'no shared .md filenames between the two rule scopes — this checkout has no duplicate-scope install',
67
+ shared_filenames: [],
68
+ duplicate_chars: 0,
69
+ };
70
+ }
71
+
72
+ return {
73
+ evaluable: true,
74
+ shared_filenames: shared,
75
+ duplicate_chars: duplicateChars,
76
+ };
77
+ }
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Detect whether a directory is a project whose `agents/` folder is managed
3
+ * by this package.
4
+ *
5
+ * `.agent-settings.yml` resolution and settings-cascade routing already have
6
+ * a project-root walker (`find_project_root_with_anchor` in
7
+ * `_lib/agent_settings.ts`), but that walker answers a different question —
8
+ * "where does the settings cascade start reading from" — and its `agents/`
9
+ * check exists only to pick a boundary anchor for that walk (its marker list
10
+ * mixes package-source-repo-only paths, e.g. `settings/.ai-council.yml`, with
11
+ * consumer-only paths). It also treats a bare `.git` anywhere in the ancestor
12
+ * chain as "a project was found", which is the right answer for "where do
13
+ * settings live" but the wrong answer for "is this THIS package's managed
14
+ * `agents/` folder" — a third-party repo with an unrelated `agents/`
15
+ * directory and its own `.git` would resolve to a root there too. No
16
+ * existing helper answers the narrower managed/unmanaged/not-a-project
17
+ * question this module exists for.
18
+ *
19
+ * Contract — pure, read-only, tolerant:
20
+ *
21
+ * - Never writes, never mutates, never touches the network.
22
+ * - Operates on the given `start` directory directly — it does not walk
23
+ * ancestors looking for a project root (that is the caller's job, e.g.
24
+ * via `find_project_root` when the caller only has a subdirectory).
25
+ * Keeping this helper non-walking keeps it a distinct primitive from the
26
+ * settings-root walker above rather than a second, subtly different copy
27
+ * of the same walk.
28
+ * - Silently tolerant of a missing/unreadable `start` — every check falls
29
+ * through to `false`, which resolves to `'not-a-project'`.
30
+ */
31
+ import * as fs from 'node:fs';
32
+ import * as path from 'node:path';
33
+
34
+ import { SECTION_HEADER as _MANAGED_GITIGNORE_HEADER } from '../sync_gitignore.js';
35
+
36
+ /**
37
+ * Three-state answer — never a boolean, because "no `agents/` folder" and
38
+ * "no project at all" route differently downstream (an unmanaged repo is a
39
+ * candidate for adoption; a bare directory outside any repo is not a
40
+ * project the P-routing question even applies to).
41
+ */
42
+ export type ManagedAgentsFolderStatus = 'managed' | 'unmanaged' | 'not-a-project';
43
+
44
+ /**
45
+ * Detection predicate — chosen after inspecting what the installer actually
46
+ * writes into a consumer project (verified against source, not invented):
47
+ *
48
+ * is_project := <start>/.git exists (file or directory — worktrees and
49
+ * submodules use a `.git` file, not a directory).
50
+ * has_agents := <start>/agents is a directory.
51
+ * has_marker := ANY of —
52
+ * (a) <start>/.gitignore contains the managed-block header line
53
+ * `# event4u/agent-config` (`SECTION_HEADER` in
54
+ * `sync_gitignore.ts`) — installed by `refresh --project` /
55
+ * `sync:gitignore`. Strongest signal: the literal package name, so
56
+ * a third-party repo carries it only if it also runs this package.
57
+ * (b) <start>/agents/overrides/ is a directory — scaffolded by
58
+ * `install.ts` for every consumer project (the "guaranteed
59
+ * minimal-consumer surface", ADR-020).
60
+ * (c) a resolvable `.agent-settings.yml` exists — canonical
61
+ * `<start>/agents/settings/.agent-settings.yml`, or the legacy
62
+ * `<start>/.agent-settings.yml` fallback (see
63
+ * `project_settings_path` in `_lib/agent_settings.ts`).
64
+ *
65
+ * status := has_agents && has_marker → 'managed'
66
+ * is_project (else) → 'unmanaged'
67
+ * otherwise → 'not-a-project'
68
+ *
69
+ * Rejected alternatives:
70
+ *
71
+ * - `agents/` existence alone (no marker). Rejected: this is exactly the
72
+ * false positive the roadmap phase calls out — an unrelated multi-agent
73
+ * framework repo, or any project that happens to name a directory
74
+ * `agents/`, would read as managed with zero package-specific evidence.
75
+ * - Reusing `find_project_root_with_anchor`'s `_AGENTS_DIR_MARKERS` list
76
+ * verbatim (`roadmaps`, `settings/.ai-council.yml`,
77
+ * `roadmaps-progress.md`, `overrides`). Rejected: two of those four
78
+ * (`settings/.ai-council.yml`, `roadmaps-progress.md`) are `pkg`-scope
79
+ * only per `docs/contracts/agents-layout.md`'s consumer-slim-profile
80
+ * table — they never appear in an installed consumer project, so
81
+ * requiring "any one" would under-detect nothing (they're just dead
82
+ * weight for the consumer case) but reusing the *function* would also
83
+ * inherit its `.git`-anchor and `.agent-settings.yml`-layer-fallback
84
+ * semantics, which answer "where is the settings root" rather than
85
+ * "is `agents/` managed" (see module docblock).
86
+ * - `agents/roadmaps/` as a marker. Rejected: it is listed as "Optional"
87
+ * even in the consumer-slim profile — a managed project with zero
88
+ * roadmaps yet (the common case right after install) would false-
89
+ * negative.
90
+ */
91
+ function _existsAt(dir: string, ...segments: readonly string[]): boolean {
92
+ try {
93
+ fs.statSync(path.join(dir, ...segments));
94
+ return true;
95
+ } catch {
96
+ return false;
97
+ }
98
+ }
99
+
100
+ function _isDirAt(dir: string, ...segments: readonly string[]): boolean {
101
+ try {
102
+ return fs.statSync(path.join(dir, ...segments)).isDirectory();
103
+ } catch {
104
+ return false;
105
+ }
106
+ }
107
+
108
+ function _isFileAt(dir: string, ...segments: readonly string[]): boolean {
109
+ try {
110
+ return fs.statSync(path.join(dir, ...segments)).isFile();
111
+ } catch {
112
+ return false;
113
+ }
114
+ }
115
+
116
+ /** `true` when `start` sits at the root of a git repository (or worktree). */
117
+ function _isGitProject(start: string): boolean {
118
+ // `.git` is a directory in a normal clone, a file in a worktree or
119
+ // submodule checkout — `statSync` (not `lstatSync`) is deliberate so a
120
+ // broken symlink named `.git` does not count as present.
121
+ return _existsAt(start, '.git');
122
+ }
123
+
124
+ /** `true` when `<start>/.gitignore` carries the managed-block header line. */
125
+ function _hasManagedGitignoreBlock(start: string): boolean {
126
+ if (!_isFileAt(start, '.gitignore')) {
127
+ return false;
128
+ }
129
+ let text: string;
130
+ try {
131
+ text = fs.readFileSync(path.join(start, '.gitignore'), 'utf-8');
132
+ } catch {
133
+ return false;
134
+ }
135
+ return text
136
+ .split(/\r\n|\r|\n/)
137
+ .some((line) => line.trim() === _MANAGED_GITIGNORE_HEADER);
138
+ }
139
+
140
+ /** `true` when `<start>/agents/overrides` exists as a directory. */
141
+ function _hasOverridesDir(start: string): boolean {
142
+ return _isDirAt(start, 'agents', 'overrides');
143
+ }
144
+
145
+ /**
146
+ * `true` when a resolvable `.agent-settings.yml` exists — canonical
147
+ * `agents/settings/.agent-settings.yml`, or the legacy repo-root
148
+ * `.agent-settings.yml`.
149
+ */
150
+ function _hasResolvableAgentSettings(start: string): boolean {
151
+ return (
152
+ _isFileAt(start, 'agents', 'settings', '.agent-settings.yml') ||
153
+ _isFileAt(start, '.agent-settings.yml')
154
+ );
155
+ }
156
+
157
+ /**
158
+ * Classify `start` as `'managed'` (an `agents/` folder this package
159
+ * installed and can safely write project facts into), `'unmanaged'` (a real
160
+ * project — has a `.git` — with no such folder, or an `agents/` folder this
161
+ * package did not install), or `'not-a-project'` (no `.git` at `start` at
162
+ * all — e.g. a bare directory outside any repo).
163
+ *
164
+ * Read-only. Does not walk ancestors — `start` is checked directly; pass a
165
+ * project root (e.g. from `find_project_root`) when the caller only has a
166
+ * subdirectory.
167
+ */
168
+ export function detect_managed_agents_folder(start: string): ManagedAgentsFolderStatus {
169
+ if (!_isGitProject(start)) {
170
+ return 'not-a-project';
171
+ }
172
+ const hasAgentsDir = _isDirAt(start, 'agents');
173
+ const hasMarker =
174
+ _hasManagedGitignoreBlock(start) ||
175
+ _hasOverridesDir(start) ||
176
+ _hasResolvableAgentSettings(start);
177
+ if (hasAgentsDir && hasMarker) {
178
+ return 'managed';
179
+ }
180
+ return 'unmanaged';
181
+ }
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Payload-hash × cache-hit drift aggregator (pure, no-I/O).
3
+ *
4
+ * `road-to-cache-economy.md` Phase 3, step 6: the
5
+ * `orchestration` object's `payload_hash` and `cache_hit` fields are both
6
+ * `null`-by-default and read by nothing (per the roadmap's own defect list).
7
+ * This module is the reader: it joins the two fields recorded on the SAME
8
+ * audit-log-v1 line — `payload_hash` names which spawn-payload shape a
9
+ * dispatch used, `cache_hit` is the provider-reported prompt-cache hit for
10
+ * that dispatch — so prefix-stability drift becomes visible.
11
+ *
12
+ * Cohort split (the roadmap's own verify criterion — "a cohort dispatched
13
+ * with a deliberately unstable payload shows a lower read share than a
14
+ * stable one"):
15
+ *
16
+ * - STABLE cohort: every occurrence of a `payload_hash` AFTER its first —
17
+ * a hash that repeats means the same payload shape was dispatched again,
18
+ * so a cache hit on the repeat is the signal a stable prefix predicts.
19
+ * - UNSTABLE cohort: every `payload_hash` that occurs exactly once in the
20
+ * window — a payload that never repeats can never show a repeat-hit, so
21
+ * its (necessarily first-call) `cache_hit` value is the unstable-payload
22
+ * baseline.
23
+ *
24
+ * A hash's FIRST occurrence is excluded from the stable cohort — nothing
25
+ * exists yet for a first call to hit, so counting it would understate the
26
+ * stable cohort's hit rate for a reason that has nothing to do with prefix
27
+ * stability.
28
+ *
29
+ * Zero recorded lines is a VALID state (both fields are lean-init
30
+ * extensions with no caller wiring a real value yet) — the aggregator
31
+ * returns a report with empty cohorts rather than failing, and the CLI
32
+ * wrapper states that plainly rather than presenting empty input as a green
33
+ * result.
34
+ */
35
+
36
+ export interface PayloadHashLine {
37
+ payload_hash: string | null;
38
+ cache_hit: boolean | null;
39
+ }
40
+
41
+ export interface HashGroupStat {
42
+ payload_hash: string;
43
+ occurrences: number;
44
+ hit_count: number;
45
+ hit_rate: number;
46
+ }
47
+
48
+ export interface CohortStat {
49
+ n: number;
50
+ hit_count: number;
51
+ hit_rate: number | null;
52
+ }
53
+
54
+ export interface PayloadHashDriftReport {
55
+ total_lines: number;
56
+ /** Lines carrying both a non-null `payload_hash` and a boolean `cache_hit`. */
57
+ lines_with_data: number;
58
+ /** Per-hash breakdown, most-occurrences first. */
59
+ groups: HashGroupStat[];
60
+ stable_cohort: CohortStat;
61
+ unstable_cohort: CohortStat;
62
+ /** True only when BOTH cohorts have data AND the stable cohort's hit rate is strictly higher. */
63
+ drift_visible: boolean;
64
+ }
65
+
66
+ function emptyCohort(): CohortStat {
67
+ return { n: 0, hit_count: 0, hit_rate: null };
68
+ }
69
+
70
+ /**
71
+ * Aggregates already-parsed audit-log-v1 orchestration lines. `lines` order
72
+ * matters — it is read as chronological (the CLI wrapper reads
73
+ * `agents/runtime/state/audit/*.jsonl` in filename-sorted order, matching
74
+ * `readAuditLines`), since "first occurrence of a hash" is the only signal
75
+ * that decides which cohort an occurrence falls into.
76
+ */
77
+ export function aggregatePayloadHashDrift(lines: readonly PayloadHashLine[]): PayloadHashDriftReport {
78
+ const withData = lines.filter((l) => l.payload_hash !== null && l.cache_hit !== null);
79
+
80
+ const byHash = new Map<string, boolean[]>();
81
+ for (const l of withData) {
82
+ const hash = l.payload_hash as string;
83
+ const arr = byHash.get(hash) ?? [];
84
+ arr.push(l.cache_hit as boolean);
85
+ byHash.set(hash, arr);
86
+ }
87
+
88
+ const groups: HashGroupStat[] = [];
89
+ const stable = emptyCohort();
90
+ const unstable = emptyCohort();
91
+
92
+ for (const [hash, hits] of byHash) {
93
+ const hitCount = hits.filter(Boolean).length;
94
+ groups.push({
95
+ payload_hash: hash,
96
+ occurrences: hits.length,
97
+ hit_count: hitCount,
98
+ hit_rate: hitCount / hits.length,
99
+ });
100
+
101
+ if (hits.length === 1) {
102
+ unstable.n += 1;
103
+ if (hits[0] === true) unstable.hit_count += 1;
104
+ } else {
105
+ // Every occurrence AFTER the first (repeat dispatches of the same payload shape).
106
+ const repeats = hits.slice(1);
107
+ stable.n += repeats.length;
108
+ stable.hit_count += repeats.filter(Boolean).length;
109
+ }
110
+ }
111
+
112
+ groups.sort((a, b) => b.occurrences - a.occurrences || a.payload_hash.localeCompare(b.payload_hash));
113
+ stable.hit_rate = stable.n > 0 ? stable.hit_count / stable.n : null;
114
+ unstable.hit_rate = unstable.n > 0 ? unstable.hit_count / unstable.n : null;
115
+
116
+ const driftVisible = stable.hit_rate !== null && unstable.hit_rate !== null && stable.hit_rate > unstable.hit_rate;
117
+
118
+ return {
119
+ total_lines: lines.length,
120
+ lines_with_data: withData.length,
121
+ groups,
122
+ stable_cohort: stable,
123
+ unstable_cohort: unstable,
124
+ drift_visible: driftVisible,
125
+ };
126
+ }