gentyr 1.3.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 (599) hide show
  1. package/.claude/agents/antipattern-hunter.md +176 -0
  2. package/.claude/agents/code-reviewer.md +205 -0
  3. package/.claude/agents/code-writer.md +154 -0
  4. package/.claude/agents/deputy-cto.md +309 -0
  5. package/.claude/agents/feedback-agent.md +101 -0
  6. package/.claude/agents/investigator.md +136 -0
  7. package/.claude/agents/product-manager.md +97 -0
  8. package/.claude/agents/project-manager.md +116 -0
  9. package/.claude/agents/repo-hygiene-expert.md +626 -0
  10. package/.claude/agents/secret-manager.md +324 -0
  11. package/.claude/agents/test-writer.md +354 -0
  12. package/.claude/commands/configure-personas.md +144 -0
  13. package/.claude/commands/cto-report.md +36 -0
  14. package/.claude/commands/demo.md +89 -0
  15. package/.claude/commands/deputy-cto.md +345 -0
  16. package/.claude/commands/hotfix.md +31 -0
  17. package/.claude/commands/overdrive-gentyr.md +167 -0
  18. package/.claude/commands/product-manager.md +32 -0
  19. package/.claude/commands/push-migrations.md +86 -0
  20. package/.claude/commands/push-secrets.md +97 -0
  21. package/.claude/commands/services.json.example +30 -0
  22. package/.claude/commands/setup-gentyr.md +396 -0
  23. package/.claude/commands/show.md +42 -0
  24. package/.claude/commands/spawn-tasks.md +79 -0
  25. package/.claude/commands/toggle-automation-gentyr.md +75 -0
  26. package/.claude/commands/toggle-product-manager.md +19 -0
  27. package/.claude/commands/triage.md +69 -0
  28. package/.claude/hooks/README.md +686 -0
  29. package/.claude/hooks/__tests__/README.md +129 -0
  30. package/.claude/hooks/agent-tracker.js +434 -0
  31. package/.claude/hooks/antipattern-hunter-hook.js +401 -0
  32. package/.claude/hooks/api-key-watcher.js +289 -0
  33. package/.claude/hooks/block-no-verify.js +301 -0
  34. package/.claude/hooks/bypass-approval-hook.js +313 -0
  35. package/.claude/hooks/compliance-checker.js +1309 -0
  36. package/.claude/hooks/config-reader.js +143 -0
  37. package/.claude/hooks/credential-file-guard.js +1139 -0
  38. package/.claude/hooks/credential-health-check.js +168 -0
  39. package/.claude/hooks/credential-sync-hook.js +79 -0
  40. package/.claude/hooks/cto-notification-hook.js +656 -0
  41. package/.claude/hooks/feedback-launcher.js +424 -0
  42. package/.claude/hooks/feedback-orchestrator.js +367 -0
  43. package/.claude/hooks/gentyr-splash.js +47 -0
  44. package/.claude/hooks/gentyr-sync.js +389 -0
  45. package/.claude/hooks/hourly-automation.js +3340 -0
  46. package/.claude/hooks/key-sync.js +899 -0
  47. package/.claude/hooks/lib/approval-utils.js +731 -0
  48. package/.claude/hooks/lib/feature-branch-helper.js +102 -0
  49. package/.claude/hooks/lib/worktree-manager.js +330 -0
  50. package/.claude/hooks/mapping-validator.js +285 -0
  51. package/.claude/hooks/plan-executor.js +398 -0
  52. package/.claude/hooks/playwright-cli-guard.js +104 -0
  53. package/.claude/hooks/playwright-health-check.js +71 -0
  54. package/.claude/hooks/pre-commit-review.js +725 -0
  55. package/.claude/hooks/prompts/local-spec-enforcement.md +310 -0
  56. package/.claude/hooks/prompts/mapping-fix.md +92 -0
  57. package/.claude/hooks/prompts/mapping-review.md +140 -0
  58. package/.claude/hooks/prompts/schema-mapper.md +185 -0
  59. package/.claude/hooks/prompts/spec-enforcement.md +233 -0
  60. package/.claude/hooks/protected-action-approval-hook.js +336 -0
  61. package/.claude/hooks/protected-action-gate.js +562 -0
  62. package/.claude/hooks/protected-actions.json +208 -0
  63. package/.claude/hooks/protected-actions.json.template +122 -0
  64. package/.claude/hooks/quota-monitor.js +490 -0
  65. package/.claude/hooks/reporters/jest-failure-reporter.js +401 -0
  66. package/.claude/hooks/reporters/playwright-failure-reporter.js +446 -0
  67. package/.claude/hooks/reporters/vitest-failure-reporter.js +443 -0
  68. package/.claude/hooks/schema-mapper-hook.js +544 -0
  69. package/.claude/hooks/secret-leak-detector.js +216 -0
  70. package/.claude/hooks/session-reviver.js +514 -0
  71. package/.claude/hooks/slash-command-prefetch.js +1145 -0
  72. package/.claude/hooks/stale-work-detector.js +205 -0
  73. package/.claude/hooks/stop-continue-hook.js +414 -0
  74. package/.claude/hooks/todo-maintenance.js +522 -0
  75. package/.claude/hooks/todo-processing-prompt.md +75 -0
  76. package/.claude/hooks/usage-optimizer.js +791 -0
  77. package/.claude/mcp/README.md +246 -0
  78. package/.claude/settings.json.template +168 -0
  79. package/.mcp.json.template +207 -0
  80. package/CLAUDE.md +340 -0
  81. package/CLAUDE.md.gentyr-section +89 -0
  82. package/LICENSE +21 -0
  83. package/README.md +297 -0
  84. package/cli/commands/init.js +471 -0
  85. package/cli/commands/migrate.js +132 -0
  86. package/cli/commands/protect.js +271 -0
  87. package/cli/commands/scaffold.js +48 -0
  88. package/cli/commands/status.js +133 -0
  89. package/cli/commands/sync.js +101 -0
  90. package/cli/commands/uninstall.js +207 -0
  91. package/cli/index.js +111 -0
  92. package/cli/lib/config-gen.js +214 -0
  93. package/cli/lib/resolve-framework.js +97 -0
  94. package/cli/lib/state.js +140 -0
  95. package/cli/lib/symlinks.js +260 -0
  96. package/docs/AUTOMATION-SYSTEMS.md +484 -0
  97. package/docs/BINARY-PATCHING.md +212 -0
  98. package/docs/CHANGELOG.md +2830 -0
  99. package/docs/CREDENTIAL-DETECTION.md +151 -0
  100. package/docs/CTO-DASHBOARD.md +476 -0
  101. package/docs/DEPLOYMENT-FLOW.md +477 -0
  102. package/docs/DEVELOPER.md +116 -0
  103. package/docs/Executive.md +372 -0
  104. package/docs/SECRET-PATHS.md +77 -0
  105. package/docs/SETUP-GUIDE.md +419 -0
  106. package/docs/STACK.md +109 -0
  107. package/docs/TESTING.md +440 -0
  108. package/docs/assets/claude-logo.svg +3 -0
  109. package/docs/sessions/2026-01-24-spec-suite-implementation.md +190 -0
  110. package/docs/sessions/2026-02-15-feedback-e2e-audit.md +484 -0
  111. package/docs/sessions/2026-02-20-credential-rotation-experiments.md +340 -0
  112. package/docs/sessions/TEST-COVERAGE-REPORT-2026-02-20.md +168 -0
  113. package/docs/shared/EPHEMERAL-STATE-FILES.md +115 -0
  114. package/docs/shared/PROTECTION-SYSTEM.md +341 -0
  115. package/husky/post-commit +10 -0
  116. package/husky/pre-commit +40 -0
  117. package/husky/pre-push +94 -0
  118. package/package.json +43 -0
  119. package/packages/cto-dashboard/package-lock.json +3510 -0
  120. package/packages/cto-dashboard/package.json +41 -0
  121. package/packages/cto-dashboard/pnpm-lock.yaml +2168 -0
  122. package/packages/mcp-servers/dist/__testUtils__/fixtures.d.ts +220 -0
  123. package/packages/mcp-servers/dist/__testUtils__/fixtures.d.ts.map +1 -0
  124. package/packages/mcp-servers/dist/__testUtils__/fixtures.js +376 -0
  125. package/packages/mcp-servers/dist/__testUtils__/fixtures.js.map +1 -0
  126. package/packages/mcp-servers/dist/__testUtils__/index.d.ts +121 -0
  127. package/packages/mcp-servers/dist/__testUtils__/index.d.ts.map +1 -0
  128. package/packages/mcp-servers/dist/__testUtils__/index.js +180 -0
  129. package/packages/mcp-servers/dist/__testUtils__/index.js.map +1 -0
  130. package/packages/mcp-servers/dist/__testUtils__/schemas.d.ts +84 -0
  131. package/packages/mcp-servers/dist/__testUtils__/schemas.d.ts.map +1 -0
  132. package/packages/mcp-servers/dist/__testUtils__/schemas.js +309 -0
  133. package/packages/mcp-servers/dist/__testUtils__/schemas.js.map +1 -0
  134. package/packages/mcp-servers/dist/agent-reports/index.d.ts +7 -0
  135. package/packages/mcp-servers/dist/agent-reports/index.d.ts.map +1 -0
  136. package/packages/mcp-servers/dist/agent-reports/index.js +8 -0
  137. package/packages/mcp-servers/dist/agent-reports/index.js.map +1 -0
  138. package/packages/mcp-servers/dist/agent-reports/server.d.ts +22 -0
  139. package/packages/mcp-servers/dist/agent-reports/server.d.ts.map +1 -0
  140. package/packages/mcp-servers/dist/agent-reports/server.js +535 -0
  141. package/packages/mcp-servers/dist/agent-reports/server.js.map +1 -0
  142. package/packages/mcp-servers/dist/agent-reports/types.d.ts +258 -0
  143. package/packages/mcp-servers/dist/agent-reports/types.d.ts.map +1 -0
  144. package/packages/mcp-servers/dist/agent-reports/types.js +81 -0
  145. package/packages/mcp-servers/dist/agent-reports/types.js.map +1 -0
  146. package/packages/mcp-servers/dist/agent-tracker/index.d.ts +5 -0
  147. package/packages/mcp-servers/dist/agent-tracker/index.d.ts.map +1 -0
  148. package/packages/mcp-servers/dist/agent-tracker/index.js +5 -0
  149. package/packages/mcp-servers/dist/agent-tracker/index.js.map +1 -0
  150. package/packages/mcp-servers/dist/agent-tracker/server.d.ts +12 -0
  151. package/packages/mcp-servers/dist/agent-tracker/server.d.ts.map +1 -0
  152. package/packages/mcp-servers/dist/agent-tracker/server.js +919 -0
  153. package/packages/mcp-servers/dist/agent-tracker/server.js.map +1 -0
  154. package/packages/mcp-servers/dist/agent-tracker/types.d.ts +328 -0
  155. package/packages/mcp-servers/dist/agent-tracker/types.d.ts.map +1 -0
  156. package/packages/mcp-servers/dist/agent-tracker/types.js +128 -0
  157. package/packages/mcp-servers/dist/agent-tracker/types.js.map +1 -0
  158. package/packages/mcp-servers/dist/chrome-bridge/browser-tips.d.ts +27 -0
  159. package/packages/mcp-servers/dist/chrome-bridge/browser-tips.d.ts.map +1 -0
  160. package/packages/mcp-servers/dist/chrome-bridge/browser-tips.js +167 -0
  161. package/packages/mcp-servers/dist/chrome-bridge/browser-tips.js.map +1 -0
  162. package/packages/mcp-servers/dist/chrome-bridge/index.d.ts +6 -0
  163. package/packages/mcp-servers/dist/chrome-bridge/index.d.ts.map +1 -0
  164. package/packages/mcp-servers/dist/chrome-bridge/index.js +6 -0
  165. package/packages/mcp-servers/dist/chrome-bridge/index.js.map +1 -0
  166. package/packages/mcp-servers/dist/chrome-bridge/server.d.ts +13 -0
  167. package/packages/mcp-servers/dist/chrome-bridge/server.d.ts.map +1 -0
  168. package/packages/mcp-servers/dist/chrome-bridge/server.js +959 -0
  169. package/packages/mcp-servers/dist/chrome-bridge/server.js.map +1 -0
  170. package/packages/mcp-servers/dist/chrome-bridge/types.d.ts +41 -0
  171. package/packages/mcp-servers/dist/chrome-bridge/types.d.ts.map +1 -0
  172. package/packages/mcp-servers/dist/chrome-bridge/types.js +8 -0
  173. package/packages/mcp-servers/dist/chrome-bridge/types.js.map +1 -0
  174. package/packages/mcp-servers/dist/cloudflare/index.d.ts +8 -0
  175. package/packages/mcp-servers/dist/cloudflare/index.d.ts.map +1 -0
  176. package/packages/mcp-servers/dist/cloudflare/index.js +8 -0
  177. package/packages/mcp-servers/dist/cloudflare/index.js.map +1 -0
  178. package/packages/mcp-servers/dist/cloudflare/server.d.ts +16 -0
  179. package/packages/mcp-servers/dist/cloudflare/server.d.ts.map +1 -0
  180. package/packages/mcp-servers/dist/cloudflare/server.js +253 -0
  181. package/packages/mcp-servers/dist/cloudflare/server.js.map +1 -0
  182. package/packages/mcp-servers/dist/cloudflare/types.d.ts +141 -0
  183. package/packages/mcp-servers/dist/cloudflare/types.d.ts.map +1 -0
  184. package/packages/mcp-servers/dist/cloudflare/types.js +53 -0
  185. package/packages/mcp-servers/dist/cloudflare/types.js.map +1 -0
  186. package/packages/mcp-servers/dist/codecov/index.d.ts +7 -0
  187. package/packages/mcp-servers/dist/codecov/index.d.ts.map +1 -0
  188. package/packages/mcp-servers/dist/codecov/index.js +7 -0
  189. package/packages/mcp-servers/dist/codecov/index.js.map +1 -0
  190. package/packages/mcp-servers/dist/codecov/server.d.ts +21 -0
  191. package/packages/mcp-servers/dist/codecov/server.d.ts.map +1 -0
  192. package/packages/mcp-servers/dist/codecov/server.js +376 -0
  193. package/packages/mcp-servers/dist/codecov/server.js.map +1 -0
  194. package/packages/mcp-servers/dist/codecov/types.d.ts +269 -0
  195. package/packages/mcp-servers/dist/codecov/types.d.ts.map +1 -0
  196. package/packages/mcp-servers/dist/codecov/types.js +128 -0
  197. package/packages/mcp-servers/dist/codecov/types.js.map +1 -0
  198. package/packages/mcp-servers/dist/cto-report/index.d.ts +9 -0
  199. package/packages/mcp-servers/dist/cto-report/index.d.ts.map +1 -0
  200. package/packages/mcp-servers/dist/cto-report/index.js +9 -0
  201. package/packages/mcp-servers/dist/cto-report/index.js.map +1 -0
  202. package/packages/mcp-servers/dist/cto-report/server.d.ts +14 -0
  203. package/packages/mcp-servers/dist/cto-report/server.d.ts.map +1 -0
  204. package/packages/mcp-servers/dist/cto-report/server.js +859 -0
  205. package/packages/mcp-servers/dist/cto-report/server.js.map +1 -0
  206. package/packages/mcp-servers/dist/cto-report/types.d.ts +213 -0
  207. package/packages/mcp-servers/dist/cto-report/types.d.ts.map +1 -0
  208. package/packages/mcp-servers/dist/cto-report/types.js +29 -0
  209. package/packages/mcp-servers/dist/cto-report/types.js.map +1 -0
  210. package/packages/mcp-servers/dist/cto-reports/index.d.ts +7 -0
  211. package/packages/mcp-servers/dist/cto-reports/index.d.ts.map +1 -0
  212. package/packages/mcp-servers/dist/cto-reports/index.js +8 -0
  213. package/packages/mcp-servers/dist/cto-reports/index.js.map +1 -0
  214. package/packages/mcp-servers/dist/cto-reports/server.d.ts +20 -0
  215. package/packages/mcp-servers/dist/cto-reports/server.d.ts.map +1 -0
  216. package/packages/mcp-servers/dist/cto-reports/server.js +538 -0
  217. package/packages/mcp-servers/dist/cto-reports/server.js.map +1 -0
  218. package/packages/mcp-servers/dist/cto-reports/types.d.ts +236 -0
  219. package/packages/mcp-servers/dist/cto-reports/types.d.ts.map +1 -0
  220. package/packages/mcp-servers/dist/cto-reports/types.js +77 -0
  221. package/packages/mcp-servers/dist/cto-reports/types.js.map +1 -0
  222. package/packages/mcp-servers/dist/deputy-cto/index.d.ts +7 -0
  223. package/packages/mcp-servers/dist/deputy-cto/index.d.ts.map +1 -0
  224. package/packages/mcp-servers/dist/deputy-cto/index.js +8 -0
  225. package/packages/mcp-servers/dist/deputy-cto/index.js.map +1 -0
  226. package/packages/mcp-servers/dist/deputy-cto/server.d.ts +23 -0
  227. package/packages/mcp-servers/dist/deputy-cto/server.d.ts.map +1 -0
  228. package/packages/mcp-servers/dist/deputy-cto/server.js +1700 -0
  229. package/packages/mcp-servers/dist/deputy-cto/server.js.map +1 -0
  230. package/packages/mcp-servers/dist/deputy-cto/types.d.ts +439 -0
  231. package/packages/mcp-servers/dist/deputy-cto/types.d.ts.map +1 -0
  232. package/packages/mcp-servers/dist/deputy-cto/types.js +102 -0
  233. package/packages/mcp-servers/dist/deputy-cto/types.js.map +1 -0
  234. package/packages/mcp-servers/dist/elastic-logs/index.d.ts +5 -0
  235. package/packages/mcp-servers/dist/elastic-logs/index.d.ts.map +1 -0
  236. package/packages/mcp-servers/dist/elastic-logs/index.js +5 -0
  237. package/packages/mcp-servers/dist/elastic-logs/index.js.map +1 -0
  238. package/packages/mcp-servers/dist/elastic-logs/server.d.ts +18 -0
  239. package/packages/mcp-servers/dist/elastic-logs/server.d.ts.map +1 -0
  240. package/packages/mcp-servers/dist/elastic-logs/server.js +259 -0
  241. package/packages/mcp-servers/dist/elastic-logs/server.js.map +1 -0
  242. package/packages/mcp-servers/dist/elastic-logs/types.d.ts +107 -0
  243. package/packages/mcp-servers/dist/elastic-logs/types.d.ts.map +1 -0
  244. package/packages/mcp-servers/dist/elastic-logs/types.js +31 -0
  245. package/packages/mcp-servers/dist/elastic-logs/types.js.map +1 -0
  246. package/packages/mcp-servers/dist/feedback-explorer/index.d.ts +2 -0
  247. package/packages/mcp-servers/dist/feedback-explorer/index.d.ts.map +1 -0
  248. package/packages/mcp-servers/dist/feedback-explorer/index.js +2 -0
  249. package/packages/mcp-servers/dist/feedback-explorer/index.js.map +1 -0
  250. package/packages/mcp-servers/dist/feedback-explorer/server.d.ts +21 -0
  251. package/packages/mcp-servers/dist/feedback-explorer/server.d.ts.map +1 -0
  252. package/packages/mcp-servers/dist/feedback-explorer/server.js +580 -0
  253. package/packages/mcp-servers/dist/feedback-explorer/server.js.map +1 -0
  254. package/packages/mcp-servers/dist/feedback-explorer/types.d.ts +331 -0
  255. package/packages/mcp-servers/dist/feedback-explorer/types.d.ts.map +1 -0
  256. package/packages/mcp-servers/dist/feedback-explorer/types.js +40 -0
  257. package/packages/mcp-servers/dist/feedback-explorer/types.js.map +1 -0
  258. package/packages/mcp-servers/dist/feedback-reporter/index.d.ts +9 -0
  259. package/packages/mcp-servers/dist/feedback-reporter/index.d.ts.map +1 -0
  260. package/packages/mcp-servers/dist/feedback-reporter/index.js +9 -0
  261. package/packages/mcp-servers/dist/feedback-reporter/index.js.map +1 -0
  262. package/packages/mcp-servers/dist/feedback-reporter/server.d.ts +36 -0
  263. package/packages/mcp-servers/dist/feedback-reporter/server.d.ts.map +1 -0
  264. package/packages/mcp-servers/dist/feedback-reporter/server.js +392 -0
  265. package/packages/mcp-servers/dist/feedback-reporter/server.js.map +1 -0
  266. package/packages/mcp-servers/dist/feedback-reporter/types.d.ts +152 -0
  267. package/packages/mcp-servers/dist/feedback-reporter/types.d.ts.map +1 -0
  268. package/packages/mcp-servers/dist/feedback-reporter/types.js +67 -0
  269. package/packages/mcp-servers/dist/feedback-reporter/types.js.map +1 -0
  270. package/packages/mcp-servers/dist/github/index.d.ts +7 -0
  271. package/packages/mcp-servers/dist/github/index.d.ts.map +1 -0
  272. package/packages/mcp-servers/dist/github/index.js +7 -0
  273. package/packages/mcp-servers/dist/github/index.js.map +1 -0
  274. package/packages/mcp-servers/dist/github/server.d.ts +15 -0
  275. package/packages/mcp-servers/dist/github/server.d.ts.map +1 -0
  276. package/packages/mcp-servers/dist/github/server.js +686 -0
  277. package/packages/mcp-servers/dist/github/server.js.map +1 -0
  278. package/packages/mcp-servers/dist/github/types.d.ts +660 -0
  279. package/packages/mcp-servers/dist/github/types.d.ts.map +1 -0
  280. package/packages/mcp-servers/dist/github/types.js +209 -0
  281. package/packages/mcp-servers/dist/github/types.js.map +1 -0
  282. package/packages/mcp-servers/dist/index.d.ts +30 -0
  283. package/packages/mcp-servers/dist/index.d.ts.map +1 -0
  284. package/packages/mcp-servers/dist/index.js +32 -0
  285. package/packages/mcp-servers/dist/index.js.map +1 -0
  286. package/packages/mcp-servers/dist/makerkit-docs/index.d.ts +5 -0
  287. package/packages/mcp-servers/dist/makerkit-docs/index.d.ts.map +1 -0
  288. package/packages/mcp-servers/dist/makerkit-docs/index.js +5 -0
  289. package/packages/mcp-servers/dist/makerkit-docs/index.js.map +1 -0
  290. package/packages/mcp-servers/dist/makerkit-docs/server.d.ts +15 -0
  291. package/packages/mcp-servers/dist/makerkit-docs/server.d.ts.map +1 -0
  292. package/packages/mcp-servers/dist/makerkit-docs/server.js +252 -0
  293. package/packages/mcp-servers/dist/makerkit-docs/server.js.map +1 -0
  294. package/packages/mcp-servers/dist/makerkit-docs/types.d.ts +74 -0
  295. package/packages/mcp-servers/dist/makerkit-docs/types.d.ts.map +1 -0
  296. package/packages/mcp-servers/dist/makerkit-docs/types.js +20 -0
  297. package/packages/mcp-servers/dist/makerkit-docs/types.js.map +1 -0
  298. package/packages/mcp-servers/dist/onepassword/index.d.ts +2 -0
  299. package/packages/mcp-servers/dist/onepassword/index.d.ts.map +1 -0
  300. package/packages/mcp-servers/dist/onepassword/index.js +2 -0
  301. package/packages/mcp-servers/dist/onepassword/index.js.map +1 -0
  302. package/packages/mcp-servers/dist/onepassword/server.d.ts +2 -0
  303. package/packages/mcp-servers/dist/onepassword/server.d.ts.map +1 -0
  304. package/packages/mcp-servers/dist/onepassword/server.js +159 -0
  305. package/packages/mcp-servers/dist/onepassword/server.js.map +1 -0
  306. package/packages/mcp-servers/dist/onepassword/types.d.ts +55 -0
  307. package/packages/mcp-servers/dist/onepassword/types.d.ts.map +1 -0
  308. package/packages/mcp-servers/dist/onepassword/types.js +22 -0
  309. package/packages/mcp-servers/dist/onepassword/types.js.map +1 -0
  310. package/packages/mcp-servers/dist/playwright/helpers.d.ts +20 -0
  311. package/packages/mcp-servers/dist/playwright/helpers.d.ts.map +1 -0
  312. package/packages/mcp-servers/dist/playwright/helpers.js +31 -0
  313. package/packages/mcp-servers/dist/playwright/helpers.js.map +1 -0
  314. package/packages/mcp-servers/dist/playwright/index.d.ts +5 -0
  315. package/packages/mcp-servers/dist/playwright/index.d.ts.map +1 -0
  316. package/packages/mcp-servers/dist/playwright/index.js +5 -0
  317. package/packages/mcp-servers/dist/playwright/index.js.map +1 -0
  318. package/packages/mcp-servers/dist/playwright/server.d.ts +13 -0
  319. package/packages/mcp-servers/dist/playwright/server.d.ts.map +1 -0
  320. package/packages/mcp-servers/dist/playwright/server.js +1201 -0
  321. package/packages/mcp-servers/dist/playwright/server.js.map +1 -0
  322. package/packages/mcp-servers/dist/playwright/types.d.ts +216 -0
  323. package/packages/mcp-servers/dist/playwright/types.d.ts.map +1 -0
  324. package/packages/mcp-servers/dist/playwright/types.js +172 -0
  325. package/packages/mcp-servers/dist/playwright/types.js.map +1 -0
  326. package/packages/mcp-servers/dist/playwright-feedback/browser-manager.d.ts +39 -0
  327. package/packages/mcp-servers/dist/playwright-feedback/browser-manager.d.ts.map +1 -0
  328. package/packages/mcp-servers/dist/playwright-feedback/browser-manager.js +71 -0
  329. package/packages/mcp-servers/dist/playwright-feedback/browser-manager.js.map +1 -0
  330. package/packages/mcp-servers/dist/playwright-feedback/index.d.ts +5 -0
  331. package/packages/mcp-servers/dist/playwright-feedback/index.d.ts.map +1 -0
  332. package/packages/mcp-servers/dist/playwright-feedback/index.js +5 -0
  333. package/packages/mcp-servers/dist/playwright-feedback/index.js.map +1 -0
  334. package/packages/mcp-servers/dist/playwright-feedback/server.d.ts +34 -0
  335. package/packages/mcp-servers/dist/playwright-feedback/server.d.ts.map +1 -0
  336. package/packages/mcp-servers/dist/playwright-feedback/server.js +538 -0
  337. package/packages/mcp-servers/dist/playwright-feedback/server.js.map +1 -0
  338. package/packages/mcp-servers/dist/playwright-feedback/types.d.ts +305 -0
  339. package/packages/mcp-servers/dist/playwright-feedback/types.d.ts.map +1 -0
  340. package/packages/mcp-servers/dist/playwright-feedback/types.js +123 -0
  341. package/packages/mcp-servers/dist/playwright-feedback/types.js.map +1 -0
  342. package/packages/mcp-servers/dist/product-manager/server.d.ts +17 -0
  343. package/packages/mcp-servers/dist/product-manager/server.d.ts.map +1 -0
  344. package/packages/mcp-servers/dist/product-manager/server.js +690 -0
  345. package/packages/mcp-servers/dist/product-manager/server.js.map +1 -0
  346. package/packages/mcp-servers/dist/product-manager/types.d.ts +286 -0
  347. package/packages/mcp-servers/dist/product-manager/types.d.ts.map +1 -0
  348. package/packages/mcp-servers/dist/product-manager/types.js +99 -0
  349. package/packages/mcp-servers/dist/product-manager/types.js.map +1 -0
  350. package/packages/mcp-servers/dist/programmatic-feedback/index.d.ts +7 -0
  351. package/packages/mcp-servers/dist/programmatic-feedback/index.d.ts.map +1 -0
  352. package/packages/mcp-servers/dist/programmatic-feedback/index.js +7 -0
  353. package/packages/mcp-servers/dist/programmatic-feedback/index.js.map +1 -0
  354. package/packages/mcp-servers/dist/programmatic-feedback/sandbox.d.ts +19 -0
  355. package/packages/mcp-servers/dist/programmatic-feedback/sandbox.d.ts.map +1 -0
  356. package/packages/mcp-servers/dist/programmatic-feedback/sandbox.js +174 -0
  357. package/packages/mcp-servers/dist/programmatic-feedback/sandbox.js.map +1 -0
  358. package/packages/mcp-servers/dist/programmatic-feedback/server.d.ts +35 -0
  359. package/packages/mcp-servers/dist/programmatic-feedback/server.d.ts.map +1 -0
  360. package/packages/mcp-servers/dist/programmatic-feedback/server.js +465 -0
  361. package/packages/mcp-servers/dist/programmatic-feedback/server.js.map +1 -0
  362. package/packages/mcp-servers/dist/programmatic-feedback/types.d.ts +127 -0
  363. package/packages/mcp-servers/dist/programmatic-feedback/types.d.ts.map +1 -0
  364. package/packages/mcp-servers/dist/programmatic-feedback/types.js +80 -0
  365. package/packages/mcp-servers/dist/programmatic-feedback/types.js.map +1 -0
  366. package/packages/mcp-servers/dist/render/index.d.ts +8 -0
  367. package/packages/mcp-servers/dist/render/index.d.ts.map +1 -0
  368. package/packages/mcp-servers/dist/render/index.js +8 -0
  369. package/packages/mcp-servers/dist/render/index.js.map +1 -0
  370. package/packages/mcp-servers/dist/render/server.d.ts +15 -0
  371. package/packages/mcp-servers/dist/render/server.d.ts.map +1 -0
  372. package/packages/mcp-servers/dist/render/server.js +428 -0
  373. package/packages/mcp-servers/dist/render/server.js.map +1 -0
  374. package/packages/mcp-servers/dist/render/types.d.ts +273 -0
  375. package/packages/mcp-servers/dist/render/types.d.ts.map +1 -0
  376. package/packages/mcp-servers/dist/render/types.js +102 -0
  377. package/packages/mcp-servers/dist/render/types.js.map +1 -0
  378. package/packages/mcp-servers/dist/resend/index.d.ts +7 -0
  379. package/packages/mcp-servers/dist/resend/index.d.ts.map +1 -0
  380. package/packages/mcp-servers/dist/resend/index.js +7 -0
  381. package/packages/mcp-servers/dist/resend/index.js.map +1 -0
  382. package/packages/mcp-servers/dist/resend/server.d.ts +15 -0
  383. package/packages/mcp-servers/dist/resend/server.d.ts.map +1 -0
  384. package/packages/mcp-servers/dist/resend/server.js +298 -0
  385. package/packages/mcp-servers/dist/resend/server.js.map +1 -0
  386. package/packages/mcp-servers/dist/resend/types.d.ts +222 -0
  387. package/packages/mcp-servers/dist/resend/types.d.ts.map +1 -0
  388. package/packages/mcp-servers/dist/resend/types.js +58 -0
  389. package/packages/mcp-servers/dist/resend/types.js.map +1 -0
  390. package/packages/mcp-servers/dist/review-queue/index.d.ts +6 -0
  391. package/packages/mcp-servers/dist/review-queue/index.d.ts.map +1 -0
  392. package/packages/mcp-servers/dist/review-queue/index.js +6 -0
  393. package/packages/mcp-servers/dist/review-queue/index.js.map +1 -0
  394. package/packages/mcp-servers/dist/review-queue/server.d.ts +17 -0
  395. package/packages/mcp-servers/dist/review-queue/server.d.ts.map +1 -0
  396. package/packages/mcp-servers/dist/review-queue/server.js +348 -0
  397. package/packages/mcp-servers/dist/review-queue/server.js.map +1 -0
  398. package/packages/mcp-servers/dist/review-queue/types.d.ts +162 -0
  399. package/packages/mcp-servers/dist/review-queue/types.d.ts.map +1 -0
  400. package/packages/mcp-servers/dist/review-queue/types.js +56 -0
  401. package/packages/mcp-servers/dist/review-queue/types.js.map +1 -0
  402. package/packages/mcp-servers/dist/secret-sync/server.d.ts +19 -0
  403. package/packages/mcp-servers/dist/secret-sync/server.d.ts.map +1 -0
  404. package/packages/mcp-servers/dist/secret-sync/server.js +1139 -0
  405. package/packages/mcp-servers/dist/secret-sync/server.js.map +1 -0
  406. package/packages/mcp-servers/dist/secret-sync/types.d.ts +442 -0
  407. package/packages/mcp-servers/dist/secret-sync/types.d.ts.map +1 -0
  408. package/packages/mcp-servers/dist/secret-sync/types.js +113 -0
  409. package/packages/mcp-servers/dist/secret-sync/types.js.map +1 -0
  410. package/packages/mcp-servers/dist/session-events/index.d.ts +5 -0
  411. package/packages/mcp-servers/dist/session-events/index.d.ts.map +1 -0
  412. package/packages/mcp-servers/dist/session-events/index.js +5 -0
  413. package/packages/mcp-servers/dist/session-events/index.js.map +1 -0
  414. package/packages/mcp-servers/dist/session-events/server.d.ts +11 -0
  415. package/packages/mcp-servers/dist/session-events/server.d.ts.map +1 -0
  416. package/packages/mcp-servers/dist/session-events/server.js +290 -0
  417. package/packages/mcp-servers/dist/session-events/server.js.map +1 -0
  418. package/packages/mcp-servers/dist/session-events/types.d.ts +213 -0
  419. package/packages/mcp-servers/dist/session-events/types.d.ts.map +1 -0
  420. package/packages/mcp-servers/dist/session-events/types.js +69 -0
  421. package/packages/mcp-servers/dist/session-events/types.js.map +1 -0
  422. package/packages/mcp-servers/dist/session-restart/index.d.ts +9 -0
  423. package/packages/mcp-servers/dist/session-restart/index.d.ts.map +1 -0
  424. package/packages/mcp-servers/dist/session-restart/index.js +9 -0
  425. package/packages/mcp-servers/dist/session-restart/index.js.map +1 -0
  426. package/packages/mcp-servers/dist/session-restart/server.d.ts +20 -0
  427. package/packages/mcp-servers/dist/session-restart/server.d.ts.map +1 -0
  428. package/packages/mcp-servers/dist/session-restart/server.js +411 -0
  429. package/packages/mcp-servers/dist/session-restart/server.js.map +1 -0
  430. package/packages/mcp-servers/dist/session-restart/types.d.ts +26 -0
  431. package/packages/mcp-servers/dist/session-restart/types.d.ts.map +1 -0
  432. package/packages/mcp-servers/dist/session-restart/types.js +16 -0
  433. package/packages/mcp-servers/dist/session-restart/types.js.map +1 -0
  434. package/packages/mcp-servers/dist/setup-helper/index.d.ts +5 -0
  435. package/packages/mcp-servers/dist/setup-helper/index.d.ts.map +1 -0
  436. package/packages/mcp-servers/dist/setup-helper/index.js +5 -0
  437. package/packages/mcp-servers/dist/setup-helper/index.js.map +1 -0
  438. package/packages/mcp-servers/dist/setup-helper/server.d.ts +14 -0
  439. package/packages/mcp-servers/dist/setup-helper/server.d.ts.map +1 -0
  440. package/packages/mcp-servers/dist/setup-helper/server.js +454 -0
  441. package/packages/mcp-servers/dist/setup-helper/server.js.map +1 -0
  442. package/packages/mcp-servers/dist/setup-helper/types.d.ts +81 -0
  443. package/packages/mcp-servers/dist/setup-helper/types.d.ts.map +1 -0
  444. package/packages/mcp-servers/dist/setup-helper/types.js +41 -0
  445. package/packages/mcp-servers/dist/setup-helper/types.js.map +1 -0
  446. package/packages/mcp-servers/dist/shared/audited-server.d.ts +31 -0
  447. package/packages/mcp-servers/dist/shared/audited-server.d.ts.map +1 -0
  448. package/packages/mcp-servers/dist/shared/audited-server.js +126 -0
  449. package/packages/mcp-servers/dist/shared/audited-server.js.map +1 -0
  450. package/packages/mcp-servers/dist/shared/constants.d.ts +26 -0
  451. package/packages/mcp-servers/dist/shared/constants.d.ts.map +1 -0
  452. package/packages/mcp-servers/dist/shared/constants.js +41 -0
  453. package/packages/mcp-servers/dist/shared/constants.js.map +1 -0
  454. package/packages/mcp-servers/dist/shared/index.d.ts +6 -0
  455. package/packages/mcp-servers/dist/shared/index.d.ts.map +1 -0
  456. package/packages/mcp-servers/dist/shared/index.js +6 -0
  457. package/packages/mcp-servers/dist/shared/index.js.map +1 -0
  458. package/packages/mcp-servers/dist/shared/readonly-db.d.ts +11 -0
  459. package/packages/mcp-servers/dist/shared/readonly-db.d.ts.map +1 -0
  460. package/packages/mcp-servers/dist/shared/readonly-db.js +47 -0
  461. package/packages/mcp-servers/dist/shared/readonly-db.js.map +1 -0
  462. package/packages/mcp-servers/dist/shared/resolve-framework.d.ts +20 -0
  463. package/packages/mcp-servers/dist/shared/resolve-framework.d.ts.map +1 -0
  464. package/packages/mcp-servers/dist/shared/resolve-framework.js +65 -0
  465. package/packages/mcp-servers/dist/shared/resolve-framework.js.map +1 -0
  466. package/packages/mcp-servers/dist/shared/server.d.ts +86 -0
  467. package/packages/mcp-servers/dist/shared/server.d.ts.map +1 -0
  468. package/packages/mcp-servers/dist/shared/server.js +291 -0
  469. package/packages/mcp-servers/dist/shared/server.js.map +1 -0
  470. package/packages/mcp-servers/dist/shared/types.d.ts +113 -0
  471. package/packages/mcp-servers/dist/shared/types.d.ts.map +1 -0
  472. package/packages/mcp-servers/dist/shared/types.js +36 -0
  473. package/packages/mcp-servers/dist/shared/types.js.map +1 -0
  474. package/packages/mcp-servers/dist/show/server.d.ts +12 -0
  475. package/packages/mcp-servers/dist/show/server.d.ts.map +1 -0
  476. package/packages/mcp-servers/dist/show/server.js +97 -0
  477. package/packages/mcp-servers/dist/show/server.js.map +1 -0
  478. package/packages/mcp-servers/dist/show/types.d.ts +19 -0
  479. package/packages/mcp-servers/dist/show/types.d.ts.map +1 -0
  480. package/packages/mcp-servers/dist/show/types.js +32 -0
  481. package/packages/mcp-servers/dist/show/types.js.map +1 -0
  482. package/packages/mcp-servers/dist/specs-browser/index.d.ts +5 -0
  483. package/packages/mcp-servers/dist/specs-browser/index.d.ts.map +1 -0
  484. package/packages/mcp-servers/dist/specs-browser/index.js +5 -0
  485. package/packages/mcp-servers/dist/specs-browser/index.js.map +1 -0
  486. package/packages/mcp-servers/dist/specs-browser/server.d.ts +13 -0
  487. package/packages/mcp-servers/dist/specs-browser/server.d.ts.map +1 -0
  488. package/packages/mcp-servers/dist/specs-browser/server.js +692 -0
  489. package/packages/mcp-servers/dist/specs-browser/server.js.map +1 -0
  490. package/packages/mcp-servers/dist/specs-browser/types.d.ts +337 -0
  491. package/packages/mcp-servers/dist/specs-browser/types.d.ts.map +1 -0
  492. package/packages/mcp-servers/dist/specs-browser/types.js +134 -0
  493. package/packages/mcp-servers/dist/specs-browser/types.js.map +1 -0
  494. package/packages/mcp-servers/dist/supabase/index.d.ts +10 -0
  495. package/packages/mcp-servers/dist/supabase/index.d.ts.map +1 -0
  496. package/packages/mcp-servers/dist/supabase/index.js +10 -0
  497. package/packages/mcp-servers/dist/supabase/index.js.map +1 -0
  498. package/packages/mcp-servers/dist/supabase/server.d.ts +20 -0
  499. package/packages/mcp-servers/dist/supabase/server.d.ts.map +1 -0
  500. package/packages/mcp-servers/dist/supabase/server.js +451 -0
  501. package/packages/mcp-servers/dist/supabase/server.js.map +1 -0
  502. package/packages/mcp-servers/dist/supabase/types.d.ts +196 -0
  503. package/packages/mcp-servers/dist/supabase/types.d.ts.map +1 -0
  504. package/packages/mcp-servers/dist/supabase/types.js +76 -0
  505. package/packages/mcp-servers/dist/supabase/types.js.map +1 -0
  506. package/packages/mcp-servers/dist/todo-db/index.d.ts +5 -0
  507. package/packages/mcp-servers/dist/todo-db/index.d.ts.map +1 -0
  508. package/packages/mcp-servers/dist/todo-db/index.js +5 -0
  509. package/packages/mcp-servers/dist/todo-db/index.js.map +1 -0
  510. package/packages/mcp-servers/dist/todo-db/server.d.ts +13 -0
  511. package/packages/mcp-servers/dist/todo-db/server.d.ts.map +1 -0
  512. package/packages/mcp-servers/dist/todo-db/server.js +649 -0
  513. package/packages/mcp-servers/dist/todo-db/server.js.map +1 -0
  514. package/packages/mcp-servers/dist/todo-db/types.d.ts +225 -0
  515. package/packages/mcp-servers/dist/todo-db/types.d.ts.map +1 -0
  516. package/packages/mcp-servers/dist/todo-db/types.js +69 -0
  517. package/packages/mcp-servers/dist/todo-db/types.js.map +1 -0
  518. package/packages/mcp-servers/dist/user-feedback/index.d.ts +7 -0
  519. package/packages/mcp-servers/dist/user-feedback/index.d.ts.map +1 -0
  520. package/packages/mcp-servers/dist/user-feedback/index.js +8 -0
  521. package/packages/mcp-servers/dist/user-feedback/index.js.map +1 -0
  522. package/packages/mcp-servers/dist/user-feedback/server.d.ts +25 -0
  523. package/packages/mcp-servers/dist/user-feedback/server.d.ts.map +1 -0
  524. package/packages/mcp-servers/dist/user-feedback/server.js +914 -0
  525. package/packages/mcp-servers/dist/user-feedback/server.js.map +1 -0
  526. package/packages/mcp-servers/dist/user-feedback/types.d.ts +415 -0
  527. package/packages/mcp-servers/dist/user-feedback/types.d.ts.map +1 -0
  528. package/packages/mcp-servers/dist/user-feedback/types.js +132 -0
  529. package/packages/mcp-servers/dist/user-feedback/types.js.map +1 -0
  530. package/packages/mcp-servers/dist/vercel/index.d.ts +9 -0
  531. package/packages/mcp-servers/dist/vercel/index.d.ts.map +1 -0
  532. package/packages/mcp-servers/dist/vercel/index.js +9 -0
  533. package/packages/mcp-servers/dist/vercel/index.js.map +1 -0
  534. package/packages/mcp-servers/dist/vercel/server.d.ts +17 -0
  535. package/packages/mcp-servers/dist/vercel/server.d.ts.map +1 -0
  536. package/packages/mcp-servers/dist/vercel/server.js +265 -0
  537. package/packages/mcp-servers/dist/vercel/server.js.map +1 -0
  538. package/packages/mcp-servers/dist/vercel/types.d.ts +189 -0
  539. package/packages/mcp-servers/dist/vercel/types.d.ts.map +1 -0
  540. package/packages/mcp-servers/dist/vercel/types.js +65 -0
  541. package/packages/mcp-servers/dist/vercel/types.js.map +1 -0
  542. package/packages/mcp-servers/package-lock.json +3765 -0
  543. package/packages/mcp-servers/package.json +64 -0
  544. package/packages/mcp-servers/test/reporters/test-failure-reporter.ts +372 -0
  545. package/packages/mcp-servers/vitest.config.ts +27 -0
  546. package/scripts/__tests__/README.md +163 -0
  547. package/scripts/apply-credential-hardening.sh +271 -0
  548. package/scripts/credential-providers/manual.js +56 -0
  549. package/scripts/credential-providers/onepassword.js +85 -0
  550. package/scripts/credential-providers/provider-interface.js +104 -0
  551. package/scripts/encrypt-credential.js +337 -0
  552. package/scripts/feedback-launcher.js +338 -0
  553. package/scripts/feedback-orchestrator.js +373 -0
  554. package/scripts/fix-mcp-launcher-issues.sh +97 -0
  555. package/scripts/force-spawn-tasks.js +651 -0
  556. package/scripts/force-triage-reports.js +560 -0
  557. package/scripts/generate-protected-actions-spec.js +142 -0
  558. package/scripts/generate-proxy-certs.sh +158 -0
  559. package/scripts/grant-chrome-ext-permissions.sh +242 -0
  560. package/scripts/mcp-launcher.js +125 -0
  561. package/scripts/merge-settings.cjs +167 -0
  562. package/scripts/patch-clawd.py +844 -0
  563. package/scripts/patch-credential-cache.py +313 -0
  564. package/scripts/patches/credential-file-guard-patched.mjs +573 -0
  565. package/scripts/patches/credential-file-guard.js.patched +573 -0
  566. package/scripts/patches/verify-tokenizer.mjs +132 -0
  567. package/scripts/protect-framework.sh +478 -0
  568. package/scripts/readme-chrome.template +12 -0
  569. package/scripts/reap-completed-agents.js +439 -0
  570. package/scripts/reinstall.sh +86 -0
  571. package/scripts/resign-node.sh +185 -0
  572. package/scripts/rotation-proxy.js +656 -0
  573. package/scripts/rotation-stress-monitor.mjs +862 -0
  574. package/scripts/setup-automation-service.sh +648 -0
  575. package/scripts/setup-check.js +251 -0
  576. package/scripts/watch-claude-version.js +142 -0
  577. package/specs/framework/CORE-INVARIANTS.md +161 -0
  578. package/specs/patterns/AGENT-PATTERNS.md +223 -0
  579. package/specs/patterns/HOOK-PATTERNS.md +242 -0
  580. package/specs/patterns/MCP-SERVER-PATTERNS.md +144 -0
  581. package/templates/config/gitignore.template +14 -0
  582. package/templates/config/merge-chain-check.yml.template +51 -0
  583. package/templates/config/package.json.template +18 -0
  584. package/templates/config/pnpm-workspace.yaml +5 -0
  585. package/templates/config/services.json.template +18 -0
  586. package/templates/config/tsconfig.base.json +17 -0
  587. package/templates/scaffold/integrations/_template/.gitkeep +0 -0
  588. package/templates/scaffold/packages/logger/package.json +17 -0
  589. package/templates/scaffold/packages/logger/src/logger.ts +44 -0
  590. package/templates/scaffold/packages/shared/package.json +17 -0
  591. package/templates/scaffold/packages/shared/src/errors.ts +43 -0
  592. package/templates/scaffold/products/_product/apps/backend/package.json +21 -0
  593. package/templates/scaffold/products/_product/apps/backend/src/index.ts +17 -0
  594. package/templates/scaffold/products/_product/apps/extension/.gitkeep +0 -0
  595. package/templates/scaffold/products/_product/apps/web/.gitkeep +0 -0
  596. package/templates/scaffold/specs/global/.gitkeep +0 -0
  597. package/templates/scaffold/specs/local/.gitkeep +0 -0
  598. package/templates/scaffold/specs/reference/.gitkeep +0 -0
  599. package/version.json +15 -0
@@ -0,0 +1,859 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CTO Report MCP Server
4
+ *
5
+ * Provides comprehensive metrics and status reports for CTO oversight.
6
+ * Aggregates data from session JSONL files, todo-db, deputy-cto, agent-reports
7
+ * (database: cto-reports.db), and agent-tracker.
8
+ *
9
+ * Protocol: JSON-RPC 2.0 over stdin/stdout (stdio MCP)
10
+ *
11
+ * @version 1.0.0
12
+ */
13
+ import * as fs from 'fs';
14
+ import * as path from 'path';
15
+ import * as os from 'os';
16
+ import { McpServer } from '../shared/server.js';
17
+ import { openReadonlyDb } from '../shared/readonly-db.js';
18
+ import { GetReportArgsSchema, GetSessionMetricsArgsSchema, GetTaskMetricsArgsSchema, } from './types.js';
19
+ // ============================================================================
20
+ // Configuration
21
+ // ============================================================================
22
+ const PROJECT_DIR = path.resolve(process.env['CLAUDE_PROJECT_DIR'] || process.cwd());
23
+ const TODO_DB_PATH = path.join(PROJECT_DIR, '.claude', 'todo.db');
24
+ const DEPUTY_CTO_DB_PATH = path.join(PROJECT_DIR, '.claude', 'deputy-cto.db');
25
+ const CTO_REPORTS_DB_PATH = path.join(PROJECT_DIR, '.claude', 'cto-reports.db');
26
+ const AUTONOMOUS_CONFIG_PATH = path.join(PROJECT_DIR, '.claude', 'autonomous-mode.json');
27
+ const AUTOMATION_STATE_PATH = path.join(PROJECT_DIR, '.claude', 'hourly-automation-state.json');
28
+ const KEY_ROTATION_STATE_PATH = path.join(os.homedir(), '.claude', 'api-key-rotation.json');
29
+ const AGENT_TRACKER_PATH = path.join(PROJECT_DIR, '.claude', 'state', 'agent-tracker-history.json');
30
+ const AUTOMATION_CONFIG_PATH = path.join(PROJECT_DIR, '.claude', 'state', 'automation-config.json');
31
+ const CREDENTIALS_PATH = path.join(os.homedir(), '.claude', '.credentials.json');
32
+ const ANTHROPIC_API_URL = 'https://api.anthropic.com/api/oauth/usage';
33
+ const ANTHROPIC_BETA_HEADER = 'oauth-2025-04-20';
34
+ const COOLDOWN_MINUTES = 55;
35
+ // Protected files for system health check
36
+ const PROTECTED_FILES = [
37
+ path.join(PROJECT_DIR, '.claude', 'hooks', 'pre-commit-review.js'),
38
+ path.join(PROJECT_DIR, 'eslint.config.js'),
39
+ path.join(PROJECT_DIR, '.husky', 'pre-commit'),
40
+ ];
41
+ // Claude session directory - path format: ~/.claude/projects/-{project-path}
42
+ // Claude Code replaces all non-alphanumeric characters with hyphens
43
+ function getSessionDir() {
44
+ const projectPath = PROJECT_DIR.replace(/[^a-zA-Z0-9]/g, '-').replace(/^-/, '');
45
+ return path.join(os.homedir(), '.claude', 'projects', `-${projectPath}`);
46
+ }
47
+ function calculateHoursUntil(isoDate) {
48
+ const resetTime = new Date(isoDate).getTime();
49
+ const now = Date.now();
50
+ const hoursUntil = (resetTime - now) / (1000 * 60 * 60);
51
+ return Math.max(0, Math.round(hoursUntil * 10) / 10);
52
+ }
53
+ function parseBucket(bucket) {
54
+ if (!bucket) {
55
+ return null;
56
+ }
57
+ return {
58
+ utilization: bucket.utilization,
59
+ resets_at: bucket.resets_at,
60
+ resets_in_hours: calculateHoursUntil(bucket.resets_at),
61
+ };
62
+ }
63
+ /**
64
+ * Get an access token from available sources.
65
+ * Checks rotation state first (project-level, accumulates keys from multiple accounts),
66
+ * then falls back to credentials file (user-level, current session only).
67
+ */
68
+ function getAccessToken() {
69
+ // Source 1: Rotation state (project-level, has accumulated keys)
70
+ if (fs.existsSync(KEY_ROTATION_STATE_PATH)) {
71
+ try {
72
+ const state = JSON.parse(fs.readFileSync(KEY_ROTATION_STATE_PATH, 'utf8'));
73
+ if (state?.version === 1 && state.keys) {
74
+ // Prefer the active key
75
+ const activeToken = state.active_key_id ? state.keys[state.active_key_id]?.accessToken : undefined;
76
+ if (activeToken)
77
+ return activeToken;
78
+ // Fall back to any key with a token (prefer active, then try any)
79
+ let fallbackToken = null;
80
+ for (const keyData of Object.values(state.keys)) {
81
+ if (keyData.accessToken) {
82
+ if (keyData.status === 'active')
83
+ return keyData.accessToken;
84
+ if (!fallbackToken)
85
+ fallbackToken = keyData.accessToken;
86
+ }
87
+ }
88
+ if (fallbackToken)
89
+ return fallbackToken;
90
+ }
91
+ }
92
+ catch {
93
+ // Silently fall through to next source
94
+ }
95
+ }
96
+ // Source 2: Credentials file (user-level, current session)
97
+ if (fs.existsSync(CREDENTIALS_PATH)) {
98
+ try {
99
+ const creds = JSON.parse(fs.readFileSync(CREDENTIALS_PATH, 'utf8'));
100
+ if (creds.claudeAiOauth?.accessToken) {
101
+ if (creds.claudeAiOauth.expiresAt && creds.claudeAiOauth.expiresAt < Date.now()) {
102
+ return null;
103
+ }
104
+ return creds.claudeAiOauth.accessToken;
105
+ }
106
+ }
107
+ catch {
108
+ // Silently return null
109
+ }
110
+ }
111
+ return null;
112
+ }
113
+ async function getQuotaStatus() {
114
+ const emptyStatus = {
115
+ five_hour: null,
116
+ seven_day: null,
117
+ extra_usage_enabled: false,
118
+ error: null,
119
+ };
120
+ const accessToken = getAccessToken();
121
+ if (!accessToken) {
122
+ return { ...emptyStatus, error: 'No credentials found' };
123
+ }
124
+ try {
125
+ const response = await fetch(ANTHROPIC_API_URL, {
126
+ method: 'GET',
127
+ headers: {
128
+ Authorization: `Bearer ${accessToken}`,
129
+ 'Content-Type': 'application/json',
130
+ 'User-Agent': 'claude-code/2.1.14',
131
+ 'anthropic-beta': ANTHROPIC_BETA_HEADER,
132
+ },
133
+ });
134
+ if (!response.ok) {
135
+ return { ...emptyStatus, error: `API error: ${response.status}` };
136
+ }
137
+ const data = await response.json();
138
+ return {
139
+ five_hour: parseBucket(data.five_hour),
140
+ seven_day: parseBucket(data.seven_day),
141
+ extra_usage_enabled: data.extra_usage?.is_enabled ?? false,
142
+ error: null,
143
+ };
144
+ }
145
+ catch (err) {
146
+ const message = err instanceof Error ? err.message : String(err);
147
+ return { ...emptyStatus, error: `Fetch error: ${message}` };
148
+ }
149
+ }
150
+ function getTokenUsage(hours) {
151
+ const sessionDir = getSessionDir();
152
+ const since = Date.now() - (hours * 60 * 60 * 1000);
153
+ const totals = {
154
+ input: 0,
155
+ output: 0,
156
+ cache_read: 0,
157
+ cache_creation: 0,
158
+ total: 0,
159
+ };
160
+ if (!fs.existsSync(sessionDir)) {
161
+ return totals;
162
+ }
163
+ const files = fs.readdirSync(sessionDir).filter(f => f.endsWith('.jsonl'));
164
+ for (const file of files) {
165
+ const filePath = path.join(sessionDir, file);
166
+ // Check file modification time first - skip files not modified in time range
167
+ const stat = fs.statSync(filePath);
168
+ if (stat.mtime.getTime() < since) {
169
+ continue;
170
+ }
171
+ const content = fs.readFileSync(filePath, 'utf8');
172
+ const lines = content.split('\n').filter(l => l.trim());
173
+ for (const line of lines) {
174
+ try {
175
+ const entry = JSON.parse(line);
176
+ // Check timestamp
177
+ if (entry.timestamp) {
178
+ const entryTime = new Date(entry.timestamp).getTime();
179
+ if (entryTime < since) {
180
+ continue;
181
+ }
182
+ }
183
+ // Extract usage
184
+ const usage = entry.message?.usage;
185
+ if (usage) {
186
+ totals.input += usage.input_tokens || 0;
187
+ totals.output += usage.output_tokens || 0;
188
+ totals.cache_read += usage.cache_read_input_tokens || 0;
189
+ totals.cache_creation += usage.cache_creation_input_tokens || 0;
190
+ }
191
+ }
192
+ catch {
193
+ // Skip malformed JSONL lines
194
+ }
195
+ }
196
+ }
197
+ totals.total = totals.input + totals.output + totals.cache_read + totals.cache_creation;
198
+ return totals;
199
+ }
200
+ // ============================================================================
201
+ // Autonomous Mode Status
202
+ // ============================================================================
203
+ function getAutonomousModeStatus() {
204
+ let enabled = false;
205
+ // Get config
206
+ if (fs.existsSync(AUTONOMOUS_CONFIG_PATH)) {
207
+ const config = JSON.parse(fs.readFileSync(AUTONOMOUS_CONFIG_PATH, 'utf8'));
208
+ enabled = config.enabled === true;
209
+ }
210
+ // Get next run time
211
+ let next_run_minutes = null;
212
+ if (enabled && fs.existsSync(AUTOMATION_STATE_PATH)) {
213
+ const state = JSON.parse(fs.readFileSync(AUTOMATION_STATE_PATH, 'utf8'));
214
+ const lastRun = state.lastRun || 0;
215
+ const now = Date.now();
216
+ const timeSinceLastRun = now - lastRun;
217
+ const cooldownMs = COOLDOWN_MINUTES * 60 * 1000;
218
+ if (timeSinceLastRun >= cooldownMs) {
219
+ next_run_minutes = 0;
220
+ }
221
+ else {
222
+ next_run_minutes = Math.ceil((cooldownMs - timeSinceLastRun) / 60000);
223
+ }
224
+ }
225
+ else if (enabled) {
226
+ next_run_minutes = 0; // First run
227
+ }
228
+ return { enabled, next_run_minutes };
229
+ }
230
+ // ============================================================================
231
+ // Session Metrics
232
+ // ============================================================================
233
+ /**
234
+ * Parse task type from message content.
235
+ * Supports formats:
236
+ * - [Task][type-name] ... → extracts "type-name"
237
+ * - [Task] ... → returns "unknown"
238
+ */
239
+ function parseTaskType(messageContent) {
240
+ if (!messageContent.startsWith('[Task]')) {
241
+ return null;
242
+ }
243
+ // Check for [Task][type] format
244
+ const typeMatch = messageContent.match(/^\[Task\]\[([^\]]+)\]/);
245
+ if (typeMatch && typeMatch[1]) {
246
+ return typeMatch[1];
247
+ }
248
+ // Legacy [Task] format without type
249
+ return 'unknown';
250
+ }
251
+ function getSessionMetricsData(hours) {
252
+ const since = Date.now() - (hours * 60 * 60 * 1000);
253
+ const sessionDir = getSessionDir();
254
+ const metrics = {
255
+ task_triggered: 0,
256
+ user_triggered: 0,
257
+ task_by_type: {},
258
+ };
259
+ if (!fs.existsSync(sessionDir)) {
260
+ return metrics;
261
+ }
262
+ const files = fs.readdirSync(sessionDir).filter(f => f.endsWith('.jsonl'));
263
+ for (const file of files) {
264
+ const filePath = path.join(sessionDir, file);
265
+ // Check file modification time - only count recent sessions
266
+ const stat = fs.statSync(filePath);
267
+ if (stat.mtime.getTime() < since) {
268
+ continue;
269
+ }
270
+ // Read file and detect task session by checking if first user message starts with [Task]
271
+ const content = fs.readFileSync(filePath, 'utf8');
272
+ const lines = content.split('\n').filter(l => l.trim());
273
+ let taskType = null;
274
+ for (const line of lines) {
275
+ try {
276
+ const entry = JSON.parse(line);
277
+ // Look for first user message
278
+ if (entry.type === 'human' || entry.type === 'user') {
279
+ const messageContent = typeof entry.message?.content === 'string'
280
+ ? entry.message.content
281
+ : entry.content;
282
+ if (messageContent) {
283
+ taskType = parseTaskType(messageContent);
284
+ }
285
+ break; // Stop after first user message
286
+ }
287
+ }
288
+ catch {
289
+ // Skip malformed JSONL lines
290
+ }
291
+ }
292
+ if (taskType !== null) {
293
+ metrics.task_triggered++;
294
+ metrics.task_by_type[taskType] = (metrics.task_by_type[taskType] || 0) + 1;
295
+ }
296
+ else {
297
+ metrics.user_triggered++;
298
+ }
299
+ }
300
+ return metrics;
301
+ }
302
+ function getPendingItems() {
303
+ const items = {
304
+ cto_questions: 0,
305
+ commit_rejections: 0,
306
+ pending_triage: 0,
307
+ commits_blocked: false,
308
+ };
309
+ // Check deputy-cto database
310
+ if (fs.existsSync(DEPUTY_CTO_DB_PATH)) {
311
+ const db = openReadonlyDb(DEPUTY_CTO_DB_PATH);
312
+ const pending = db.prepare("SELECT COUNT(*) as count FROM questions WHERE status = 'pending'").get();
313
+ const rejections = db.prepare("SELECT COUNT(*) as count FROM questions WHERE type = 'rejection' AND status = 'pending'").get();
314
+ db.close();
315
+ items.cto_questions = pending?.count || 0;
316
+ items.commit_rejections = rejections?.count || 0;
317
+ }
318
+ // Check cto-reports database for pending triage (deputy-cto responsibility, not CTO)
319
+ if (fs.existsSync(CTO_REPORTS_DB_PATH)) {
320
+ const db = openReadonlyDb(CTO_REPORTS_DB_PATH);
321
+ const pending = db.prepare("SELECT COUNT(*) as count FROM reports WHERE triage_status = 'pending'").get();
322
+ items.pending_triage = pending?.count || 0;
323
+ db.close();
324
+ }
325
+ // G020: Block commits when ANY pending items exist (questions OR triage)
326
+ items.commits_blocked = items.cto_questions > 0 || items.pending_triage > 0;
327
+ return items;
328
+ }
329
+ // ============================================================================
330
+ // Triage Metrics
331
+ // ============================================================================
332
+ function getTriageMetrics() {
333
+ const metrics = {
334
+ pending: 0,
335
+ in_progress: 0,
336
+ self_handled_24h: 0,
337
+ self_handled_7d: 0,
338
+ escalated_24h: 0,
339
+ escalated_7d: 0,
340
+ dismissed_24h: 0,
341
+ dismissed_7d: 0,
342
+ };
343
+ if (!fs.existsSync(CTO_REPORTS_DB_PATH)) {
344
+ return metrics;
345
+ }
346
+ const db = openReadonlyDb(CTO_REPORTS_DB_PATH);
347
+ const now = Date.now();
348
+ const cutoff24h = new Date(now - 24 * 60 * 60 * 1000).toISOString();
349
+ const cutoff7d = new Date(now - 7 * 24 * 60 * 60 * 1000).toISOString();
350
+ const pending = db.prepare("SELECT COUNT(*) as count FROM reports WHERE triage_status = 'pending'").get();
351
+ metrics.pending = pending?.count || 0;
352
+ const inProgress = db.prepare("SELECT COUNT(*) as count FROM reports WHERE triage_status = 'in_progress'").get();
353
+ metrics.in_progress = inProgress?.count || 0;
354
+ const selfHandled24h = db.prepare("SELECT COUNT(*) as count FROM reports WHERE triage_status = 'self_handled' AND triage_completed_at >= ?").get(cutoff24h);
355
+ metrics.self_handled_24h = selfHandled24h?.count || 0;
356
+ const selfHandled7d = db.prepare("SELECT COUNT(*) as count FROM reports WHERE triage_status = 'self_handled' AND triage_completed_at >= ?").get(cutoff7d);
357
+ metrics.self_handled_7d = selfHandled7d?.count || 0;
358
+ const escalated24h = db.prepare("SELECT COUNT(*) as count FROM reports WHERE triage_status = 'escalated' AND triage_completed_at >= ?").get(cutoff24h);
359
+ metrics.escalated_24h = escalated24h?.count || 0;
360
+ const escalated7d = db.prepare("SELECT COUNT(*) as count FROM reports WHERE triage_status = 'escalated' AND triage_completed_at >= ?").get(cutoff7d);
361
+ metrics.escalated_7d = escalated7d?.count || 0;
362
+ const dismissed24h = db.prepare("SELECT COUNT(*) as count FROM reports WHERE triage_status = 'dismissed' AND triage_completed_at >= ?").get(cutoff24h);
363
+ metrics.dismissed_24h = dismissed24h?.count || 0;
364
+ const dismissed7d = db.prepare("SELECT COUNT(*) as count FROM reports WHERE triage_status = 'dismissed' AND triage_completed_at >= ?").get(cutoff7d);
365
+ metrics.dismissed_7d = dismissed7d?.count || 0;
366
+ db.close();
367
+ return metrics;
368
+ }
369
+ function getTaskMetricsData(hours) {
370
+ const metrics = {
371
+ pending_total: 0,
372
+ in_progress_total: 0,
373
+ completed_total: 0,
374
+ by_section: {},
375
+ completed_24h: 0,
376
+ completed_24h_by_section: {},
377
+ };
378
+ if (!fs.existsSync(TODO_DB_PATH)) {
379
+ return metrics;
380
+ }
381
+ const db = openReadonlyDb(TODO_DB_PATH);
382
+ // Get current task counts by section and status
383
+ const tasks = db.prepare(`
384
+ SELECT section, status, COUNT(*) as count
385
+ FROM tasks
386
+ GROUP BY section, status
387
+ `).all();
388
+ for (const row of tasks) {
389
+ if (!metrics.by_section[row.section]) {
390
+ metrics.by_section[row.section] = { pending: 0, in_progress: 0, completed: 0 };
391
+ }
392
+ metrics.by_section[row.section][row.status] = row.count;
393
+ // Accumulate totals
394
+ if (row.status === 'pending') {
395
+ metrics.pending_total += row.count;
396
+ }
397
+ else if (row.status === 'in_progress') {
398
+ metrics.in_progress_total += row.count;
399
+ }
400
+ else if (row.status === 'completed') {
401
+ metrics.completed_total += row.count;
402
+ }
403
+ }
404
+ // Get completed tasks within time range
405
+ const since = Date.now() - (hours * 60 * 60 * 1000);
406
+ const sinceTimestamp = Math.floor(since / 1000);
407
+ const completed = db.prepare(`
408
+ SELECT section, COUNT(*) as count
409
+ FROM tasks
410
+ WHERE status = 'completed' AND completed_timestamp >= ?
411
+ GROUP BY section
412
+ `).all(sinceTimestamp);
413
+ let total = 0;
414
+ for (const row of completed) {
415
+ metrics.completed_24h_by_section[row.section] = row.count;
416
+ total += row.count;
417
+ }
418
+ metrics.completed_24h = total;
419
+ db.close();
420
+ return metrics;
421
+ }
422
+ // ============================================================================
423
+ // System Health
424
+ // ============================================================================
425
+ function getSystemHealth() {
426
+ let protectionStatus = 'unknown';
427
+ let allProtected = true;
428
+ let anyExists = false;
429
+ for (const file of PROTECTED_FILES) {
430
+ if (fs.existsSync(file)) {
431
+ anyExists = true;
432
+ try {
433
+ const stats = fs.statSync(file);
434
+ if (stats.uid !== 0) {
435
+ allProtected = false;
436
+ }
437
+ }
438
+ catch {
439
+ allProtected = false;
440
+ }
441
+ }
442
+ }
443
+ if (anyExists) {
444
+ protectionStatus = allProtected ? 'protected' : 'unprotected';
445
+ }
446
+ return { protection_status: protectionStatus };
447
+ }
448
+ function getAgentActivity() {
449
+ const result = {
450
+ spawns_24h: 0,
451
+ spawns_7d: 0,
452
+ by_type: {},
453
+ };
454
+ if (!fs.existsSync(AGENT_TRACKER_PATH)) {
455
+ return result;
456
+ }
457
+ const content = fs.readFileSync(AGENT_TRACKER_PATH, 'utf8');
458
+ const history = JSON.parse(content);
459
+ const now = Date.now();
460
+ const cutoff24h = now - 24 * 60 * 60 * 1000;
461
+ const cutoff7d = now - 7 * 24 * 60 * 60 * 1000;
462
+ for (const agent of history.agents || []) {
463
+ const agentTime = new Date(agent.timestamp).getTime();
464
+ if (agentTime >= cutoff7d) {
465
+ result.spawns_7d++;
466
+ if (agentTime >= cutoff24h) {
467
+ result.spawns_24h++;
468
+ result.by_type[agent.type] = (result.by_type[agent.type] || 0) + 1;
469
+ }
470
+ }
471
+ }
472
+ return result;
473
+ }
474
+ function getHookExecutions() {
475
+ const result = {
476
+ total_24h: 0,
477
+ success_rate: 100,
478
+ by_hook: {},
479
+ recent_failures: [],
480
+ };
481
+ if (!fs.existsSync(AGENT_TRACKER_PATH)) {
482
+ return result;
483
+ }
484
+ const content = fs.readFileSync(AGENT_TRACKER_PATH, 'utf8');
485
+ const history = JSON.parse(content);
486
+ const now = Date.now();
487
+ const cutoff24h = now - 24 * 60 * 60 * 1000;
488
+ let successCount = 0;
489
+ for (const exec of history.hookExecutions || []) {
490
+ const execTime = new Date(exec.timestamp).getTime();
491
+ if (execTime < cutoff24h)
492
+ continue;
493
+ result.total_24h++;
494
+ if (exec.status === 'success')
495
+ successCount++;
496
+ // Aggregate by hook
497
+ if (!result.by_hook[exec.hookType]) {
498
+ result.by_hook[exec.hookType] = { total: 0, success: 0, failure: 0 };
499
+ }
500
+ const stats = result.by_hook[exec.hookType];
501
+ stats.total++;
502
+ if (exec.status === 'success')
503
+ stats.success++;
504
+ if (exec.status === 'failure')
505
+ stats.failure++;
506
+ // Collect recent failures
507
+ if (exec.status === 'failure' && result.recent_failures.length < 5) {
508
+ result.recent_failures.push({
509
+ hook: exec.hookType,
510
+ error: exec.metadata?.error || 'Unknown error',
511
+ timestamp: exec.timestamp,
512
+ });
513
+ }
514
+ }
515
+ if (result.total_24h > 0) {
516
+ result.success_rate = Math.round((successCount / result.total_24h) * 100);
517
+ }
518
+ return result;
519
+ }
520
+ function getKeyRotationMetrics(hours) {
521
+ if (!fs.existsSync(KEY_ROTATION_STATE_PATH)) {
522
+ return null;
523
+ }
524
+ const content = fs.readFileSync(KEY_ROTATION_STATE_PATH, 'utf8');
525
+ const state = JSON.parse(content);
526
+ if (!state || state.version !== 1 || typeof state.keys !== 'object') {
527
+ throw new Error(`Invalid key rotation state file at ${KEY_ROTATION_STATE_PATH}`);
528
+ }
529
+ const now = Date.now();
530
+ const since = now - (hours * 60 * 60 * 1000);
531
+ // Count keys by status and build active key list
532
+ const keys = [];
533
+ let fiveHourSum = 0;
534
+ let sevenDaySum = 0;
535
+ let activeKeysWithData = 0;
536
+ let expiredKeys = 0;
537
+ let invalidKeys = 0;
538
+ let exhaustedKeys = 0;
539
+ for (const [keyId, keyData] of Object.entries(state.keys)) {
540
+ if (keyData.status === 'expired') {
541
+ expiredKeys++;
542
+ continue;
543
+ }
544
+ if (keyData.status === 'invalid') {
545
+ invalidKeys++;
546
+ continue;
547
+ }
548
+ if (keyData.status === 'exhausted') {
549
+ exhaustedKeys++;
550
+ }
551
+ // Include active and exhausted keys in the list
552
+ if (keyData.status !== 'active' && keyData.status !== 'exhausted')
553
+ continue;
554
+ const isCurrent = keyId === state.active_key_id;
555
+ keys.push({
556
+ key_id: `${keyId.slice(0, 8)}...`,
557
+ subscription_type: keyData.subscriptionType || 'unknown',
558
+ five_hour_pct: keyData.last_usage?.five_hour ?? null,
559
+ seven_day_pct: keyData.last_usage?.seven_day ?? null,
560
+ is_current: isCurrent,
561
+ });
562
+ // Accumulate for aggregate (active keys only)
563
+ if (keyData.status === 'active' && keyData.last_usage) {
564
+ fiveHourSum += keyData.last_usage.five_hour ?? 0;
565
+ sevenDaySum += keyData.last_usage.seven_day ?? 0;
566
+ activeKeysWithData++;
567
+ }
568
+ }
569
+ // Count rotation events in time range
570
+ const rotationEvents24h = state.rotation_log.filter(entry => entry.timestamp >= since && entry.event === 'key_switched').length;
571
+ // Compute aggregate (% of total capacity)
572
+ const aggregate = activeKeysWithData > 0 ? {
573
+ active_keys: activeKeysWithData,
574
+ five_hour_pct: Math.round(fiveHourSum / activeKeysWithData),
575
+ seven_day_pct: Math.round(sevenDaySum / activeKeysWithData),
576
+ } : null;
577
+ return {
578
+ current_key_id: state.active_key_id ? `${state.active_key_id.slice(0, 8)}...` : null,
579
+ active_keys: keys.length - exhaustedKeys,
580
+ expired_keys: expiredKeys,
581
+ invalid_keys: invalidKeys,
582
+ exhausted_keys: exhaustedKeys,
583
+ keys,
584
+ rotation_events_24h: rotationEvents24h,
585
+ aggregate,
586
+ };
587
+ }
588
+ // ============================================================================
589
+ // Usage Projection
590
+ // ============================================================================
591
+ const DEFAULT_COOLDOWNS = {
592
+ hourly_tasks: 55,
593
+ triage_check: 5,
594
+ antipattern_hunter: 360,
595
+ schema_mapper: 1440,
596
+ lint_checker: 30,
597
+ todo_maintenance: 15,
598
+ task_runner: 60,
599
+ triage_per_item: 60,
600
+ };
601
+ function getUsageProjection() {
602
+ const defaults = { ...DEFAULT_COOLDOWNS };
603
+ const effective = { ...DEFAULT_COOLDOWNS };
604
+ const result = {
605
+ factor: 1.0,
606
+ target_pct: 90,
607
+ projected_at_reset_pct: null,
608
+ constraining_metric: null,
609
+ last_updated: null,
610
+ effective_cooldowns: effective,
611
+ default_cooldowns: defaults,
612
+ };
613
+ if (!fs.existsSync(AUTOMATION_CONFIG_PATH)) {
614
+ return result;
615
+ }
616
+ const content = fs.readFileSync(AUTOMATION_CONFIG_PATH, 'utf8');
617
+ const config = JSON.parse(content);
618
+ if (!config || config.version !== 1) {
619
+ throw new Error(`Invalid automation config at ${AUTOMATION_CONFIG_PATH}`);
620
+ }
621
+ // Merge defaults from config
622
+ if (config.defaults) {
623
+ Object.assign(defaults, config.defaults);
624
+ result.default_cooldowns = defaults;
625
+ }
626
+ // Merge effective (dynamically adjusted) values
627
+ if (config.effective) {
628
+ Object.assign(effective, config.defaults || {}, config.effective);
629
+ result.effective_cooldowns = effective;
630
+ }
631
+ // Extract adjustment info
632
+ if (config.adjustment) {
633
+ result.factor = config.adjustment.factor ?? 1.0;
634
+ result.target_pct = config.adjustment.target_pct ?? 90;
635
+ result.projected_at_reset_pct = config.adjustment.projected_at_reset ?? null;
636
+ result.constraining_metric = config.adjustment.constraining_metric ?? null;
637
+ result.last_updated = config.adjustment.last_updated ?? null;
638
+ }
639
+ return result;
640
+ }
641
+ // ============================================================================
642
+ // Product-Market-Fit Summary
643
+ // ============================================================================
644
+ const PRODUCT_MANAGER_DB_PATH = path.join(PROJECT_DIR, '.claude', 'state', 'product-manager.db');
645
+ function getProductMarketFitSummary() {
646
+ // Check feature toggle
647
+ let pmEnabled = false;
648
+ if (fs.existsSync(AUTONOMOUS_CONFIG_PATH)) {
649
+ try {
650
+ const config = JSON.parse(fs.readFileSync(AUTONOMOUS_CONFIG_PATH, 'utf8'));
651
+ pmEnabled = config.productManagerEnabled === true;
652
+ }
653
+ catch {
654
+ // Default to disabled
655
+ }
656
+ }
657
+ if (!pmEnabled) {
658
+ return {
659
+ enabled: false,
660
+ status: 'not_started',
661
+ sections_populated: 0,
662
+ total_sections: 6,
663
+ sections: [],
664
+ compliance: null,
665
+ last_updated: null,
666
+ tip: 'Enable product-market-fit analysis with /toggle-product-manager or ask the deputy CTO.',
667
+ };
668
+ }
669
+ if (!fs.existsSync(PRODUCT_MANAGER_DB_PATH)) {
670
+ return {
671
+ enabled: true,
672
+ status: 'not_started',
673
+ sections_populated: 0,
674
+ total_sections: 6,
675
+ sections: [],
676
+ compliance: null,
677
+ last_updated: null,
678
+ tip: 'Start product-market-fit analysis with /product-manager.',
679
+ };
680
+ }
681
+ const db = openReadonlyDb(PRODUCT_MANAGER_DB_PATH);
682
+ try {
683
+ const meta = db.prepare("SELECT status, last_updated_at FROM analysis_meta WHERE id = 'default'").get();
684
+ if (!meta) {
685
+ db.close();
686
+ return {
687
+ enabled: true,
688
+ status: 'not_started',
689
+ sections_populated: 0,
690
+ total_sections: 6,
691
+ sections: [],
692
+ compliance: null,
693
+ last_updated: null,
694
+ tip: 'Start product-market-fit analysis with /product-manager.',
695
+ };
696
+ }
697
+ const sections = db.prepare('SELECT section_number, title, content FROM sections ORDER BY section_number').all();
698
+ const LIST_SECTIONS = [2, 6];
699
+ const sectionInfos = [];
700
+ let populatedCount = 0;
701
+ for (const sec of sections) {
702
+ const isList = LIST_SECTIONS.includes(sec.section_number);
703
+ let populated = false;
704
+ let contentPreview = null;
705
+ let entryCount;
706
+ if (isList) {
707
+ const count = db.prepare('SELECT COUNT(*) as c FROM section_entries WHERE section_number = ?').get(sec.section_number).c;
708
+ populated = count > 0;
709
+ entryCount = count;
710
+ if (populated) {
711
+ const firstEntry = db.prepare('SELECT content FROM section_entries WHERE section_number = ? ORDER BY id LIMIT 1').get(sec.section_number);
712
+ if (firstEntry?.content) {
713
+ contentPreview = firstEntry.content.length > 200
714
+ ? firstEntry.content.slice(0, 200) + '...'
715
+ : firstEntry.content;
716
+ }
717
+ }
718
+ }
719
+ else {
720
+ populated = !!sec.content;
721
+ if (populated && sec.content) {
722
+ contentPreview = sec.content.length > 200
723
+ ? sec.content.slice(0, 200) + '...'
724
+ : sec.content;
725
+ }
726
+ }
727
+ if (populated)
728
+ populatedCount++;
729
+ const info = {
730
+ number: sec.section_number,
731
+ title: sec.title,
732
+ populated,
733
+ content_preview: contentPreview,
734
+ };
735
+ if (entryCount !== undefined) {
736
+ info.entry_count = entryCount;
737
+ }
738
+ sectionInfos.push(info);
739
+ }
740
+ // Compliance stats
741
+ let compliance = null;
742
+ const totalPainPoints = db.prepare("SELECT COUNT(*) as c FROM section_entries WHERE section_number = 6").get().c;
743
+ if (totalPainPoints > 0) {
744
+ const mapped = db.prepare("SELECT COUNT(DISTINCT pain_point_id) as c FROM pain_point_personas").get().c;
745
+ compliance = {
746
+ total_pain_points: totalPainPoints,
747
+ mapped,
748
+ unmapped: totalPainPoints - mapped,
749
+ pct: Math.round((mapped / totalPainPoints) * 100),
750
+ };
751
+ }
752
+ db.close();
753
+ return {
754
+ enabled: true,
755
+ status: meta.status,
756
+ sections_populated: populatedCount,
757
+ total_sections: 6,
758
+ sections: sectionInfos,
759
+ compliance,
760
+ last_updated: meta.last_updated_at,
761
+ tip: 'Use /show product-market-fit or ask the deputy CTO for the full untruncated analysis.',
762
+ };
763
+ }
764
+ catch {
765
+ try {
766
+ db.close();
767
+ }
768
+ catch { /* ignore */ }
769
+ return {
770
+ enabled: true,
771
+ status: 'not_started',
772
+ sections_populated: 0,
773
+ total_sections: 6,
774
+ sections: [],
775
+ compliance: null,
776
+ last_updated: null,
777
+ tip: 'Use /show product-market-fit or ask the deputy CTO for the full untruncated analysis.',
778
+ };
779
+ }
780
+ }
781
+ // ============================================================================
782
+ // Tool Implementations
783
+ // ============================================================================
784
+ async function getReport(args) {
785
+ const hours = args.hours ?? 24;
786
+ const tokenUsage = getTokenUsage(hours);
787
+ const quotaStatus = await getQuotaStatus();
788
+ const keyRotation = getKeyRotationMetrics(hours);
789
+ const report = {
790
+ generated_at: new Date().toISOString(),
791
+ hours,
792
+ system_health: getSystemHealth(),
793
+ autonomous_mode: getAutonomousModeStatus(),
794
+ quota: quotaStatus,
795
+ usage: {
796
+ plan_type: 'unknown',
797
+ tokens_24h: tokenUsage,
798
+ estimated_remaining_pct: keyRotation?.aggregate?.seven_day_pct != null
799
+ ? 100 - keyRotation.aggregate.seven_day_pct
800
+ : quotaStatus.seven_day?.utilization
801
+ ? 100 - quotaStatus.seven_day.utilization
802
+ : null,
803
+ },
804
+ usage_projection: getUsageProjection(),
805
+ key_rotation: keyRotation,
806
+ agents: getAgentActivity(),
807
+ hooks: getHookExecutions(),
808
+ sessions: getSessionMetricsData(hours),
809
+ pending_items: getPendingItems(),
810
+ triage: getTriageMetrics(),
811
+ tasks: getTaskMetricsData(hours),
812
+ product_market_fit: getProductMarketFitSummary(),
813
+ };
814
+ return report;
815
+ }
816
+ function getSessionMetrics(args) {
817
+ const hours = args.hours ?? 24;
818
+ return {
819
+ hours,
820
+ sessions: getSessionMetricsData(hours),
821
+ };
822
+ }
823
+ function getTaskMetrics(args) {
824
+ const hours = args.hours ?? 24;
825
+ return {
826
+ hours,
827
+ tasks: getTaskMetricsData(hours),
828
+ };
829
+ }
830
+ // ============================================================================
831
+ // Server Setup
832
+ // ============================================================================
833
+ const tools = [
834
+ {
835
+ name: 'get_report',
836
+ description: 'Generate comprehensive CTO report with token usage, session metrics, pending items, and task status.',
837
+ schema: GetReportArgsSchema,
838
+ handler: getReport,
839
+ },
840
+ {
841
+ name: 'get_session_metrics',
842
+ description: 'Get session metrics only: task-triggered vs user-triggered sessions within time range.',
843
+ schema: GetSessionMetricsArgsSchema,
844
+ handler: getSessionMetrics,
845
+ },
846
+ {
847
+ name: 'get_task_metrics',
848
+ description: 'Get task metrics only: counts by section/status and recently completed tasks.',
849
+ schema: GetTaskMetricsArgsSchema,
850
+ handler: getTaskMetrics,
851
+ },
852
+ ];
853
+ const server = new McpServer({
854
+ name: 'cto-report',
855
+ version: '1.0.0',
856
+ tools,
857
+ });
858
+ server.start();
859
+ //# sourceMappingURL=server.js.map