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,2830 @@
1
+ # GENTYR Framework Changelog
2
+
3
+ ## 2026-02-22 - npm CLI Package Migration
4
+
5
+ ### Added
6
+
7
+ **`cli/` package — `npx gentyr` CLI** (`cli/index.js`, `cli/commands/*.js`, `cli/lib/*.js`):
8
+ - `gentyr init [--op-token <token>]` — first-time project setup; replaces `setup.sh --path . [--protect]`
9
+ - `gentyr sync` — force rebuild MCP servers, re-merge settings.json, regenerate .mcp.json, deploy staged hooks; also runs automatically on SessionStart when framework version or config hash changes
10
+ - `gentyr status` — print installation state (model, framework path, version, protection status)
11
+ - `gentyr protect` / `gentyr unprotect` — enable/disable root-owned file protection; replaces `setup.sh --protect-only` / `--unprotect-only`
12
+ - `gentyr uninstall` — full teardown; replaces `setup.sh --uninstall`
13
+ - `gentyr migrate` — convert legacy `.claude-framework` symlink installs to `node_modules/gentyr` npm model
14
+ - `gentyr scaffold <name>` — scaffold new project directory
15
+
16
+ **CLI lib modules** (`cli/lib/`):
17
+ - `resolve-framework.js` — resolves `node_modules/gentyr` (preferred) then `.claude-framework` (fallback)
18
+ - `symlinks.js` — creates directory, agent, and reporter symlinks from framework into target project
19
+ - `config-gen.js` — generates `.mcp.json`, merges `settings.json`, updates `CLAUDE.md`, updates `.gitignore`
20
+ - `state.js` — reads/writes `gentyr-state.json`; tracks installed version, config hash, install model
21
+ - `init.js` — shared init logic used by both `init` and `migrate` commands
22
+
23
+ **`packages/mcp-servers/src/shared/resolve-framework.ts`**:
24
+ - Shared TypeScript framework path resolver for MCP servers
25
+ - Exports `resolveFrameworkDir()`, `resolveFrameworkRelative()`, `detectInstallModel()`
26
+ - Prefers `node_modules/gentyr`, falls back to `.claude-framework`
27
+ - Used by MCP servers that need to reference the framework directory
28
+
29
+ **`scripts/hooks/gentyr-sync.js`** (staged hook):
30
+ - SessionStart hook; detects framework version or config template changes and auto-runs `npx gentyr sync`
31
+ - Fast path: under 5ms when nothing changed (compares two small JSON files)
32
+ - Registered in `settings.json.template` under `SessionStart`
33
+
34
+ **`scripts/hooks/playwright-cli-guard.js`** (staged hook):
35
+ - PreToolUse(Bash) hook; detects CLI-based Playwright invocations and warns agents to use MCP tools instead
36
+ - Non-blocking: emits `systemMessage` warning, never prevents execution
37
+ - Registered in `settings.json.template` under `PreToolUse > Bash`
38
+ - Tests: `.claude/hooks/__tests__/playwright-cli-guard.test.js` (23 tests, `node --test`)
39
+
40
+ ### Changed
41
+
42
+ **`package.json`**:
43
+ - Removed `"private": true`; package is now publishable
44
+ - Added `"bin": { "gentyr": "./cli/index.js" }` — enables `npx gentyr` and global install
45
+ - Added `"prepare": "npm run build:mcp"` — MCP servers build automatically on `npm install`
46
+ - Added `"build:mcp"` script — `cd packages/mcp-servers && npm install && npm run build`
47
+ - Version bumped to `1.3.0`
48
+
49
+ **`settings.json.template`**:
50
+ - Added `gentyr-sync.js` to SessionStart hooks
51
+ - Added `playwright-cli-guard.js` to PreToolUse(Bash) hooks
52
+
53
+ **34+ files updated** to reference `node_modules/gentyr` instead of `.claude-framework`:
54
+ - `CLAUDE.md`, `README.md` — install instructions rewritten for npm-based workflow
55
+ - `docs/AUTOMATION-SYSTEMS.md`, `docs/TESTING.md`, `docs/SETUP-GUIDE.md`, `docs/STACK.md`, `docs/shared/PROTECTION-SYSTEM.md`, `docs/shared/EPHEMERAL-STATE-FILES.md` — references updated
56
+ - Multiple `.claude/agents/`, `.claude/commands/`, `.claude/hooks/` files — path references updated
57
+ - `scripts/*.js`, `scripts/*.sh` — dual-path support (`node_modules/gentyr` + `.claude-framework` fallback)
58
+
59
+ ### Fixed (Security — from code-reviewer)
60
+
61
+ **Command injection in `cli/commands/protect.js`**:
62
+ - `SUDO_USER` / `USER` environment variables were passed directly to `chown` via shell string interpolation
63
+ - Added `assertSafeName()` validator (`/^[a-z_][a-z0-9_-]{0,31}$/i`); throws on unsafe values
64
+ - Switched from `execSync` to `execFileSync` throughout
65
+
66
+ **Shell injection in `cli/commands/init.js`**:
67
+ - `--op-token` value was interpolated directly into a shell command
68
+ - Added `isValidOpToken()` validator (`/^[a-zA-Z0-9_-]{10,}$/`); rejects tokens with shell metacharacters
69
+
70
+ **Dead code removed in `cli/commands/init.js`**:
71
+ - `fs.symlinkSync().catch?.()` was unreachable — `symlinkSync` is synchronous and does not return a promise
72
+ - Removed the `.catch?.()` call
73
+
74
+ **`execSync` replaced with `execFileSync`** across all CLI command files:
75
+ - Zero remaining `execSync` calls in the CLI package
76
+
77
+ ### Deprecated
78
+
79
+ `scripts/setup.sh` is now the legacy install path. The `--path` flag, `--protect`, `--unprotect`, `--protect-only`, `--unprotect-only`, and `--uninstall` modes are superseded by the `npx gentyr` CLI. `setup.sh` will be removed in v2.0.
80
+
81
+ ---
82
+
83
+ ## 2026-02-22 - Security: SQL Injection Fix in Supabase MCP Server
84
+
85
+ ### Fixed
86
+
87
+ **SQL injection vulnerability in Supabase MCP server** (`packages/mcp-servers/src/supabase/types.ts`, `packages/mcp-servers/src/supabase/server.ts`):
88
+ - Added shared `sqlIdentifier` Zod validator (`/^[a-zA-Z_][a-zA-Z0-9_]*$/`) to all 6 schemas that accept table or function names: `SelectArgsSchema`, `InsertArgsSchema`, `UpdateArgsSchema`, `DeleteArgsSchema`, `RpcArgsSchema`, and `DescribeTableArgsSchema`
89
+ - Table/function names were previously interpolated directly into SQL strings with no validation, allowing injection via malicious identifier strings
90
+ - `SqlArgsSchema` intentionally left unrestricted — it accepts raw SQL by design
91
+ - Defense-in-depth: `describeTable()` also adds single-quote escaping as a secondary guard
92
+
93
+ ### Tests
94
+
95
+ **320 new vitest tests** (`packages/mcp-servers/src/supabase/__tests__/supabase-schemas.test.ts`):
96
+ - Coverage across all 6 affected schemas: valid identifiers, injection payloads (DROP, UNION, comment sequences), regex boundary cases, and edge cases (empty string, leading digits, special characters)
97
+ - Total: 1414 tests passing across 28 test files
98
+
99
+ ---
100
+
101
+ ## 2026-02-22 - OP_SERVICE_ACCOUNT_TOKEN Sync & Desync Detection
102
+
103
+ ### Added
104
+
105
+ **OP token desync detection in `credential-health-check.js`** (`scripts/hooks/credential-health-check.js`, `.claude/hooks/credential-health-check.js`):
106
+ - At `SessionStart`, the hook now compares the shell `OP_SERVICE_ACCOUNT_TOKEN` environment variable against the value stored in `.mcp.json`
107
+ - If they differ, `opTokenDesync = true` is set; `process.env` is always overwritten with the `.mcp.json` value (source of truth)
108
+ - A `desyncPrefix` warning is prepended to any output message: "GENTYR: OP_SERVICE_ACCOUNT_TOKEN in shell differs from .mcp.json (source of truth). Run `npx gentyr sync` to re-sync."
109
+ - When all credentials are valid but a desync exists, the warning is emitted as the sole message rather than silent success
110
+ - Template copy (`scripts/hooks/credential-health-check.js`) synced to match the runtime copy; both files are now identical
111
+
112
+ **`setup.sh` section 3c — OP shell profile sync** (`scripts/setup.sh`):
113
+ - During install with `--op-token`, writes a `# BEGIN GENTYR OP` / `# END GENTYR OP` managed block to `~/.zshrc` (or `~/.bashrc`) containing `export OP_SERVICE_ACCOUNT_TOKEN=<token>`
114
+ - Idempotent: removes any existing managed block and any legacy unmanaged `export OP_SERVICE_ACCOUNT_TOKEN=` lines before writing
115
+ - During uninstall, removes the managed block from all detected shell profiles
116
+
117
+ **`validateShellSync()` in `setup-validate.js`** (`scripts/setup-validate.js`):
118
+ - New validator in the `SERVICE_VALIDATORS` registry (key: `shellSync`)
119
+ - Reads `.mcp.json` token as source of truth and compares against the `# BEGIN GENTYR OP` block in `~/.zshrc` / `~/.bashrc`
120
+ - Reports `fail` if: no managed block exists, legacy unmanaged export found, or tokens differ; reports `warn` if `.mcp.json` unreadable or no shell profile found
121
+ - Remediation message: "Run `npx gentyr sync` to re-sync shell profile with .mcp.json token"
122
+
123
+ ### Tests
124
+
125
+ **11 new tests + 4 fixed assertions** (`.claude/hooks/__tests__/credential-health-check.test.js`):
126
+ - New `OP Token Desync Detection` describe block with 11 tests covering: desync warning when shell token differs from `.mcp.json`, silent success when tokens match, desync warning prepended to missing-credential messages, desync warning prepended to 1Password auth failure messages, `process.env` always overwritten with `.mcp.json` value, no desync when shell token is absent, and no token value exposure in output
127
+ - Fixed 4 existing test assertions that broke after desync changes (pattern updates for `desyncPrefix` and template literal matching)
128
+ - Total: 42 tests passing (was 31 before)
129
+
130
+ ### Documentation
131
+
132
+ **Updated files**:
133
+ - `docs/AUTOMATION-SYSTEMS.md` — Hook Registration table updated to include `credential-health-check` at `SessionStart`; new "Credential Health Check Hook" section added
134
+ - `CLAUDE.md` — New "Credential Health Check Hook" bullet; uninstall description updated to mention shell profile block removal
135
+ - `docs/SETUP-GUIDE.md` — Phase 1 updated with shell profile sync behavior and managed block format
136
+ - `docs/CHANGELOG.md` — This entry
137
+
138
+ ---
139
+
140
+ ## 2026-02-22 - Bypass Security Hardening (Phase 2) + Fix Unknown Accounts
141
+
142
+ ### Added
143
+
144
+ **HMAC verification in `executeBypass()`** (`packages/mcp-servers/src/deputy-cto/server.ts`):
145
+ - When the CTO types `APPROVE BYPASS <code>`, the UserPromptSubmit hook now writes an HMAC-SHA256 signature into `bypass-approval-token.json` over `code|request_id|expires_timestamp|bypass-approved`
146
+ - `execute_bypass` verifies this signature using the root-owned protection key before proceeding
147
+ - Forged token files are detected, deleted, and rejected with `FORGERY DETECTED: Invalid bypass approval token signature`
148
+ - Matches the verification pattern already used by `executeHotfixPromotion()`
149
+
150
+ **`pending_triage_count` in `get_pending_count` result** (`packages/mcp-servers/src/deputy-cto/server.ts`, `types.ts`):
151
+ - `GetPendingCountResult` now includes `pending_triage_count` alongside `pending_count`
152
+ - Lets the CTO see the split between pending questions and pending triage reports when `commits_blocked: true`
153
+
154
+ **Account profile resolution in `syncKeys()`** (`.claude/hooks/key-sync.js`, `.claude/hooks/api-key-watcher.js`):
155
+ - `fetchAccountProfile(accessToken)` exported from `key-sync.js`; calls `https://api.anthropic.com/api/oauth/profile` to resolve `account_uuid` and `email`
156
+ - `syncKeys()` now calls this for every active/exhausted key with `account_uuid === null` after the token refresh loop
157
+ - Fixes "unknown" accounts in the CTO notification status line caused by keys added by automation or token refresh paths that skipped the interactive SessionStart profile-resolution
158
+ - `api-key-watcher.js` now imports `fetchAccountProfile` from `key-sync.js` instead of maintaining a local copy
159
+
160
+ **Fingerprint cross-match in quota display hooks** (`.claude/hooks/cto-notification-hook.js`, `.claude/hooks/slash-command-prefetch.js`):
161
+ - Fallback deduplication for null-UUID keys: after building the account map, checks if any fingerprint-based entry (`fp:` prefix) matches a UUID-bearing entry by `seven_day + seven_day_sonnet` values
162
+ - Merges matches to prevent "unknown" appearing in the status line even when the profile API is temporarily unavailable
163
+
164
+ ### Changed
165
+
166
+ **`requestBypass` rate limit** (`packages/mcp-servers/src/deputy-cto/server.ts`):
167
+ - Maximum 3 pending bypass-request questions allowed at a time
168
+ - `request_bypass` returns an error if the limit is reached, asking the agent to wait
169
+
170
+ **`reportToCto` rate limit** (`packages/mcp-servers/src/agent-reports/server.ts`):
171
+ - Maximum 5 untriaged reports per reporting agent allowed at a time
172
+ - `report_to_cto` returns an error if the limit is reached
173
+
174
+ ### Removed
175
+
176
+ **`spawn_implementation_task` tool** (`packages/mcp-servers/src/deputy-cto/server.ts`, `types.ts`):
177
+ - Removed the tool that spawned background Claude instances directly from the deputy-cto server
178
+ - Task spawning is now exclusively managed by the agent-tracker MCP server and hourly automation
179
+
180
+ ### Tests
181
+
182
+ **15 new vitest tests** (`packages/mcp-servers/src/deputy-cto/__tests__/deputy-cto.test.ts`, `packages/mcp-servers/src/agent-reports/__tests__/agent-reports.test.ts`):
183
+ - HMAC verification: forged token, missing HMAC, missing key, valid HMAC (4 tests)
184
+ - `get_pending_count` triage count (3 tests)
185
+ - `requestBypass` rate limiting (3 tests)
186
+ - `reportToCto` rate limiting (4 tests, in agent-reports test file)
187
+ - Total: 1093 tests passing across 27 test files
188
+
189
+ ### Documentation
190
+
191
+ **Updated files**:
192
+ - `docs/AUTOMATION-SYSTEMS.md` — Deputy-CTO Security Guards section expanded with Phase 2 details; `syncKeys()` process updated with profile resolution step
193
+ - `docs/CHANGELOG.md` — This entry
194
+ - `CLAUDE.md` — Key Sync Module updated with `fetchAccountProfile` export and `syncKeys()` profile resolution step
195
+ - `plans/fix-unknown-accounts.md` — Removed (plan fully implemented)
196
+ - `plans/TRIAGE-COMMAND.md` — Removed (plan fully implemented in prior session)
197
+
198
+ ---
199
+
200
+ ## 2026-02-21 - Rotation Proxy E2E Validation + Triage Command
201
+
202
+ ### Added
203
+
204
+ **`/triage` slash command** (`.claude/commands/triage.md`, `scripts/force-triage-reports.js`):
205
+ - On-demand force-spawn of the deputy-CTO triage cycle
206
+ - Bypasses hourly automation's triage check interval, automation-enabled flag, and CTO activity gate
207
+ - Prefetch handler in `slash-command-prefetch.js` injects pending report counts into the command
208
+ - Calls `force_triage_reports` on the agent-tracker MCP server
209
+ - Returns spawned session ID for `claude --resume` workflow
210
+ - Preserves concurrency guard, agent tracker registration, and per-item triage cooldown filtering
211
+ - Mirrors the `/spawn-tasks` pattern
212
+
213
+ **`force_triage_reports` MCP tool** (`packages/mcp-servers/src/agent-tracker/server.ts`, `types.ts`):
214
+ - New tool in agent-tracker server; calls `scripts/force-triage-reports.js` via execFileSync
215
+ - Returns `{ agentId, pid, sessionId, pendingReports }` result
216
+
217
+ **Deputy-CTO test coverage** (`packages/mcp-servers/src/deputy-cto/__tests__/deputy-cto.test.ts`):
218
+ - 284 lines of new vitest tests for deputy-cto server
219
+
220
+ ### Fixed
221
+
222
+ **TLS CONNECT `head` buffer handling** (`scripts/rotation-proxy.js`):
223
+ - Added `clientSocket.unshift(head)` before wrapping CONNECT socket in TLSSocket
224
+ - The `head` parameter contains early client data (TLS ClientHello) sent before the 200 response arrives; dropping it caused intermittent ECONNRESET errors
225
+ - Success rate went from ~20% to 100% in controlled tests
226
+ - This is the textbook fix for Node.js HTTPS MITM proxies
227
+
228
+ ### Tests
229
+
230
+ **`scripts/__tests__/rotation-proxy.test.js`** (NEW, 60 unit tests):
231
+ - Code structure: `head` buffer unshift in MITM CONNECT handler, transparent passthrough head forwarding
232
+ - Behavioral: `parseHttpRequest()`, `rebuildRequest()`, domain routing, log rotation threshold, `loadCerts()`, `getActiveToken()`, `rotateOnExhaustion()`, 429 retry cap
233
+ - Uses Node's built-in test runner (`node:test`)
234
+ - All 120 tests passing: 60 quota-monitor + 60 rotation-proxy
235
+
236
+ ### Documentation
237
+
238
+ **Updated files**:
239
+ - `CLAUDE.md` — Added `/triage` command under Automation Service; added CONNECT head buffer handling note to Rotation Proxy section
240
+ - `docs/CHANGELOG.md` — This entry
241
+
242
+ ---
243
+
244
+ ## 2026-02-21 - Rotation Proxy (replaces binary patching for credential swap)
245
+
246
+ ### Added
247
+
248
+ **Rotation proxy server** (`scripts/rotation-proxy.js`):
249
+ - Local MITM proxy on localhost:18080 that intercepts api.anthropic.com and mcp-proxy.anthropic.com
250
+ - Swaps Authorization header with active key from rotation state (`~/.claude/api-key-rotation.json`) on each request
251
+ - On 429 response: marks key exhausted, calls `selectActiveKey()`, retries request (max 2 retries)
252
+ - SSE streaming support for long-running API requests
253
+ - Health endpoint at `GET /__health` - returns active key ID, uptime, request count
254
+ - Structured JSON logging to `~/.claude/rotation-proxy.log` (1MB max with rotation)
255
+ - Runs as launchd KeepAlive service (`com.local.gentyr-rotation-proxy`) — auto-restarts on crash
256
+
257
+ **TLS certificate generation** (`scripts/generate-proxy-certs.sh`):
258
+ - One-time CA + server cert creation for MITM interception
259
+ - Trusts CA in macOS System Keychain automatically
260
+ - Idempotent: skips if certs already exist; `--remove` cleans up
261
+
262
+ **Proxy integration in launch points**:
263
+ - `scripts/setup-automation-service.sh`: provisions proxy launchd plist before automation plist; adds `HTTPS_PROXY/HTTP_PROXY/NO_PROXY` to automation environment
264
+ - `scripts/setup.sh`: cert generation in step 5c; shell profile integration (step 6d) with `BEGIN/END GENTYR PROXY` markers; cert removal + profile cleanup on uninstall
265
+ - `.claude/hooks/hourly-automation.js`: `checkProxyHealth()` before agent spawning; proxy env vars in `buildSpawnEnv()`
266
+ - `.claude/hooks/session-reviver.js`: proxy env vars in `buildSpawnEnv()`
267
+
268
+ ### Changed
269
+
270
+ **Adoption tracking removed** (`.claude/hooks/quota-monitor.js`):
271
+ - Removed `pendingAudit.adopted`, `adoptionCheckCount`, `ADOPTION_CONFIRMED/TIMEOUT` logic (now handled at network layer by proxy)
272
+ - Simplified `pendingAudit` creation; rotation audit logging retained
273
+
274
+ **Binary patching archived** (`scripts/patch-credential-cache.js`, `scripts/watch-claude-version.js`):
275
+ - `patch-credential-cache.js`: deprecation banner added; no code changes; kept for reference
276
+ - `watch-claude-version.js`: all credential patch logic removed; now only handles Clawd mascot patch on binary updates
277
+
278
+ ### Removed
279
+
280
+ **Adoption tracking tests** (`.claude/hooks/__tests__/quota-monitor-adoption-tracking.test.js`):
281
+ - Deleted: adoption tracking no longer exists in quota-monitor
282
+
283
+ ### Tests
284
+
285
+ - Updated `quota-monitor-rotation-audit.test.js`: removed adoption tracking assertions
286
+ - All tests passing: quota-monitor (27), rotation-audit (33), adaptive (42) = 102 total
287
+
288
+ ### Documentation
289
+
290
+ **Updated files**:
291
+ - `CLAUDE.md` - Rotation Proxy section added; Binary Patch Research marked ARCHIVED; quota-monitor adoption tracking notes removed
292
+
293
+ ---
294
+
295
+ ## 2026-02-21 - Seamless Credential Rotation + Health Auditing
296
+
297
+ ### Changed
298
+
299
+ **Seamless rotation for quota-based switches** (`.claude/hooks/quota-monitor.js`):
300
+ - Removed disruptive kill/restart paths (old lines 432-491): no more AppleScript terminal injection, no more orphaned process spawning
301
+ - Interactive sessions: now receive `continue: true` with system message explaining adoption timing (credentials written to Keychain, picked up at SRA or r6T, not immediate)
302
+ - Automated sessions: now receive `continue: false` with stopReason (clean stop for session-reviver to resume with fresh credentials from Keychain)
303
+ - Removed unused imports: `spawn`, `getClaudePid`, `detectTerminal`, `generateRestartScript`, `shellEscape`
304
+ - Updated doc comment to reflect seamless rotation behavior (version 2.0.0)
305
+
306
+ **Post-rotation health audit** (`.claude/hooks/quota-monitor.js`):
307
+ - Added `pendingAudit` field to throttle state
308
+ - Added `verifyPendingAudit()` function to verify rotation success
309
+ - Writes audit results to `rotation-audit.log`
310
+ - Imports `readKeychainCredentials` and `generateKeyId` from key-sync.js
311
+
312
+ **Shared keychain reader** (`.claude/hooks/key-sync.js`):
313
+ - New export: `readKeychainCredentials()` - reads and parses macOS Keychain credentials directly
314
+ - Used by quota-monitor for post-rotation auditing and by monitor-token-swap for state verification
315
+
316
+ **Rotation health monitoring** (`scripts/monitor-token-swap.mjs`):
317
+ - Added `--audit` flag: prints rotation health report (recent rotations, pending audits, current state, Keychain status, alerts)
318
+ - Refactored `readKeychainState()` to delegate to shared `readKeychainCredentials()` from key-sync.js
319
+ - Audit mode shows rotation success rate, credential sync status, and system health metrics
320
+
321
+ ### Added
322
+
323
+ **Binary patch research** (`scripts/patch-credential-cache.py`):
324
+ - Dry-run only research script for Claude Code's `iB()` credential memoization
325
+ - Searches for 9 patterns in Bun SEA binary (all found on v2.1.34)
326
+ - Proposes Approach A: setInterval injection to periodically clear `iB.cache` (60-second TTL)
327
+ - Not production-ready; exists for future reference if immediate adoption needed for quota rotation
328
+ - Test coverage: `scripts/__tests__/patch-credential-cache.test.js` (37 tests)
329
+
330
+ ### Tests
331
+
332
+ **Test updates**:
333
+ - Updated quota-monitor tests for seamless rotation paths (186 tests total, all passing)
334
+ - Added `readKeychainCredentials()` coverage in key-sync tests
335
+ - Added `--audit` flag tests for monitor-token-swap
336
+ - Created `patch-credential-cache.test.js` with 37 tests for binary patch research script
337
+ - Fixed `readKeychainState` test to match new delegation pattern
338
+
339
+ ### Documentation
340
+
341
+ **Updated files**:
342
+ - `CLAUDE.md` - Seamless rotation behavior, rotation monitoring tools, binary patch research note
343
+ - `docs/AUTOMATION-SYSTEMS.md` - Updated session flow diagrams and quota-monitor steps
344
+ - `MEMORY.md` - Added seamless rotation pattern note
345
+
346
+ ---
347
+
348
+ ## 2026-02-21 - Priority-Based Urgent Task Dispatch
349
+
350
+ ### Added
351
+
352
+ **Priority field in TODO database** (`packages/mcp-servers/src/todo-db/`):
353
+ - New `priority` field in task schema with values `'normal' | 'urgent'`
354
+ - Exposed in `CreateTaskArgsSchema` with default value `'normal'`
355
+ - Exposed in `ListTasksArgsSchema` as optional filter parameter
356
+ - Auto-migration added: `ALTER TABLE tasks ADD COLUMN priority TEXT NOT NULL DEFAULT 'normal'` runs on server init if column missing
357
+ - Type exports: `TASK_PRIORITY` constant array, `TaskPriority` type from `shared/constants.ts`
358
+
359
+ **Urgent dispatcher in hourly automation** (`.claude/hooks/hourly-automation.js`):
360
+ - New `tryDispatchUrgentTasks()` step runs before task runner (bypasses 1-hour age filter)
361
+ - Urgent tasks are NOT age-gated — they dispatch immediately when spawned
362
+ - Concurrency limit enforced: urgent dispatcher respects global agent cap
363
+ - Queries for tasks with `status='pending' AND priority='urgent'`
364
+ - Uses same `spawnTaskAgent()` flow as regular task runner
365
+
366
+ **Governance routing for triage self-handle** (`packages/mcp-servers/src/deputy-cto/server.ts`):
367
+ - Triage self-handle path now routes through `create_task` with `priority: 'urgent'` instead of ungoverned `spawn_implementation_task`
368
+ - Ensures ALL task spawning goes through centralized governance (concurrency limits, tracking, recovery)
369
+ - Urgent priority ensures immediate dispatch without waiting for 1-hour age threshold
370
+
371
+ ### Changed
372
+
373
+ **Force-spawn script** (`scripts/force-spawn-tasks.js`):
374
+ - Updated to support priority filter in task queries
375
+ - No behavioral changes (force-spawn bypasses priority entirely, spawns all matching tasks)
376
+
377
+ ### Tests
378
+
379
+ **Test coverage**:
380
+ - 76 vitest tests (MCP servers) + 113 node:test tests (hooks) = 189 total tests
381
+ - All tests passing
382
+ - TypeScript build clean
383
+ - Coverage includes priority field validation, schema migration, urgent dispatcher logic
384
+
385
+ ### Files Modified
386
+
387
+ **10 files across 3 areas**:
388
+ - MCP server: `shared/constants.ts`, `todo-db/types.ts`, `todo-db/server.ts`, `__testUtils__/schemas.ts`
389
+ - Hooks: `hourly-automation.js`
390
+ - Scripts: `force-spawn-tasks.js`
391
+ - Tests: `todo-db.test.ts`, `hourly-automation.test.js`
392
+
393
+ ---
394
+
395
+ ## 2026-02-21 - Health Data Freshness Gate + Monitor Actuation Mode
396
+
397
+ ### Added
398
+
399
+ **Health data freshness gate** (`.claude/hooks/key-sync.js`):
400
+ - New `HEALTH_DATA_MAX_AGE_MS` export (15 minutes) - usage data older than this is treated as unknown
401
+ - `selectActiveKey()` now nulls out usage data when `last_health_check` is older than 15 minutes
402
+ - Effect: prevents uninformed key switches when health data is stale
403
+ - Stale keys pass "usable" filter (not proven exhausted) but are excluded from comparison logic
404
+ - System stays put with current key rather than making blind decisions on outdated data
405
+
406
+ **Monitor actuation mode** (`scripts/monitor-token-swap.mjs`):
407
+ - New `--act` CLI flag enables actuation mode (default remains observation-only)
408
+ - DESYNC auto-fix: after 3 consecutive polls (~90s) with Keychain-vs-active desync, writes active key to Keychain automatically
409
+ - Actuation rotation: when `--act` enabled and active key >=90% usage, rotates to lower-usage alternative on different account with 5-min cooldown
410
+ - Stale-data health refresh (ALWAYS ON): deep checks now write fresh `last_health_check` and `last_usage` back to rotation state for ALL keys
411
+ - Email propagation: usage data propagates to all keys sharing same `account_email`
412
+ - New alert counters: `ACT_ROTATION`, `ACT_DESYNC_FIX`
413
+
414
+ **Test coverage** (`.claude/hooks/__tests__/health-data-freshness-gate.test.js`):
415
+ - 25 new tests covering `HEALTH_DATA_MAX_AGE_MS` constant and freshness gate behavior
416
+ - Code structure validation (8 tests): export check, value check, comment check, freshness loop placement
417
+ - Behavioral logic (9 tests): staleness detection, null-out logic, filter effects, comparison exclusion
418
+ - Integration scenarios (8 tests): no-switch with stale data, exhausted-current fallback to stale
419
+
420
+ ### Changed
421
+
422
+ **Global hooks configuration** (`~/.claude/settings.json`):
423
+ - Added PostToolUse hook: `quota-monitor.js` with absolute path, timeout 10s (fires for ALL projects)
424
+ - Added Stop hook: `stop-continue-hook.js` with absolute path, timeout 5s (fires for ALL projects)
425
+ - Ensures quota monitoring works even in projects without their own hooks
426
+
427
+ ### Fixed
428
+
429
+ **Usage optimizer maxKey computation** (`.claude/hooks/usage-optimizer.js`):
430
+ - Moved `maxKey5h`/`maxKey7d` computation to after exhausted key filtering
431
+ - Prevents exhausted keys from biasing effectiveUsage upward
432
+
433
+ ### Tests
434
+
435
+ **Test results**:
436
+ - All 25 new freshness gate tests pass
437
+ - All existing key-sync tests pass (deduplication, expired-filter, proactive-refresh)
438
+ - All quota-monitor adaptive tests pass
439
+ - Code review verified all critical logic (freshness gate, actuation rotation, DESYNC fix, email propagation)
440
+
441
+ ### Documentation
442
+
443
+ **Updated files**:
444
+ - `CLAUDE.md` - Added freshness gate documentation to Key Sync Module section
445
+ - `docs/CHANGELOG.md` - This entry
446
+
447
+ **Files modified (8 total)**:
448
+ - `.claude/hooks/key-sync.js` - Added `HEALTH_DATA_MAX_AGE_MS` constant + freshness gate in `selectActiveKey()`
449
+ - `scripts/monitor-token-swap.mjs` - Added `--act` actuation mode + DESYNC auto-fix + health refresh
450
+ - `~/.claude/settings.json` - Added global PostToolUse and Stop hooks
451
+ - `.claude/hooks/__tests__/health-data-freshness-gate.test.js` - New test suite (25 tests)
452
+ - `.claude/hooks/usage-optimizer.js` - Fixed maxKey computation timing
453
+ - `.claude/hooks/__tests__/usage-optimizer.test.js` - Updated tests
454
+ - `.claude/hooks/hourly-automation.js` - Updated tests
455
+ - `.claude/hooks/__tests__/hourly-automation.test.js` - Updated tests
456
+
457
+ ---
458
+
459
+ ## 2026-02-21 - Fix GENTYR Monitoring Gaps: Step 8 Violation Fixes
460
+
461
+ ### Fixed
462
+
463
+ **3 security violations in hourly-automation hook** (`.claude/hooks/hourly-automation.js`):
464
+
465
+ 1. **VIOLATION 1: Missing schema validation in readPersistentAlerts**
466
+ - Risk: Malformed persistent-alerts.json could cause type confusion or runtime errors
467
+ - Fix: Added comprehensive validation for top-level structure (`typeof`, null checks, `Array.isArray`)
468
+ - Fix: Alert entries missing required `severity` (string) or `resolved` (boolean) fields are now dropped
469
+ - Impact: Prevents injection or corruption attacks via malformed alert files
470
+
471
+ 2. **VIOLATION 2: Missing API response validation in checkCiStatus**
472
+ - Risk: Unexpected GitHub API responses could cause null pointer exceptions
473
+ - Fix: Added `Array.isArray(runs)` validation before accessing runs array
474
+ - Fix: Added `typeof latestRun.conclusion !== 'string'` validation before comparing conclusion
475
+ - Impact: Graceful degradation when GitHub API returns unexpected data
476
+
477
+ 3. **VIOLATION 3: Prompt injection risk in spawnAlertEscalation**
478
+ - Risk: Alert fields containing backticks, template literals, or newlines could inject arbitrary commands into agent prompt
479
+ - Fix: Created `sanitizeAlertField()` function (strips backticks, newlines, `${` syntax, truncates to 200 chars)
480
+ - Fix: Applied sanitization to ALL alert fields before prompt interpolation: title, key, severity, source, first_detected_at
481
+ - Fix: Moved sanitization before `registerSpawn` call to protect the description field
482
+ - Fix: Added `Number.isFinite` safety check on age calculation
483
+ - Impact: Prevents malicious alert data from executing arbitrary code in agent context
484
+
485
+ ### Added
486
+
487
+ **Test coverage** (`.claude/hooks/__tests__/hourly-automation.test.js`):
488
+ - 4 structural tests for VIOLATION 1 (schema validation)
489
+ - 3 structural tests for VIOLATION 2 (CI API response validation)
490
+ - 8 structural tests for VIOLATION 3 (sanitization placement)
491
+ - 14 behavioral tests for `sanitizeAlertField` function
492
+ - 15 behavioral tests for `readPersistentAlerts` with file I/O
493
+ - Total: 44 new tests added
494
+
495
+ ### Tests
496
+
497
+ **Test results**:
498
+ - All 102 hourly-automation tests pass (58 existing + 44 new)
499
+ - All 202 usage-optimizer tests pass
500
+ - Code review: All violations addressed, 2 follow-up fixes applied (sanitize in registerSpawn, safe age calculation)
501
+
502
+ ### Context
503
+
504
+ This completes Step 8 (final step) of the "Fix GENTYR Monitoring Gaps" plan. GAPs 1-7 were implemented in a prior session. All monitoring gap fixes are now complete.
505
+
506
+ **Files modified (2 total)**:
507
+ - `.claude/hooks/hourly-automation.js` - 3 violation fixes + 2 follow-up improvements
508
+ - `.claude/hooks/__tests__/hourly-automation.test.js` - 44 new tests
509
+
510
+ ---
511
+
512
+ ## 2026-02-21 - Usage Optimizer: 7 Cascading Bug Fixes + Trajectory Alignment
513
+
514
+ ### Fixed
515
+
516
+ **7 interconnected bugs causing permanent over-throttling** (factor stuck at 0.099, automation +913% slower):
517
+
518
+ 1. **Bug 1: Reset time selection picks last, not earliest** (`.claude/hooks/usage-optimizer.js`)
519
+ - When multiple keys have different reset times, the optimizer must use the earliest reset time to be conservative
520
+ - Previous: Used arbitrary last key's reset time (could be far in future)
521
+ - Fix: Changed `resetAt5h = k['5h_reset']` to `resetAt5h = k['5h_reset'] < resetAt5h`
522
+
523
+ 2. **Bug 2: Exhausted accounts (7d >= 99.5%) pollute aggregate + EMA rate** (`.claude/hooks/usage-optimizer.js`)
524
+ - Exhausted keys should be filtered from both aggregate averaging AND trajectory rate calculation
525
+ - Previous: Filtered from aggregate but still included in EMA rate calculation
526
+ - Fix: Added `exhaustedKeyIds` Set, filter from both `calculateAggregate()` and `calculateTrajectory()`
527
+
528
+ 3. **Bug 3: No tiered factor recovery from extreme throttling** (`.claude/hooks/usage-optimizer.js`)
529
+ - When factor hits MIN_FACTOR (0.05), 10% MAX_CHANGE_PER_CYCLE limit prevents recovery
530
+ - Fix: Two-tier recovery system:
531
+ - Tier 1 (hard reset): When factor <= 0.15 AND current usage < 63%, reset factor to 1.0 immediately
532
+ - Tier 2 (gradual boost): When factor < 0.5 AND current usage < target, apply 1.5x boost per cycle
533
+
534
+ 4. **Bug 4: No per-key reset boundary detection** (`.claude/hooks/usage-optimizer.js`)
535
+ - Reset detection only looked at aggregate utilization drop, missing individual key resets
536
+ - Fix: Added PER_KEY_RESET_DROP_THRESHOLD (50pp) check — if ANY key's 5h drops >50pp between snapshots, reset factor to 1.0
537
+
538
+ 5. **Bug 5: Key-count discontinuity causes spurious rate spikes** (`.claude/hooks/usage-optimizer.js`)
539
+ - When number of active keys changes between snapshots, rate calculation becomes invalid
540
+ - Fix: Added key-count validation — reject snapshot pairs where key counts differ
541
+
542
+ 6. **Bug 6: Trajectory.ts not aligned with optimizer** (`packages/cto-dashboard/src/utils/trajectory.ts`)
543
+ - Dashboard trajectory calculation didn't filter exhausted accounts (inconsistent with optimizer)
544
+ - Fix: Added same exhausted account filtering (7d >= 0.995) to `getQuotaTrajectory()`
545
+
546
+ 7. **Bug 7: maxKey computed from all keys including exhausted** (`.claude/hooks/usage-optimizer.js`)
547
+ - When computing effectiveUsage (max of average vs. maxKey), exhausted keys biased maxKey upward
548
+ - Fix: Moved maxKey5h/maxKey7d computation to after active key filtering
549
+
550
+ ### Added
551
+
552
+ **Utility function** (`.claude/hooks/usage-optimizer.js`):
553
+ - `resetOptimizer()` export for manual cleanup after polluted data (clears snapshots, resets factor to 1.0)
554
+
555
+ **Test coverage** (`.claude/hooks/__tests__/usage-optimizer.test.js`):
556
+ - 13 new tests covering reset time selection, exhausted account filtering, tier-1/tier-2 recovery, per-key reset detection, key-count validation
557
+ - 3 new trajectory tests for exhausted account filtering (`packages/cto-dashboard/src/utils/__tests__/trajectory.test.ts`)
558
+
559
+ ### Tests
560
+
561
+ **Test results**:
562
+ - All 202 usage-optimizer tests pass (189 existing + 13 new)
563
+ - All 23 trajectory tests pass (20 existing + 3 new)
564
+ - All 25 cto-report tests pass
565
+ - Code review: 1 minor concern addressed (maxKey bug fix added as Bug 7)
566
+
567
+ ### Impact
568
+
569
+ **Before fixes**: Factor stuck at 0.099 (MIN_FACTOR), all automation throttled to +913% slower (essentially paused)
570
+
571
+ **After fixes**: Factor can reset to 1.0 on usage drop or key reset, tier-1 recovery provides immediate escape from extreme throttling, tier-2 recovery prevents gradual descent back to MIN_FACTOR
572
+
573
+ **Post-deploy action required**: Call `resetOptimizer()` on target project to clear polluted usage-snapshots.json and reset factor from 0.099 to 1.0
574
+
575
+ **Files modified (5 total)**:
576
+ - `.claude/hooks/usage-optimizer.js` - 7 bug fixes + resetOptimizer() export
577
+ - `packages/cto-dashboard/src/utils/trajectory.ts` - Exhausted account filtering alignment
578
+ - `.claude/hooks/__tests__/usage-optimizer.test.js` - 13 new tests
579
+ - `packages/cto-dashboard/src/utils/__tests__/trajectory.test.ts` - 3 new tests
580
+ - `.claude/hooks/hourly-automation.js` - Updated tests (not functionality)
581
+
582
+ ---
583
+
584
+ ## 2026-02-21 - Product Manager Agent & PMF Analysis System
585
+
586
+ ### Added
587
+
588
+ **Product Manager MCP Server** (2 files):
589
+ - `packages/mcp-servers/src/product-manager/server.ts` - 13 MCP tools with SQLite DB, sequential section lock, markdown auto-generation
590
+ - `packages/mcp-servers/src/product-manager/types.ts` - Zod schemas for 6 analysis sections (market_space, buyer_personas, competitor_differentiation, pricing_models, niche_strengths, user_sentiment)
591
+
592
+ **Agent & Command Integration** (2 files):
593
+ - `.claude/agents/product-manager.md` - Opus model agent with read-only codebase access, WebSearch/WebFetch for research
594
+ - `.claude/commands/product-manager.md` - `/product-manager` slash command with status display and workflow options
595
+
596
+ **Dashboard Integration** (3 files):
597
+ - `packages/cto-dashboard/src/utils/product-manager-reader.ts` - Data reader for PMF analysis state
598
+ - `packages/cto-dashboard/src/components/ProductManagerSection.tsx` - Ink/React dashboard component
599
+ - Modified: `packages/cto-dashboard/src/App.tsx`, `index.tsx`, `components/index.ts`, `mock-data.ts`
600
+
601
+ **System Integration** (4 files):
602
+ - `packages/mcp-servers/src/shared/constants.ts` - Added PRODUCT-MANAGER to VALID_SECTIONS
603
+ - `packages/mcp-servers/src/todo-db/server.ts` - CHECK constraint + migration for PRODUCT-MANAGER section
604
+ - `.claude/hooks/agent-tracker.js` - New agent type registration
605
+ - `.claude/hooks/hourly-automation.js` - SECTION_AGENT_MAP entry
606
+ - `.claude/hooks/slash-command-prefetch.js` - Prefetch handler
607
+
608
+ **User Feedback Access Control** (2 files):
609
+ - `packages/mcp-servers/src/user-feedback/server.ts` - cto_protected migration + CTO-only access control for deletePersona
610
+ - `packages/mcp-servers/src/user-feedback/types.ts` - cto_protected + caller fields added to persona schema
611
+
612
+ **MCP Tools** (13 tools):
613
+ - `initiate_analysis` - Start PMF analysis (creates pending_approval state)
614
+ - `approve_analysis` - CTO approval to proceed
615
+ - `get_analysis_status` - Check overall progress
616
+ - `read_section` - Read content with prior context cascading
617
+ - `write_section` - Write single-content sections (1, 3, 4, 5)
618
+ - `add_entry` - Add list entries (sections 2, 6)
619
+ - `list_pain_points` - Query user_sentiment entries
620
+ - `map_pain_point_persona` - Link pain points to user-feedback personas
621
+ - `clear_and_respawn` - Wipe and rebuild analysis via task chain
622
+ - `get_compliance_report` - Persona mapping coverage stats
623
+ - `regenerate_md` - Export to `pmf-analysis.md`
624
+ - `delete_analysis` - Reset state
625
+ - `update_analysis_metadata` - Update timestamps and metadata
626
+
627
+ **Analysis Workflow**:
628
+ 1. User/deputy-CTO calls `initiate_analysis` → state: pending_approval
629
+ 2. Deputy-CTO approves → state: approved
630
+ 3. Hourly automation spawns PRODUCT-MANAGER agent tasks for each section (sequential)
631
+ 4. Agent researches via WebSearch/WebFetch, reads codebase, writes sections
632
+ 5. After Section 6 completes, persona evaluation task maps pain points to user-feedback personas
633
+ 6. `regenerate_md` exports full analysis to markdown
634
+
635
+ **Sequential Lock**:
636
+ - Each section requires all prior sections to be populated before writing
637
+ - Context cascading: `read_section` returns all previous sections as context
638
+ - Prevents fragmented or out-of-order analysis
639
+
640
+ ### Tests
641
+
642
+ **New test files** (4 files):
643
+ - `packages/mcp-servers/src/product-manager/__tests__/product-manager.test.ts` - 32 tests covering all 13 MCP tools, state machine, sequential lock, persona mapping
644
+ - `.claude/hooks/__tests__/agent-tracker-product-manager.test.js` - 11 tests for agent type registration
645
+ - `.claude/hooks/__tests__/hourly-automation-product-manager.test.js` - 14 tests for task spawning
646
+ - `.claude/hooks/__tests__/slash-command-prefetch-product-manager.test.js` - 30 tests for command prefetch handler
647
+
648
+ **Test results**:
649
+ - All 1092 mcp-servers tests pass
650
+ - All 55 hook tests pass
651
+ - Clean TypeScript build for both packages/mcp-servers and packages/cto-dashboard
652
+ - Mock dashboard renders ProductManagerSection correctly
653
+
654
+ ### Fixed
655
+
656
+ **Critical security/compliance issues** (identified during code review):
657
+ 1. `deletePersona` missing CTO-protected access control - FIXED (requires deputy-CTO caller)
658
+ 2. PRODUCT-MANAGER missing from spawn-tasks pending query - FIXED (added to slash-command-prefetch.js)
659
+ 3. AddEntryArgsSchema.section not constrained to valid values (2, 6) - FIXED (Zod enum)
660
+ 4. `clearAndRespawn` opens todo.db without WAL pragma - FIXED (added pragma)
661
+ 5. `mapPainPointPersona` silently continues on persona verification failure - FIXED (throws error)
662
+ 6. metadata field not validated as JSON - FIXED (Zod z.record)
663
+
664
+ ### Impact
665
+
666
+ This session delivered the 11th agent (PRODUCT-MANAGER) and a complete PMF analysis system:
667
+ 1. **Market research automation**: Agent uses WebSearch/WebFetch for competitive intelligence
668
+ 2. **Codebase analysis**: Read-only access to understand product features
669
+ 3. **Sequential workflow**: 6 sections populate in order with context cascading
670
+ 4. **Persona integration**: Pain points map to user-feedback personas for automated testing
671
+ 5. **CTO oversight**: Analysis requires approval before starting
672
+ 6. **Dashboard visibility**: CTO sees PMF progress in main dashboard
673
+
674
+ All changes backward-compatible. New agent joins existing 10-agent ecosystem. Full integration with task runner, deputy-CTO triage, and hourly automation.
675
+
676
+ ## 2026-02-21 - Dashboard Sections as Agent-Facing MCP Tools & Slash Commands
677
+
678
+ ### Added
679
+
680
+ **Show MCP Server** (3 files):
681
+ - `packages/mcp-servers/src/show/types.ts` - Zod schemas and constants for 12 dashboard sections (`QUOTA`, `ACCOUNTS`, `DEPUTY_CTO`, `USAGE`, `AUTOMATIONS`, `TESTING`, `DEPLOYMENTS`, `WORKTREES`, `INFRA`, `LOGGING`, `TIMELINE`, `TASKS`)
682
+ - `packages/mcp-servers/src/show/server.ts` - 12 MCP tools generated from data-driven loop: `show_quota`, `show_accounts`, `show_deputy_cto`, etc. Each tool spawns the dashboard binary with `--section <name>` and optional `--limit <N>` flags
683
+ - `.mcp.json.template` - Registered `show` MCP server entry
684
+
685
+ **Slash Command Integration** (2 files):
686
+ - `.claude/commands/show.md` - New `/show` slash command reference page listing all 12 section tools with descriptions and usage examples
687
+ - `.claude/hooks/slash-command-prefetch.js` - Added `show` sentinel and lightweight `handleShow()` handler for instant command reference
688
+
689
+ **Dashboard CLI Enhancement** (1 file):
690
+ - `packages/cto-dashboard/src/index.tsx` - Added `--section <name>` and `--limit <N>` CLI flags with `renderSection()` function that renders individual dashboard sections. Includes exhaustiveness check, invalid section warning, and support for all 12 sections.
691
+
692
+ **Agent Guidance** (2 files):
693
+ - `CLAUDE.md.gentyr-section` - Added "Status Displays" section encouraging agents to use `mcp__show__*` tools before token-heavy operations, deployments, test runs, etc. Added `/show` to slash commands list.
694
+ - `.claude/agents/deputy-cto.md` - Added `mcp__show__*` to `allowedTools` and brief "Status Displays" usage guidance
695
+
696
+ **Use cases**:
697
+ - `mcp__show__show_quota()` before token-heavy operations
698
+ - `mcp__show__show_testing()` before writing or running tests
699
+ - `mcp__show__show_deployments()` before triggering deploys
700
+ - `mcp__show__show_tasks()` before creating tasks
701
+ - `mcp__show__show_worktrees()` before provisioning worktrees
702
+ - `mcp__show__show_automations()` before spawning agents
703
+
704
+ **Architecture**:
705
+ - Tools use `execFileSync` to spawn the dashboard binary (prevents shell injection)
706
+ - Pass `{ limit: N }` to expand the number of rows shown
707
+ - Renders rich terminal displays (Ink-based React components)
708
+ - Works with both `--mock` (development) and live MCP connections
709
+
710
+ ### Tests
711
+
712
+ **Test results**:
713
+ - All 760 cto-dashboard tests pass
714
+ - All 1060 mcp-servers tests pass
715
+ - Both packages build cleanly
716
+ - All 12 sections verified working with `--mock` flag
717
+
718
+ ### Documentation
719
+
720
+ **Updated documentation** (1 file):
721
+ - `CLAUDE.md.gentyr-section` - Added comprehensive "Status Displays" section with usage guidance and tool listings
722
+
723
+ ### Impact
724
+
725
+ This session delivered agent-facing status displays:
726
+ 1. **12 MCP tools**: Agents can now check individual dashboard sections on-demand without viewing the full CTO report
727
+ 2. **Contextual usage**: Tools support passing `{ limit: N }` for expanded views
728
+ 3. **Slash command**: `/show` provides quick reference for all available section tools
729
+ 4. **Integration**: Works with both mock data (development) and live MCP connections (production)
730
+
731
+ All changes backward-compatible. Full dashboard (`/cto-report`) still available. New tools provide granular, on-demand access to specific metrics.
732
+
733
+ ## 2026-02-21 - CTO Dashboard: Hotfix Pathway, Deployments Upgrade, Worktree Visualization
734
+
735
+ ### Added
736
+
737
+ **CTO Emergency Hotfix Pathway** (4 files):
738
+ - `packages/mcp-servers/src/deputy-cto/types.ts` - Zod schemas for `RequestHotfixPromotionArgs`, `ExecuteHotfixPromotionArgs`, `HotfixRequest`
739
+ - `packages/mcp-servers/src/deputy-cto/server.ts` - `request_hotfix_promotion` and `execute_hotfix_promotion` MCP tools, `hotfix_requests` DB table
740
+ - `.claude/hooks/bypass-approval-hook.js` - APPROVE HOTFIX pattern matching, 6-char code validation, HMAC token writing to `hotfix-approval-token.json`
741
+ - `.claude/commands/hotfix.md` - New `/hotfix` slash command with CTO approval workflow
742
+
743
+ **Hotfix workflow**:
744
+ 1. Agent calls `request_hotfix_promotion` → validates staging has unreleased commits → returns 6-char approval code
745
+ 2. Agent presents code to user: `APPROVE HOTFIX <code>`
746
+ 3. User types approval → bypass-approval-hook writes HMAC token (5-minute expiry)
747
+ 4. Agent calls `execute_hotfix_promotion` with code → validates token → spawns staging→main promotion immediately (bypasses 24h stability window + midnight gate)
748
+
749
+ **DEPLOYMENTS Section Upgrade** (3 files):
750
+ - `packages/cto-dashboard/src/utils/deployments-reader.ts` - Added `localDevCount` (counts active worktrees), `stagingFreezeActive` (boolean flag) to pipeline data
751
+ - `packages/cto-dashboard/src/components/DeploymentsSection.tsx` - 4-column EnvironmentHealth (added Local Dev), PipelineDetail shows worktree count + freeze snowflake (❄)
752
+ - `packages/cto-dashboard/src/mock-data.ts` - Added preview deploys, `localDevCount`, `stagingFreezeActive`, `getMockWorktrees()` for realistic rendering
753
+
754
+ **Pipeline visualization**:
755
+ ```
756
+ local dev (3) → preview ✓ → staging ✓ ❄ → production (24h gate) Last: 5h ago
757
+ ```
758
+
759
+ **WORKTREES Section** (2 new files, 3 modified):
760
+ - `packages/cto-dashboard/src/utils/worktree-reader.ts` - Reads git worktree state, agent tracker DB, maps to pipeline stages
761
+ - `packages/cto-dashboard/src/components/WorktreeSection.tsx` - Full visualization: summary cards, worktree table (branch, agent, stage, stale flag, files), cleanup hints
762
+ - `packages/cto-dashboard/src/components/index.ts` - Added WorktreeSection export
763
+ - `packages/cto-dashboard/src/App.tsx` - Added worktrees prop, WorktreeSection rendering
764
+ - `packages/cto-dashboard/src/index.tsx` - Wired worktree data loading (mock + live paths)
765
+
766
+ **Worktree details displayed**:
767
+ - Branch name, agent ID, pipeline stage, creation time, modified files count
768
+ - Stale indicator for worktrees >3 days old
769
+ - Cleanup hints for merged branches
770
+
771
+ ### Fixed
772
+
773
+ **Critical deputy-cto tool registration bug** (1 file):
774
+ - `packages/mcp-servers/src/deputy-cto/server.ts` - `request_hotfix_promotion` and `execute_hotfix_promotion` were defined as tool handlers but never added to the `tools` array
775
+ - Result: Tools were invisible to MCP clients (would have failed at runtime)
776
+ - Fix: Added both tools to the array before passing to `McpServer` constructor
777
+
778
+ ### Tests
779
+
780
+ **New test files** (1 file):
781
+ - `.claude/hooks/__tests__/bypass-approval-hotfix.test.js` - 8 unit tests for APPROVE HOTFIX pattern matching, HMAC token generation, expiry, invalid code rejection
782
+
783
+ **Updated test files** (3 files):
784
+ - `packages/cto-dashboard/src/utils/__tests__/account-overview-reader.test.ts` - Added tests for worktree integration (schema changes)
785
+ - `packages/mcp-servers/src/deputy-cto/__tests__/deputy-cto.test.ts` - Tests for hotfix promotion tools (validation, DB writes, approval flow)
786
+ - Mock data validation tests for deployments-reader and worktree-reader
787
+
788
+ **Test results**:
789
+ - TypeScript build clean for both `cto-dashboard` and `mcp-servers`
790
+ - All existing tests pass
791
+ - Mock mode dashboard renders all 3 new features correctly
792
+
793
+ ### Documentation
794
+
795
+ **Updated documentation** (2 files):
796
+ - `README.md` - Regenerated via `generate-readme.js` with new dashboard sections visible
797
+ - `docs/DEPLOYMENT-FLOW.md` - Added "Emergency Hotfix Pathway" section with workflow, prerequisites, safety measures; added `APPROVE HOTFIX` to CTO approval gates table
798
+
799
+ ### Impact
800
+
801
+ This session delivered 3 major CTO dashboard enhancements:
802
+ 1. **Emergency hotfix pathway**: CTO can approve immediate staging→main promotion when production is broken (bypasses 24h + midnight gates)
803
+ 2. **Deployments visibility**: Pipeline now shows local dev worktrees and staging freeze status at a glance
804
+ 3. **Worktree tracking**: CTO sees all active feature branches, agent assignments, stale work, and cleanup hints
805
+
806
+ All changes isolated to dashboard + deputy-CTO MCP server. No changes to core automation or promotion logic.
807
+
808
+ ## 2026-02-21 - Chrome Bridge: Contextual Browser Automation Tips
809
+
810
+ ### Added
811
+
812
+ **Contextual browser automation tips** (3 files):
813
+ - `packages/mcp-servers/src/chrome-bridge/browser-tips.ts` - BrowserTip interface, BrowserTipTracker class with session-scoped deduplication
814
+ - 14 contextual tips (5 general + 9 site-specific) sourced from docs/SETUP-GUIDE.md
815
+ - Tips are injected into chrome-bridge tool responses based on hostname and tool usage
816
+ - Each tip shown at most once per Claude Code session (MCP server lifetime)
817
+ - Domain boundary hostname matching (github.com matches *.github.com)
818
+ - Only shown on interactive tools: `navigate`, `computer`, `form_input`, `find`, `read_page`
819
+ - `packages/mcp-servers/src/chrome-bridge/server.ts` - Import BrowserTipTracker, cache URLs on navigate, appendTips method called at both return paths in executeTool
820
+ - `packages/mcp-servers/src/chrome-bridge/index.ts` - Re-export browser-tips module
821
+
822
+ **Site-specific tips included**:
823
+ - GitHub: Form input preference for special characters in token names
824
+ - 1Password: Field creation workflow (chevron + button + form_input + save verification)
825
+ - Render: One-time API key capture with get_page_text
826
+ - Vercel: One-time token capture, Team ID extraction
827
+ - Cloudflare: Zone ID extraction, multi-step wizard navigation
828
+ - Supabase: Reveal button for service_role key, multi-value extraction
829
+ - Elastic Cloud: Dev Tools Console API key creation (REST command preferred over UI)
830
+ - Resend: One-time API key capture, permission dropdown selection
831
+ - Codecov: GitHub OAuth disruption, manual login fallback, token extraction
832
+
833
+ ### Tests
834
+
835
+ **New test files** (2 files):
836
+ - `packages/mcp-servers/src/chrome-bridge/__tests__/browser-tips.test.ts` - 38 unit tests for BrowserTipTracker (hostname matching, deduplication, tool filtering)
837
+ - `packages/mcp-servers/src/chrome-bridge/__tests__/appendTips.test.ts` - 24 integration tests for appendTips method (error exclusion, URL caching, anti-spam)
838
+
839
+ **Test results**:
840
+ - 93 chrome-bridge tests pass (31 existing + 62 new)
841
+ - TypeScript compilation clean (pre-existing deputy-cto unused variable warnings unrelated)
842
+
843
+ ### Fixed
844
+
845
+ **Browser automation quirks** (2 files):
846
+ - Hostname matching: Changed from `endsWith(h)` to `hostname === h || hostname.endsWith('.' + h)` for proper domain boundary matching (prevents "github.com" from matching "notgithub.com")
847
+ - Tip text: Fixed reference to `zoom` as standalone tool when it's actually a `computer` action
848
+
849
+ ### Design
850
+
851
+ **Anti-spam measures**:
852
+ - 5 interactive tools gate: Only `navigate`, `computer`, `form_input`, `find`, `read_page` trigger tips
853
+ - Per-tip Set deduplication: Each tip ID tracked, shown once per session
854
+ - Error exclusion: Tips never appended to error responses
855
+ - Session-scoped tracker: Tips reset on MCP server restart (new Claude Code session)
856
+
857
+ ### Why This Feature
858
+
859
+ **Problem**: Agents using chrome-bridge MCP struggled with site-specific UI quirks. Browser automation tips existed only in docs/SETUP-GUIDE.md and were never shown to agents during actual browser automation.
860
+
861
+ **Solution**: Tips are now injected into chrome-bridge tool responses based on the site being visited. Agents see relevant guidance at the moment they need it.
862
+
863
+ ## 2026-02-21 - CTO Dashboard: Per-Account Quota Bars in Usage Trajectory
864
+
865
+ ### Added
866
+
867
+ **Per-account quota visualization** (4 files):
868
+ - `packages/cto-dashboard/src/components/UsageTrajectory.tsx` - Added `AccountQuotaBars` component showing per-account quota usage for 5-hour and 7-day windows
869
+ - Email-based deduplication: Multiple keys with the same `account_email` are merged to show one bar per account
870
+ - Invalid account filtering: Accounts with `status: 'invalid'` are excluded from display
871
+ - Truncated email labels: Shows first 20 chars + "..." for long email addresses
872
+ - Active account indicator: "*" suffix marks the currently active account
873
+ - `packages/cto-dashboard/src/App.tsx` - Passes `verifiedQuota` and `accountOverview` props to `UsageTrajectory`
874
+ - `packages/cto-dashboard/src/mock-data.ts` - Updated mock data to 3 distinct accounts for realistic quota bar rendering
875
+
876
+ ### Fixed
877
+
878
+ **Zod schema bug in account-overview-reader** (1 file):
879
+ - `packages/cto-dashboard/src/utils/account-overview-reader.ts` - Fixed critical schema parsing bug
880
+ - Root cause: Strict Zod schema expected `resets_at` as string, but actual data includes Date objects (from active keys) and ISO strings (from exhausted keys)
881
+ - Schema also expected `account_uuid` and `account_email` as required strings, but some keys have null values
882
+ - Result: Entire parse failed with `hasData: false`, causing quota bars to never render in production
883
+ - Fix: Changed `resets_at` to `z.unknown()`, `account_uuid` and `account_email` to `.nullable().optional()`
884
+ - This was the root cause preventing quota bars from showing in production (entire parse was failing)
885
+
886
+ ### Tests
887
+
888
+ **New test files** (2 files):
889
+ - `packages/cto-dashboard/src/components/__tests__/UsageTrajectory.test.tsx` - Updated for new props, added 7 new tests for deduplication and filtering (36 tests total, up from 29)
890
+ - `packages/cto-dashboard/src/utils/__tests__/account-overview-reader.test.ts` - New comprehensive test suite with 38 tests covering schema parsing, sorting, events, edge cases (96% statement coverage)
891
+
892
+ **Test results**:
893
+ - 760 tests pass across 22 test files (up from 719 across 21)
894
+ - Build passes (TypeScript compiles)
895
+ - Mock dashboard renders correctly with 3 accounts
896
+ - Live dashboard renders correctly with 4 real accounts (filtered from 32 keys)
897
+ - `generate-readme.js` successfully regenerates README with quota bars visible
898
+
899
+ ### Documentation
900
+
901
+ - README.md updated via `generate-readme.js` to show per-account quota bars in USAGE TRAJECTORY section
902
+ - Bars display format: `Total`, then individual accounts with usage percentages and progress bars
903
+
904
+ ## 2026-02-21 - Merge Chain Enforcement: Local Guards, Worktrees, and Stale Work Detection
905
+
906
+ ### Added
907
+
908
+ **Local branch protection guards** (2 files):
909
+ - Pre-commit guard blocks direct commits to `main`, `staging`, `preview` - enforcement in `.claude/hooks/pre-commit-review.js`
910
+ - Pre-push guard blocks direct pushes to protected branches - enforcement in `templates/config/husky/pre-push.template`
911
+ - Both guards are unbypassable (cannot be disabled with `--no-verify`)
912
+ - Exception: Promotion pipeline agents with `GENTYR_PROMOTION_PIPELINE=true` environment variable
913
+ - Provides immediate local feedback before attempting forbidden operations
914
+
915
+ **Git worktrees for concurrent agents** (2 files):
916
+ - `.claude/hooks/lib/worktree-manager.js` - Worktree lifecycle management (create, provision, cleanup)
917
+ - `.claude/hooks/lib/feature-branch-helper.js` - Branch naming and protection checks
918
+ - Enables multiple agents to work concurrently on separate feature branches without checkout conflicts
919
+ - Each agent gets isolated working directory at `.claude/worktrees/<branch-name>/`
920
+ - Worktree provisioning: symlinks to `.claude/agents/`, `.claude/hooks/`, `.husky/`, generates worktree-specific `.mcp.json`
921
+ - State isolation: SQLite databases remain in main project, shared via `CLAUDE_PROJECT_DIR`
922
+ - Automatic cleanup after branch merged to preview (6-hour cycle)
923
+
924
+ **Stale work detection** (1 file):
925
+ - `.claude/hooks/stale-work-detector.js` - Detects uncommitted changes, unpushed commits, and stale feature branches (3+ days)
926
+ - Runs every 24 hours via hourly automation
927
+ - Reports to deputy-CTO with category `git-hygiene`
928
+ - Surfaced in `/deputy-cto` briefing under "Merge Chain Status"
929
+
930
+ **Deputy-CTO merge chain integration** (2 files):
931
+ - `packages/mcp-servers/src/deputy-cto/server.ts` - Added `get_merge_chain_status` MCP tool
932
+ - `.claude/commands/deputy-cto.md` - Updated briefing to include merge chain status (commits ahead, active branches, stale branches)
933
+ - Provides structured view of feature branches, promotion pipeline status, and stale work
934
+
935
+ **Template files for setup.sh** (2 files):
936
+ - `CLAUDE.md.gentyr-section` - GENTYR framework instructions template (includes Team Spawning section)
937
+ - `CLAUDE.md.makerkit-section` - Makerkit integration instructions template
938
+ - Used by `scripts/setup.sh` to inject framework and integration docs into project CLAUDE.md files
939
+
940
+ ### Changed
941
+
942
+ **Agent spawning uses worktrees** (3 files):
943
+ - `.claude/hooks/hourly-automation.js` - Task agent spawning now creates worktrees and uses `cwd: worktreePath`
944
+ - `.claude/agents/code-writer.md` - Added feature branch workflow section (git workflow, PR creation, merge completion)
945
+ - `.claude/agents/test-writer.md` - Added worktree awareness and feature branch context
946
+
947
+ **Gitignore template** (1 file):
948
+ - `templates/config/gitignore.template` - Added `.claude/worktrees/` to prevent worktree tracking
949
+
950
+ ### Documentation
951
+
952
+ **DEPLOYMENT-FLOW.md** (1 file):
953
+ - Added "Local Branch Protection" section documenting pre-commit and pre-push guards
954
+ - Added "Git Worktrees for Concurrent Agents" section documenting worktree architecture
955
+ - Added "Stale Work Detection" section documenting detection categories and integration
956
+ - Updated "Feature Branch Workflow" section to mention automated branch creation
957
+
958
+ **Implementation plan** (1 file):
959
+ - Created `/Users/jonathantodd/.claude/plans/sequential-sprouting-map.md` - Complete 3-phase implementation plan
960
+ - Phase 1: Local branch guards (pre-commit + pre-push)
961
+ - Phase 2: Worktrees + feature branch auto-creation
962
+ - Phase 3: Stale work detection + deputy-CTO integration
963
+
964
+ ### Impact
965
+
966
+ This implementation makes the merge chain airtight with local enforcement, enables concurrent agent workflows via worktrees, and provides CTO visibility into stale work. All enforcement happens before remote operations, providing immediate feedback and preventing forbidden merges at the earliest possible point.
967
+
968
+ ## 2026-02-20 - Slash Command Detection Fix
969
+
970
+ ### Fixed
971
+
972
+ **Slash commands not being recognized by UserPromptSubmit hooks** (2 files):
973
+ - Root cause: Hooks receive JSON stdin like `{"prompt":"/restart-session",...}` but were only checking for HTML sentinel markers that exist in expanded .md content
974
+ - Impact: All 10 GENTYR slash commands were non-functional
975
+ - Fix: Added `extractPrompt()` to parse JSON stdin and extract raw prompt field
976
+ - Fix: Added `matchesCommand()` to check both bare `/command-name` and sentinel markers
977
+ - Files changed:
978
+ - `.claude/hooks/slash-command-prefetch.js` - Added JSON parsing for command detection (lines 66-90)
979
+ - `.claude/hooks/cto-notification-hook.js` - Updated slash command suppression logic (lines 507-519)
980
+
981
+ ### Tests
982
+
983
+ - **slash-command-detection**: 30/30 pass (new test file validates extractPrompt and matchesCommand)
984
+ - **cto-notification-hook**: 26/26 pass (8 new tests for slash command suppression)
985
+
986
+ ## 2026-02-20 - Credential File Guard: Tiered Blocking with CTO Approval
987
+
988
+ ### Added
989
+
990
+ **CTO-approvable file access for credential-file-guard** (8 files):
991
+ - Split blocked credential files into two protection tiers:
992
+ 1. **Always-blocked** - protection-key, approval tokens, .env files - hard deny with no escape hatch
993
+ 2. **Approvable** - services.json, .mcp.json, api-key-rotation.json, credential-provider.json, vault-mappings.json - deny with CTO approval code
994
+ - Approval flow via approval-utils.js: create HMAC-signed request → deputy-CTO generates one-time code → user types code → hook validates HMAC + expiry
995
+ - Files changed:
996
+ - `.claude/hooks/credential-file-guard.js` - Core tiered blocking logic with approval flow integration
997
+ - `.claude/hooks/protected-actions.json` - Added `files` section with 5 approvable file configs
998
+ - `.claude/hooks/protected-action-approval-hook.js` - Updated `getValidPhrases()` to include file phrases
999
+ - `.claude/hooks/lib/approval-utils.js` - Updated `createRequest` to add HMAC signature, argsHash, approval_mode
1000
+ - `packages/mcp-servers/src/deputy-cto/server.ts` - Fixed HMAC argsHash bug in `approveProtectedAction`, added `files` field to TypeScript interface
1001
+
1002
+ ### Fixed
1003
+
1004
+ **Deputy-CTO HMAC argsHash bug**:
1005
+ - `approveProtectedAction` was missing `argsHash` in HMAC computation (both verify and sign paths)
1006
+ - Would cause "FORGERY DETECTED" errors for gate-originated approval requests
1007
+ - Fixed by adding `argsHash` to `computeHmac(phrase, action, argsHash)` calls in verify and sign paths
1008
+ - Added 7 new test cases in `packages/mcp-servers/src/deputy-cto/__tests__/hmac-argshash.test.ts`
1009
+
1010
+ ### Tests
1011
+
1012
+ - **credential-file-guard**: 117/117 pass (13 new tests for approval flow)
1013
+ - **approval-hook**: 18/18 pass (8 new tests in `protected-action-approval-hook-files.test.js`)
1014
+ - **MCP servers**: 939/939 pass (7 new HMAC argsHash tests)
1015
+
1016
+ ### Known Follow-up Items
1017
+
1018
+ 1. HIGH: `checkApproval()` in approval-utils.js lacks HMAC verification (mitigated by ALWAYS_BLOCKED_SUFFIXES on approval file)
1019
+ 2. MEDIUM: Runtime files (.claude/hooks/.claude/) committed by prior checkpoint - need git rm --cached and .gitignore update (RESOLVED)
1020
+ 3. MEDIUM: HMAC key handling inconsistency (raw Buffer vs base64 string) between createRequest and computeHmac
1021
+ 4. MEDIUM: No HMAC integrity tests for credential-file-guard approval flow
1022
+ 5. LOW: Grep/Glob tools don't support approval path (intentional hard-block only)
1023
+
1024
+ ## 2026-02-20 - Protection System: Fix Token File EACCES Errors
1025
+
1026
+ ### Fixed
1027
+
1028
+ **Token file handling under sticky-bit protection** (4 files):
1029
+ - Root cause: `commit-approval-token.json` was missing from pre-creation loop in `setup.sh`, and hooks used `fs.unlinkSync()` (delete semantics) to clear tokens, which fails under sticky-bit protection on `.claude/`
1030
+ - Changes:
1031
+ 1. **`scripts/setup.sh`** - Added `commit-approval-token.json` to pre-creation loop (line 603)
1032
+ 2. **`.claude/hooks/pre-commit-review.js`** - Changed 2 `unlinkSync` calls to `writeFileSync(path, '{}')` pattern, added empty-object early-exit check
1033
+ 3. **`.claude/hooks/block-no-verify.js`** - Changed 7 `unlinkSync` calls to `clearToken()` helper using overwrite pattern, added empty-object early-exit check
1034
+ 4. **`packages/mcp-servers/src/deputy-cto/server.ts`** - Changed 2 `unlinkSync` calls to `writeFileSync(path, '{}')`, added empty-object early-exit check
1035
+ - Result: All token files can now be safely written/cleared under sticky-bit protection without EACCES errors
1036
+ - Pattern: Pre-create file during setup → overwrite with data to activate → overwrite with `{}` to consume/clear → treat `{}` as "no token"
1037
+
1038
+ ### Documentation
1039
+
1040
+ **Created `docs/shared/EPHEMERAL-STATE-FILES.md`**:
1041
+ - Comprehensive guide to the pre-create + overwrite pattern for ephemeral state files
1042
+ - Lists all 6 state files using this pattern with their writers/consumers
1043
+ - Step-by-step instructions for adding new state files
1044
+ - Common mistakes and how to avoid them
1045
+ - Critical for maintaining sticky-bit protection compatibility
1046
+
1047
+ ### Validation
1048
+
1049
+ - Code review: CLEAN, no violations
1050
+ - Test writer: No test updates needed (existing tests don't test token clearing behavior directly)
1051
+ - Pre-existing test failures confirmed (unrelated to changes)
1052
+ - TypeScript compiles clean with project tsconfig
1053
+ - All JS files pass syntax check
1054
+
1055
+ ## 2026-02-20 - Usage Optimizer: Per-Account Deduplication Fix
1056
+
1057
+ ### Fixed
1058
+
1059
+ **Double-counting bug in usage optimizer and dashboard** (`.claude/hooks/usage-optimizer.js`, `packages/cto-dashboard/src/utils/data-reader.ts`):
1060
+ - Root cause: When the same Anthropic account was discovered through multiple sources (environment variable, rotation state, Keychain, credentials file), each discovery was treated as a separate key for quota calculations
1061
+ - Result: Usage projections were inflated, causing premature throttling and incorrect dashboard metrics
1062
+ - Fix: `getApiKeys()` now includes `accountId` field (from `account_uuid`) in all returned key objects
1063
+ - `collectSnapshot()` deduplicates keys by `accountId` before building snapshots, using fingerprint fallback (`fp:${five_hour}:${seven_day}`) when `accountId` is null
1064
+ - `getKeyRotationMetrics()` in dashboard reader performs same per-account deduplication for consistent metrics
1065
+ - Warning messages changed from "Key" to "Account" to reflect deduplication scope
1066
+
1067
+ ### Tests
1068
+
1069
+ - **Updated 3 existing tests** in `.claude/hooks/__tests__/usage-optimizer.test.js`:
1070
+ - `getApiKeys()` structure test now asserts `accountId` field presence
1071
+ - `collectSnapshot()` tests updated for new `rawKeyData`/`keyLookup`/`accountMap` variables
1072
+ - Warning message assertions changed from "Key" to "Account"
1073
+ - **Added 6 new behavioral tests** in "Per-Account Deduplication" describe block:
1074
+ - Deduplication by `accountId` when present
1075
+ - Fingerprint fallback when `accountId` is null
1076
+ - `accountId` preference over fingerprint when both exist
1077
+ - `accountId` field presence in all key source objects (env, rotation state, keychain, credentials)
1078
+ - **Updated dashboard tests** in `packages/cto-dashboard/src/utils/__tests__/data-reader.test.ts`:
1079
+ - `getKeyRotationMetrics()` tests updated for account deduplication logic
1080
+ - All 173 optimizer tests passing (was 167)
1081
+ - All 662 dashboard tests passing
1082
+
1083
+ ### Impact
1084
+
1085
+ This fix ensures accurate quota tracking when using multi-source credential discovery. Projects with the same account configured in both environment variables and rotation state will no longer show inflated usage projections or premature automation throttling.
1086
+
1087
+ ---
1088
+
1089
+ ## 2026-02-20 - macOS Compatibility: Setup Script Group Name Fix
1090
+
1091
+ ### Fixed
1092
+
1093
+ **macOS "illegal group name" error in setup scripts** (`scripts/setup-automation-service.sh`, `scripts/protect-framework.sh`, `scripts/setup.sh`):
1094
+ - Root cause: macOS does not create a default group matching the username; commands like `chown $SUDO_USER:$SUDO_USER` fail with "illegal group name"
1095
+ - Fix: Replaced hardcoded `$SUDO_USER:$SUDO_USER` with `$SUDO_USER:$(id -gn "$SUDO_USER" 2>/dev/null || echo staff)` at 3 call sites (setup-automation-service.sh lines 181, 231; similar patterns in protect-framework.sh and setup.sh)
1096
+ - Hardened `get_original_group()` function with explicit empty-check and OS-aware fallback (staff on Darwin, username on Linux)
1097
+ - Lines affected: setup-automation-service.sh:181, 231; protect-framework.sh:118-127; setup.sh:170-179
1098
+
1099
+ ### Added
1100
+
1101
+ **File Protection Error Handling documentation** (`.claude/agents/`, `CLAUDE.md.gentyr-section`):
1102
+ - Added "Permission Denied on Protected Files" section to 3 agent configs: code-writer.md, code-reviewer.md, project-manager.md
1103
+ - Added "File Protection Error Handling" section to CLAUDE.md.gentyr-section (deployed to target projects via setup.sh)
1104
+ - Instructs agents to use `mcp__setup-helper__gentyr_setup({ action: "unprotect" })` when encountering Permission denied errors on protected files
1105
+ - Prevents agents from attempting `chmod`/`chown` directly; enforces use of MCP tool for safe unprotect/protect workflow
1106
+
1107
+ **Protection System Documentation** (`docs/shared/PROTECTION-SYSTEM.md`):
1108
+ - Comprehensive guide to GENTYR's 7-layer protection architecture
1109
+ - Threat model, trust boundaries, and attack vectors prevented
1110
+ - Layer-by-layer breakdown: Root Ownership, Protected Action Gate, MCP Server Allowlist, Credential File Guard, Bash Command Filter, Secret Leak Detector, Deputy-CTO Commit Review
1111
+ - Fail-closed design principles and G001 compliance
1112
+
1113
+ ### Impact
1114
+
1115
+ This fix enables GENTYR installation on macOS systems where the primary user does not have a matching group name (the default macOS configuration). Previously, `sudo scripts/setup.sh --protect` would fail with "chown: illegal group name" errors during systemd service setup and file protection operations.
1116
+
1117
+ ---
1118
+
1119
+ ## 2026-02-20 - Usage Optimizer: Remove Factor Caps for Aggressive Throttling
1120
+
1121
+ ### Changed
1122
+
1123
+ **Usage optimizer factor range expansion** (`.claude/hooks/usage-optimizer.js`):
1124
+ - MAX_FACTOR: 2.0 to 20.0 (up to 20x speedup; MIN_EFFECTIVE_MINUTES=5 is the real ceiling)
1125
+ - MIN_FACTOR: 0.5 to 0.05 (up to 20x slowdown; sufficient to essentially pause automation)
1126
+ - Recovery threshold: `currentFactor <= MIN_FACTOR + 0.01` to `currentFactor <= 0.15` with explanatory comment (threshold now independent of MIN_FACTOR value)
1127
+ - MAX_CHANGE_PER_CYCLE: 0.10 unchanged (factor moves at most ±10% per cycle)
1128
+ - MIN_EFFECTIVE_MINUTES: 5 unchanged (no cooldown goes below 5 minutes)
1129
+
1130
+ **Rationale**: The previous 0.5-2.0 range limited the optimizer to only 2x slowdown/speedup. When aggressive throttling was needed (e.g., approaching quota ceiling), the factor hit the floor and couldn't go lower. The new 0.05-20.0 range provides 20x dynamic range in both directions while preserving safety invariants.
1131
+
1132
+ ### Tests
1133
+
1134
+ - **Updated 6 existing assertions** in `.claude/hooks/__tests__/usage-optimizer.test.js`:
1135
+ - Constant value regexes for MIN_FACTOR (0.05), MAX_FACTOR (20.0)
1136
+ - Recovery threshold detection regex
1137
+ - Behavioral recovery test values
1138
+ - **Added 10 new boundary tests**:
1139
+ - 5 extreme factor boundary tests (MIN_EFFECTIVE_MINUTES floor enforcement, extreme slowdown scenarios)
1140
+ - 5 recovery threshold boundary tests (inclusive/exclusive boundary, independence from MIN_FACTOR)
1141
+ - All 166 tests passing (was 156 tests)
1142
+
1143
+ ### Fixed
1144
+
1145
+ **Documentation alignment**:
1146
+ - Updated `docs/AUTOMATION-SYSTEMS.md` to reflect new 0.05-20.0 range (was 0.5-2.0)
1147
+ - Factor effects table now shows full dynamic range examples
1148
+ - Recovery threshold documentation updated to reflect 0.15 fixed value
1149
+
1150
+ ### Impact
1151
+
1152
+ The usage optimizer can now throttle automation by up to 20x when approaching quota limits, preventing quota exhaustion in high-utilization scenarios. The 0.15 recovery threshold ensures the optimizer doesn't get trapped at extreme slowdown when usage drops far below target.
1153
+
1154
+ ---
1155
+
1156
+ ## 2026-02-20 - Secret-Sync MCP Server: Security Hardening
1157
+
1158
+ ### Fixed
1159
+
1160
+ **HIGH: Path traversal vulnerability via confFile parameter** (`packages/mcp-servers/src/secret-sync/types.ts`, `packages/mcp-servers/src/secret-sync/server.ts`):
1161
+ - Schema-level defense: Added Zod regex `/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/` to `confFile` field in `ServicesConfigSchema` to reject path traversal attempts (line 56)
1162
+ - Runtime boundary check: Added `safeProjectPath()` helper function to verify resolved paths stay within project directory (defense-in-depth)
1163
+ - Updated both `confFile` construction sites in `syncSecrets` and `listMappings` tools to use `safeProjectPath()` instead of bare `path.join()`
1164
+ - Blocks 50+ attack vectors: null bytes, Unicode normalization tricks, symlink targets, URL-encoded traversal sequences, backslashes, etc.
1165
+
1166
+ **MEDIUM: Protected services.json from agent modification** (`.claude/hooks/credential-file-guard.js`, `scripts/protect-framework.sh`):
1167
+ - Added `.claude/config/services.json` to credential-file-guard BLOCKED_PATH_SUFFIXES array (prevents write/overwrite operations)
1168
+ - Added to protect-framework.sh PROTECTED_FILES array for root ownership enforcement when `--protect` flag is used
1169
+
1170
+ **MEDIUM: Removed "local" from "all" target expansion** (`packages/mcp-servers/src/secret-sync/server.ts`):
1171
+ - All three tool functions (`syncSecrets`, `listMappings`, `verifySecrets`) now expand "all" to 3 remote targets only: `['render-production', 'render-staging', 'vercel']`
1172
+ - Local file system operations now require explicit opt-in (`target: 'local'`)
1173
+ - Prevents accidental writes to project directory when agent uses `target: 'all'`
1174
+
1175
+ **LOW: Added op-secrets.conf to .gitignore** (`.gitignore`):
1176
+ - Prevents accidental commits of generated local secrets configuration file
1177
+ - Placed in "Generated secret config" section with clear comment
1178
+
1179
+ ### Tests
1180
+
1181
+ - **New security defense tests**: `packages/mcp-servers/src/secret-sync/__tests__/secret-sync.test.ts` (12 new tests, 79 total in file)
1182
+ - Zod schema rejection tests: path traversal strings (`../../../etc/passwd`), absolute paths, empty strings, Unicode normalization attacks
1183
+ - `safeProjectPath` boundary check tests: symlink resolution, null byte injection, directory escape attempts
1184
+ - "all" target expansion verification: ensures local is excluded from remote batch operations
1185
+ - Attack vector coverage: 50+ malicious path patterns tested
1186
+ - All 873 tests passing (23 test files across MCP servers, hooks, and dashboard)
1187
+ - TypeScript build: clean
1188
+ - Code review: PASS (no violations)
1189
+
1190
+ ### Changed
1191
+
1192
+ **Files modified (6 total):**
1193
+ - `packages/mcp-servers/src/secret-sync/types.ts` (added regex validation to confFile schema)
1194
+ - `packages/mcp-servers/src/secret-sync/server.ts` (added `safeProjectPath()` helper, updated 2 construction sites)
1195
+ - `.claude/hooks/credential-file-guard.js` (added services.json to blocked paths)
1196
+ - `scripts/protect-framework.sh` (added services.json to protected files)
1197
+ - `.gitignore` (added op-secrets.conf)
1198
+ - `packages/mcp-servers/src/secret-sync/__tests__/secret-sync.test.ts` (12 new security tests)
1199
+
1200
+ ### Impact
1201
+
1202
+ This hardening eliminates path traversal vulnerabilities in the secret-sync MCP server's local file operations. The multi-layer defense (Zod schema + runtime boundary check) ensures agents cannot write outside the project directory or modify protected configuration files, even with sophisticated attack patterns.
1203
+
1204
+ ---
1205
+
1206
+ ## 2026-02-20 - CTO Dashboard: Readonly Database Fix for Protected Directories
1207
+
1208
+ ### Fixed
1209
+
1210
+ **SQLite WAL-mode readonly access in root-owned directories** (`packages/cto-dashboard/src/utils/readonly-db.ts`, `packages/mcp-servers/src/shared/readonly-db.ts`, `packages/vscode-extension/src/extension/readonly-db.ts`):
1211
+ - Root cause: When `setup.sh --protect` makes `.claude/` root-owned, SQLite cannot create `-shm`/`-wal` files needed for WAL mode even with `{ readonly: true }` option
1212
+ - Fix: Created `openReadonlyDb()` helper function (3 identical implementations for dashboard, MCP servers, and VS Code extension)
1213
+ - Fallback strategy: On readonly directory error, copies database to `/tmp`, converts journal mode from WAL to DELETE, reopens as readonly, patches `close()` method to clean up temp file
1214
+ - Applied to 25 call sites across 12 files: replaced `new Database(path, { readonly: true })` with `openReadonlyDb(path)`
1215
+
1216
+ ### Changed
1217
+
1218
+ **Files modified (12 total):**
1219
+ - `packages/cto-dashboard/src/utils/readonly-db.ts` (new, 56 lines)
1220
+ - `packages/cto-dashboard/src/utils/data-reader.ts` (4 call sites)
1221
+ - `packages/cto-dashboard/src/utils/deputy-cto-reader.ts` (1 call site)
1222
+ - `packages/cto-dashboard/src/utils/timeline-aggregator.ts` (2 call sites)
1223
+ - `packages/mcp-servers/src/shared/readonly-db.ts` (new, 51 lines)
1224
+ - `packages/mcp-servers/src/cto-report/server.ts` (3 call sites)
1225
+ - `packages/mcp-servers/src/deputy-cto/server.ts` (1 call site)
1226
+ - `packages/mcp-servers/src/feedback-explorer/server.ts` (3 call sites)
1227
+ - `packages/mcp-servers/src/user-feedback/server.ts` (1 call site)
1228
+ - `packages/vscode-extension/src/extension/readonly-db.ts` (new, 51 lines)
1229
+ - `packages/vscode-extension/src/extension/DataService.ts` (4 call sites)
1230
+
1231
+ ### Tests
1232
+
1233
+ - **New test file**: `packages/cto-dashboard/src/utils/__tests__/readonly-db.test.ts` (20 tests, 418 lines)
1234
+ - Direct readonly open path (normal directories)
1235
+ - Fallback temp-copy path (readonly directories)
1236
+ - Temp file cleanup on `.close()`
1237
+ - Error propagation for non-readonly errors
1238
+ - All 632 dashboard tests + 847 MCP server tests + 20 new tests passing
1239
+ - TypeScript build: clean
1240
+ - Code review: PASS (no violations)
1241
+
1242
+ ### Impact
1243
+
1244
+ This fix enables the CTO dashboard, MCP servers, and VS Code extension to read SQLite databases in protected GENTYR installations where `.claude/` directories are root-owned. Previously, all three components would fail with `SQLITE_READONLY_DIRECTORY` errors when attempting to open databases for reading.
1245
+
1246
+ ---
1247
+
1248
+ ## 2026-02-20 - Autonomous Restartless Credential Rotation
1249
+
1250
+ ### Implemented
1251
+
1252
+ **Unified proactive refresh and pre-expiry swap** (`.claude/hooks/quota-monitor.js`, `.claude/hooks/key-sync.js`):
1253
+ - **Step 4b unified**: Combined expired-token refresh and approaching-expiry proactive refresh into single loop using `isExpired`/`isApproachingExpiry` variables
1254
+ - **Shared expiry constant**: `EXPIRY_BUFFER_MS` (10 min) exported from `key-sync.js`, imported by `quota-monitor.js` for consistent timing
1255
+ - **Proactive standby refresh**: Non-active tokens within 10 min of expiry are refreshed automatically to keep standby pool perpetually fresh
1256
+ - **Pre-expiry restartless swap**: When active key approaches expiry and valid standby exists, writes standby to Keychain; Claude Code's `SRA()` (5 min buffer) or `r6T()` (401 recovery) picks up new token seamlessly without restart
1257
+ - **Idle session coverage**: `key-sync.js` also performs proactive refresh and pre-expiry swap during `syncKeys()` runs (called every 10 min by launchd even when no Claude Code process is active)
1258
+ - **Date.now() consistency**: Cached into `now4b` variable to prevent time drift within execution (matches `key-sync.js` pattern)
1259
+
1260
+ ### Tests
1261
+
1262
+ - **New test file**: `.claude/hooks/__tests__/proactive-refresh-and-swap.test.js` (35 tests, 592 lines)
1263
+ - Step 4b: `EXPIRY_BUFFER_MS` import verification, `isApproachingExpiry` variable presence, refresh loop behavior
1264
+ - Step 4c: Pre-expiry restartless swap trigger logic, standby selection, `updateActiveCredentials()` call verification
1265
+ - `key-sync.js`: proactive refresh in `syncKeys()`, pre-expiry swap logic, shared constant export
1266
+ - Coverage: all new autonomous rotation behaviors across both files
1267
+ - **Updated existing tests**: `.claude/hooks/__tests__/key-sync-expired-filter.test.js`, `.claude/hooks/__tests__/quota-monitor.test.js` (updated for new source patterns)
1268
+ - **Total**: 130 hook tests passing (92 existing + 35 new + 3 updated)
1269
+
1270
+ ### Documentation
1271
+
1272
+ - **Implementation guide**: `docs/sessions/2026-02-20-credential-rotation-experiments.md` updated with detailed coverage matrix, autonomous rotation architecture, and `SRA()`/`r6T()` recovery path analysis
1273
+ - **CLAUDE.md**: Updated quota-monitor and key-sync sections with new proactive refresh and pre-expiry swap capabilities
1274
+
1275
+ ### Research Findings
1276
+
1277
+ **Token expiry vs revocation behavior** (documented in `docs/sessions/2026-02-20-credential-rotation-experiments.md`):
1278
+ - Naturally expired OAuth tokens return HTTP **401** (`authentication_error`) — **recoverable** by Claude Code's built-in `r6T()` retry handler
1279
+ - Revoked tokens (via `refresh_token` grant) return HTTP **403** (`permission_error`) — **terminal**, no recovery
1280
+ - This means `refreshExpiredToken()` inadvertently causes unrecoverable 403 by revoking the old token, when waiting for natural expiry would yield a recoverable 401
1281
+
1282
+ **Claude Code token architecture**:
1283
+ - Uses `Authorization: Bearer <oauth-token>` with `anthropic-beta: oauth-2025-04-20` for `/v1/messages` calls
1284
+ - `SRA()` proactive refresh fires 5 minutes before `expiresAt`: clears credential cache → re-reads from disk → if new valid token found, adopts it seamlessly
1285
+ - `r6T()` fires on HTTP 401: clears cache → re-reads Keychain → retries with new credentials
1286
+ - The `org:create_api_key` scope and API key creation endpoint are optional; Bearer auth is the primary path
1287
+
1288
+ **Restartless rotation strategy identified**: Write new account's token to Keychain/file without refreshing the old one. When old token expires → `SRA()` or `r6T()` picks up new token from disk → seamless recovery, no restart needed.
1289
+
1290
+ ### Bugs Found
1291
+
1292
+ **Missing process kill in automated rotation** (`.claude/hooks/quota-monitor.js:318-354`):
1293
+ - Automated session rotation spawns new `claude --resume` process but never kills the old one
1294
+ - Interactive sessions correctly kill via `generateRestartScript()` with `kill -TERM`/`kill -9`
1295
+ - Confirmed 33 orphaned processes consuming ~2GB total RAM
1296
+
1297
+ **Selective proxy routing in Bun** (informational):
1298
+ - `HTTPS_PROXY` routes eval, profile, and mcp_servers calls through proxy
1299
+ - `/v1/messages` (main SDK call) bypasses the proxy entirely
1300
+ - Proxy-based 401 injection is not viable for triggering credential recovery
1301
+
1302
+ ## 2026-02-19 - Credential Lifecycle: invalid_grant Sentinel, Dead-Key Pruning, Secret Manager Agent
1303
+
1304
+ ### Added
1305
+
1306
+ **invalid_grant sentinel in `refreshExpiredToken`** (`.claude/hooks/key-sync.js`):
1307
+ - `refreshExpiredToken` now returns the string `'invalid_grant'` (not `null`) when the OAuth server responds HTTP 400 + `{ error: 'invalid_grant' }`, distinguishing a permanently revoked refresh token from a transient network failure
1308
+ - All 4 callers updated atomically: `syncKeys()`, `api-key-watcher.js`, `quota-monitor.js`, `stop-continue-hook.js`
1309
+ - On `invalid_grant`: key status set to `'invalid'`, rotation log records `refresh_token_invalid_grant` reason, key excluded from all future rotation candidates
1310
+
1311
+ **`pruneDeadKeys()` garbage collection** (`.claude/hooks/key-sync.js`):
1312
+ - New exported function removes keys with `status === 'invalid'` where `last_health_check` (or `added_at`) is older than 7 days
1313
+ - Never prunes the currently active key
1314
+ - Removes orphaned `rotation_log` entries that reference pruned keys
1315
+ - Called automatically at the end of every `syncKeys()` run
1316
+
1317
+ **Dashboard event display** (`packages/cto-dashboard/src/utils/account-overview-reader.ts`):
1318
+ - Added `refresh_token_invalid_grant` reason mapping to human-readable description "Refresh token revoked for {key}"
1319
+
1320
+ **CTO report key status breakdown** (`packages/mcp-servers/src/cto-report/`):
1321
+ - `types.ts`: Added optional `expired_keys`, `invalid_keys`, `exhausted_keys` fields to `KeyRotationMetrics` interface
1322
+ - `server.ts`: `getKeyRotationMetrics()` counts and returns those three fields
1323
+
1324
+ **Secret Manager Agent** (`.claude/agents/secret-manager.md`):
1325
+ - New specialized agent for secret lifecycle management via GENTYR's 1Password-based system
1326
+ - Operations-only: uses MCP tools (`secret-sync`, `onepassword`, `todo-db`, `agent-reports`) without editing files
1327
+ - Handles: adding/rotating secrets, syncing to Render/Vercel, diagnosing missing runtime credentials, setting up local dev secrets
1328
+ - Creates TODO tasks for code-writer when `services.json` changes are needed
1329
+ - Reports security findings (shadow secrets, plain-type secrets, mismatched vault refs) to deputy-CTO
1330
+
1331
+ **`/setup-gentyr` Phase 2: Claude Account Inventory** (`.claude/commands/setup-gentyr.md`, `.claude/hooks/slash-command-prefetch.js`):
1332
+ - New `getAccountInventory()` function in `slash-command-prefetch.js` reads rotation state, deduplicates accounts by `account_uuid`, and injects data into prefetch payload
1333
+ - Phase 2 added to setup flow: displays current Claude account inventory (email, status, quota), offers guided login loop to add additional accounts for quota rotation
1334
+ - Existing phases renumbered 3–8 (was 2–7)
1335
+
1336
+ ### Tests
1337
+
1338
+ - **New test file:** `.claude/hooks/__tests__/invalid-grant-and-prune.test.js` (43 tests)
1339
+ - `refreshExpiredToken` sentinel return value verification across all 4 caller files (static analysis)
1340
+ - `pruneDeadKeys` behavior: prunes keys older than 7 days, never prunes active key, removes orphaned log entries
1341
+ - `syncKeys` marks key `invalid` and logs `refresh_token_invalid_grant` on sentinel
1342
+ - All callers handle sentinel path by marking key `invalid`
1343
+ - All 135 hook tests passing (92 existing + 43 new)
1344
+ - TypeScript build: clean
1345
+
1346
+ ### Verification
1347
+
1348
+ - Code review: PASS — no violations, no security issues, TypeScript compiles clean
1349
+ - Static analysis confirms sentinel string `'invalid_grant'` returned (not `null`) in HTTP 400 + error body path
1350
+ - `pruneDeadKeys` never touches active key in all test scenarios
1351
+
1352
+ **Total Changes:** 1 new agent, 1 new test file, 7 modified files, 43 new tests, 135 hook tests passing
1353
+
1354
+ ---
1355
+
1356
+ ## 2026-02-18 - Binary Patching: Clawd Mascot Customization
1357
+
1358
+ ### Added
1359
+
1360
+ **Clawd Mascot Patcher** (`scripts/patch-clawd.py`, ~600 lines):
1361
+ - Version-agnostic binary patcher for Claude Code CLI mascot customization
1362
+ - Replaces stock Clawd with #29 Winged Eye design (sparkle wings, dark pupil, amber bases)
1363
+ - Structural pattern detection using regex instead of hardcoded offsets
1364
+ - Dynamic variable extraction for React createElement calls
1365
+ - Exact-length replacement with empty-string padding
1366
+ - 9 validation gates before and after writing
1367
+ - Atomic write via temp file + os.rename() to prevent corruption
1368
+ - Idempotent operation: detects already-patched binary and skips
1369
+ - CLI flags: --dry-run, --restore, --binary, --no-color
1370
+ - Automatic codesign and xattr quarantine clearing
1371
+ - Colored terminal output with detailed block analysis
1372
+
1373
+ **Binary Patching Documentation** (`docs/BINARY-PATCHING.md`):
1374
+ - Complete guide to customizing the Clawd mascot in Claude Code binary
1375
+ - Architecture explanation: Bun-compiled executable with embedded JS source
1376
+ - Mascot function locations and offset discovery methods
1377
+ - Theme color system and available color names
1378
+ - Byte-count compensation techniques (empty string padding, string adjustment)
1379
+ - Current design specification: #29 Winged Eye with unicode char reference
1380
+ - Automated patching workflow with safety gates
1381
+ - Manual patching fallback instructions
1382
+ - Rollback procedures
1383
+ - Technical lessons learned from binary patching experiments
1384
+
1385
+ ### Fixed
1386
+
1387
+ **Code Review Fixes Applied:**
1388
+ - CRITICAL: Raw string bug in unicode escape sequences (lines 462, 475) - used r-prefix raw strings to preserve literal \u sequences
1389
+ - CRITICAL: Non-atomic write pattern - replaced direct file.write() with temp file + os.rename()
1390
+ - MEDIUM: Dead code removed - unused brace_depth variable in return block extraction
1391
+ - MEDIUM: Regex $ handling - fixed \w+ to [\w$]+ to match JavaScript identifiers with $
1392
+ - LOW: Missing verification - added binary execution check after codesign recovery
1393
+ - LOW: Incomplete mascot char list - added all quadrant block characters to detection set
1394
+
1395
+ ### Tests
1396
+
1397
+ **Manual Testing:**
1398
+ - --dry-run on patched binary: detects 4 blocks, all "already patched"
1399
+ - --dry-run on stock binary: detects 4 blocks, builds correct replacements with exact byte match
1400
+ - Full patch cycle: detect → backup → patch → codesign → verify
1401
+ - Idempotency verified: re-run on patched binary does nothing
1402
+ - Visual verification: mascot displays correctly in terminal
1403
+
1404
+ ### Technical Details
1405
+
1406
+ **Design #29 Winged Eye:**
1407
+ ```
1408
+ ▗▘ ✦ ▝▖ Row 1: wing tips + sparkle (penguinShimmer)
1409
+ ▐▌ ● ▐▌ Row 2: wings + dark pupil (penguinShimmer wings, clawd_body eye)
1410
+ ▀ ▀ Row 3: wing bases (chromeYellow)
1411
+ ```
1412
+
1413
+ **Pattern Detection:**
1414
+ - Searches for flexDirection:"column",alignItems:"center" + clawd_body + mascot unicode chars
1415
+ - Extracts React import variable (e.g., x$, mB) dynamically
1416
+ - Extracts Flex and Text component variables dynamically
1417
+ - Builds replacement with exact byte count using empty-string padding (,"")
1418
+
1419
+ **Safety Mechanisms:**
1420
+ - Byte count verification before and after every replacement
1421
+ - Binary execution test after patching
1422
+ - Automatic backup creation before any write
1423
+ - Codesign restoration with verification
1424
+ - Idempotent operation prevents double-patching corruption
1425
+
1426
+ ---
1427
+
1428
+ ## 2026-02-18 - CTO Dashboard: Account Overview Section
1429
+
1430
+ ### Added
1431
+
1432
+ **Account Overview Section** (`packages/cto-dashboard/`):
1433
+ - New `account-overview-reader.ts` data reader module (~226 lines)
1434
+ - Parses `~/.claude/api-key-rotation.json` for per-account details and rotation events
1435
+ - Reads key metadata: status, subscription type, email, expiry, usage quotas
1436
+ - Filters and formats rotation event log (last 24h, max 20 events, excludes noisy health_check events)
1437
+ - Account sorting: current key first, then by status (active → exhausted → expired → invalid), then by added date
1438
+ - New `AccountOverviewSection.tsx` component (~115 lines)
1439
+ - Per-account table with truncated key IDs, status indicators, subscription type, email, expiry date
1440
+ - Per-key quota bars: 5h, 7d, and conditional 7d-sonnet (only shown if >10pp difference from 7d)
1441
+ - Event history timeline (last 24h) with color-coded event types and timestamps
1442
+ - Title shows account count and 24h rotation count
1443
+ - Mock data integration in `mock-data.ts`
1444
+ - `getMockAccountOverview()` returns 3 mock accounts with realistic quota spreads
1445
+ - 8 mock rotation events covering all event types (key_added, key_switched, key_exhausted, key_removed)
1446
+ - Section wired into `App.tsx` between Quota & System Status and Deputy CTO sections
1447
+ - Barrel export added to `components/index.ts`
1448
+
1449
+ ### Fixed
1450
+
1451
+ **Code Review Findings (all addressed):**
1452
+ - HIGH: React key collision risk — truncated 8-char key IDs used as React keys caused potential collisions
1453
+ - Fixed by adding index suffix: `key={`${account.keyId}-${idx}`}` for AccountRow components
1454
+ - MEDIUM: Dead fields removed — `fiveHourResetsAt` and `sevenDayResetsAt` were always null (reset times now stored in rotation state)
1455
+ - Removed from `AccountKeyDetail` interface
1456
+ - MEDIUM: Module-level constant prevents testability — `KEY_ROTATION_STATE_PATH` was a module-level constant
1457
+ - Refactored to lazy getter function `getKeyRotationStatePath()` for test isolation
1458
+
1459
+ ### Tests
1460
+
1461
+ - **New test file:** `packages/cto-dashboard/src/components/__tests__/AccountOverviewSection.test.tsx` (30 tests)
1462
+ - Empty state rendering
1463
+ - Account table structure and ordering (current key first, then by status)
1464
+ - Quota bar rendering with conditional 7d-sonnet logic
1465
+ - Event history formatting and color coding
1466
+ - Edge cases: missing emails, no expiry dates, null usage data
1467
+ - **Modified:** `mock-data.ts` — added `getMockAccountOverview()` function
1468
+ - **Modified:** `account-overview-reader.ts` — fixed React key collision, removed dead fields, refactored path getter
1469
+ - All 632 tests passing across 18 test files (up from 602)
1470
+ - TypeScript build: clean
1471
+ - README generation: clean (Account Overview section renders in mock mode)
1472
+
1473
+ ### Verification
1474
+
1475
+ **Live Mode Testing:**
1476
+ - Dashboard renders 12 real accounts from `~/.claude/api-key-rotation.json`
1477
+ - Event history shows 8 rotation events from last 24h
1478
+ - Quota bars display correct percentages from last_usage snapshots
1479
+ - Current key marked with `*` prefix and cyan color
1480
+
1481
+ **Mock Mode Testing:**
1482
+ - `npm run generate:readme` successfully regenerates README with Account Overview section
1483
+ - Mock data shows 3 accounts with varied statuses (active, exhausted) and quota spreads
1484
+ - Event timeline demonstrates all event type color coding
1485
+
1486
+ **Total Changes:** 2 new files, 4 modified files, 30 new tests, 632 total tests passing
1487
+
1488
+ ---
1489
+
1490
+ ## 2026-02-18 - Automatic Account Rotation & Session Recovery
1491
+
1492
+ ### Added
1493
+
1494
+ **Quota Monitor Hook** (`.claude/hooks/quota-monitor.js`, ~230 lines):
1495
+ - PostToolUse hook that monitors API quota usage every 5 minutes
1496
+ - Triggers credential rotation at 95% utilization threshold
1497
+ - Interactive sessions: spawns auto-restart script with new credentials
1498
+ - Automated sessions: writes quota-interrupted state for session-reviver pickup
1499
+ - All-accounts-exhausted detection: writes paused-sessions.json with pause reason and timestamp
1500
+ - Cooldown protection: 10-minute rotation cooldown prevents rotation loops
1501
+
1502
+ **Session Reviver Hook** (`.claude/hooks/session-reviver.js`, ~320 lines):
1503
+ - Called from hourly-automation.js to recover interrupted automated sessions
1504
+ - Mode 1 (Quota-interrupted pickup): Reads quota-interrupted-sessions.json and re-spawns sessions with --resume after credential rotation
1505
+ - Mode 2 (Historical dead session recovery): Scans agent-tracker-history.json for unexpectedly dead agents (process_already_dead) within last 7 days and re-spawns pending TODOs
1506
+ - Mode 3 (Paused session resume): Reads paused-sessions.json and checks if any account has recovered, then resumes paused sessions
1507
+ - Limits: Max 3 revivals per cycle, 7-day historical window
1508
+ - TODO reconciliation integration with reap-completed-agents.js
1509
+
1510
+ **Recovery CLI Script** (`scripts/recover-interrupted-sessions.js`, ~200 lines):
1511
+ - One-time manual recovery tool for interrupted sessions
1512
+ - Accepts `--path`, `--dry-run`, `--max-concurrent` flags
1513
+ - Cross-references agent-tracker-history with TODO database
1514
+ - Identifies in_progress tasks with no corresponding live process
1515
+ - Re-spawns sessions with original task context
1516
+
1517
+ ### Changed
1518
+
1519
+ **Key Sync Module** (`.claude/hooks/key-sync.js`):
1520
+ - Exported `checkKeyHealth()`, `selectActiveKey()`, `HIGH_USAGE_THRESHOLD` (80%), `EXHAUSTED_THRESHOLD` (95%) for reuse
1521
+ - Added 120 lines of public API functions for credential rotation workflows
1522
+
1523
+ **API Key Watcher** (`.claude/hooks/api-key-watcher.js`):
1524
+ - Refactored to use shared functions from key-sync.js (~100 lines removed, +10 added)
1525
+ - Moved `checkKeyHealth`, `selectActiveKey`, threshold constants to imports
1526
+ - Added local `ANTHROPIC_BETA_HEADER` constant for `fetchAccountProfile`
1527
+
1528
+ **Agent Tracker** (`.claude/hooks/agent-tracker.js`):
1529
+ - Added `SESSION_REVIVED` to `AGENT_TYPES`
1530
+ - Added `QUOTA_MONITOR` and `SESSION_REVIVER` to `HOOK_TYPES`
1531
+
1532
+ **Slash Command Prefetch** (`.claude/hooks/slash-command-prefetch.js`):
1533
+ - Made 6 utility functions into named exports: `getSessionDir`, `discoverSessionId`, `getClaudePid`, `detectTerminal`, `shellEscape`, `generateRestartScript`
1534
+ - Enables reuse in quota-monitor.js for restart script generation
1535
+
1536
+ **Settings Template** (`.claude/settings.json.template`):
1537
+ - Added PostToolUse section registering quota-monitor.js
1538
+
1539
+ **Stop-Continue Hook** (`.claude/hooks/stop-continue-hook.js`):
1540
+ - Added quota death detection: reads session JSONL for rate_limit errors
1541
+ - Attempts credential rotation on quota death
1542
+ - Writes recovery state to quota-interrupted-sessions.json for session-reviver pickup
1543
+ - Fixed full-file read replaced with head-only read (4KB) for performance
1544
+
1545
+ **Reap Completed Agents** (`scripts/reap-completed-agents.js`):
1546
+ - Added TODO reconciliation: marks completed or resets to pending based on reap reason
1547
+ - Added `todoReconciled` field to result object
1548
+
1549
+ **Hourly Automation** (`.claude/hooks/hourly-automation.js`):
1550
+ - Integrated session-reviver call after key-sync block with 10-minute cooldown
1551
+
1552
+ **Config Reader** (`.claude/hooks/config-reader.js`):
1553
+ - Added `session_reviver: 10` (minutes) to cooldown defaults
1554
+
1555
+ ### Fixed
1556
+
1557
+ **Code Review Fixes Applied:**
1558
+ - CRITICAL: `ANTHROPIC_BETA_HEADER` undefined in api-key-watcher.js (now defined locally)
1559
+ - HIGH: Full transcript file read in stop-hook replaced with 4KB head-read for performance
1560
+ - MEDIUM: Changed `stdio: 'inherit'` to `'ignore'` in session-reviver.js to prevent stdio pollution
1561
+ - MEDIUM: Stored only `resets_at` timestamp from raw API instead of full response object
1562
+ - LOW: Default project path uses `process.cwd()` instead of hardcoded path
1563
+ - LOW: `isProcessAlive` handles EPERM consistently across platforms
1564
+
1565
+ ### Known Technical Debt
1566
+
1567
+ **Pre-existing Architectural Patterns (not introduced by this change):**
1568
+ - Race condition on shared state files (no file locking) - systemic pattern across framework
1569
+ - Duplicate utility functions (readHead, readTail, etc.) across multiple modules - consolidation candidate
1570
+ - Inconsistent `getSessionDir` implementations across 4 files - should be unified
1571
+
1572
+ ### Technical Details
1573
+
1574
+ **Recovery Workflow:**
1575
+ 1. Session hits quota limit during execution
1576
+ 2. Stop-continue-hook detects rate_limit error in JSONL tail
1577
+ 3. Attempts credential rotation via key-sync
1578
+ 4. Writes interrupted session state to quota-interrupted-sessions.json
1579
+ 5. Session-reviver picks up interrupted state during next hourly automation cycle
1580
+ 6. Re-spawns session with --resume flag and new credentials
1581
+ 7. Agent continues from interruption point
1582
+
1583
+ **Paused Sessions Workflow:**
1584
+ 1. Quota-monitor detects all accounts exhausted (all keys >= 95%)
1585
+ 2. Writes paused-sessions.json with pause reason and timestamp
1586
+ 3. Session-reviver checks paused state every hourly cycle
1587
+ 4. When any account recovers below 95%, resumes paused sessions
1588
+ 5. Logs recovery and clears paused state
1589
+
1590
+ **Files Created (3 total):**
1591
+ - `.claude/hooks/quota-monitor.js` (230 lines)
1592
+ - `.claude/hooks/session-reviver.js` (320 lines)
1593
+ - `scripts/recover-interrupted-sessions.js` (200 lines)
1594
+
1595
+ **Files Modified (9 total):**
1596
+ - `.claude/hooks/key-sync.js` (+120 lines)
1597
+ - `.claude/hooks/api-key-watcher.js` (-100/+10 lines)
1598
+ - `.claude/hooks/agent-tracker.js` (+3 lines)
1599
+ - `.claude/hooks/slash-command-prefetch.js` (+6 exports)
1600
+ - `.claude/settings.json.template` (+12 lines)
1601
+ - `.claude/hooks/stop-continue-hook.js` (+130 lines)
1602
+ - `scripts/reap-completed-agents.js` (+60 lines)
1603
+ - `.claude/hooks/hourly-automation.js` (+20 lines)
1604
+ - `.claude/hooks/config-reader.js` (+1 line)
1605
+
1606
+ **Total Changes:** +750 lines added across 12 files
1607
+
1608
+ ---
1609
+
1610
+ ## 2026-02-18 - Deputy-CTO Identity Injection and Investigator Session History
1611
+
1612
+ ### Changed
1613
+
1614
+ **`/deputy-cto` command now fully assumes the deputy-CTO identity** by receiving the agent's complete knowledge base at session start, rather than operating as a generic assistant following session flow instructions.
1615
+
1616
+ **Prefetch hook — agent instructions injection** (`.claude/hooks/slash-command-prefetch.js`):
1617
+ - `handleDeputyCto()` now reads `.claude/agents/deputy-cto.md` at hook invocation time
1618
+ - Strips YAML frontmatter (between `---` markers) before injecting content
1619
+ - Injects the stripped markdown as `agentInstructions` in the prefetch output under `gathered.agentInstructions`
1620
+ - Non-fatal: if the agent file is missing, `agentInstructions` is set to `null` and the hook continues normally
1621
+
1622
+ **Deputy-CTO command — "Your Identity" section** (`.claude/commands/deputy-cto.md`):
1623
+ - Added a new "Your Identity" section before "Session Behavior"
1624
+ - Instructs Claude to locate the `agentInstructions` field injected by the prefetch hook and absorb it as its own identity
1625
+ - Clarifies interactive-session differences from autonomous mode (wait for CTO input, present options rather than deciding unilaterally, use `AskUserQuestion` for batch review)
1626
+
1627
+ **Investigator agent — mandatory session history search** (`.claude/agents/investigator.md`):
1628
+ - Added "Claude Session History (MANDATORY)" section with a table of `mcp__claude-sessions__*` tools (`search_sessions`, `list_sessions`, `read_session`)
1629
+ - Session history search is now step 1 in the Investigation Workflow (was previously absent); all subsequent steps shifted from 1-7 to 2-8
1630
+ - Prevents circular re-investigation of previously-explored issues and surfaces decisions not captured in code or docs
1631
+
1632
+ ### Why This Matters
1633
+
1634
+ **Deputy-CTO identity**: Previously, `/deputy-cto` sessions ran Claude as a generic assistant following the command's session flow instructions. The deputy-cto agent's commit review criteria, decision framework, powers, and operating modes were only available in autonomous (pre-commit hook) contexts. Now both paths use the same identity and knowledge base, giving interactive CTO briefing sessions the full context they need to accurately represent the agent's standing policies and decision criteria.
1635
+
1636
+ **Investigator session history**: AI agents frequently re-investigate the same problems across sessions. The mandatory session history step surfaces prior work, failed approaches, and decisions before the agent spends time rediscovering them.
1637
+
1638
+ ### Audit
1639
+
1640
+ All 10 slash commands were audited. The remaining 8 commands already follow their correct patterns and required no changes.
1641
+
1642
+ **Files Modified (3 total):**
1643
+ - `.claude/hooks/slash-command-prefetch.js` - ~12 lines added to `handleDeputyCto()`
1644
+ - `.claude/commands/deputy-cto.md` - ~8 lines added (new "Your Identity" section)
1645
+ - `.claude/agents/investigator.md` - ~25 lines added (mandatory session history section and workflow reorder)
1646
+
1647
+ ---
1648
+
1649
+ ## 2026-02-17 - CTO Dashboard: Elastic/Elasticsearch Integration Fixes
1650
+
1651
+ ### Fixed
1652
+
1653
+ **Elasticsearch field mapping errors** (`packages/cto-dashboard/src/utils/logging-reader.ts`, `packages/cto-dashboard/src/utils/infra-reader.ts`):
1654
+ - Terms aggregations were failing with HTTP 400 errors because fields (`level`, `service`, `module`) are mapped as `text` type in the Elastic Serverless deployment and require the `.keyword` suffix for aggregations
1655
+ - Updated all terms aggregation fields: `level` -> `level.keyword`, `service` -> `service.keyword`, `module` -> `module.keyword`
1656
+ - Updated term filter fields in top-errors and top-warnings queries to use `level.keyword`
1657
+
1658
+ **Elasticsearch endpoint resolution** (`packages/cto-dashboard/src/utils/credentials.ts`):
1659
+ - Dashboard previously only looked for `ELASTIC_ENDPOINT`; Elastic Cloud hosted deployments use `ELASTIC_CLOUD_ID` (base64-encoded Cloud ID format) instead
1660
+ - Added `resolveElasticEndpoint()` helper: tries `ELASTIC_ENDPOINT` first, then decodes `ELASTIC_CLOUD_ID` (splits on `:`, base64-decodes the second segment, extracts the ES host from the `$`-delimited decoded string)
1661
+ - Both `logging-reader.ts` and `infra-reader.ts` updated to call `resolveElasticEndpoint()` instead of `resolveCredential('ELASTIC_ENDPOINT')` directly
1662
+
1663
+ **Storage estimation 403 fallback** (`packages/cto-dashboard/src/utils/logging-reader.ts`):
1664
+ - `queryStorage()` was calling `_cat/indices` which requires the `monitor` cluster privilege; the read-only API key returns 403
1665
+ - On a 403 response `queryStorage()` now falls back to doc-count estimation (total document count × estimated bytes-per-doc) instead of returning null storage data
1666
+
1667
+ ### Added
1668
+
1669
+ **`ELASTIC_API_KEY_WRITE` vault mapping** (`vault-mappings.json`):
1670
+ - Added mapping for write-capable Elastic API key to support log ingestion use cases
1671
+ - Read-only key (`ELASTIC_API_KEY`) continues to be used by dashboard queries
1672
+
1673
+ **Sample log data seeding:**
1674
+ - Ingested 200 realistic sample log entries into the Elastic Serverless deployment covering multiple services, levels, and modules
1675
+ - Verified all dashboard queries (timeseries, level/service breakdowns, top errors/warnings) return correct data after seeding
1676
+
1677
+ ### Tests
1678
+
1679
+ - 47 new tests in `packages/cto-dashboard/src/utils/__tests__/credentials.test.ts` covering:
1680
+ - `resolveElasticEndpoint()`: `ELASTIC_ENDPOINT` priority, `ELASTIC_CLOUD_ID` base64 decode path, malformed Cloud ID handling
1681
+ - `.keyword` field naming: all aggregation and filter fields use the `.keyword` suffix
1682
+ - Storage 403 fallback: `queryStorage()` returns doc-count estimate when `_cat/indices` is unauthorized
1683
+ - All 545 tests pass across 16 test files (up from 498)
1684
+ - TypeScript builds clean
1685
+ - Code review: PASS, no violations
1686
+
1687
+ **Total Changes:** 3 modified files, 1 vault-mappings.json update, 47 new tests, 545 total tests passing
1688
+
1689
+ ---
1690
+
1691
+ ## 2026-02-17 - CTO Dashboard: Layout Fixes, Environment-Based Deployments, Title-in-Border
1692
+
1693
+ ### Changed
1694
+
1695
+ **Section Component — Title-in-Border Rendering** (`packages/cto-dashboard/src/components/Section.tsx`):
1696
+ - Sections now render titles inline in the top border: `╭─ TITLE ──────╮`
1697
+ - Uses `borderTop={false}` on the inner Box and a custom Text element for the top line
1698
+ - All sections across the dashboard use this style automatically when a title prop is provided
1699
+
1700
+ **Deployments Section Restructure** (`packages/cto-dashboard/src/components/DeploymentsSection.tsx`, `packages/cto-dashboard/src/utils/deployments-reader.ts`):
1701
+ - Added `DeployEnvironment` type (`preview | staging | production`) and `inferEnvironment()` function to `deployments-reader.ts`
1702
+ - `inferEnvironment()` classifies deploys by service name keywords (`staging`, `stg`, `preview`, `dev`) and Vercel `target` field, defaulting to `production`
1703
+ - Added `byEnvironment` grouping (`preview`, `staging`, `production` arrays, newest-first, up to 5 each) to `DeploymentsData`
1704
+ - Replaced old platform-based layout (ServiceList/Render/Vercel split) with per-environment layout:
1705
+ - `EnvironmentHealth` component: Production/Staging/Preview side-by-side with health dot, last deploy time, and deploy count
1706
+ - `PipelineDetail` component: 3-stage pipeline (preview → staging → production) with check timestamps
1707
+ - `EnvironmentDeploys` per-environment table: time, status dot, service (24w), platform (9w), status (10w), commit message (25w)
1708
+ - `DeployStats` footer: 24h total, success rate, failure count, frequency
1709
+
1710
+ **Infrastructure Section Layout Fix** (`packages/cto-dashboard/src/components/InfraSection.tsx`):
1711
+ - Restructured from 5-column card grid to clean tabular row layout
1712
+ - Aligned columns: Provider (16w) | Status (14w) | Detail (20w) | Extra
1713
+ - Each provider gets one row with consistent alignment and no wrapping
1714
+
1715
+ **Testing Section Chart Fix** (`packages/cto-dashboard/src/components/TestingSection.tsx`):
1716
+ - Changed `yDomain` minimum from `1` to `5` for better chart readability when data values are low
1717
+
1718
+ ### Tests
1719
+
1720
+ - 53 new tests in `packages/cto-dashboard/src/utils/__tests__/deployments-reader.test.ts` covering `inferEnvironment`, `normalizeRenderStatus`, `normalizeVercelStatus`, `truncateMessage`, `byEnvironment` grouping, and `stats` computation
1721
+ - Fixed timing-sensitive `UsageTrends` test regex
1722
+ - All 498 tests pass across 15 test files
1723
+ - TypeScript builds clean
1724
+
1725
+ ### Code Review
1726
+
1727
+ - All changes pass review with no violations
1728
+ - No mocked/placeholder code, no credential leaks, no security regressions
1729
+ - Pre-existing pattern noted: external API responses use TypeScript `as` casts rather than Zod validation (systemic, not a regression)
1730
+
1731
+ **Total Changes:** 4 modified files, 53 new tests, 498 total tests passing
1732
+
1733
+ ---
1734
+
1735
+ ## 2026-02-17 - Usage Optimizer and CTO Dashboard Bug Fixes
1736
+
1737
+ ### Fixed
1738
+
1739
+ **Three interconnected bugs causing all automated instances to display "+100% slower":**
1740
+
1741
+ 1. **Runaway 7-day projection** (`.claude/hooks/usage-optimizer.js`)
1742
+ - Linear rate extrapolation over long horizons (e.g. 155h remaining until 7d reset) was
1743
+ producing projections as high as 483%, which slammed the optimizer factor to MIN_FACTOR (0.5)
1744
+ and kept it there permanently — causing all automation cooldowns to double
1745
+ - Fix: Added `MAX_PROJECTION = 1.5` cap on both `projected5h` and `projected7d` to prevent
1746
+ linear extrapolation from producing nonsensical values
1747
+
1748
+ 2. **No factor recovery** (`.claude/hooks/usage-optimizer.js`)
1749
+ - Once the factor reached MIN_FACTOR (0.5), the 10% MAX_CHANGE_PER_CYCLE limit prevented
1750
+ recovery as long as the inflated projection kept pushing the factor down each cycle
1751
+ - Fix: Added recovery clause — when factor is stuck at MIN_FACTOR AND current usage is below
1752
+ 45% (half of the 90% target), the factor is reset to 1.0 and adjustment resumes normally
1753
+
1754
+ 3. **Wrong display unit for projected_at_reset** (`packages/cto-dashboard/src/utils/automated-instances.ts`)
1755
+ - `projected_at_reset` is stored as a 0-1 fraction but was passed directly to the Footer
1756
+ component which expected a percentage integer — showing "5%" instead of "483%"
1757
+ - Fix: Multiply `projected_at_reset` by 100 when assigning to `currentProjected`
1758
+
1759
+ ### Tests
1760
+
1761
+ - 11 new tests in `usage-optimizer.test.js` covering projection cap enforcement and factor recovery
1762
+ - 10 new tests in `automated-instances.test.ts` covering `currentProjected` unit conversion
1763
+ - All 54 automated-instances tests pass; all 132 usage-optimizer tests pass
1764
+ - Code review: all 3 changes approved with no violations
1765
+
1766
+ **Total Changes:** 2 files modified, 21 new tests
1767
+
1768
+ ---
1769
+
1770
+ ## 2026-02-17 - CTO Dashboard: Deployments, Infrastructure, and Logging Overhaul
1771
+
1772
+ ### Added
1773
+
1774
+ **Deployments Section Overhaul** (`packages/cto-dashboard/src/components/DeploymentsSection.tsx`, `packages/cto-dashboard/src/utils/deployments-reader.ts`):
1775
+ - `PipelineDetail` component at the top showing a 3-stage pipeline (preview → staging → production) with timestamps
1776
+ - Per-platform deploy tables: Render and Vercel each display 5 most recent deploys with service name (width 20), status, age (width 9), and commit message (width 30, constrained)
1777
+ - `DeployStats` footer row: total deploy count, success rate, failure count, and deploy frequency
1778
+ - `deployments-reader.ts` enriched with `lastPreviewCheck`, `lastStagingCheck`, and stats computation from deploy history
1779
+
1780
+ **Infrastructure Section Overhaul** (`packages/cto-dashboard/src/components/InfraSection.tsx`, `packages/cto-dashboard/src/utils/infra-reader.ts`):
1781
+ - Per-platform event tables: Render deploy events and Vercel deployment events
1782
+ - Load metrics: Render `lastDeployAt`, Vercel `buildingCount`, Cloudflare `planName`
1783
+ - Cloudflare nameserver list added to display
1784
+ - Elasticsearch detail row removed from InfraSection (moved to dedicated LOGGING section)
1785
+ - `InfraSection` now accepts optional `deployments` prop to avoid duplicate Render/Vercel API calls
1786
+ - Credential bug fixed: `CF_API_TOKEN` corrected to `CLOUDFLARE_API_TOKEN` (line 145 of `infra-reader.ts`)
1787
+
1788
+ **New LOGGING Section** (`packages/cto-dashboard/src/utils/logging-reader.ts`, `packages/cto-dashboard/src/components/LoggingSection.tsx`):
1789
+ - `logging-reader.ts`: Elasticsearch queries for 24h volume timeseries (24 hourly buckets), level/service/source breakdowns, top 5 errors, top 5 warnings, storage estimates via `_cat/indices`, and source coverage assessment for 9 expected sources (api, worker, deployment, ci-cd, testing, database, cdn, auth, cron)
1790
+ - `LoggingSection.tsx`: Full section with LineGraph (volume timeseries), BarCharts (by level, by service), top errors/warnings tables, source coverage dot indicators (active/low-volume/missing), and storage footer
1791
+ - Wired into `index.tsx` via `getLoggingData` in `Promise.allSettled` parallel fetch block
1792
+ - Wired into `App.tsx` between `InfraSection` and `FeedbackPersonas`
1793
+ - Exported from `components/index.ts`
1794
+
1795
+ ### Tests
1796
+
1797
+ - 45 new tests in `packages/cto-dashboard/src/utils/__tests__/logging-reader.test.ts` covering `parseSizeToBytes`, `assessSourceCoverage`, credential absence, storage estimation, `hasData` flag, and volumeTimeseries padding
1798
+ - New `packages/cto-dashboard/src/components/__tests__/AutomatedInstances.test.tsx` — 35 tests (created in preceding session)
1799
+ - All 445 tests pass across 14 test files
1800
+ - TypeScript build compiles clean
1801
+
1802
+ ### Code Review Findings (informational, not blocking)
1803
+
1804
+ - Duplicated `truncate`/`statusColor` utilities across 3 component files — candidate for shared `formatters.ts` extraction
1805
+ - Render `updatedAt` used as proxy for `lastDeployAt` (documented with inline comment)
1806
+ - URL validation on trusted credential store values (informational)
1807
+
1808
+ **Total Changes:** 3 new files, 7 modified files, 445 tests passing
1809
+
1810
+ ---
1811
+
1812
+ ## 2026-02-17 - CTO Dashboard: Token Usage Bar Chart and Testing Section Fixes
1813
+
1814
+ ### Added
1815
+
1816
+ **Automated Instances — Token Usage Bar Chart:**
1817
+
1818
+ 1. **Token usage by automation type** (`packages/cto-dashboard/src/utils/automated-instances.ts`)
1819
+ - New `getAutomationTokenUsage()` async function reads session JSONL files from `~/.claude/projects/`
1820
+ - Extracts `[Task][agent-type]` prefix from the first user message to identify automation sessions
1821
+ - Sums all token usage fields (input, output, cache read, cache creation) per session
1822
+ - Rolls up raw agent types into INSTANCE_DEFINITIONS display names
1823
+ - Helper functions: `getSessionDir()`, `buildAgentTypeToDisplayName()`, `SessionEntry` interface
1824
+ - `tokensByType: Record<string, number>` field added to `AutomatedInstancesData` type
1825
+
1826
+ 2. **Bar chart rendering** (`packages/cto-dashboard/src/components/AutomatedInstances.tsx`)
1827
+ - Horizontal bar chart (via `@pppp606/ink-chart` `BarChart`) rendered between Footer and Tip
1828
+ - Conditionally shown only when `tokensByType` has entries
1829
+ - Values sorted descending, formatted with `formatNumber()`
1830
+ - Title: "Token Usage by Automation (24h)"
1831
+
1832
+ 3. **Async data integration** (`packages/cto-dashboard/src/index.tsx`)
1833
+ - `getAutomationTokenUsage` added to `Promise.allSettled` parallel fetch block
1834
+ - Result merged into `automatedInstances.tokensByType` on success
1835
+
1836
+ ### Fixed
1837
+
1838
+ **Testing Section agent breakdown display** (`packages/cto-dashboard/src/components/TestingSection.tsx`):
1839
+ - Removed Jest from agent breakdown (not used by any agent type in testing-reader)
1840
+ - Expanded "PW" abbreviation to full "Playwright" label
1841
+ - Column width adjustments: COL_NAME 35→34, COL_AGE 9→10, COL_FW 9→11 for better alignment
1842
+
1843
+ ### Tests
1844
+
1845
+ - **New:** `packages/cto-dashboard/src/components/__tests__/AutomatedInstances.test.tsx` — 35 tests covering empty state, table structure, footer, bar chart rendering, run counts, freq adjustments, until-next display, and render consistency
1846
+ - **Updated:** `automated-instances.test.ts` — added `tokensByType` shape validation, 2 new describe blocks (11 tests) for JSONL parsing logic
1847
+ - **Updated:** `TestingSection.test.tsx` — removed Jest assertions, uses "Playwright" label, updated zero-counts test data
1848
+ - All 390 tests pass across 13 test files (up from 343/12)
1849
+ - TypeScript build compiles clean
1850
+
1851
+ **Total Changes:** 1 new test file, 5 modified files, 390 tests passing
1852
+
1853
+ ---
1854
+
1855
+ ## 2026-02-17 - CTO Dashboard: Deployments, Infrastructure, and Testing Graph
1856
+
1857
+ ### Added
1858
+
1859
+ **CTO Dashboard — New Sections and Shared Utilities:**
1860
+
1861
+ 1. **Shared credential resolution module** (`packages/cto-dashboard/src/utils/credentials.ts`)
1862
+ - Common `resolveCredential()` function: env var → vault-mappings.json → `op read` chain
1863
+ - Shared `fetchWithTimeout()` helper used by all data readers
1864
+ - `loadOpTokenFromMcpJson()` for headless token resolution
1865
+
1866
+ 2. **Deployments data reader** (`packages/cto-dashboard/src/utils/deployments-reader.ts`)
1867
+ - Fetches Render services and deploys, Vercel projects and deployments in parallel
1868
+ - All calls via `Promise.allSettled` with 10s timeouts (independently degradable)
1869
+ - Reads pipeline promotion state from local automation state file
1870
+ - Combines and sorts deploys from both platforms (newest first, up to 8)
1871
+
1872
+ 3. **Infrastructure health reader** (`packages/cto-dashboard/src/utils/infra-reader.ts`)
1873
+ - 5-provider health queries: Render, Vercel, Supabase, Elasticsearch, Cloudflare
1874
+ - Each provider independently degradable — missing credentials or API failures return `{ available: false }`
1875
+ - Elasticsearch aggregation query returns 1h log totals, error/warn counts, top services
1876
+
1877
+ 4. **DeploymentsSection component** (`packages/cto-dashboard/src/components/DeploymentsSection.tsx`)
1878
+ - Side-by-side Render service list and Vercel project list
1879
+ - Combined recent deploy timeline with platform badge and status color
1880
+ - Pipeline promotion state footer
1881
+
1882
+ 5. **InfraSection component** (`packages/cto-dashboard/src/components/InfraSection.tsx`)
1883
+ - 5-provider health status row with colored dots
1884
+ - Elasticsearch logs detail row when available
1885
+
1886
+ ### Modified
1887
+
1888
+ 6. **TestingSection** (`packages/cto-dashboard/src/components/TestingSection.tsx`)
1889
+ - Replaced old 7-day sparkline with LineGraph using 42 x 4h buckets for higher resolution
1890
+ - Codecov sparkline retained
1891
+
1892
+ 7. **testing-reader.ts** (`packages/cto-dashboard/src/utils/testing-reader.ts`)
1893
+ - Added `testActivityTimeseries` field (42 buckets, 4h resolution, ~7-day window)
1894
+ - Switched to shared credentials module
1895
+
1896
+ 8. **App.tsx** — Renders DeploymentsSection and InfraSection between Testing and FeedbackPersonas
1897
+
1898
+ 9. **index.tsx** — Fetches deployments and infra data in parallel at startup
1899
+
1900
+ 10. **components/index.ts** — Added exports for DeploymentsSection and InfraSection
1901
+
1902
+ ### Fixed
1903
+
1904
+ - **Vercel availability bug** (`infra-reader.ts`): `errorDeploys >= 0` always-true check replaced with `available: true` inside success path
1905
+
1906
+ ### Tests
1907
+
1908
+ - Updated 3 test cases in `TestingSection.test.tsx` to match LineGraph (replaces sparkline)
1909
+ - All 343 tests pass across 12 test files
1910
+ - TypeScript build compiles clean
1911
+
1912
+ **Total Changes:** 5 new files, 5 modified files, 343 tests passing
1913
+
1914
+ ---
1915
+
1916
+ ## 2026-02-16 - CTO Dashboard Trajectory Forecast Graph
1917
+
1918
+ ### Added
1919
+
1920
+ **Visual Trajectory Forecasting:**
1921
+
1922
+ 1. **Trajectory Forecast Chart** (UsageTrends component)
1923
+ - Combined visualization showing historical usage transitioning to linear projections
1924
+ - 3 series: cyan 5h line, magenta 7d line, gray 90% target overlay
1925
+ - X-axis labels: "[timeAgo] → now → reset: Xh" to separate history from forecast
1926
+ - Projection point generation using linear extrapolation clamped to [0, 100]
1927
+ - Graceful degradation (only renders when projection data exists)
1928
+
1929
+ ### Fixed
1930
+
1931
+ **Multi-Account Reset Time Bug:**
1932
+ - Previously: `trajectory.ts` arbitrarily took the last API key's reset time during iteration
1933
+ - Now: Picks the **earliest** reset time across all keys (most conservative estimate for aggregate quota tracking)
1934
+
1935
+ ### Modified
1936
+
1937
+ **Files Changed (3 total):**
1938
+ - `packages/cto-dashboard/src/utils/trajectory.ts` (lines 174-175) - Fixed reset time selection logic
1939
+ - `packages/cto-dashboard/src/components/UsageTrends.tsx` - Added forecast chart with projection helpers
1940
+ - `packages/cto-dashboard/src/App.tsx` - Updated props from `{snapshots, hasData}` to `{trajectory: TrajectoryResult}`
1941
+
1942
+ **Tests Added (2 files, 48 tests):**
1943
+ - `packages/cto-dashboard/src/utils/__tests__/trajectory.test.ts` (21 tests)
1944
+ - `packages/cto-dashboard/src/components/__tests__/UsageTrends.test.tsx` (27 tests)
1945
+
1946
+ **Documentation:**
1947
+ - `docs/Executive.md` - Updated Usage Trends section to describe forecast chart and distinguish from text-based trajectory section
1948
+
1949
+ **Total Changes:** +165 lines added, 3 files modified, 48 tests added, 330 total tests passing
1950
+
1951
+ ---
1952
+
1953
+ ## 2026-02-16 - Multi-Layer Credential Detection
1954
+
1955
+ ### Added
1956
+
1957
+ **4-Layer Credential Detection Architecture:**
1958
+
1959
+ 1. **Shared Key Sync Module** (`key-sync.js`)
1960
+ - Multi-source credential reading (env var, macOS Keychain, credentials file)
1961
+ - User-level rotation state I/O at `~/.claude/api-key-rotation.json`
1962
+ - OAuth token refresh for expired credentials
1963
+ - Subscription tier detection (Free, Pro, Team)
1964
+ - Rate limit tier tracking (tier-1 through tier-5)
1965
+
1966
+ 2. **Detection Layers**
1967
+ - Layer 1: launchd `WatchPaths` - instant file change detection on `~/.claude/.credentials.json`
1968
+ - Layer 2: 10-minute `StartInterval` - automation service key-sync calls
1969
+ - Layer 3: SessionStart hook (`api-key-watcher.js`) - full discovery on Claude Code start
1970
+ - Layer 4: PreToolUse hook (`credential-sync-hook.js`) - throttled mid-session checks (30-min)
1971
+
1972
+ 3. **Key Features**
1973
+ - Aggregates credentials from all sources without short-circuiting
1974
+ - Shared rotation state registry across all projects (user-level)
1975
+ - Per-project rotation event logging
1976
+ - Automatic OAuth token refresh before expiration
1977
+ - Health checks and capacity alerts
1978
+
1979
+ **Files Created (2 total):**
1980
+ - `.claude/hooks/key-sync.js` (328 lines) - Shared credential detection module
1981
+ - `.claude/hooks/credential-sync-hook.js` (80 lines) - Throttled PreToolUse hook
1982
+
1983
+ **Files Modified (11 total):**
1984
+ - `.claude/hooks/api-key-watcher.js` - Refactored to thin wrapper around key-sync.js (v2.0.0)
1985
+ - `.claude/hooks/usage-optimizer.js` - Updated rotation state path to user-level
1986
+ - `.claude/hooks/cto-notification-hook.js` - Updated rotation state path
1987
+ - `.claude/hooks/credential-file-guard.js` - Added comment about user-level path coverage
1988
+ - `.claude/hooks/hourly-automation.js` - Added key-sync step after usage optimizer
1989
+ - `.claude/settings.json.template` - Added credential-sync-hook PreToolUse entry
1990
+ - `scripts/setup-automation-service.sh` - Added WatchPaths to launchd plist template
1991
+ - `packages/cto-dashboard/src/utils/data-reader.ts` - Updated rotation state path
1992
+ - `packages/mcp-servers/src/cto-report/server.ts` - Updated rotation state path
1993
+ - `.claude/hooks/__tests__/api-key-watcher.test.js` - Multiple test updates (75 tests passing)
1994
+ - `.claude/hooks/__tests__/usage-optimizer.test.js` - Updated assertion (107 tests passing)
1995
+
1996
+ **Documentation:**
1997
+ - `docs/CREDENTIAL-DETECTION.md` - Test coverage details for 4-layer architecture
1998
+ - `README.md` - Added Multi-Layer Credential Detection section
1999
+ - `CLAUDE.md` - (unchanged, no agent-facing updates needed)
2000
+
2001
+ **Total Changes:** +408 lines added, 11 files modified, 182 tests passing
2002
+
2003
+ ### Code Review Findings
2004
+
2005
+ **9 Issues Identified:**
2006
+
2007
+ 1. **CRITICAL**: Plaintext token aggregation without restrictive file permissions
2008
+ 2. **HIGH**: Race condition on rotation state file (3 concurrent callers, no file locking)
2009
+ 3. **HIGH**: Missing Zod validation on external API responses (OAuth token endpoint)
2010
+ 4. **MEDIUM**: Timeout mismatch in credential-sync-hook (5s timeout but OAuth refresh can exceed)
2011
+ 5. **MEDIUM**: Error swallowing in key-sync.js catch blocks (no telemetry)
2012
+ 6. **MEDIUM**: No retry logic for transient Keychain failures
2013
+ 7. **LOW**: Magic number for throttle cooldown (30 * 60 * 1000 should be constant)
2014
+ 8. **LOW**: Missing JSDoc for public functions in key-sync.js
2015
+ 9. **LOW**: No telemetry for credential source usage patterns
2016
+
2017
+ ### Test Coverage
2018
+
2019
+ **Coverage Status:**
2020
+ - `api-key-watcher.js` - 75 tests passing (full coverage)
2021
+ - `usage-optimizer.js` - 107 tests passing (full coverage)
2022
+ - `key-sync.js` - 0% coverage (new module, tests recommended)
2023
+ - `credential-sync-hook.js` - 0% coverage (new hook, tests recommended)
2024
+
2025
+ **Coverage Gaps:**
2026
+ - `refreshExpiredToken()` - 0% coverage (security-critical OAuth flow)
2027
+ - `updateActiveCredentials()` - 0% behavioral coverage (dual-write to state)
2028
+ - `readCredentialSources()` - indirect coverage only
2029
+ - Recommendation: Create `.claude/hooks/__tests__/key-sync.test.js`
2030
+
2031
+ ### Architecture Decisions
2032
+
2033
+ **Why user-level rotation state:**
2034
+ - Supports multi-project workflows (same API key across multiple repos)
2035
+ - Prevents state desync when same key used in multiple projects
2036
+ - Enables global key tracking and quota aggregation
2037
+ - Backward compatible with project-level fallback
2038
+
2039
+ **Why 4 detection layers:**
2040
+ - Layer 1 (WatchPaths): Instant response to file changes (macOS only)
2041
+ - Layer 2 (StartInterval): Cross-platform periodic checks
2042
+ - Layer 3 (SessionStart): Initial discovery on new sessions
2043
+ - Layer 4 (PreToolUse): Detects mid-session changes without restart
2044
+
2045
+ **Why shared key-sync module:**
2046
+ - DRY principle (single source of truth for credential logic)
2047
+ - Consistent behavior across all detection layers
2048
+ - Easier testing and maintenance
2049
+ - Supports future OAuth flow changes
2050
+
2051
+ ---
2052
+
2053
+ ## 2026-02-16 - Chrome Extension Bridge
2054
+
2055
+ ### Added
2056
+
2057
+ **Chrome Bridge MCP Server:**
2058
+
2059
+ 1. **Protocol Reverse Engineering**
2060
+ - Extracted Claude for Chrome extension protocol from Claude Desktop app.asar
2061
+ - Discovered Unix domain socket bridge at `/tmp/claude-mcp-browser-bridge-{username}/*.sock`
2062
+ - Binary framing protocol: 4-byte LE uint32 length prefix + UTF-8 JSON payload
2063
+ - Archived extraction to `~/Documents/archives/claude-desktop-app-extract-2026-02-16/`
2064
+
2065
+ 2. **18 Chrome Extension Tools**
2066
+ - **Tab management** (4): `tabs_context_mcp`, `tabs_create_mcp`, `navigate`, `switch_browser`
2067
+ - **Page interaction** (6): `read_page`, `get_page_text`, `find`, `form_input`, `computer`, `javascript_tool`
2068
+ - **Debugging** (2): `read_console_messages`, `read_network_requests`
2069
+ - **Media** (3): `gif_creator`, `upload_image`, `resize_window`
2070
+ - **Workflows** (3): `shortcuts_list`, `shortcuts_execute`, `update_plan`
2071
+
2072
+ 3. **Standalone MCP Server** (`chrome-bridge`)
2073
+ - Pure proxy architecture (no Zod validation, Chrome handles its own validation)
2074
+ - Multi-socket support (connects to all available Chrome instances)
2075
+ - Tab routing (remembers which socket owns which tab)
2076
+ - Connection resilience (exponential backoff, max 100 reconnect attempts)
2077
+ - Request serialization (per-socket queuing prevents response interleaving)
2078
+ - Proper timeout handling (2s for tabs_context_mcp, 120s for other tools)
2079
+ - Windows-compatible (null-safe `process.getuid` check)
2080
+
2081
+ 4. **Integration**
2082
+ - Added to `.mcp.json.template` as direct server (no launcher needed)
2083
+ - Added `mcp-chrome-bridge` bin entry to package.json
2084
+ - Re-exported as ChromeBridge in packages/mcp-servers/src/index.ts
2085
+
2086
+ ### Technical Details
2087
+
2088
+ **Files Created (3 total):**
2089
+ - `packages/mcp-servers/src/chrome-bridge/types.ts` (51 lines) - Protocol types
2090
+ - `packages/mcp-servers/src/chrome-bridge/server.ts` (997 lines) - Socket client + JSON-RPC server
2091
+ - `packages/mcp-servers/src/chrome-bridge/index.ts` (4 lines) - Re-exports
2092
+
2093
+ **Files Modified:**
2094
+ - `packages/mcp-servers/package.json` - Added bin entry
2095
+ - `.mcp.json.template` - Added chrome-bridge server config
2096
+ - `packages/mcp-servers/src/index.ts` - Added ChromeBridge export
2097
+ - `README.md` - Updated server count, directory structure, MCP server list, version history
2098
+ - `CLAUDE.md` - Added Chrome Browser Automation section
2099
+
2100
+ **Total Changes:** +1,052 lines added
2101
+
2102
+ ### Testing
2103
+
2104
+ **Manual Testing:**
2105
+ - TypeScript compilation: Clean
2106
+ - MCP server initialization: Successful
2107
+ - Live connection test: Retrieved tab context from 9 Chrome tabs
2108
+ - Socket discovery: Detected Chrome extension socket
2109
+ - Tool execution: `tabs_context_mcp` returned complete tab list
2110
+
2111
+ ### Architecture Decisions
2112
+
2113
+ **Why not use McpServer base class:**
2114
+ - Chrome extension handles its own validation (no need for Zod schemas)
2115
+ - Binary content support (screenshots) incompatible with text-only base class
2116
+ - Proxy pattern requires custom content normalization
2117
+ - Simpler to implement raw JSON-RPC for pure proxy use case
2118
+
2119
+ **Security:**
2120
+ - Socket ownership validation (only connects to user's own sockets via UID check)
2121
+ - No credential storage (local socket communication only)
2122
+ - Fail-safe reconnection logic (prevents infinite loops)
2123
+
2124
+ ### Use Cases
2125
+
2126
+ **Example: Multi-Browser Testing**
2127
+ - Developer has Chrome instances on multiple displays
2128
+ - chrome-bridge discovers all sockets automatically
2129
+ - Routes tab operations to correct browser instance
2130
+ - Maintains tab-to-socket mapping for efficient targeting
2131
+
2132
+ **Example: Long-Running Automation**
2133
+ - Browser crashes mid-automation
2134
+ - Socket connection lost
2135
+ - chrome-bridge reconnects with exponential backoff
2136
+ - Automation resumes when browser restarts
2137
+
2138
+ ### Requirements
2139
+
2140
+ - Claude for Chrome extension installed and running
2141
+ - Chrome browser with extension socket active
2142
+ - Unix-like OS with domain socket support (macOS, Linux)
2143
+
2144
+ ---
2145
+
2146
+ ## 2026-02-15 - MCP Server Thread-Safety Improvements
2147
+
2148
+ ### Fixed
2149
+
2150
+ **Feedback System MCP Server Refactoring:**
2151
+
2152
+ 1. **Thread-safety in McpServer base class**
2153
+ - Eliminated instance-level mutable state (`_captureMode`, `_capturedResponse`)
2154
+ - Refactored `handleRequest()` and `handleToolCall()` to return responses instead of using side-effect methods
2155
+ - Replaced `sendResponse`/`sendSuccess`/`sendError` with pure `createSuccessResponse`/`createErrorResponse`/`writeResponse`
2156
+ - Updated all 68 tests across server.test.ts and audited-server.test.ts
2157
+
2158
+ 2. **Resource cleanup in factories**
2159
+ - Added `process.on('exit')` DB cleanup handler in `createUserFeedbackServer` factory
2160
+ - Removed signal handler leaks from `createFeedbackReporterServer` and `createPlaywrightFeedbackServer`
2161
+ - Moved SIGINT/SIGTERM handlers to auto-start guards only
2162
+
2163
+ 3. **Verification**
2164
+ - TypeScript build: clean
2165
+ - Unit tests: 529 passed (16 files)
2166
+ - Integration tests: 21 passed (2 files)
2167
+ - Zero regressions
2168
+
2169
+ **Project Organization:**
2170
+ - Moved Executive.md, STUBBED-PROBLEM.md, and TESTING.md from root to `/docs`
2171
+ - Updated README.md reference to docs/TESTING.md
2172
+ - Root directory now contains only essential files (README, CLAUDE, LICENSE, package files, version.json, and CLAUDE.md.gentyr-section template)
2173
+
2174
+ ## 2026-02-15 - AI User Feedback System
2175
+
2176
+ ### Added
2177
+
2178
+ **AI User Feedback System (Phase 1-8 complete):**
2179
+
2180
+ 1. **Data Layer** - `user-feedback` MCP server
2181
+ - 16 tools for persona/feature CRUD, persona-feature mapping, feedback run lifecycle, and session management
2182
+ - SQLite schema with personas, features, persona_features, feedback_runs, and feedback_sessions tables
2183
+ - Support for 4 consumption modes: gui, cli, api, sdk
2184
+ - Persona cooldown tracking and rate limiting (4h default, max 5 per run)
2185
+ - 43 unit tests passing
2186
+
2187
+ 2. **Configuration Interface** - `/configure-personas` slash command
2188
+ - Interactive persona management (create, edit, delete)
2189
+ - Feature registration with file/URL glob patterns
2190
+ - Persona-feature mapping with priority and test scenarios
2191
+ - Dry run: `get_personas_for_changes` previews which personas would trigger
2192
+
2193
+ 3. **GUI Testing** - `playwright-feedback` MCP server
2194
+ - 20 user-perspective-only tools (navigate, click, type, screenshot, read_text)
2195
+ - No developer tools (no evaluate_javascript, get_page_source, etc.)
2196
+ - Browser context isolation per session
2197
+ - 34 unit tests passing
2198
+
2199
+ 4. **Programmatic Testing** - `programmatic-feedback` MCP server
2200
+ - CLI mode: execFile with shell injection prevention
2201
+ - API mode: HTTP fetch with base URL validation
2202
+ - SDK mode: worker thread sandbox with blocked dangerous modules
2203
+ - 12 tools supporting 3 testing modes
2204
+ - 47 unit tests passing
2205
+
2206
+ 5. **Reporting Bridge** - `feedback-reporter` MCP server
2207
+ - Bridges findings from feedback sessions to agent-reports pipeline
2208
+ - Severity-to-priority mapping (critical→critical, high→high, medium→normal, low/info→low)
2209
+ - Persona-named reporting agents (e.g., "feedback-agent [power-user]")
2210
+ - Category: 'user-feedback' (added to REPORT_CATEGORIES)
2211
+ - 21 unit tests passing
2212
+
2213
+ 6. **Feedback Agent** - `feedback-agent.md`
2214
+ - Restricted tool access: only playwright-feedback, programmatic-feedback, feedback-reporter
2215
+ - Disallowed: Read, Write, Edit, Bash, Glob, Grep, WebFetch, WebSearch, Task, NotebookEdit
2216
+ - Persona-driven instructions: stays in character, tests as real user
2217
+ - Reports findings via feedback-reporter tools
2218
+
2219
+ 7. **Session Launcher** - `scripts/feedback-launcher.js`
2220
+ - Generates isolated .mcp.json configs for feedback sessions
2221
+ - Spawns Claude Code sessions with feedback-agent
2222
+ - Passes persona config and test scenarios via chat prompt
2223
+ - Detached process spawning for fire-and-forget execution
2224
+
2225
+ 8. **Orchestration Pipeline** - `scripts/feedback-orchestrator.js`
2226
+ - Detects staging changes and matches affected features
2227
+ - Selects personas mapped to matched features
2228
+ - Respects 4h per-persona cooldown and max-5-per-run limit
2229
+ - Creates feedback_run and feedback_session records
2230
+ - Spawns feedback agents via feedback-launcher
2231
+
2232
+ **Testing Infrastructure:**
2233
+
2234
+ - Toy app (server.js, cli.js) with 5 intentional bugs for end-to-end testing
2235
+ - 9 integration tests covering full pipeline: persona CRUD → feature registration → change analysis → feedback run lifecycle → reporter bridge
2236
+ - Feedback agent stub for simulating sessions without spawning real Claude sessions
2237
+ - 475 MCP server unit tests: ALL PASSING
2238
+ - 9 integration tests: ALL PASSING
2239
+
2240
+ **Modified Files:**
2241
+
2242
+ - `.mcp.json.template` - Added user-feedback, playwright-feedback, programmatic-feedback, feedback-reporter servers
2243
+ - `packages/mcp-servers/src/agent-reports/types.ts` - Added 'user-feedback' category
2244
+ - `.claude/agents/feedback-agent.md` - New agent definition
2245
+ - `.claude/commands/configure-personas.md` - New slash command
2246
+ - `scripts/feedback-launcher.js` - New launcher script
2247
+ - `scripts/feedback-orchestrator.js` - New orchestration pipeline
2248
+ - `tests/README.md` - Documentation for feedback system tests
2249
+ - `tests/fixtures/toy-app/` - Toy application with intentional bugs
2250
+ - `tests/integration/feedback-pipeline.test.ts` - Integration tests
2251
+ - `tests/integration/mocks/feedback-agent-stub.ts` - Agent simulation stub
2252
+
2253
+ **Known Remaining Work (not in scope):**
2254
+
2255
+ - Move feedback-launcher.js and feedback-orchestrator.js to .claude/hooks/ after unprotect
2256
+ - Add feedback pipeline block to hourly-automation.js
2257
+ - Add `user_feedback: 120` cooldown default to config-reader.js
2258
+
2259
+ ## 2026-02-15 - Usage Optimizer Improvements
2260
+
2261
+ ### Enhanced
2262
+
2263
+ **Six behavioral improvements to usage-optimizer.js:**
2264
+
2265
+ 1. **MIN_EFFECTIVE_MINUTES floor constant**
2266
+ - Added 2-minute floor to prevent cooldowns from going below practical minimums
2267
+ - `applyFactor()` clamps adjusted cooldowns to never go below 2 minutes
2268
+ - Prevents impractical sub-minute cooldowns that cause scheduler thrashing
2269
+
2270
+ 2. **Reset-boundary detection**
2271
+ - New `RESET_BOUNDARY_DROP_THRESHOLD = 0.30` constant
2272
+ - Detects when 5-hour utilization drops >30pp between snapshots
2273
+ - Indicates quota reset occurred, clears trajectory data to start fresh
2274
+ - Prevents false trajectory calculations across reset boundaries
2275
+
2276
+ 3. **EMA rate smoothing**
2277
+ - New `calculateEmaRate()` function with alpha=0.3
2278
+ - Exponential moving average smooths noisy utilization rates
2279
+ - Reduces overreaction to single anomalous snapshots
2280
+ - More stable cooldown adjustments over time
2281
+
2282
+ 4. **Max-key awareness**
2283
+ - `calculateAggregate()` now tracks `maxKey5h` and `maxKey7d`
2284
+ - Uses highest utilization across all keys for trajectory projection
2285
+ - Prevents underutilization when one key is saturated
2286
+ - Ensures system doesn't spawn tasks on exhausted keys
2287
+
2288
+ 5. **Per-key rate tracking**
2289
+ - New `perKeyUtilization` object tracks each key's 5h/7d rates
2290
+ - Logs warnings when any individual key exceeds 80% utilization
2291
+ - Helps identify single-key bottlenecks before hitting hard limits
2292
+ - Provides visibility into multi-key quota distribution
2293
+
2294
+ 6. **Enhanced logging**
2295
+ - Direction tracking: "projected-at-reset falling behind target" messages
2296
+ - `hoursUntilReset` included in all adjustment logs and config writes
2297
+ - More context for understanding optimizer behavior in production
2298
+
2299
+ ### Changed
2300
+
2301
+ **Modified Files:**
2302
+ - `.claude/hooks/usage-optimizer.js` - All 6 improvements implemented
2303
+ - `.claude/hooks/__tests__/usage-optimizer.test.js` - 27 new behavioral tests added
2304
+
2305
+ **Total Changes:** +412 lines added (including tests)
2306
+
2307
+ ### Testing
2308
+
2309
+ **New Test Suite (27 behavioral tests):**
2310
+ - MIN_EFFECTIVE_MINUTES floor enforcement tests (4)
2311
+ - Reset-boundary detection tests (5)
2312
+ - EMA rate smoothing tests (5)
2313
+ - Max-key awareness tests (4)
2314
+ - Per-key utilization tracking tests (4)
2315
+ - Enhanced logging tests (5)
2316
+
2317
+ **Test Results:**
2318
+ - All 107 usage-optimizer tests passing (80 existing + 27 new)
2319
+ - Code review: No violations
2320
+ - TypeScript compilation: Passed
2321
+
2322
+ ### Technical Details
2323
+
2324
+ **Behavioral Examples:**
2325
+
2326
+ **Floor Enforcement:**
2327
+ ```
2328
+ Target: 1 min cooldown → Clamped to 2 min
2329
+ Target: 0.5 min cooldown → Clamped to 2 min
2330
+ Prevents scheduler thrashing
2331
+ ```
2332
+
2333
+ **Reset Detection:**
2334
+ ```
2335
+ Snapshot 1: 5h=0.75 (75%)
2336
+ Snapshot 2: 5h=0.40 (40%)
2337
+ Drop = 35pp > 30pp threshold → Reset detected
2338
+ Action: Clear trajectory, start fresh
2339
+ ```
2340
+
2341
+ **EMA Smoothing:**
2342
+ ```
2343
+ Snapshot 1: rate=8.0 (spike)
2344
+ Snapshot 2: rate=2.0 (normal)
2345
+ EMA rate = 0.3*8.0 + 0.7*2.0 = 3.8 (smoothed)
2346
+ Prevents overreaction to outliers
2347
+ ```
2348
+
2349
+ **Max-Key Awareness:**
2350
+ ```
2351
+ Key A: 5h=0.60, 7d=0.50
2352
+ Key B: 5h=0.85, 7d=0.70 (saturated)
2353
+ Aggregate uses maxKey: 5h=0.85, 7d=0.70
2354
+ Prevents spawning tasks on exhausted keys
2355
+ ```
2356
+
2357
+ ### Use Cases
2358
+
2359
+ **Example 1: Quota Reset Boundary**
2360
+ - System samples quota at 11:58 AM (75% used)
2361
+ - Quota resets at 12:00 PM
2362
+ - Next sample at 12:08 PM (5% used)
2363
+ - Reset detector triggers, clears trajectory
2364
+ - Prevents false "rate slowed dramatically" calculation
2365
+
2366
+ **Example 2: Single-Key Saturation**
2367
+ - Project has 3 API keys
2368
+ - Key #1 hits 90% utilization
2369
+ - Keys #2 and #3 at 40% utilization
2370
+ - Max-key tracking uses 90% for trajectory
2371
+ - System reduces spawn rate to avoid key exhaustion
2372
+
2373
+ **Example 3: Noisy Environment**
2374
+ - Network glitch causes one anomalous sample (spike)
2375
+ - EMA smoothing reduces impact of outlier
2376
+ - Cooldown adjustment remains stable
2377
+ - Prevents unnecessary spawn rate swings
2378
+
2379
+ ### Backward Compatibility
2380
+
2381
+ Fully backward compatible:
2382
+ - All changes are internal to usage-optimizer.js
2383
+ - No config schema changes
2384
+ - No MCP tool changes
2385
+ - Existing snapshots remain valid
2386
+ - No breaking changes to hourly-automation.js integration
2387
+
2388
+ ---
2389
+
2390
+ ## 2026-02-15 - CTO Activity Gate for Autonomous Automation
2391
+
2392
+ ### Added
2393
+
2394
+ **24-Hour CTO Activity Gate**
2395
+ - New fail-closed safety mechanism for autonomous automation system
2396
+ - All timer-based automations (task runner, health monitors, promotion pipelines, etc.) require CTO briefing within past 24 hours
2397
+ - `checkCtoActivityGate()` function validates CTO activity before running any automation
2398
+ - Prevents runaway automation when CTO is not actively engaged with the project
2399
+
2400
+ **Deputy-CTO MCP Tool**
2401
+ - `mcp__deputy-cto__record_cto_briefing` - Records timestamp when CTO runs `/deputy-cto`
2402
+ - Updates `lastCtoBriefing` in deputy-cto config database
2403
+ - Automatically refreshes the 24-hour automation window
2404
+
2405
+ **Configuration Schema Extension**
2406
+ - Added `lastCtoBriefing` field to deputy-cto config (ISO 8601 timestamp)
2407
+ - Persisted in `.claude/deputy-cto-config.db` SQLite database
2408
+
2409
+ **Status Reporting**
2410
+ - `mcp__deputy-cto__get_status` now includes gate status:
2411
+ - `activityGate.open` - Whether automation is currently allowed
2412
+ - `activityGate.hoursSinceLastBriefing` - Hours since last CTO activity
2413
+ - `activityGate.reason` - Human-readable explanation
2414
+
2415
+ ### Changed
2416
+
2417
+ **Hourly Automation Service**
2418
+ - Modified `hourly-automation.js` main() to check CTO activity gate before running
2419
+ - If gate is closed, logs reason and exits gracefully (no automations run)
2420
+ - Gate check happens immediately after config load
2421
+
2422
+ **`/deputy-cto` Command**
2423
+ - Added `mcp__deputy-cto__record_cto_briefing()` as step 0 in opening briefing
2424
+ - CTO activity is automatically recorded at the start of every briefing session
2425
+ - Ensures automation window is refreshed each time CTO engages
2426
+
2427
+ ### Security Features (G001 Compliance)
2428
+
2429
+ **Fail-Closed Design:**
2430
+ - Missing `lastCtoBriefing` field → automation gated
2431
+ - Invalid timestamp → automation gated
2432
+ - Parse errors → automation gated
2433
+ - Timestamp >24h old → automation gated
2434
+
2435
+ **Why This Matters:**
2436
+ - Prevents autonomous agents from running indefinitely without human oversight
2437
+ - Ensures CTO remains engaged with automated decision-making
2438
+ - Creates natural checkpoint for reviewing autonomous actions (daily)
2439
+ - Reduces risk of automation drift from project goals
2440
+
2441
+ ### Technical Details
2442
+
2443
+ **Files Modified (5 total):**
2444
+ - `packages/mcp-servers/src/deputy-cto/types.ts` - Added lastCtoBriefing to config type, new tool schemas
2445
+ - `packages/mcp-servers/src/deputy-cto/server.ts` - Added recordCtoBriefing() function, registered tool
2446
+ - `.claude/hooks/hourly-automation.js` - Added checkCtoActivityGate() and gate check in main()
2447
+ - `.claude/commands/deputy-cto.md` - Added record_cto_briefing() as step 0
2448
+ - `packages/mcp-servers/src/deputy-cto/__tests__/deputy-cto.test.ts` - 12 new tests for gate feature
2449
+
2450
+ **Total Changes:** +203 lines added, -14 lines removed
2451
+
2452
+ ### Testing
2453
+
2454
+ **New Test Suite (12 tests):**
2455
+ - `record_cto_briefing` tool functionality
2456
+ - `get_status` includes gate information
2457
+ - Gate opens when briefing is recent (<24h)
2458
+ - Gate closes when briefing is old (>24h)
2459
+ - Gate closes when briefing is missing
2460
+ - Gate closes on invalid timestamp
2461
+ - Fail-closed behavior on all error conditions
2462
+
2463
+ **Test Results:**
2464
+ - TypeScript compilation: ✓ Passed
2465
+ - All 330 tests passing (318 existing + 12 new)
2466
+ - Code review: ✓ No violations
2467
+
2468
+ ### Use Cases
2469
+
2470
+ **Example 1: Fresh Installation**
2471
+ - User installs GENTYR, autonomous mode enabled by default
2472
+ - Hourly automation runs, checks gate → closed (no briefing yet)
2473
+ - User runs `/deputy-cto` → briefing recorded
2474
+ - Hourly automation runs, checks gate → open (briefing fresh)
2475
+
2476
+ **Example 2: Inactive Project**
2477
+ - User is away for 2 days
2478
+ - Hourly automation runs every hour → gate closed after 24h
2479
+ - No tasks spawned, no promotions, no health checks
2480
+ - User returns, runs `/deputy-cto` → automation resumes
2481
+
2482
+ **Example 3: Active Development**
2483
+ - User runs `/deputy-cto` daily as part of workflow
2484
+ - Gate always open, automation runs normally
2485
+ - Natural cadence of human oversight and automated execution
2486
+
2487
+ ### Backward Compatibility
2488
+
2489
+ Fully backward compatible:
2490
+ - Existing deputy-cto config database migrates seamlessly (lastCtoBriefing defaults to null)
2491
+ - First run of `/deputy-cto` populates the field
2492
+ - Projects without deputy-cto installed are unaffected (no automation anyway)
2493
+
2494
+ ---
2495
+
2496
+ ## 2026-02-03 - CTO Approval System for MCP Actions
2497
+
2498
+ ### Added
2499
+
2500
+ **Protected MCP Action Gate**
2501
+ - New PreToolUse hook: `protected-action-gate.js` - Blocks protected MCP actions until CTO approval
2502
+ - New UserPromptSubmit hook: `protected-action-approval-hook.js` - Processes CTO approval phrases
2503
+ - Configuration file: `protected-actions.json.template` - Maps approval phrases to MCP tools
2504
+ - Approval utilities library: `.claude/hooks/lib/approval-utils.js` - Encryption, code generation, validation
2505
+
2506
+ **CLI Utilities**
2507
+ - `scripts/encrypt-credential.js` - Encrypt credentials for protected-actions.json
2508
+ - `scripts/generate-protected-actions-spec.js` - Auto-generate spec file from config
2509
+
2510
+ **Deputy-CTO MCP Tools**
2511
+ - `mcp__deputy-cto__list_protections` - List all protected MCP actions and their approval phrases
2512
+ - `mcp__deputy-cto__get_protected_action_request` - Get details of pending approval request by code
2513
+
2514
+ **Setup Script Integration**
2515
+ - Added `--protect-mcp` flag to setup.sh for protecting MCP action config files
2516
+ - Protection includes: `protected-actions.json`, `protected-action-approvals.json`
2517
+
2518
+ **Agent Instructions**
2519
+ - Updated `CLAUDE.md.gentyr-section` with CTO-Protected Actions workflow section
2520
+ - Agents now instructed to stop and wait for CTO approval when actions are blocked
2521
+
2522
+ ### Security Fixes
2523
+
2524
+ **G001 Fail-Closed Compliance**
2525
+ - Fixed fail-open vulnerability in protected-action-gate.js
2526
+ - Now properly fails closed when config is missing or invalid
2527
+ - Added explicit error handling for all edge cases
2528
+
2529
+ **Cryptographic Security**
2530
+ - Replaced weak RNG (Math.random) with crypto.randomBytes for approval code generation
2531
+ - 6-character codes now use cryptographically secure random values
2532
+
2533
+ **Protection Integrity**
2534
+ - Updated do_unprotect() to include new approval system files
2535
+ - Ensures uninstall properly removes all protected files
2536
+
2537
+ ### Changed
2538
+
2539
+ **Hook Configuration**
2540
+ - `.claude/settings.json.template` updated with new hook registrations:
2541
+ - PreToolUse: protected-action-gate.js
2542
+ - UserPromptSubmit: protected-action-approval-hook.js
2543
+
2544
+ ### Technical Details
2545
+
2546
+ **Approval Workflow:**
2547
+ 1. Agent calls protected MCP action (e.g., production deployment tool)
2548
+ 2. PreToolUse hook blocks the action, generates 6-character code
2549
+ 3. Agent displays: "Action blocked. CTO must type: APPROVE PROD A7X9K2"
2550
+ 4. CTO types approval phrase in chat
2551
+ 5. UserPromptSubmit hook validates phrase and code, creates one-time approval token
2552
+ 6. Agent retries action, PreToolUse hook allows it (one-time use, 5-minute expiry)
2553
+
2554
+ **Configuration Schema:**
2555
+ ```json
2556
+ {
2557
+ "protections": [
2558
+ {
2559
+ "phrase": "APPROVE PROD",
2560
+ "encryptedCredential": "...",
2561
+ "tools": [
2562
+ { "server": "mcp-server", "tool": "deploy_to_production" }
2563
+ ]
2564
+ }
2565
+ ]
2566
+ }
2567
+ ```
2568
+
2569
+ **Files Created (13 total):**
2570
+ - `.claude/hooks/lib/approval-utils.js` (269 lines)
2571
+ - `.claude/hooks/protected-action-gate.js` (137 lines)
2572
+ - `.claude/hooks/protected-action-approval-hook.js` (120 lines)
2573
+ - `.claude/hooks/protected-actions.json.template` (52 lines)
2574
+ - `scripts/encrypt-credential.js` (85 lines)
2575
+ - `scripts/generate-protected-actions-spec.js` (116 lines)
2576
+ - `.claude/hooks/__tests__/approval-utils.test.js` (231 lines)
2577
+ - `.claude/hooks/__tests__/protected-action-gate.test.js` (189 lines)
2578
+ - `.claude/hooks/__tests__/protected-action-approval-hook.test.js` (192 lines)
2579
+
2580
+ **Files Modified:**
2581
+ - `.claude/settings.json.template` (+14 lines)
2582
+ - `CLAUDE.md.gentyr-section` (+7 lines)
2583
+ - `packages/mcp-servers/src/deputy-cto/server.ts` (+98 lines)
2584
+ - `packages/mcp-servers/src/deputy-cto/types.ts` (+23 lines)
2585
+ - `scripts/setup.sh` (+32 lines)
2586
+
2587
+ **Total Changes:** +1565 lines added
2588
+
2589
+ ### Testing
2590
+
2591
+ All new components include comprehensive unit tests:
2592
+ - approval-utils.test.js: Encryption, code generation, validation
2593
+ - protected-action-gate.test.js: Hook blocking behavior, fail-closed compliance
2594
+ - protected-action-approval-hook.test.js: Approval phrase processing, token creation
2595
+
2596
+ ### Use Cases
2597
+
2598
+ **Example 1: Production Deployment**
2599
+ Protect production deployment tools to require explicit CTO approval before execution.
2600
+
2601
+ **Example 2: Database Migrations**
2602
+ Prevent agents from running migrations without CTO review and approval.
2603
+
2604
+ **Example 3: API Key Rotation**
2605
+ Require CTO approval before rotating production API keys.
2606
+
2607
+ ### Security Considerations
2608
+
2609
+ - Approval codes expire after 5 minutes
2610
+ - One-time use tokens (cannot be reused)
2611
+ - Fail-closed design (blocks on any error)
2612
+ - Credentials encrypted with AES-256-GCM
2613
+ - Cryptographically secure random code generation
2614
+
2615
+ ---
2616
+
2617
+ ## 2026-01-31 - Deputy CTO Task Assignment Feature
2618
+
2619
+ ### Added
2620
+
2621
+ **Deputy CTO Agent: Task Assignment Capability**
2622
+ - Added `mcp__todo-db__create_task` to deputy-cto allowed tools
2623
+ - New "Task Assignment" section with urgency-based decision criteria
2624
+ - Reduces resource usage by queuing non-urgent tasks instead of immediate spawning
2625
+
2626
+ **Decision Framework:**
2627
+ - **Urgent tasks** (immediate spawning via `spawn_implementation_task`):
2628
+ - Security issues or vulnerabilities
2629
+ - Blocking issues preventing commits
2630
+ - Time-sensitive fixes
2631
+ - CTO explicitly requests immediate action
2632
+ - **Non-urgent tasks** (queued via `mcp__todo-db__create_task`):
2633
+ - Feature implementation from plans
2634
+ - Refactoring work
2635
+ - Documentation updates
2636
+ - General improvements
2637
+
2638
+ ### Changed
2639
+
2640
+ **`.claude/agents/deputy-cto.md`**
2641
+ - Added `mcp__todo-db__create_task` to allowedTools
2642
+ - Updated "Your Powers" section to list both spawn and queue options
2643
+ - Added "Task Assignment" section with urgency criteria and code examples
2644
+
2645
+ **`.claude/commands/deputy-cto.md`**
2646
+ - Replaced "Spawning Implementation Tasks" section with "Task Assignment"
2647
+ - Added urgency-based decision criteria
2648
+ - Added code examples for both immediate spawning and queuing
2649
+
2650
+ ### Technical Details
2651
+
2652
+ The deputy-cto agent now intelligently chooses between:
2653
+ 1. **Immediate spawning** - Fire-and-forget Claude sessions for urgent work
2654
+ 2. **Task queuing** - Adding tasks to todo.db for agent pickup during normal workflow
2655
+
2656
+ This reduces unnecessary resource consumption while maintaining responsiveness for critical issues.
2657
+
2658
+ ### Files Modified
2659
+
2660
+ - `.claude/agents/deputy-cto.md` (configuration changes)
2661
+ - `.claude/commands/deputy-cto.md` (documentation changes)
2662
+
2663
+ ### Review Status
2664
+
2665
+ - Code Reviewer: APPROVED - Changes well-structured, consistent, correct tool usage
2666
+ - Test Writer: N/A - Markdown configuration files, no executable code
2667
+
2668
+ ---
2669
+
2670
+ ## 2026-01-29 - CLAUDE.md Agent Instructions Feature
2671
+
2672
+ ### Added
2673
+
2674
+ **Setup Script: CLAUDE.md Management**
2675
+ - Automatic injection of agent workflow instructions into target project CLAUDE.md files
2676
+ - Template file: `CLAUDE.md.gentyr-section` with golden rules and standard workflow
2677
+ - Smart append/replace logic:
2678
+ - Creates CLAUDE.md if it doesn't exist
2679
+ - Appends section to existing files
2680
+ - Replaces section on re-install (no duplicates)
2681
+ - Uses `<!-- GENTYR-FRAMEWORK-START/END -->` markers for idempotency
2682
+
2683
+ **Uninstall Cleanup**
2684
+ - Removes GENTYR section from CLAUDE.md
2685
+ - Deletes file if empty after removal
2686
+ - Preserves project-specific content
2687
+
2688
+ **Agent Workflow Documentation**
2689
+ - Golden rules: Never skip agents, always follow order, one agent per role
2690
+ - Standard sequence: INVESTIGATOR → CODE-WRITER → TEST-WRITER → CODE-REVIEWER → PROJECT-MANAGER → SUMMARY
2691
+ - CTO reporting guidelines for architecture, security, breaking changes, blockers
2692
+ - Slash command reference
2693
+
2694
+ ### Changed
2695
+
2696
+ **scripts/setup.sh**
2697
+ - Added section 8: CLAUDE.md agent instructions injection
2698
+ - Added CLAUDE.md cleanup in uninstall section
2699
+ - Skip CLAUDE.md operations if file is write-protected
2700
+
2701
+ **README.md**
2702
+ - Expanded "Custom CLAUDE.md" section with installation behavior details
2703
+ - Documented template location and content
2704
+ - Added uninstall behavior explanation
2705
+
2706
+ ### Files Modified
2707
+
2708
+ - `scripts/setup.sh` (+47 lines)
2709
+ - `CLAUDE.md` (new, 60 lines) - Framework's own CLAUDE.md
2710
+ - `CLAUDE.md.gentyr-section` (new, 34 lines) - Template for target projects
2711
+ - `README.md` (+20 lines)
2712
+ - `docs/CHANGELOG.md` (+35 lines, this entry)
2713
+
2714
+ ### Technical Details
2715
+
2716
+ **Idempotency:**
2717
+ - Section markers ensure re-installs replace old section instead of appending duplicates
2718
+ - Sed-based removal using marker comments
2719
+
2720
+ **Protection Integration:**
2721
+ - Setup skips CLAUDE.md if write-protected (post-protection state)
2722
+ - Uninstall skips cleanup if write-protected
2723
+
2724
+ ### Use Case
2725
+
2726
+ Before this feature, each project needed manual CLAUDE.md creation with agent workflow instructions. Now the framework automatically provides:
2727
+ - Consistent agent workflow across all projects
2728
+ - Up-to-date best practices for multi-agent coordination
2729
+ - Standardized CTO reporting conventions
2730
+
2731
+ Projects can still add custom instructions above/below the framework section.
2732
+
2733
+ ---
2734
+
2735
+ ## 2026-01-24 - Spec Suite System
2736
+
2737
+ ### Added
2738
+
2739
+ **MCP Server: specs-browser**
2740
+ - 9 new MCP tools for spec and suite management:
2741
+ - `createSpec` - Create new specification files
2742
+ - `editSpec` - Edit existing specifications
2743
+ - `deleteSpec` - Delete specifications
2744
+ - `get_specs_for_file` - Get all applicable specs for a file (main + subspecs)
2745
+ - `listSuites` - List all configured spec suites
2746
+ - `getSuite` - Get suite configuration details
2747
+ - `createSuite` - Create new spec suite
2748
+ - `editSuite` - Modify suite configuration
2749
+ - `deleteSuite` - Remove spec suite
2750
+
2751
+ **Compliance Checker**
2752
+ - Suite-based enforcement system
2753
+ - Pattern matching for file scoping using glob patterns
2754
+ - `loadSuitesConfig()` - Load suite configuration
2755
+ - `getSuitesForFile()` - Determine applicable suites for a file
2756
+ - `getAllApplicableSpecs()` - Collect specs from matching suites (global)
2757
+ - `getAllExploratorySpecs()` - Collect specs from matching suites (local)
2758
+ - `matchesGlob()` - Simple glob pattern matcher
2759
+
2760
+ **Configuration**
2761
+ - New config file: `.claude/hooks/suites-config.json`
2762
+ - Suite schema with scope, priority, and enabled flags
2763
+ - Backward compatibility with legacy enforcement
2764
+
2765
+ **Documentation**
2766
+ - Comprehensive spec suites section in `.claude/hooks/README.md`
2767
+ - Session documentation: `docs/sessions/2026-01-24-spec-suite-implementation.md`
2768
+ - Updated README.md with spec suite examples
2769
+
2770
+ ### Changed
2771
+
2772
+ **Compliance Prompts**
2773
+ - `spec-enforcement.md` - Added optional Suite Context section
2774
+ - `local-spec-enforcement.md` - Added Suite Context and Scope Constraint sections
2775
+
2776
+ **README.md**
2777
+ - Updated Specification Enforcement section with suite examples
2778
+ - Updated specs-browser description to include CRUD operations
2779
+ - Updated MCP tools examples
2780
+
2781
+ ### Technical Details
2782
+
2783
+ **Files Modified (7 total):**
2784
+ - `.claude/hooks/README.md` (+89 lines)
2785
+ - `.claude/hooks/compliance-checker.js` (+382 lines major refactor)
2786
+ - `.claude/hooks/prompts/local-spec-enforcement.md` (+24 lines)
2787
+ - `.claude/hooks/prompts/spec-enforcement.md` (+9 lines)
2788
+ - `README.md` (+34 lines)
2789
+ - `packages/mcp-servers/src/specs-browser/server.ts` (+442 lines)
2790
+ - `packages/mcp-servers/src/specs-browser/types.ts` (+232 lines)
2791
+
2792
+ **Total Changes:** +1101 lines, -111 lines
2793
+
2794
+ ### Verification
2795
+
2796
+ - TypeScript build: ✓ Passed
2797
+ - JavaScript syntax check: ✓ Passed
2798
+ - Code review: ✓ No violations
2799
+ - Vitest tests: ✓ 51 tests passing
2800
+
2801
+ ### Testing
2802
+
2803
+ **specs-browser/__tests__/specs-browser.test.ts**
2804
+ - Fixed test cleanup issue in Suite Management describe block
2805
+ - Added `afterEach` to remove `.claude` directory created during tests
2806
+ - All 51 tests now pass consistently across test runs
2807
+ - Root cause: Missing cleanup caused directory persistence across runs
2808
+
2809
+ ### Architecture
2810
+
2811
+ Spec suites allow projects to:
2812
+ 1. Group related specifications (global + local)
2813
+ 2. Scope specs to specific file patterns using glob syntax
2814
+ 3. Reduce enforcement noise by checking only relevant specs
2815
+ 4. Configure priority when multiple suites match
2816
+
2817
+ Example use case: Integration-specific specs only check integration files, not the entire codebase.
2818
+
2819
+ ### Backward Compatibility
2820
+
2821
+ Fully backward compatible:
2822
+ - Legacy behavior if suites-config.json doesn't exist
2823
+ - Existing spec-file-mappings.json still supported
2824
+ - No breaking changes to existing workflows
2825
+
2826
+ ---
2827
+
2828
+ ## Previous Releases
2829
+
2830
+ See git history for pre-2026-01-24 changes.