@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
@@ -6,6 +6,20 @@
6
6
  // Local-JSONL swap replaces the upstream `mcp__claude-flow__memory_store`
7
7
  // dependency. Pricing constants are kept in sync with REFERENCE.md.
8
8
  //
9
+ // Dedup + main/subagent split, and the logic driving them, are mirrored
10
+ // (not imported) from `src/scripts/_lib/cc_transcript.ts`: this file ships
11
+ // to consumers as a plain `.mjs` run via bare `node` (see the `/cost:report`
12
+ // command doc), and `tsx` — the only thing in this repo that can execute a
13
+ // `.ts` module at runtime — is a devDependency, never shipped. A shared
14
+ // `.ts` import here would work in this repo's own dev shell and break for
15
+ // every consumer. On this repo's own transcripts, 50.3% of assistant/usage
16
+ // records in a single active session file are replays (message.id +
17
+ // requestId collide) — the resumed/compacted-session mechanic rewrites
18
+ // prior turns back into the transcript — so an un-deduped sum overstates
19
+ // real spend by roughly 2x, on top of never having counted subagent legs
20
+ // (they live in a sibling `<sessionId>/subagents/agent-*.jsonl` tree the
21
+ // old single-file read never visited).
22
+ //
9
23
  // Env:
10
24
  // TRACK_CWD=<path> override which project's sessions to scan
11
25
  // TRACK_SESSION=<file> pin to a specific session jsonl
@@ -15,17 +29,20 @@
15
29
  // TRACK_STORE=<path> override (default: agents/cost-tracking/sessions.jsonl)
16
30
 
17
31
  import { readFileSync, writeFileSync, readdirSync, statSync, existsSync, mkdirSync, appendFileSync } from 'node:fs';
18
- import { join, dirname } from 'node:path';
32
+ import { join, dirname, basename } from 'node:path';
19
33
  import { homedir } from 'node:os';
20
34
 
21
35
  const PROJECTS_DIR = join(homedir(), '.claude', 'projects');
22
36
  const DEFAULT_STORE = 'agents/cost-tracking/sessions.jsonl';
23
37
 
24
- // USD per 1M tokens.
38
+ // USD per 1M tokens. cache_write_5m / cache_write_1h are Anthropic's two
39
+ // cache-write TTL rates (1.25x / 2x of `input`) — a single flat rate here
40
+ // previously priced every write at the 5m rate regardless of the TTL the
41
+ // call actually used.
25
42
  const PRICING = {
26
- haiku: { input: 0.25, output: 1.25, cache_write: 0.30, cache_read: 0.03 },
27
- sonnet: { input: 3.00, output: 15.00, cache_write: 3.75, cache_read: 0.30 },
28
- opus: { input: 15.00, output: 75.00, cache_write: 18.75, cache_read: 1.50 },
43
+ haiku: { input: 0.25, output: 1.25, cache_write_5m: 0.30, cache_write_1h: 0.50, cache_read: 0.03 },
44
+ sonnet: { input: 3.00, output: 15.00, cache_write_5m: 3.75, cache_write_1h: 6.00, cache_read: 0.30 },
45
+ opus: { input: 15.00, output: 75.00, cache_write_5m: 18.75, cache_write_1h: 30.00, cache_read: 1.50 },
29
46
  };
30
47
 
31
48
  function modelTier(model) {
@@ -37,16 +54,59 @@ function modelTier(model) {
37
54
  return 'unknown';
38
55
  }
39
56
 
57
+ // A record's cache_creation_input_tokens is split into ephemeral_5m /
58
+ // ephemeral_1h by `usage.cache_creation` (see usageTokens()). Any part of
59
+ // cache_creation_input_tokens NOT covered by that split (older records that
60
+ // predate the TTL breakdown) is priced at the 5m rate — Anthropic's default
61
+ // TTL — rather than silently dropped.
40
62
  function costForUsage(tier, u) {
41
63
  const p = PRICING[tier];
42
64
  if (!p || !u) return 0;
65
+ const knownSplit = (u.ephemeral_5m_input_tokens || 0) + (u.ephemeral_1h_input_tokens || 0);
66
+ const unaccounted = Math.max(0, (u.cache_creation_input_tokens || 0) - knownSplit);
43
67
  return (u.input_tokens || 0) / 1e6 * p.input
44
68
  + (u.output_tokens || 0) / 1e6 * p.output
45
- + (u.cache_creation_input_tokens || 0) / 1e6 * p.cache_write
69
+ + ((u.ephemeral_5m_input_tokens || 0) + unaccounted) / 1e6 * p.cache_write_5m
70
+ + (u.ephemeral_1h_input_tokens || 0) / 1e6 * p.cache_write_1h
46
71
  + (u.cache_read_input_tokens || 0) / 1e6 * p.cache_read;
47
72
  }
48
73
 
49
- function encodeProjectPath(cwd) { return cwd.replace(/\//g, '-'); }
74
+ // Normalize a raw `message.usage` block into the flat shape costForUsage()
75
+ // and the model-tally accumulator both consume, pulling the TTL split out
76
+ // of the nested `cache_creation` object Anthropic ships it under.
77
+ function usageTokens(raw) {
78
+ const cc = (raw && raw.cache_creation) || {};
79
+ return {
80
+ input_tokens: Number(raw?.input_tokens) || 0,
81
+ output_tokens: Number(raw?.output_tokens) || 0,
82
+ cache_creation_input_tokens: Number(raw?.cache_creation_input_tokens) || 0,
83
+ cache_read_input_tokens: Number(raw?.cache_read_input_tokens) || 0,
84
+ ephemeral_5m_input_tokens: Number(cc.ephemeral_5m_input_tokens) || 0,
85
+ ephemeral_1h_input_tokens: Number(cc.ephemeral_1h_input_tokens) || 0,
86
+ };
87
+ }
88
+
89
+ // Subagent iff a non-empty top-level agentId OR isSidechain === true —
90
+ // both signals are checked because observed subagent transcripts carry
91
+ // both, but a differently-shaped one could carry only one.
92
+ function classifyBucket(rec) {
93
+ const hasAgentId = typeof rec.agentId === 'string' && rec.agentId.length > 0;
94
+ return (hasAgentId || rec.isSidechain === true) ? 'subagent' : 'main';
95
+ }
96
+
97
+ // message.id + requestId together identify one real API call; Claude Code
98
+ // can replay the same turn into more than one transcript file (see the
99
+ // header comment) and this is what collapses those replays back to one.
100
+ function dedupKey(rec) {
101
+ const id = typeof rec.message?.id === 'string' ? rec.message.id : '';
102
+ const reqId = typeof rec.requestId === 'string' ? rec.requestId : '';
103
+ return `${id} ${reqId}`;
104
+ }
105
+
106
+ // Claude Code encodes BOTH separators and dots: `/x/.claude/y` → `-x--claude-y`.
107
+ // Replacing only `/` never resolves a dotted path segment, so any cwd under
108
+ // `.claude/worktrees/` silently missed its project dir and exited 2.
109
+ function encodeProjectPath(cwd) { return cwd.replace(/[/.]/g, '-'); }
50
110
 
51
111
  function findProjectDir(cwd) {
52
112
  const c = join(PROJECTS_DIR, encodeProjectPath(cwd));
@@ -60,37 +120,101 @@ function findActiveSession(dir) {
60
120
  return e[0] ? join(dir, e[0].f) : null;
61
121
  }
62
122
 
63
- function summarizeSession(jsonlPath) {
64
- const lines = readFileSync(jsonlPath, 'utf-8').split('\n').filter(Boolean);
123
+ // Recursively list every *.jsonl under dir — how the sibling
124
+ // <sessionId>/subagents/agent-*.jsonl tree gets visited without a second
125
+ // code path.
126
+ function walkJsonl(dir) {
127
+ const out = [];
128
+ const stack = [dir];
129
+ while (stack.length > 0) {
130
+ const cur = stack.pop();
131
+ let entries;
132
+ try { entries = readdirSync(cur, { withFileTypes: true }); } catch { continue; }
133
+ for (const entry of entries) {
134
+ const full = join(cur, entry.name);
135
+ if (entry.isDirectory()) stack.push(full);
136
+ else if (entry.isFile() && entry.name.endsWith('.jsonl')) out.push(full);
137
+ }
138
+ }
139
+ return out;
140
+ }
141
+
142
+ // The active session's own file plus every transcript under its sibling
143
+ // <sessionId>/ directory (subagent legs, and any nested sub-subagent legs).
144
+ function collectSessionFiles(projectDir, sessionPath) {
145
+ const files = [sessionPath];
146
+ const sideDir = join(projectDir, basename(sessionPath, '.jsonl'));
147
+ if (existsSync(sideDir) && statSync(sideDir).isDirectory()) {
148
+ files.push(...walkJsonl(sideDir));
149
+ }
150
+ return files;
151
+ }
152
+
153
+ function emptyBucketSlot() {
154
+ return { messages: 0, input_tokens: 0, output_tokens: 0,
155
+ cache_creation_input_tokens: 0, cache_read_input_tokens: 0, cost_usd: 0 };
156
+ }
157
+
158
+ function summarizeSession(files) {
65
159
  const byModel = {};
66
160
  const byTier = { haiku: 0, sonnet: 0, opus: 0, unknown: 0 };
161
+ const byBucket = { main: emptyBucketSlot(), subagent: emptyBucketSlot() };
67
162
  let messageCount = 0, totalCost = 0, firstTs = null, lastTs = null;
68
163
  let sessionId = null, cwd = null;
69
- for (const line of lines) {
70
- let m; try { m = JSON.parse(line); } catch { continue; }
71
- if (!sessionId && m.sessionId) sessionId = m.sessionId;
72
- if (!cwd && m.cwd) cwd = m.cwd;
73
- if (m.timestamp) {
74
- if (!firstTs || m.timestamp < firstTs) firstTs = m.timestamp;
75
- if (!lastTs || m.timestamp > lastTs) lastTs = m.timestamp;
164
+ let totalSeen = 0;
165
+ const seen = new Set();
166
+
167
+ for (const file of files) {
168
+ let text;
169
+ try { text = readFileSync(file, 'utf-8'); } catch { continue; }
170
+ for (const line of text.split('\n')) {
171
+ if (!line.trim()) continue;
172
+ let m; try { m = JSON.parse(line); } catch { continue; }
173
+ if (!sessionId && m.sessionId) sessionId = m.sessionId;
174
+ if (!cwd && m.cwd) cwd = m.cwd;
175
+ if (m.timestamp) {
176
+ if (!firstTs || m.timestamp < firstTs) firstTs = m.timestamp;
177
+ if (!lastTs || m.timestamp > lastTs) lastTs = m.timestamp;
178
+ }
179
+ if (m.type !== 'assistant' || !m.message?.usage) continue;
180
+
181
+ totalSeen++;
182
+ const key = dedupKey(m);
183
+ if (seen.has(key)) continue; // replay — see the header comment
184
+ seen.add(key);
185
+
186
+ const bucket = classifyBucket(m);
187
+ const model = m.message.model || 'unknown';
188
+ const tier = modelTier(model);
189
+ const u = usageTokens(m.message.usage);
190
+ const cost = costForUsage(tier, u);
191
+
192
+ const slot = byModel[model] || { tier, input_tokens: 0, output_tokens: 0,
193
+ cache_creation_input_tokens: 0, cache_read_input_tokens: 0, messages: 0, cost_usd: 0 };
194
+ slot.input_tokens += u.input_tokens;
195
+ slot.output_tokens += u.output_tokens;
196
+ slot.cache_creation_input_tokens += u.cache_creation_input_tokens;
197
+ slot.cache_read_input_tokens += u.cache_read_input_tokens;
198
+ slot.messages++; slot.cost_usd += cost;
199
+ byModel[model] = slot;
200
+
201
+ const bs = byBucket[bucket];
202
+ bs.input_tokens += u.input_tokens;
203
+ bs.output_tokens += u.output_tokens;
204
+ bs.cache_creation_input_tokens += u.cache_creation_input_tokens;
205
+ bs.cache_read_input_tokens += u.cache_read_input_tokens;
206
+ bs.messages++; bs.cost_usd += cost;
207
+
208
+ messageCount++; byTier[tier] += cost; totalCost += cost;
76
209
  }
77
- if (m.type !== 'assistant' || !m.message?.usage) continue;
78
- messageCount++;
79
- const model = m.message.model || 'unknown';
80
- const tier = modelTier(model);
81
- const u = m.message.usage;
82
- const cost = costForUsage(tier, u);
83
- const slot = byModel[model] || { tier, input_tokens: 0, output_tokens: 0,
84
- cache_creation_input_tokens: 0, cache_read_input_tokens: 0, messages: 0, cost_usd: 0 };
85
- slot.input_tokens += u.input_tokens || 0;
86
- slot.output_tokens += u.output_tokens || 0;
87
- slot.cache_creation_input_tokens += u.cache_creation_input_tokens || 0;
88
- slot.cache_read_input_tokens += u.cache_read_input_tokens || 0;
89
- slot.messages++; slot.cost_usd += cost;
90
- byModel[model] = slot; byTier[tier] += cost; totalCost += cost;
91
210
  }
211
+
212
+ const dedupedCount = messageCount;
213
+ const dedup_ratio = totalSeen > 0 ? (totalSeen - dedupedCount) / totalSeen : 0;
92
214
  return { sessionId, cwd, startedAt: firstTs, endedAt: lastTs, messageCount,
93
- byModel, byTier, total_cost_usd: totalCost, capturedAt: new Date().toISOString() };
215
+ byModel, byTier, byBucket, total_cost_usd: totalCost,
216
+ totalRecordsSeen: totalSeen, dedupedRecordsCount: dedupedCount, dedup_ratio,
217
+ capturedAt: new Date().toISOString() };
94
218
  }
95
219
 
96
220
  function persistJsonl(summary, store) {
@@ -111,7 +235,8 @@ function main() {
111
235
  if (!sessionPath || !existsSync(sessionPath)) {
112
236
  console.error(`cost-track: no session jsonl in ${projectDir}`); process.exit(2);
113
237
  }
114
- const summary = summarizeSession(sessionPath);
238
+ const files = collectSessionFiles(projectDir, sessionPath);
239
+ const summary = summarizeSession(files);
115
240
  if (process.env.TRACK_OUT) writeFileSync(process.env.TRACK_OUT, JSON.stringify(summary, null, 2));
116
241
  const store = process.env.TRACK_STORE || DEFAULT_STORE;
117
242
  let res = { ok: false, reason: 'dry-run' };
@@ -125,7 +250,9 @@ function main() {
125
250
  console.log(`| Project | \`${summary.cwd}\` |`);
126
251
  console.log(`| First message | ${summary.startedAt} |`);
127
252
  console.log(`| Last message | ${summary.endedAt} |`);
128
- console.log(`| Assistant messages | ${summary.messageCount} |`);
253
+ console.log(`| Assistant messages (deduped) | ${summary.messageCount} |`);
254
+ console.log(`| Replay dedup ratio | ${(summary.dedup_ratio * 100).toFixed(1)}% (${summary.dedupedRecordsCount}/${summary.totalRecordsSeen} records kept) |`);
255
+ console.log(`| Transcript files scanned | ${files.length} |`);
129
256
  console.log(`| **Total cost** | **$${summary.total_cost_usd.toFixed(6)}** |`);
130
257
  console.log(`| Persisted | ${res.ok ? `\`${res.path}\`` : `**FAILED** (${res.reason})`} |`);
131
258
  console.log('\n## Per-model breakdown\n');
@@ -139,6 +266,14 @@ function main() {
139
266
  for (const [t, c] of Object.entries(summary.byTier).sort((a, b) => b[1] - a[1])) {
140
267
  if (c > 0) console.log(`| ${t} | $${c.toFixed(6)} |`);
141
268
  }
269
+ console.log('\n## Agent-bucket breakdown\n');
270
+ console.log('_main = the orchestrator session; subagent = Task-tool legs, previously uncounted or merged in._\n');
271
+ console.log('| Bucket | Messages | Input | Output | Cache write | Cache read | Cost |');
272
+ console.log('|---|---:|---:|---:|---:|---:|---:|');
273
+ for (const bucket of ['main', 'subagent']) {
274
+ const b = summary.byBucket[bucket];
275
+ console.log(`| ${bucket} | ${b.messages} | ${b.input_tokens} | ${b.output_tokens} | ${b.cache_creation_input_tokens} | ${b.cache_read_input_tokens} | $${b.cost_usd.toFixed(6)} |`);
276
+ }
142
277
  }
143
278
 
144
279
  main();
@@ -64,6 +64,11 @@ interface KvBucket {
64
64
  total_cost_usd: number;
65
65
  input_tokens: number;
66
66
  output_tokens: number;
67
+ // Additive (cost-summary/v1 stays additive-only per the schema doc):
68
+ // absent-on-row reads as 0 via `_int`, so rows written before this
69
+ // extension aggregate identically to explicit zeros.
70
+ cache_read_input_tokens: number;
71
+ cache_creation_input_tokens: number;
67
72
  telegraph_delta_tokens: number;
68
73
  }
69
74
 
@@ -73,6 +78,8 @@ function _zero_kv(): KvBucket {
73
78
  total_cost_usd: 0.0,
74
79
  input_tokens: 0,
75
80
  output_tokens: 0,
81
+ cache_read_input_tokens: 0,
82
+ cache_creation_input_tokens: 0,
76
83
  telegraph_delta_tokens: 0,
77
84
  };
78
85
  }
@@ -83,10 +90,21 @@ interface ModelBucket {
83
90
  total_cost_usd: number;
84
91
  input_tokens: number;
85
92
  output_tokens: number;
93
+ // Unlike telegraph fields, cache accounting IS model-scoped (the prompt
94
+ // cache itself is model-scoped — see pricing.ts), so by_model carries it.
95
+ cache_read_input_tokens: number;
96
+ cache_creation_input_tokens: number;
86
97
  }
87
98
 
88
99
  function _zero_model(): ModelBucket {
89
- return { sessions: 0, total_cost_usd: 0.0, input_tokens: 0, output_tokens: 0 };
100
+ return {
101
+ sessions: 0,
102
+ total_cost_usd: 0.0,
103
+ input_tokens: 0,
104
+ output_tokens: 0,
105
+ cache_read_input_tokens: 0,
106
+ cache_creation_input_tokens: 0,
107
+ };
90
108
  }
91
109
 
92
110
  /** Aggregate rows into the cost-summary structure (PyFloat-aware output). */
@@ -104,6 +122,8 @@ export function aggregate(rows: Row[]): Json {
104
122
  const cost = _float(row['total_cost_usd']);
105
123
  const itok = _int(row['input_tokens']);
106
124
  const otok = _int(row['output_tokens']);
125
+ const cread = _int(row['cache_read_input_tokens']);
126
+ const cwrite = _int(row['cache_creation_input_tokens']);
107
127
  const delta = _delta(row);
108
128
 
109
129
  const sessBucket = _getOr(by_sess, sid, _zero_kv);
@@ -113,6 +133,8 @@ export function aggregate(rows: Row[]): Json {
113
133
  bucket.total_cost_usd += cost;
114
134
  bucket.input_tokens += itok;
115
135
  bucket.output_tokens += otok;
136
+ bucket.cache_read_input_tokens += cread;
137
+ bucket.cache_creation_input_tokens += cwrite;
116
138
  bucket.telegraph_delta_tokens += delta;
117
139
  }
118
140
  const m = _getOr(by_model, model, _zero_model);
@@ -120,6 +142,8 @@ export function aggregate(rows: Row[]): Json {
120
142
  m.total_cost_usd += cost;
121
143
  m.input_tokens += itok;
122
144
  m.output_tokens += otok;
145
+ m.cache_read_input_tokens += cread;
146
+ m.cache_creation_input_tokens += cwrite;
123
147
  }
124
148
 
125
149
  return {
@@ -130,6 +154,8 @@ export function aggregate(rows: Row[]): Json {
130
154
  total_cost_usd: new PyFloat(totals.total_cost_usd),
131
155
  input_tokens: totals.input_tokens,
132
156
  output_tokens: totals.output_tokens,
157
+ cache_read_input_tokens: totals.cache_read_input_tokens,
158
+ cache_creation_input_tokens: totals.cache_creation_input_tokens,
133
159
  telegraph_delta_tokens: totals.telegraph_delta_tokens,
134
160
  telegraph_multiplier_version: MULTIPLIER_VERSION,
135
161
  telegraph_multiplier_active: MULTIPLIER_ACTIVE,
@@ -140,6 +166,8 @@ export function aggregate(rows: Row[]): Json {
140
166
  total_cost_usd: new PyFloat(v.total_cost_usd),
141
167
  input_tokens: v.input_tokens,
142
168
  output_tokens: v.output_tokens,
169
+ cache_read_input_tokens: v.cache_read_input_tokens,
170
+ cache_creation_input_tokens: v.cache_creation_input_tokens,
143
171
  telegraph_delta_tokens: v.telegraph_delta_tokens,
144
172
  })),
145
173
  by_conversation: _sortedEntries(by_conv).map(([k, v]) => ({
@@ -148,6 +176,8 @@ export function aggregate(rows: Row[]): Json {
148
176
  total_cost_usd: new PyFloat(v.total_cost_usd),
149
177
  input_tokens: v.input_tokens,
150
178
  output_tokens: v.output_tokens,
179
+ cache_read_input_tokens: v.cache_read_input_tokens,
180
+ cache_creation_input_tokens: v.cache_creation_input_tokens,
151
181
  telegraph_delta_tokens: v.telegraph_delta_tokens,
152
182
  })),
153
183
  by_model: _sortedEntries(by_model).map(([k, v]) => ({
@@ -156,6 +186,8 @@ export function aggregate(rows: Row[]): Json {
156
186
  total_cost_usd: new PyFloat(v.total_cost_usd),
157
187
  input_tokens: v.input_tokens,
158
188
  output_tokens: v.output_tokens,
189
+ cache_read_input_tokens: v.cache_read_input_tokens,
190
+ cache_creation_input_tokens: v.cache_creation_input_tokens,
159
191
  })),
160
192
  };
161
193
  }
@@ -444,6 +444,12 @@ function _synthesize_ai_council_block(cfg: CouncilConfig): Dict {
444
444
  if (m.model_ladder && m.model_ladder.length > 0) {
445
445
  entry['model_ladder'] = [...m.model_ladder];
446
446
  }
447
+ // road-to-cache-economy Phase 4: forward only an explicit override —
448
+ // the '5m' default needs no key, keeping the synthesized block
449
+ // byte-identical to pre-Phase-4 output when nobody opted in.
450
+ if (m.prompt_cache_ttl !== '5m') {
451
+ entry['prompt_cache_ttl'] = m.prompt_cache_ttl;
452
+ }
447
453
  members[name] = entry;
448
454
  }
449
455
  const advisors: Dict = {};
@@ -483,6 +489,7 @@ function _synthesize_ai_council_block(cfg: CouncilConfig): Dict {
483
489
  max_output_tokens: cfg.cost_budget.max_output_tokens,
484
490
  max_calls: cfg.cost_budget.max_calls,
485
491
  max_total_usd: cfg.cost_budget.max_total_usd,
492
+ daily_limit_usd: cfg.cost_budget.daily_limit_usd,
486
493
  },
487
494
  consensus_scoring: {
488
495
  enabled: cfg.consensus_scoring.enabled,
@@ -617,9 +624,16 @@ function build_members(settings: Dict, opts: BuildMembersOptions = {}): External
617
624
  // Council opts in explicitly (caching is client-default OFF): on
618
625
  // unless the operator sets `prompt_cache: false` on the member.
619
626
  const enable_prompt_cache = cfg['prompt_cache'] !== false;
627
+ // road-to-cache-economy Phase 4: absent → AnthropicClient's own
628
+ // '5m' default; only an explicit '1h' override reaches here.
629
+ const prompt_cache_ttl = (cfg['prompt_cache_ttl'] as '5m' | '1h' | undefined) ?? undefined;
620
630
  for (const sib_model of siblings[name] as string[]) {
621
631
  members.push(
622
- _construct_api_member(name, sib_model, { api_key_ref, enable_prompt_cache }),
632
+ _construct_api_member(name, sib_model, {
633
+ api_key_ref,
634
+ enable_prompt_cache,
635
+ prompt_cache_ttl,
636
+ }),
623
637
  );
624
638
  }
625
639
  continue;
@@ -632,6 +646,8 @@ function build_members(settings: Dict, opts: BuildMembersOptions = {}): External
632
646
  // Council opts in explicitly (client-default OFF); on unless
633
647
  // the operator sets `prompt_cache: false`.
634
648
  enable_prompt_cache: cfg['prompt_cache'] !== false,
649
+ // road-to-cache-economy Phase 4 — see the siblings branch above.
650
+ prompt_cache_ttl: (cfg['prompt_cache_ttl'] as '5m' | '1h' | undefined) ?? undefined,
635
651
  }),
636
652
  );
637
653
  } else if (mode === 'cli' && _CLI_PROVIDERS.has(name)) {
@@ -766,7 +782,11 @@ function _format_advisor_summary(
766
782
  function _construct_api_member(
767
783
  name: string,
768
784
  model: string | null,
769
- opts: { api_key_ref?: string | null; enable_prompt_cache?: boolean | undefined } = {},
785
+ opts: {
786
+ api_key_ref?: string | null;
787
+ enable_prompt_cache?: boolean | undefined;
788
+ prompt_cache_ttl?: '5m' | '1h' | undefined;
789
+ } = {},
770
790
  ): ExternalAIClient {
771
791
  const api_key_ref = opts.api_key_ref ?? null;
772
792
  if (name === 'anthropic') {
@@ -777,6 +797,7 @@ function _construct_api_member(
777
797
  model: model || 'claude-sonnet-4-5',
778
798
  api_key,
779
799
  enable_prompt_cache: opts.enable_prompt_cache,
800
+ prompt_cache_ttl: opts.prompt_cache_ttl,
780
801
  });
781
802
  }
782
803
  if (name === 'openai') {
@@ -2020,6 +2041,11 @@ function cmd_run(
2020
2041
  max_output_tokens: _pyInt(cost_cfg['max_output_tokens'] ?? 20_000, 20_000),
2021
2042
  max_calls: _pyInt(cost_cfg['max_calls'] ?? 10, 10),
2022
2043
  max_total_usd: _pyFloat(cost_cfg['max_total_usd'] ?? 0.0, 0.0) || 0.0,
2044
+ // Rolling 24h cap. Unwired until now: the field existed on CostBudget and
2045
+ // gated the spend-ledger append, but no caller ever passed it, so the
2046
+ // ledger could not be written at all — an archived acceptance criterion
2047
+ // claimed otherwise. 0 keeps the cap disabled, which stays the default.
2048
+ daily_limit_usd: _pyFloat(cost_cfg['daily_limit_usd'] ?? 0.0, 0.0) || 0.0,
2023
2049
  });
2024
2050
  const rounds = _resolve_rounds(args, ai_cfg);
2025
2051
  // Phase 1: stance tally — defensive read; malformed/absent block reads as off.
@@ -2184,6 +2210,11 @@ function _write_debate_round(
2184
2210
  table: PriceTable;
2185
2211
  prompt_mode: string | null;
2186
2212
  prose_synthesis: boolean | null;
2213
+ // road-to-cache-economy Phase 4: the observed wall-clock gap (ms)
2214
+ // between the previous round finishing and this round starting —
2215
+ // `null`/absent on round 1, since nothing was written to the
2216
+ // prompt cache yet. See `run_debate`'s `on_round_complete`.
2217
+ cache_gap_ms_since_previous_round?: number | null | undefined;
2187
2218
  },
2188
2219
  ): string {
2189
2220
  fs.mkdirSync(_resolveTarget(out_dir), { recursive: true });
@@ -2207,6 +2238,7 @@ function _write_debate_round(
2207
2238
  debate_total_rounds: opts.total_planned_rounds,
2208
2239
  rounds: 1,
2209
2240
  cost_usd_actual: _pyRound(actual_total, 6),
2241
+ prompt_cache_round_gap_ms: opts.cache_gap_ms_since_previous_round ?? null,
2210
2242
  responses: _serialise_responses(responses),
2211
2243
  };
2212
2244
  const out_path = path.join(_resolveTarget(out_dir), _debate_round_filename(round_number));
@@ -2410,6 +2442,11 @@ function cmd_debate(
2410
2442
  max_output_tokens: _pyInt(cost_cfg['max_output_tokens'] ?? 20_000, 20_000),
2411
2443
  max_calls: _pyInt(cost_cfg['max_calls'] ?? 10, 10),
2412
2444
  max_total_usd: _pyFloat(cost_cfg['max_total_usd'] ?? 0.0, 0.0) || 0.0,
2445
+ // Rolling 24h cap. Unwired until now: the field existed on CostBudget and
2446
+ // gated the spend-ledger append, but no caller ever passed it, so the
2447
+ // ledger could not be written at all — an archived acceptance criterion
2448
+ // claimed otherwise. 0 keeps the cap disabled, which stays the default.
2449
+ daily_limit_usd: _pyFloat(cost_cfg['daily_limit_usd'] ?? 0.0, 0.0) || 0.0,
2413
2450
  });
2414
2451
 
2415
2452
  const out_dir = _validate_council_output_path(args.output as string, {
@@ -2427,7 +2464,11 @@ function cmd_debate(
2427
2464
 
2428
2465
  const written: string[] = [];
2429
2466
 
2430
- const _on_round_complete = (round_number: number, results: CouncilResponse[]): void => {
2467
+ const _on_round_complete = (
2468
+ round_number: number,
2469
+ results: CouncilResponse[],
2470
+ cache_gap_ms_since_previous_round?: number | null,
2471
+ ): void => {
2431
2472
  const p = _write_debate_round(out_dir, round_number, results, {
2432
2473
  question,
2433
2474
  members: members as ExternalAIClient[],
@@ -2437,6 +2478,7 @@ function cmd_debate(
2437
2478
  table: table as PriceTable,
2438
2479
  prompt_mode: 'debate',
2439
2480
  prose_synthesis: _getattr<boolean | null>(args, 'prose_synthesis', null),
2481
+ cache_gap_ms_since_previous_round,
2440
2482
  });
2441
2483
  written.push(p);
2442
2484
  const errors = results.filter((r) => r.error);
Binary file