takt 0.41.0 → 0.42.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 (281) hide show
  1. package/README.md +58 -28
  2. package/builtins/en/facets/instructions/write-tests-first.md +5 -0
  3. package/builtins/en/facets/knowledge/architecture.md +13 -13
  4. package/builtins/en/facets/knowledge/cqrs-es.md +48 -0
  5. package/builtins/en/facets/knowledge/frontend.md +13 -0
  6. package/builtins/en/facets/output-contracts/frontend-review.md +1 -0
  7. package/builtins/en/facets/policies/ai-antipattern.md +19 -0
  8. package/builtins/en/facets/policies/coding.md +85 -3
  9. package/builtins/en/facets/policies/qa.md +3 -1
  10. package/builtins/en/facets/policies/review.md +5 -3
  11. package/builtins/en/facets/policies/testing.md +33 -0
  12. package/builtins/en/workflows/auto-improvement-loop.yaml +20 -4
  13. package/builtins/ja/facets/instructions/write-tests-first.md +5 -0
  14. package/builtins/ja/facets/knowledge/architecture.md +13 -13
  15. package/builtins/ja/facets/knowledge/cqrs-es.md +48 -0
  16. package/builtins/ja/facets/knowledge/frontend.md +13 -0
  17. package/builtins/ja/facets/output-contracts/frontend-review.md +1 -0
  18. package/builtins/ja/facets/policies/ai-antipattern.md +19 -0
  19. package/builtins/ja/facets/policies/coding.md +85 -3
  20. package/builtins/ja/facets/policies/qa.md +3 -1
  21. package/builtins/ja/facets/policies/review.md +5 -3
  22. package/builtins/ja/facets/policies/testing.md +33 -0
  23. package/builtins/ja/workflows/auto-improvement-loop.yaml +20 -4
  24. package/dist/agents/decompose-task-usecase.d.ts.map +1 -1
  25. package/dist/agents/decompose-task-usecase.js +3 -2
  26. package/dist/agents/decompose-task-usecase.js.map +1 -1
  27. package/dist/agents/judge-status-usecase.d.ts.map +1 -1
  28. package/dist/agents/judge-status-usecase.js +4 -3
  29. package/dist/agents/judge-status-usecase.js.map +1 -1
  30. package/dist/agents/provider-call-options.d.ts +4 -0
  31. package/dist/agents/provider-call-options.d.ts.map +1 -0
  32. package/dist/agents/provider-call-options.js +9 -0
  33. package/dist/agents/provider-call-options.js.map +1 -0
  34. package/dist/agents/runner.js +1 -1
  35. package/dist/agents/runner.js.map +1 -1
  36. package/dist/agents/structured-caller/prompt-based-structured-caller.d.ts.map +1 -1
  37. package/dist/agents/structured-caller/prompt-based-structured-caller.js +5 -4
  38. package/dist/agents/structured-caller/prompt-based-structured-caller.js.map +1 -1
  39. package/dist/app/cli/program.js +1 -1
  40. package/dist/app/cli/program.js.map +1 -1
  41. package/dist/core/models/assistant-config.d.ts +4 -0
  42. package/dist/core/models/assistant-config.d.ts.map +1 -0
  43. package/dist/core/models/assistant-config.js +4 -0
  44. package/dist/core/models/assistant-config.js.map +1 -0
  45. package/dist/core/models/config-schemas.d.ts +88 -0
  46. package/dist/core/models/config-schemas.d.ts.map +1 -1
  47. package/dist/core/models/config-schemas.js +8 -2
  48. package/dist/core/models/config-schemas.js.map +1 -1
  49. package/dist/core/models/config-types.d.ts +20 -1
  50. package/dist/core/models/config-types.d.ts.map +1 -1
  51. package/dist/core/models/index.d.ts +1 -1
  52. package/dist/core/models/index.d.ts.map +1 -1
  53. package/dist/core/models/index.js.map +1 -1
  54. package/dist/core/models/provider-profiles.d.ts +1 -1
  55. package/dist/core/models/provider-profiles.d.ts.map +1 -1
  56. package/dist/core/models/response.d.ts +1 -1
  57. package/dist/core/models/response.d.ts.map +1 -1
  58. package/dist/core/models/response.js +1 -1
  59. package/dist/core/models/response.js.map +1 -1
  60. package/dist/core/models/schema-base.d.ts +65 -0
  61. package/dist/core/models/schema-base.d.ts.map +1 -1
  62. package/dist/core/models/schema-base.js +31 -0
  63. package/dist/core/models/schema-base.js.map +1 -1
  64. package/dist/core/models/types.d.ts +2 -2
  65. package/dist/core/models/types.d.ts.map +1 -1
  66. package/dist/core/models/workflow-provider-options.d.ts +7 -0
  67. package/dist/core/models/workflow-provider-options.d.ts.map +1 -1
  68. package/dist/core/models/workflow-schemas.d.ts +277 -38
  69. package/dist/core/models/workflow-schemas.d.ts.map +1 -1
  70. package/dist/core/models/workflow-system-input-types.d.ts +8 -1
  71. package/dist/core/models/workflow-system-input-types.d.ts.map +1 -1
  72. package/dist/core/models/workflow-system-schemas.d.ts +7 -1
  73. package/dist/core/models/workflow-system-schemas.d.ts.map +1 -1
  74. package/dist/core/models/workflow-system-schemas.js +12 -1
  75. package/dist/core/models/workflow-system-schemas.js.map +1 -1
  76. package/dist/core/models/workflow-types.d.ts +2 -2
  77. package/dist/core/models/workflow-types.d.ts.map +1 -1
  78. package/dist/core/models/workflow-types.js.map +1 -1
  79. package/dist/core/workflow/engine/OptionsBuilder.d.ts +1 -0
  80. package/dist/core/workflow/engine/OptionsBuilder.d.ts.map +1 -1
  81. package/dist/core/workflow/engine/OptionsBuilder.js +9 -4
  82. package/dist/core/workflow/engine/OptionsBuilder.js.map +1 -1
  83. package/dist/core/workflow/engine/WorkflowEngine.d.ts +1 -0
  84. package/dist/core/workflow/engine/WorkflowEngine.d.ts.map +1 -1
  85. package/dist/core/workflow/engine/WorkflowEngine.js +24 -4
  86. package/dist/core/workflow/engine/WorkflowEngine.js.map +1 -1
  87. package/dist/core/workflow/engine/WorkflowRunLoop.d.ts +1 -0
  88. package/dist/core/workflow/engine/WorkflowRunLoop.d.ts.map +1 -1
  89. package/dist/core/workflow/engine/WorkflowRunLoop.js +26 -7
  90. package/dist/core/workflow/engine/WorkflowRunLoop.js.map +1 -1
  91. package/dist/core/workflow/observability/workflowSpans.d.ts +28 -0
  92. package/dist/core/workflow/observability/workflowSpans.d.ts.map +1 -0
  93. package/dist/core/workflow/observability/workflowSpans.js +107 -0
  94. package/dist/core/workflow/observability/workflowSpans.js.map +1 -0
  95. package/dist/core/workflow/permission-profile-resolution.d.ts.map +1 -1
  96. package/dist/core/workflow/permission-profile-resolution.js +1 -0
  97. package/dist/core/workflow/permission-profile-resolution.js.map +1 -1
  98. package/dist/core/workflow/phase-runner.d.ts +1 -3
  99. package/dist/core/workflow/phase-runner.d.ts.map +1 -1
  100. package/dist/core/workflow/phase-runner.js.map +1 -1
  101. package/dist/core/workflow/report-phase-runner.d.ts.map +1 -1
  102. package/dist/core/workflow/report-phase-runner.js +3 -2
  103. package/dist/core/workflow/report-phase-runner.js.map +1 -1
  104. package/dist/core/workflow/status-judgment-phase.d.ts.map +1 -1
  105. package/dist/core/workflow/status-judgment-phase.js +7 -3
  106. package/dist/core/workflow/status-judgment-phase.js.map +1 -1
  107. package/dist/core/workflow/system/system-step-effect-runner.d.ts.map +1 -1
  108. package/dist/core/workflow/system/system-step-effect-runner.js +16 -1
  109. package/dist/core/workflow/system/system-step-effect-runner.js.map +1 -1
  110. package/dist/core/workflow/types.d.ts +3 -1
  111. package/dist/core/workflow/types.d.ts.map +1 -1
  112. package/dist/features/interactive/assistantInitFiles.d.ts +2 -0
  113. package/dist/features/interactive/assistantInitFiles.d.ts.map +1 -0
  114. package/dist/features/interactive/assistantInitFiles.js +110 -0
  115. package/dist/features/interactive/assistantInitFiles.js.map +1 -0
  116. package/dist/features/interactive/conversationLoop.d.ts +5 -1
  117. package/dist/features/interactive/conversationLoop.d.ts.map +1 -1
  118. package/dist/features/interactive/conversationLoop.js +23 -3
  119. package/dist/features/interactive/conversationLoop.js.map +1 -1
  120. package/dist/features/interactive/interactive-summary.d.ts +1 -1
  121. package/dist/features/interactive/interactive-summary.d.ts.map +1 -1
  122. package/dist/features/interactive/interactive-summary.js +4 -3
  123. package/dist/features/interactive/interactive-summary.js.map +1 -1
  124. package/dist/features/interactive/interactive.d.ts +5 -3
  125. package/dist/features/interactive/interactive.d.ts.map +1 -1
  126. package/dist/features/interactive/interactive.js +4 -0
  127. package/dist/features/interactive/interactive.js.map +1 -1
  128. package/dist/features/interactive/promptSections.d.ts +2 -0
  129. package/dist/features/interactive/promptSections.d.ts.map +1 -1
  130. package/dist/features/interactive/promptSections.js +7 -1
  131. package/dist/features/interactive/promptSections.js.map +1 -1
  132. package/dist/features/interactive/slashCommandRegistry.d.ts.map +1 -1
  133. package/dist/features/interactive/slashCommandRegistry.js +1 -0
  134. package/dist/features/interactive/slashCommandRegistry.js.map +1 -1
  135. package/dist/features/tasks/execute/workflowExecution.d.ts.map +1 -1
  136. package/dist/features/tasks/execute/workflowExecution.js +12 -1
  137. package/dist/features/tasks/execute/workflowExecution.js.map +1 -1
  138. package/dist/features/tasks/execute/workflowExecutionBootstrap.d.ts +5 -1
  139. package/dist/features/tasks/execute/workflowExecutionBootstrap.d.ts.map +1 -1
  140. package/dist/features/tasks/execute/workflowExecutionBootstrap.js +6 -1
  141. package/dist/features/tasks/execute/workflowExecutionBootstrap.js.map +1 -1
  142. package/dist/infra/claude/executor.d.ts.map +1 -1
  143. package/dist/infra/claude/executor.js +27 -6
  144. package/dist/infra/claude/executor.js.map +1 -1
  145. package/dist/infra/claude/mcp-config.d.ts +7 -0
  146. package/dist/infra/claude/mcp-config.d.ts.map +1 -0
  147. package/dist/infra/claude/mcp-config.js +30 -0
  148. package/dist/infra/claude/mcp-config.js.map +1 -0
  149. package/dist/infra/claude-headless/client.d.ts.map +1 -1
  150. package/dist/infra/claude-headless/client.js +5 -40
  151. package/dist/infra/claude-headless/client.js.map +1 -1
  152. package/dist/infra/claude-headless/result-response.js +1 -1
  153. package/dist/infra/claude-headless/result-response.js.map +1 -1
  154. package/dist/infra/claude-terminal/client.d.ts +4 -0
  155. package/dist/infra/claude-terminal/client.d.ts.map +1 -0
  156. package/dist/infra/claude-terminal/client.js +314 -0
  157. package/dist/infra/claude-terminal/client.js.map +1 -0
  158. package/dist/infra/claude-terminal/command.d.ts +4 -0
  159. package/dist/infra/claude-terminal/command.d.ts.map +1 -0
  160. package/dist/infra/claude-terminal/command.js +50 -0
  161. package/dist/infra/claude-terminal/command.js.map +1 -0
  162. package/dist/infra/claude-terminal/response-normalizer.d.ts +14 -0
  163. package/dist/infra/claude-terminal/response-normalizer.d.ts.map +1 -0
  164. package/dist/infra/claude-terminal/response-normalizer.js +118 -0
  165. package/dist/infra/claude-terminal/response-normalizer.js.map +1 -0
  166. package/dist/infra/claude-terminal/tmux-backend.d.ts +7 -0
  167. package/dist/infra/claude-terminal/tmux-backend.d.ts.map +1 -0
  168. package/dist/infra/claude-terminal/tmux-backend.js +177 -0
  169. package/dist/infra/claude-terminal/tmux-backend.js.map +1 -0
  170. package/dist/infra/claude-terminal/transcript-reader.d.ts +13 -0
  171. package/dist/infra/claude-terminal/transcript-reader.d.ts.map +1 -0
  172. package/dist/infra/claude-terminal/transcript-reader.js +329 -0
  173. package/dist/infra/claude-terminal/transcript-reader.js.map +1 -0
  174. package/dist/infra/claude-terminal/types.d.ts +106 -0
  175. package/dist/infra/claude-terminal/types.d.ts.map +1 -0
  176. package/dist/infra/claude-terminal/types.js +2 -0
  177. package/dist/infra/claude-terminal/types.js.map +1 -0
  178. package/dist/infra/config/configNormalizers.d.ts +7 -1
  179. package/dist/infra/config/configNormalizers.d.ts.map +1 -1
  180. package/dist/infra/config/configNormalizers.js +31 -1
  181. package/dist/infra/config/configNormalizers.js.map +1 -1
  182. package/dist/infra/config/env/global-current-env-specs.d.ts.map +1 -1
  183. package/dist/infra/config/env/global-current-env-specs.js +5 -0
  184. package/dist/infra/config/env/global-current-env-specs.js.map +1 -1
  185. package/dist/infra/config/env/project-current-env-specs.d.ts.map +1 -1
  186. package/dist/infra/config/env/project-current-env-specs.js +5 -0
  187. package/dist/infra/config/env/project-current-env-specs.js.map +1 -1
  188. package/dist/infra/config/global/globalConfigCore.d.ts.map +1 -1
  189. package/dist/infra/config/global/globalConfigCore.js +2 -0
  190. package/dist/infra/config/global/globalConfigCore.js.map +1 -1
  191. package/dist/infra/config/global/globalConfigSerializer.d.ts.map +1 -1
  192. package/dist/infra/config/global/globalConfigSerializer.js +5 -0
  193. package/dist/infra/config/global/globalConfigSerializer.js.map +1 -1
  194. package/dist/infra/config/global/initialization.d.ts +1 -1
  195. package/dist/infra/config/global/initialization.d.ts.map +1 -1
  196. package/dist/infra/config/global/initialization.js +1 -0
  197. package/dist/infra/config/global/initialization.js.map +1 -1
  198. package/dist/infra/config/observabilityConfig.d.ts +13 -0
  199. package/dist/infra/config/observabilityConfig.d.ts.map +1 -0
  200. package/dist/infra/config/observabilityConfig.js +52 -0
  201. package/dist/infra/config/observabilityConfig.js.map +1 -0
  202. package/dist/infra/config/project/projectConfig.d.ts.map +1 -1
  203. package/dist/infra/config/project/projectConfig.js +19 -2
  204. package/dist/infra/config/project/projectConfig.js.map +1 -1
  205. package/dist/infra/config/providerOptions.d.ts +8 -2
  206. package/dist/infra/config/providerOptions.d.ts.map +1 -1
  207. package/dist/infra/config/providerOptions.js +49 -1
  208. package/dist/infra/config/providerOptions.js.map +1 -1
  209. package/dist/infra/config/providerOptionsContract.d.ts +3 -3
  210. package/dist/infra/config/providerOptionsContract.d.ts.map +1 -1
  211. package/dist/infra/config/providerOptionsContract.js +14 -0
  212. package/dist/infra/config/providerOptionsContract.js.map +1 -1
  213. package/dist/infra/config/resolveConfigValue.d.ts.map +1 -1
  214. package/dist/infra/config/resolveConfigValue.js +18 -0
  215. package/dist/infra/config/resolveConfigValue.js.map +1 -1
  216. package/dist/infra/config/resolvedConfig.d.ts +2 -1
  217. package/dist/infra/config/resolvedConfig.d.ts.map +1 -1
  218. package/dist/infra/config/traced/tracedConfigSchema.d.ts.map +1 -1
  219. package/dist/infra/config/traced/tracedConfigSchema.js +12 -0
  220. package/dist/infra/config/traced/tracedConfigSchema.js.map +1 -1
  221. package/dist/infra/git/format.d.ts.map +1 -1
  222. package/dist/infra/git/format.js +75 -8
  223. package/dist/infra/git/format.js.map +1 -1
  224. package/dist/infra/git/index.d.ts +1 -1
  225. package/dist/infra/git/index.d.ts.map +1 -1
  226. package/dist/infra/git/types.d.ts +5 -0
  227. package/dist/infra/git/types.d.ts.map +1 -1
  228. package/dist/infra/github/pr.d.ts.map +1 -1
  229. package/dist/infra/github/pr.js +174 -28
  230. package/dist/infra/github/pr.js.map +1 -1
  231. package/dist/infra/observability/otelFoundation.d.ts +6 -0
  232. package/dist/infra/observability/otelFoundation.d.ts.map +1 -0
  233. package/dist/infra/observability/otelFoundation.js +89 -0
  234. package/dist/infra/observability/otelFoundation.js.map +1 -0
  235. package/dist/infra/opencode/client.d.ts.map +1 -1
  236. package/dist/infra/opencode/client.js +19 -15
  237. package/dist/infra/opencode/client.js.map +1 -1
  238. package/dist/infra/providers/claude-terminal.d.ts +6 -0
  239. package/dist/infra/providers/claude-terminal.d.ts.map +1 -0
  240. package/dist/infra/providers/claude-terminal.js +70 -0
  241. package/dist/infra/providers/claude-terminal.js.map +1 -0
  242. package/dist/infra/providers/index.d.ts.map +1 -1
  243. package/dist/infra/providers/index.js +2 -0
  244. package/dist/infra/providers/index.js.map +1 -1
  245. package/dist/infra/providers/provider-capabilities.d.ts +1 -0
  246. package/dist/infra/providers/provider-capabilities.d.ts.map +1 -1
  247. package/dist/infra/providers/provider-capabilities.js +16 -0
  248. package/dist/infra/providers/provider-capabilities.js.map +1 -1
  249. package/dist/infra/rate-limit/detection.d.ts +2 -0
  250. package/dist/infra/rate-limit/detection.d.ts.map +1 -1
  251. package/dist/infra/rate-limit/detection.js +14 -1
  252. package/dist/infra/rate-limit/detection.js.map +1 -1
  253. package/dist/infra/task/clone-base-branch.d.ts +11 -0
  254. package/dist/infra/task/clone-base-branch.d.ts.map +1 -1
  255. package/dist/infra/task/clone-base-branch.js +34 -4
  256. package/dist/infra/task/clone-base-branch.js.map +1 -1
  257. package/dist/infra/task/clone.d.ts +1 -1
  258. package/dist/infra/task/clone.d.ts.map +1 -1
  259. package/dist/infra/task/clone.js +1 -1
  260. package/dist/infra/task/clone.js.map +1 -1
  261. package/dist/infra/task/index.d.ts +1 -1
  262. package/dist/infra/task/index.d.ts.map +1 -1
  263. package/dist/infra/task/index.js +1 -1
  264. package/dist/infra/task/index.js.map +1 -1
  265. package/dist/infra/workflow/system/system-enqueue-effect.d.ts +2 -2
  266. package/dist/infra/workflow/system/system-enqueue-effect.d.ts.map +1 -1
  267. package/dist/infra/workflow/system/system-enqueue-effect.js +5 -2
  268. package/dist/infra/workflow/system/system-enqueue-effect.js.map +1 -1
  269. package/dist/shared/constants.d.ts +1 -0
  270. package/dist/shared/constants.d.ts.map +1 -1
  271. package/dist/shared/constants.js +1 -0
  272. package/dist/shared/constants.js.map +1 -1
  273. package/dist/shared/i18n/labels_en.yaml +3 -1
  274. package/dist/shared/i18n/labels_ja.yaml +3 -1
  275. package/dist/shared/types/provider.d.ts +1 -1
  276. package/dist/shared/types/provider.d.ts.map +1 -1
  277. package/dist/shared/utils/debug.d.ts +2 -0
  278. package/dist/shared/utils/debug.d.ts.map +1 -1
  279. package/dist/shared/utils/debug.js +1 -0
  280. package/dist/shared/utils/debug.js.map +1 -1
  281. package/package.json +4 -2
package/README.md CHANGED
@@ -2,35 +2,53 @@
2
2
 
3
3
  🇯🇵 [日本語ドキュメント](./docs/README.ja.md) | 💬 [Discord Community](https://discord.gg/R2Xz3uYWxD)
4
4
 
5
- **T**AKT **A**gent **K**oordination **T**opology — Give your AI coding agents structured review loops, managed prompts, and guardrails — so they deliver quality code, not just code.
5
+ **T**AKT **A**gent **K**oordination **T**opology — Orchestrate multiple AI agents with structured review loops, managed prompts, and guardrails.
6
6
 
7
- TAKT runs AI agents (Claude Code, Codex, OpenCode, Cursor, GitHub Copilot CLI) through YAML-defined workflows with built-in review cycles. You talk to AI to define what you want, queue tasks, and let TAKT handle the execution planning, implementation, multi-stage review, and fix loops all governed by declarative workflow files.
7
+ Talk to AI to define what you want, queue it as a task, and run it with `takt run`. Planning, implementation, review, and fix loops are defined in YAML workflow files, so the process is not left to the agent's discretion. TAKT coordinates Claude Code, Codex, OpenCode, Cursor, and GitHub Copilot CLI as agents with different roles, permissions, and context.
8
+
9
+ TAKT is built primarily for AI coding workflows, but the same model applies beyond coding: any task where multiple AI agents need to coordinate, or where review, judgment, and feedback loops can improve task quality.
8
10
 
9
11
  TAKT is built with TAKT itself (dogfooding).
10
12
 
11
13
  ## Why TAKT
12
14
 
13
- **Batteries included** Architecture, security, and AI antipattern review criteria are built in. Ship code that meets a quality bar from day one.
15
+ AI coding agents are powerful, but they do not automatically create a stable development process. In long-running work, they forget instructions, accumulate polluted context, blur implementation and review responsibilities, and often force humans to repeat the same feedback again and again. That wears people down.
16
+
17
+ Adding more rules to prompts, `CLAUDE.md`, or skills can help, but it cannot enforce the process. Whether the rules are followed is still left to the agent's behavior.
18
+
19
+ TAKT treats AI agents as something to be controlled from the outside, not simply trusted.
14
20
 
15
- **Practical** A tool for daily development, not demos. Talk to AI to refine requirements, queue tasks, and run them. Worktree isolation on task execution, PR creation, and retry on failure.
21
+ Workflows define the phases, and each step receives its own persona, policy, knowledge, instruction, and output contract. TAKT manages implementation, review, fix, and re-review flows declaratively. By separating responsibilities, knowledge, and constraints, then giving each agent only what it needs for the current step, TAKT improves task quality without bloating context.
16
22
 
17
- **Reproducible** Execution paths are declared in YAML, keeping results consistent. Workflows are shareable a workflow built by one team member can be used by anyone else to run the same quality process. Every step is logged in NDJSON for full traceability from task to PR.
23
+ Reviews cannot be silently skipped. Findings route work back to fix steps, and human judgment can be requested when needed. Tasks run in isolated worktrees, and each step leaves logs and reports so the path from task to PR remains traceable.
18
24
 
19
- **Multi-agent** Orchestrate multiple agents with different personas, permissions, and review criteria. Run parallel reviewers, route failures back to implementers, aggregate results with declarative rules. Prompts are managed as independent facets (persona, policy, knowledge, instruction) that compose freely across workflows ([Faceted Prompting](./docs/faceted-prompting.md)).
25
+ At its core, TAKT runs reusable agent processes built from roles, phases, judgments, and feedback loops.
26
+
27
+ The goal is simple: make development processes reusable, reviewable, and reproducible without depending on constant human intervention.
20
28
 
21
29
  ## Requirements
22
30
 
23
- Choose one:
31
+ The provider you choose determines whether you need to install an external CLI or can run on Node.js alone via a TypeScript SDK.
32
+
33
+ These providers run via SDK (no CLI required, Node.js only):
34
+
35
+ - `claude-sdk` — `@anthropic-ai/claude-agent-sdk`
36
+ - `codex` — `@openai/codex-sdk`
37
+ - `opencode` — `@opencode-ai/sdk`
24
38
 
25
- - **Provider CLIs**: [Claude Code](https://claude.ai/code) (default `claude` provider), [Codex](https://github.com/openai/codex), [OpenCode](https://opencode.ai), [Cursor Agent](https://docs.cursor.com/), or [GitHub Copilot CLI](https://docs.github.com/en/copilot/github-copilot-in-the-cli) installed
26
- - **Direct API**: OpenAI / OpenCode API Key (no CLI required)
39
+ These providers require an external CLI:
40
+
41
+ - `claude` — [Claude Code](https://claude.ai/code)
42
+ - `claude-terminal` — [Claude Code](https://claude.ai/code) driven in an interactive terminal session (also requires [`tmux`](https://github.com/tmux/tmux))
43
+ - `copilot` — [GitHub Copilot CLI](https://docs.github.com/en/copilot/github-copilot-in-the-cli)
44
+ - `cursor` — [Cursor Agent](https://docs.cursor.com/)
27
45
 
28
46
  Optional:
29
47
 
30
48
  - [GitHub CLI](https://cli.github.com/) (`gh`) — for `takt #N` (GitHub Issue tasks)
31
49
  - [GitLab CLI](https://gitlab.com/gitlab-org/cli) (`glab`) — for GitLab Issue/MR integration (auto-detected from remote URL)
32
50
 
33
- > **OAuth and API key usage:** Whether OAuth or API key access is permitted varies by provider and use case. Check each provider's terms of service before using TAKT.
51
+ > **OAuth usage:** Whether OAuth is permitted varies by provider and use case. Check each provider's terms of service before using TAKT.
34
52
 
35
53
  ## Quick Start
36
54
 
@@ -92,7 +110,7 @@ takt list
92
110
 
93
111
  ## How It Works
94
112
 
95
- TAKT uses a music metaphor — the name itself comes from the German word for "beat" or "baton stroke," used in conducting to keep an orchestra in time. TAKT uses **workflow** and **step** consistently in both user-facing and implementation-facing terminology.
113
+ The name TAKT comes from the German word for "beat" or "baton stroke," used in conducting to keep an orchestra in time. TAKT uses **workflow** and **step** consistently in both user-facing and implementation-facing terminology.
96
114
 
97
115
  A workflow is defined by a sequence of steps. Use `steps`, `initial_step`, and `max_steps`. Each step specifies a persona (who), permissions (what's allowed), and rules (what happens next). Here's a minimal example:
98
116
 
@@ -137,10 +155,12 @@ When the same workflow name exists in multiple locations, TAKT resolves in this
137
155
 
138
156
  | Workflow | Use Case |
139
157
  |-------|----------|
140
- | `default` | Standard development. Test-first with AI antipattern review and parallel review (architecture + supervisor). |
141
- | `frontend-mini` | Frontend-focused mini configuration. |
142
- | `backend-mini` | Backend-focused mini configuration. |
143
- | `dual-mini` | Frontend + backend mini configuration. |
158
+ | `default` | Standard development workflow. Test-first with AI antipattern review and parallel review (architecture + supervisor). |
159
+ | `frontend` | Frontend development workflow. |
160
+ | `backend` | Backend development workflow. |
161
+ | `dual` | Combined frontend + backend workflow. |
162
+ | `takt-default` | The workflow used to develop TAKT itself. Directly applicable to other CLI tool development. |
163
+ | `*-mini` series | Lightweight variants of each workflow (`default-mini` / `frontend-mini` / `backend-mini` / `dual-mini`). Omits `write_tests`. |
144
164
 
145
165
  See the [Builtin Catalog](./docs/builtin-catalog.md) for all workflows and personas.
146
166
 
@@ -164,7 +184,7 @@ See the [CLI Reference](./docs/cli-reference.md) for all commands and options.
164
184
  Minimal `~/.takt/config.yaml`:
165
185
 
166
186
  ```yaml
167
- provider: claude # claude, claude-sdk, codex, opencode, cursor, or copilot
187
+ provider: claude # claude, claude-sdk, claude-terminal, codex, opencode, cursor, or copilot
168
188
  model: sonnet # passed directly to provider
169
189
  language: en # en or ja
170
190
  ```
@@ -202,7 +222,7 @@ You are a code reviewer specialized in security.
202
222
 
203
223
  Reference it in your workflow: `persona: my-reviewer`
204
224
 
205
- See the [Workflow Guide](./docs/workflows.md) and [Agent Guide](./docs/agents.md) for details.
225
+ See the [Workflow Guide](./docs/workflows.md) for details. The list of builtin personas is in the [Builtin Catalog](./docs/builtin-catalog.md).
206
226
 
207
227
  ## CI/CD
208
228
 
@@ -243,35 +263,45 @@ See the [CI/CD Guide](./docs/ci-cd.md) for full setup instructions.
243
263
 
244
264
  Workflow definitions are stored under `workflows/`.
245
265
 
246
- ## API Usage
266
+ ## Adopting Spec-Driven Development
247
267
 
248
- ```typescript
249
- import { WorkflowEngine, loadWorkflow } from 'takt';
268
+ TAKT enforces phase transitions declaratively as a YAML state machine, formalizes the artifact of each phase with output contracts, and routes deviations back via parallel review and fix loops. This structure is particularly well-suited for users who follow Spec-Driven Development (SDD) and keep the spec at the center of the process. Once the spec is well-defined, the AI cannot silently skip a phase, drop an acceptance criterion, or claim "done" without passing the verification gate.
250
269
 
251
- const config = loadWorkflow('default', process.cwd());
252
- if (!config) throw new Error('Workflow not found');
270
+ For users who want to adopt SDD, the community provides [j5ik2o/takt-sdd](https://github.com/j5ik2o/takt-sdd) as a ready-made implementation. It ships pieces for Requirements → Gap Analysis → Design → Tasks → Implementation → Validation, plus an OpenSpec-style change-proposal flow. Install in one command:
253
271
 
254
- const engine = new WorkflowEngine(config, process.cwd(), 'My task');
255
- await engine.run();
272
+ ```bash
273
+ npx create-takt-sdd
256
274
  ```
257
275
 
276
+ See [External Integrations](./docs/external-integrations.md) for other community integrations.
277
+
258
278
  ## Documentation
259
279
 
260
280
  | Document | Description |
261
281
  |----------|-------------|
262
282
  | [CLI Reference](./docs/cli-reference.md) | All commands and options |
263
283
  | [Configuration](./docs/configuration.md) | Global and project settings |
284
+ | [Design Philosophy](./docs/design-philosophy.md) | Why TAKT is built around workflows, facets, feedback loops, and traceability |
264
285
  | [Workflow Guide](./docs/workflows.md) | Creating and customizing workflows |
265
- | [Agent Guide](./docs/agents.md) | Custom agent configuration |
266
286
  | [Builtin Catalog](./docs/builtin-catalog.md) | All builtin workflows and personas |
267
287
  | [Faceted Prompting](./docs/faceted-prompting.md) | Prompt design methodology |
268
288
  | [Repertoire Packages](./docs/repertoire.md) | Installing and sharing packages |
269
289
  | [Task Management](./docs/task-management.md) | Task queuing, execution, isolation |
270
- | [Data Flow](./docs/data-flow.md) | Internal data flow and architecture diagrams |
271
290
  | [CI/CD Integration](./docs/ci-cd.md) | GitHub Actions and pipeline mode |
272
- | [Provider Sandbox & Permissions](./docs/provider-sandbox.md) | Sandbox, permission modes, and network access for Codex / OpenCode / Claude |
291
+ | [External Integrations](./docs/external-integrations.md) | Community examples that extend TAKT without modifying core (audit trails, etc.) |
273
292
  | [Changelog](./CHANGELOG.md) ([日本語](./docs/CHANGELOG.ja.md)) | Version history |
274
- | [Security Policy](./SECURITY.md) | Vulnerability reporting |
293
+
294
+ ## Sponsors
295
+
296
+ TAKT is supported by [CodeRabbit](https://coderabbit.link/nrslib) through its Open Source Support Program.
297
+
298
+ <a href="https://coderabbit.link/nrslib">
299
+ <picture>
300
+ <source media="(prefers-color-scheme: dark)" srcset="https://victorious-bubble-f69a016683.media.strapiapp.com/White_Typemark_79b9189d19.svg">
301
+ <source media="(prefers-color-scheme: light)" srcset="https://victorious-bubble-f69a016683.media.strapiapp.com/Orange_Typemark_43bf516c9d.svg">
302
+ <img alt="CodeRabbit" src="https://victorious-bubble-f69a016683.media.strapiapp.com/Orange_Typemark_43bf516c9d.svg" height="40">
303
+ </picture>
304
+ </a>
275
305
 
276
306
  ## Community
277
307
 
@@ -24,6 +24,11 @@ Refer only to files within the Report Directory shown in the Workflow Context. D
24
24
  - Include tests that would catch implementations that incorrectly reuse a response envelope when reading requests
25
25
  - Write tests that are expected to pass after implementation is complete (build errors and test failures are expected at this stage)
26
26
 
27
+ **Non-executable asset constraints:**
28
+ - Do not create tests that freeze prose, headings, or structure in explanations, guides, README files, or Markdown documentation
29
+ - For docs-only changes, do not add tests unless an explicit executable contract exists
30
+ - Tests are only needed when assets contain contracts tied to code behavior or machine processing, such as CLI examples, config examples, or generated artifacts
31
+
27
32
  **Test execution:**
28
33
  - Run tests after creating them to check results
29
34
  - Test failures and import errors are expected before implementation (including imports of not-yet-implemented modules)
@@ -374,14 +374,14 @@ Don't overlook compromises made to "just make it work."
374
374
  | Swallowed errors | Empty `catch {}`, `rescue nil` |
375
375
  | Magic numbers | Unexplained `if (status == 3)` |
376
376
 
377
- ## Strict TODO Comment Prohibition
377
+ ## Unfinished Code Detection
378
378
 
379
- "We'll do it later" never gets done. What's not done now is never done.
379
+ Unfinished-code judgment follows the coding policy. In architecture review, check whether TODO/FIXME comments, empty implementations, or stubs are being used as substitutes for required boundaries, authorization, validation, or contract updates.
380
380
 
381
- TODO comments are immediate REJECT.
381
+ TODO/FIXME without an issue number, external blocker, and removal condition is REJECT.
382
382
 
383
383
  ```kotlin
384
- // REJECT - Future-looking TODO
384
+ // REJECT - Authorization check deferred with TODO
385
385
  // TODO: Add authorization check by facility ID
386
386
  fun deleteCustomHoliday(@PathVariable id: String) {
387
387
  deleteCustomHolidayInputPort.execute(input)
@@ -398,12 +398,12 @@ fun deleteCustomHoliday(@PathVariable id: String) {
398
398
  }
399
399
  ```
400
400
 
401
- Only acceptable TODO cases:
401
+ Acceptable TODO/FIXME cases:
402
402
 
403
403
  | Condition | Example | Judgment |
404
404
  |-----------|---------|----------|
405
- | External dependency prevents implementation + Issued | `// TODO(#123): Implement after API key obtained` | Acceptable |
406
- | Technical constraint prevents + Issued | `// TODO(#456): Waiting for library bug fix` | Acceptable |
405
+ | External dependency prevents implementation + issue exists + removal condition documented | `// TODO(#123): Implement after API key obtained` | Acceptable |
406
+ | Technical constraint prevents implementation + issue exists + removal condition documented | `// TODO(#456): Waiting for library bug fix` | Acceptable |
407
407
  | "Future implementation", "add later" | `// TODO: Add validation` | REJECT |
408
408
  | "No time for now" | `// TODO: Refactor` | REJECT |
409
409
 
@@ -429,7 +429,7 @@ When NOT to apply DRY:
429
429
 
430
430
  ## Spec Compliance Verification
431
431
 
432
- Verify that changes comply with the project's documented specifications.
432
+ Contract-change consistency follows the coding policy. In architecture review, check whether changes contradict documented specifications, types, schemas, or config formats.
433
433
 
434
434
  Verification targets:
435
435
 
@@ -460,10 +460,10 @@ REJECT when these patterns are found:
460
460
 
461
461
  ## Call Chain Verification
462
462
 
463
- When new parameters/fields are added, verify not just the changed file but also callers.
463
+ Missing wiring after contract changes follows the coding policy. In architecture review, check whether new parameters or fields actually reach callers, producers, and readers instead of staying local to the changed file.
464
464
 
465
465
  Verification steps:
466
- 1. When finding new optional parameters or interface fields, `Grep` all callers
466
+ 1. When finding new optional parameters or interface fields, search all callers
467
467
  2. Check if all callers pass the new parameter
468
468
  3. If fallback value (`?? default`) exists, verify if fallback is used as intended
469
469
 
@@ -471,7 +471,7 @@ Danger patterns:
471
471
 
472
472
  | Pattern | Problem | Detection |
473
473
  |---------|---------|-----------|
474
- | `options.xxx ?? fallback` where all callers omit `xxx` | Feature implemented but always falls back | grep callers |
474
+ | `options.xxx ?? fallback` where all callers omit `xxx` | Feature implemented but always falls back | Check callers |
475
475
  | Tests set values directly with mocks | Don't go through actual call chain | Check test construction |
476
476
  | `executeXxx()` doesn't receive `options` it uses internally | No route to pass value from above | Check function signature |
477
477
 
@@ -493,12 +493,12 @@ Call chain verification applies not only to "missing wiring" but also to the rev
493
493
 
494
494
  | Pattern | Problem | Detection |
495
495
  |---------|---------|-----------|
496
- | TTY check when all callers require TTY | Unreachable branch remains | grep all callers' preconditions |
496
+ | TTY check when all callers require TTY | Unreachable branch remains | Check all callers' preconditions |
497
497
  | Null guard when callers already check null | Redundant defense | Trace caller constraints |
498
498
  | Runtime type check when TypeScript types constrain | Not trusting type safety | Check TypeScript type constraints |
499
499
 
500
500
  Verification steps:
501
- 1. When finding defensive branches (TTY check, null guard, etc.), grep all callers
501
+ 1. When finding defensive branches (TTY check, null guard, etc.), check all callers
502
502
  2. If all callers already guarantee the condition, guard is unnecessary → REJECT
503
503
  3. If some callers don't guarantee it, keep the guard
504
504
 
@@ -84,6 +84,54 @@ Event Granularity:
84
84
  - Appropriate: `ShippingAddressChanged` → Intent is clear
85
85
  - Too coarse: `OrderModified` → What changed is unclear
86
86
 
87
+ ## Event Evolution
88
+
89
+ Events are persisted contracts. When the current event type changes, old events must still be replayable. Translation of old events belongs in the upcaster / migration layer at the event-store boundary, not in the event type itself or in domain logic.
90
+
91
+ | Criteria | Judgment |
92
+ |----------|----------|
93
+ | Persisted event type or fields changed with no translation path | REJECT |
94
+ | Current event type keeps aliases or compatibility-only properties for old field names | REJECT. Keep history compatibility in upcasters |
95
+ | Aggregate or apply directly interprets old event shapes | REJECT. Convert to current events before replay |
96
+ | Event carries "previous value" only for compatibility | REJECT. Events represent the fact after it happened |
97
+ | Upcaster converts old payloads to the current event meaning | OK |
98
+ | Tests verify old payloads deserialize into current events through the upcaster | OK |
99
+
100
+ Responsibility split for event evolution:
101
+
102
+ | Responsibility | Place |
103
+ |----------------|-------|
104
+ | Current event meaning and fields | Event type |
105
+ | Translation of old payloads | Upcaster / migration layer |
106
+ | State restoration by event replay | Aggregate `apply` |
107
+ | Guarantee that old events can become current events | Upcaster tests |
108
+
109
+ ```kotlin
110
+ // NG - mixing old-field compatibility into the current event type
111
+ data class OrderAssignedEvent(
112
+ val orderId: String,
113
+ @JsonAlias("assigneeId")
114
+ val assigneeIds: List<String>
115
+ )
116
+
117
+ // OK - current event type represents only the current contract
118
+ data class OrderAssignedEvent(
119
+ val orderId: String,
120
+ val assigneeIds: List<String>
121
+ )
122
+ ```
123
+
124
+ ```kotlin
125
+ // OK - convert old payloads to current payloads in the upcaster
126
+ when (eventType) {
127
+ OrderAssignedEvent::class.java.typeName -> {
128
+ event.moveTextFieldToArray("assigneeId", "assigneeIds")
129
+ }
130
+ }
131
+ ```
132
+
133
+ Whether to keep old event classes depends on the framework and operations policy. In general, do not treat old classes as normal domain events; treat old serialized type names and payloads as the upcaster input contract and cover them with tests.
134
+
87
135
  ## Command Handlers
88
136
 
89
137
  | Criteria | Judgment |
@@ -117,6 +117,19 @@ Exception (OK for child to have local state):
117
117
  | Inappropriate useEffect dependencies | REJECT |
118
118
  | Initial load tied to unstable Context/Provider function references | REJECT |
119
119
 
120
+ ### Canonical and Derived State
121
+
122
+ State should hold canonical values such as user input, server data, and temporary UI state. Display values, aggregates, selection states, sorted results, and grouped results that can be computed from canonical state are derived values and must not be kept as independent state.
123
+
124
+ | Criteria | Judgment |
125
+ |----------|----------|
126
+ | A value that can always be computed from one state is kept as another state | REJECT |
127
+ | Multiple state fields have invariants that require constant synchronization | REJECT |
128
+ | Display labels, counts, totals, all-selected flags, sorted results, or grouped results are kept as canonical state | REJECT |
129
+ | API sending, persistence, or diffing depends on derived state instead of canonical state | REJECT |
130
+ | Only canonical state is stored, and display, aggregation, and decisions are derived via selectors, render logic, or useMemo | OK |
131
+ | Derived values required by external contracts are generated from canonical state at send or persistence boundaries | OK |
132
+
120
133
  State Placement Guidelines:
121
134
 
122
135
  | State Nature | Recommended Placement |
@@ -11,6 +11,7 @@
11
11
  |--------|--------|-------|
12
12
  | Component design | ✅ | - |
13
13
  | State management | ✅ | - |
14
+ | Canonical and derived state | ✅ | - |
14
15
  | Performance | ✅ | - |
15
16
  | Accessibility | ✅ | - |
16
17
  | Type safety | ✅ | - |
@@ -153,6 +153,25 @@ Legacy support criteria:
153
153
  - Do not add `.transform()` normalization, `LEGACY_*_MAP` mappings, or `@deprecated` type definitions
154
154
  - Support only new values and keep it simple
155
155
 
156
+ ### Over-Abstracting with Function Objects
157
+
158
+ AI often turns a small number of concrete branches into config arrays, function objects, and generic loops to make the code look "extensible". The problem is not Strategy itself; the problem is hiding differences in data without naming the concept. A Strategy is useful when it names a domain concept and makes the replacement boundary explicit.
159
+
160
+ | Pattern | Example | Verdict |
161
+ |---------|---------|---------|
162
+ | Single-use operation config array | Processing `[{ kind, fields, removedFields }]` in a loop | REJECT |
163
+ | Deletions, side effects, or exception cases are hidden in config objects | Readers must inspect config values to find destructive behavior | REJECT |
164
+ | Function object introduced when each branch is only 1-3 lines | `handlers[type]()` adds indirection only | REJECT |
165
+ | Strategy represents a domain concept and clarifies the implementation boundary | `TaxPolicy`, `PaymentMethod`, `RetryStrategy` | OK |
166
+ | Many branches share the same shape and are expected to grow | Consider a handler map | OK |
167
+
168
+ Verification approach:
169
+ 1. Grep usage sites for added arrays, Maps, Strategies, or function objects
170
+ 2. If used in only one place, check whether explicit branching would be clearer
171
+ 3. Check whether side effects, deleted fields, or compatibility behavior are hidden in config objects
172
+ 4. Prefer `when` / `switch` when branch names sufficiently express domain meaning
173
+ 5. Allow Strategy when naming the concept improves understanding
174
+
156
175
  ## Premature Caching Strategy Introduction
157
176
 
158
177
  AI tends to proactively introduce caching mechanisms to "improve" performance. Do not add caching strategies until explicitly requested.
@@ -14,6 +14,7 @@ Prioritize correctness over speed, and code accuracy over ease of implementation
14
14
  | Boy Scout | Leave touched areas a little better than you found them |
15
15
  | Fail Fast | Detect errors early. Never swallow them |
16
16
  | Project scripts first | Use project-defined scripts for tool execution. Direct invocation is a last resort |
17
+ | State normalization | Do not keep the same fact in multiple states |
17
18
 
18
19
  ## No Fallbacks or Default Arguments
19
20
 
@@ -183,6 +184,41 @@ const handlers = { A: handleA, B: handleB, C: handleC };
183
184
  handlers[type]?.();
184
185
  ```
185
186
 
187
+ ### Do Not Over-Abstract
188
+
189
+ Use abstraction to reduce duplication and real axes of change, and also to name concepts so the code is easier to understand. Turning a few concrete operations into "config objects + function objects + loops" is not abstraction if it only makes domain differences harder to read.
190
+
191
+ | Criteria | Judgment |
192
+ |----------|----------|
193
+ | A small number of branches differs by event type, state, or domain concept | Use explicit `when` / `switch` |
194
+ | The same operation with the same argument shape repeats in 3+ places | Consider abstraction |
195
+ | A config array or function object is used in only one place | REJECT. Prefer explicit branching first |
196
+ | Side effects or removed fields cannot be understood without reading config objects | REJECT |
197
+ | Strategy names a domain concept and makes interchangeable implementations explicit | OK |
198
+ | Branch names read as domain concepts | OK |
199
+
200
+ ```typescript
201
+ // ❌ Over-abstracted - readers must inspect both the config array and loop to see behavior
202
+ const operations = [
203
+ { kind: 'create', normalize: ['owner'], remove: [] },
204
+ { kind: 'revise', normalize: ['owner'], remove: ['legacyOwner'] },
205
+ ]
206
+ for (const operation of operations) {
207
+ applyOperation(record, operation)
208
+ }
209
+
210
+ // ✅ When branch meaning matters, make it explicit
211
+ switch (record.kind) {
212
+ case 'create':
213
+ normalizeOwner(record)
214
+ break
215
+ case 'revise':
216
+ removeLegacyOwner(record)
217
+ normalizeOwner(record)
218
+ break
219
+ }
220
+ ```
221
+
186
222
  ### Keep Abstraction Levels Consistent
187
223
 
188
224
  Within a single function, keep operations at the same granularity. Extract detailed operations into separate functions. Do not mix "what to do" with "how to do it."
@@ -319,11 +355,56 @@ Dependencies and triggers must match the conditions under which the behavior sho
319
355
  | Rerun conditions correspond to URL, filters, explicit refresh actions, or other intended behavior | OK |
320
356
  | Initialization and later refetch triggers are designed separately | OK |
321
357
 
358
+ ## Contract Change Consistency
359
+
360
+ When changing contracts that other code or users depend on — types, interfaces, APIs, config schemas, persistence formats, events, or file formats — keep definitions, producers, consumers, and verification aligned in the same change.
361
+
362
+ | Criteria | Judgment |
363
+ |----------|----------|
364
+ | Only the contract definition is changed, while callers, producers, or readers are not updated | REJECT |
365
+ | A new argument, field, or config value is added but there is no route to pass it to consumers | REJECT |
366
+ | Fields or values not present in the documented schema/config format are used | REJECT |
367
+ | Mocks, fixtures, or test data return shapes that differ from the real contract | REJECT |
368
+ | The contract change and updates to callers, producers, and tests are made in the same change | OK |
369
+
322
370
  ## State Management
323
371
 
324
372
  - Confine state to where it is used
325
373
  - Children do not modify state directly (notify parents via events)
326
374
  - State flow is unidirectional
375
+ - Do not keep derived values that can be computed from canonical state as independent state
376
+ - If multiple fields require constant synchronization, revisit the state model
377
+
378
+ | Criteria | Judgment |
379
+ |----------|----------|
380
+ | A value that can always be computed from one state is kept as another state | REJECT |
381
+ | Multiple states have invariants that must always stay in sync | REJECT |
382
+ | Persistence, sending, or diffing depends on derived values | REJECT |
383
+ | Only canonical state is stored, and derived values are generated at use sites or boundaries | OK |
384
+
385
+ ## Unfinished Code
386
+
387
+ Do not leave TODO/FIXME comments, empty implementations, stubs, or commented-out old implementations as substitutes for completed code. Implement what is needed now and delete what is not needed.
388
+
389
+ | Criteria | Judgment |
390
+ |----------|----------|
391
+ | TODO/FIXME without an issue number, external blocker, and removal condition | REJECT |
392
+ | Authorization, validation, persistence, or error handling is deferred with TODO | REJECT |
393
+ | Empty implementations, `return null`, `pass`, or commented-out old implementations remain | REJECT |
394
+ | An external dependency or known blocker makes implementation impossible now, with issue number and removal condition documented | Acceptable |
395
+ | TODO only for future extension | REJECT |
396
+
397
+ ## Sensitive Information Handling
398
+
399
+ Do not expose passwords, tokens, API keys, session IDs, auth headers, personal information, or other sensitive data in code, logs, error responses, or test output.
400
+
401
+ | Criteria | Judgment |
402
+ |----------|----------|
403
+ | Sensitive data is hardcoded in source code or config files | REJECT |
404
+ | Logs, exceptions, error responses, or test snapshots contain sensitive data | REJECT |
405
+ | Whole requests or DTOs are logged and may include sensitive fields | REJECT |
406
+ | Sensitive fields are explicitly omitted or masked | OK |
407
+ | Debug logs include personal data but are assumed disabled in production | Warning. Verify it cannot leak through misconfiguration |
327
408
 
328
409
  ## Error Handling
329
410
 
@@ -486,10 +567,11 @@ Verification approach:
486
567
  - **Fallbacks are prohibited by default** - Do not write fallbacks using `?? 'unknown'`, `|| 'default'`, or swallowing via `try-catch`. Propagate errors upward. If absolutely necessary, add a comment explaining why
487
568
  - **Explanatory comments** - Express intent through code. Do not write What/How comments
488
569
  - **Unused code** - Do not write "just in case" code
570
+ - **Unfinished code** - Do not leave TODO/FIXME without an issue number, external blocker, and removal condition; do not leave stubs or commented-out old code
489
571
  - **any type** - Do not break type safety
490
572
  - **Direct mutation of objects/arrays** - Create new instances with spread operators
491
573
  - **console.log** - Do not leave in production code
492
- - **Hardcoded secrets**
574
+ - **Sensitive information exposure** - Do not include sensitive data in hardcoded values, logs, error responses, or test output
493
575
  - **Scattered hardcoded contract strings** - File names and config key names must be defined as constants in one place. Scattered literals are prohibited
494
576
  - **Scattered try-catch** - Centralize error handling at the upper layer
495
577
  - **Unsolicited backward compatibility / legacy support** - Not needed unless explicitly instructed
@@ -497,6 +579,6 @@ Verification approach:
497
579
  - **Replaced code surviving after refactoring** - Remove replaced code and exports. Do not keep unless explicitly told to
498
580
  - **Workarounds that bypass safety mechanisms** - If the root fix is correct, no additional bypass is needed
499
581
  - **Direct tool execution bypassing project scripts** - `npx tool` and similar bypass the lockfile, causing version mismatches. Look for project-defined scripts (npm scripts, Makefile, etc.) first. Only consider direct execution when no script exists
500
- - **Missing wiring** - When adding new parameters or fields, grep the entire call chain to verify. If callers do not pass the value, `options.xxx ?? fallback` always uses the fallback
582
+ - **Missing wiring** - When adding new parameters or fields, search the entire call chain to verify. If callers do not pass the value, `options.xxx ?? fallback` always uses the fallback
501
583
  - **Redundant conditionals** - When if/else calls the same function with only argument differences, unify using ternary operators or spread syntax
502
- - **Copy-paste patterns** - Before writing new code, grep for existing implementations of the same kind and follow the existing pattern. Do not introduce your own style
584
+ - **Copy-paste patterns** - Before writing new code, search for existing implementations of the same kind and follow the existing pattern. Do not introduce your own style
@@ -22,7 +22,9 @@
22
22
 
23
23
  | Pattern | Verdict |
24
24
  |---------|---------|
25
- | Abandoned TODO/FIXME | Warning |
25
+ | TODO/FIXME without an issue number, external blocker, and removal condition | REJECT |
26
+ | TODO/FIXME with issue number, external blocker, and removal condition | Warning |
27
+ | Empty implementations, stubs, or commented-out old implementations left behind | REJECT |
26
28
  | @ts-ignore, @ts-expect-error without reason | Warning |
27
29
  | eslint-disable without reason | Warning |
28
30
  | Usage of deprecated APIs | Warning |
@@ -37,13 +37,15 @@ REJECT without exception if any of the following apply.
37
37
  - Unused code ("just in case" code)
38
38
  - Direct mutation of objects/arrays
39
39
  - Swallowed errors (empty catch blocks)
40
- - TODO comments (not tracked in an issue)
40
+ - TODO/FIXME without an issue number, external blocker, and removal condition
41
41
  - Essentially identical logic duplicated (DRY violation)
42
42
  - Method proliferation doing the same thing (should be absorbed by configuration differences)
43
43
  - Specific implementation leaking into generic layers (imports and branching for specific implementations in generic layers)
44
44
  - Internal implementation exported from public API (infrastructure functions or internal classes exposed publicly)
45
45
  - Replaced code/exports surviving after refactoring
46
46
  - Missing cross-validation of related fields (invariants of semantically coupled config values left unverified)
47
+ - Missing caller, producer, or test data updates after a contract change
48
+ - Sensitive data exposed in logs, error responses, or test output
47
49
 
48
50
  A DRY finding is not complete unless the proposed consolidation target is also sound. A consolidation proposal is invalid unless all of the following hold.
49
51
 
@@ -59,7 +61,7 @@ Not blocking, but improvement is recommended.
59
61
  - Tests coupled to implementation details
60
62
  - Overly complex functions/files
61
63
  - Unclear naming
62
- - Abandoned TODO/FIXME (those with issue numbers are acceptable)
64
+ - TODO/FIXME with issue number, external blocker, and removal condition
63
65
  - `@ts-ignore` or `eslint-disable` without justification
64
66
 
65
67
  ### APPROVE
@@ -73,7 +75,7 @@ Always verify facts before raising an issue.
73
75
  | Do | Do Not |
74
76
  |----|--------|
75
77
  | Open the file and check actual code | Assume "it should be fixed already" |
76
- | Search for call sites and usages with grep | Raise issues based on memory |
78
+ | Search for call sites and usages | Raise issues based on memory |
77
79
  | Cross-reference type definitions and schemas | Guess that code is dead |
78
80
  | Distinguish generated files (reports, etc.) from source | Review generated files as if they were source code |
79
81
  | Verify tool output is readable and uncorrupted | Raise issues based on garbled or abnormal output |
@@ -12,6 +12,7 @@ Every behavior change requires a corresponding test, and every bug fix requires
12
12
  | Independence | Do not depend on other tests or execution order |
13
13
  | Type safety | Code must pass the build (type check) |
14
14
  | Reproducibility | Do not depend on time or randomness. Same result every run |
15
+ | Do not freeze non-executable assets | Do not make prose or section structure that does not define runtime behavior a CI failure condition |
15
16
 
16
17
  ## Coverage Criteria
17
18
 
@@ -33,6 +34,23 @@ Every behavior change requires a corresponding test, and every bug fix requires
33
34
 
34
35
  **Note:** When a design reference is provided, UI appearance verification is elevated to medium priority. Refer to the Design Fidelity Policy.
35
36
 
37
+ ## Non-Executable Asset Tests
38
+
39
+ Tests that freeze prose, headings, or structure in non-executable assets such as explanations, guides, README files, or Markdown documentation are prohibited by default.
40
+ These assets change often during wording improvements and reorganization, so making prose diffs fail CI creates high maintenance cost.
41
+
42
+ | Criteria | Verdict |
43
+ |----------|---------|
44
+ | Exact prose, heading, or section-structure assertions for non-executable assets | REJECT |
45
+ | Scanning all non-executable assets only to enforce wording or terminology | REJECT |
46
+ | Tests that require explanatory files that may be deleted or consolidated | REJECT |
47
+ | Adding tests for docs-only changes when no executable contract exists | REJECT |
48
+ | Validating executable or machine-processed contracts such as CLI examples, config examples, or generated artifacts | OK |
49
+ | Contract tests for schemas, configuration, code, generators, or runtime behavior | OK |
50
+ | Not adding tests for docs-only changes that have no executable contract | OK |
51
+
52
+ Verify non-executable asset changes with review, Markdown lint, link checks, or sample command execution when needed.
53
+
36
54
  ## Test Structure: Given-When-Then
37
55
 
38
56
  ```typescript
@@ -57,6 +75,18 @@ test('should return NotFound error when user does not exist', async () => {
57
75
  | Clarity | Failure cause is obvious | Failure cause is unclear |
58
76
  | Focus | One test, one concept | Multiple concerns mixed |
59
77
 
78
+ ## Test Data and Fixtures
79
+
80
+ Test data should explicitly generate the minimum facts needed by each test. Mutating shared fixtures or using mocks that drift from real contracts reduces test reliability.
81
+
82
+ | Criteria | Verdict |
83
+ |----------|---------|
84
+ | Shared fixtures are mutated and reused across tests | REJECT |
85
+ | Mocks, fixtures, or factories return shapes that differ from real types or API contracts | REJECT |
86
+ | Each test hand-writes a huge full-field fixture | Warning. Consider a factory |
87
+ | Factories provide defaults and each test overrides only relevant fields | OK |
88
+ | Contract changes update fixtures, mocks, and snapshots in the same change | OK |
89
+
60
90
  ### Naming
61
91
 
62
92
  Test names describe expected behavior. Use the `should {expected behavior} when {condition}` pattern.
@@ -125,8 +155,11 @@ Verify data flow coupling that unit tests alone cannot cover.
125
155
 
126
156
  ## E2E Test Criteria
127
157
 
158
+ Design E2E tests from the entry points users actually use. Use code-level entry points such as routes, commands, endpoints, navigation, buttons, or external callbacks, not documentation assumptions alone.
159
+
128
160
  | Criteria | Verdict |
129
161
  |----------|---------|
162
+ | E2E tests are written for imagined flows without checking real entry points | REJECT |
130
163
  | Hitting production APIs without mocking external calls | REJECT. Test reproducibility is lost |
131
164
  | Mocking the core logic under test | REJECT. Defeats the purpose of E2E |
132
165
  | Using fixed sleep for timing synchronization | REJECT. Use state-based waits |