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.
- package/README.md +58 -28
- package/builtins/en/facets/instructions/write-tests-first.md +5 -0
- package/builtins/en/facets/knowledge/architecture.md +13 -13
- package/builtins/en/facets/knowledge/cqrs-es.md +48 -0
- package/builtins/en/facets/knowledge/frontend.md +13 -0
- package/builtins/en/facets/output-contracts/frontend-review.md +1 -0
- package/builtins/en/facets/policies/ai-antipattern.md +19 -0
- package/builtins/en/facets/policies/coding.md +85 -3
- package/builtins/en/facets/policies/qa.md +3 -1
- package/builtins/en/facets/policies/review.md +5 -3
- package/builtins/en/facets/policies/testing.md +33 -0
- package/builtins/en/workflows/auto-improvement-loop.yaml +20 -4
- package/builtins/ja/facets/instructions/write-tests-first.md +5 -0
- package/builtins/ja/facets/knowledge/architecture.md +13 -13
- package/builtins/ja/facets/knowledge/cqrs-es.md +48 -0
- package/builtins/ja/facets/knowledge/frontend.md +13 -0
- package/builtins/ja/facets/output-contracts/frontend-review.md +1 -0
- package/builtins/ja/facets/policies/ai-antipattern.md +19 -0
- package/builtins/ja/facets/policies/coding.md +85 -3
- package/builtins/ja/facets/policies/qa.md +3 -1
- package/builtins/ja/facets/policies/review.md +5 -3
- package/builtins/ja/facets/policies/testing.md +33 -0
- package/builtins/ja/workflows/auto-improvement-loop.yaml +20 -4
- package/dist/agents/decompose-task-usecase.d.ts.map +1 -1
- package/dist/agents/decompose-task-usecase.js +3 -2
- package/dist/agents/decompose-task-usecase.js.map +1 -1
- package/dist/agents/judge-status-usecase.d.ts.map +1 -1
- package/dist/agents/judge-status-usecase.js +4 -3
- package/dist/agents/judge-status-usecase.js.map +1 -1
- package/dist/agents/provider-call-options.d.ts +4 -0
- package/dist/agents/provider-call-options.d.ts.map +1 -0
- package/dist/agents/provider-call-options.js +9 -0
- package/dist/agents/provider-call-options.js.map +1 -0
- package/dist/agents/runner.js +1 -1
- package/dist/agents/runner.js.map +1 -1
- package/dist/agents/structured-caller/prompt-based-structured-caller.d.ts.map +1 -1
- package/dist/agents/structured-caller/prompt-based-structured-caller.js +5 -4
- package/dist/agents/structured-caller/prompt-based-structured-caller.js.map +1 -1
- package/dist/app/cli/program.js +1 -1
- package/dist/app/cli/program.js.map +1 -1
- package/dist/core/models/assistant-config.d.ts +4 -0
- package/dist/core/models/assistant-config.d.ts.map +1 -0
- package/dist/core/models/assistant-config.js +4 -0
- package/dist/core/models/assistant-config.js.map +1 -0
- package/dist/core/models/config-schemas.d.ts +88 -0
- package/dist/core/models/config-schemas.d.ts.map +1 -1
- package/dist/core/models/config-schemas.js +8 -2
- package/dist/core/models/config-schemas.js.map +1 -1
- package/dist/core/models/config-types.d.ts +20 -1
- package/dist/core/models/config-types.d.ts.map +1 -1
- package/dist/core/models/index.d.ts +1 -1
- package/dist/core/models/index.d.ts.map +1 -1
- package/dist/core/models/index.js.map +1 -1
- package/dist/core/models/provider-profiles.d.ts +1 -1
- package/dist/core/models/provider-profiles.d.ts.map +1 -1
- package/dist/core/models/response.d.ts +1 -1
- package/dist/core/models/response.d.ts.map +1 -1
- package/dist/core/models/response.js +1 -1
- package/dist/core/models/response.js.map +1 -1
- package/dist/core/models/schema-base.d.ts +65 -0
- package/dist/core/models/schema-base.d.ts.map +1 -1
- package/dist/core/models/schema-base.js +31 -0
- package/dist/core/models/schema-base.js.map +1 -1
- package/dist/core/models/types.d.ts +2 -2
- package/dist/core/models/types.d.ts.map +1 -1
- package/dist/core/models/workflow-provider-options.d.ts +7 -0
- package/dist/core/models/workflow-provider-options.d.ts.map +1 -1
- package/dist/core/models/workflow-schemas.d.ts +277 -38
- package/dist/core/models/workflow-schemas.d.ts.map +1 -1
- package/dist/core/models/workflow-system-input-types.d.ts +8 -1
- package/dist/core/models/workflow-system-input-types.d.ts.map +1 -1
- package/dist/core/models/workflow-system-schemas.d.ts +7 -1
- package/dist/core/models/workflow-system-schemas.d.ts.map +1 -1
- package/dist/core/models/workflow-system-schemas.js +12 -1
- package/dist/core/models/workflow-system-schemas.js.map +1 -1
- package/dist/core/models/workflow-types.d.ts +2 -2
- package/dist/core/models/workflow-types.d.ts.map +1 -1
- package/dist/core/models/workflow-types.js.map +1 -1
- package/dist/core/workflow/engine/OptionsBuilder.d.ts +1 -0
- package/dist/core/workflow/engine/OptionsBuilder.d.ts.map +1 -1
- package/dist/core/workflow/engine/OptionsBuilder.js +9 -4
- package/dist/core/workflow/engine/OptionsBuilder.js.map +1 -1
- package/dist/core/workflow/engine/WorkflowEngine.d.ts +1 -0
- package/dist/core/workflow/engine/WorkflowEngine.d.ts.map +1 -1
- package/dist/core/workflow/engine/WorkflowEngine.js +24 -4
- package/dist/core/workflow/engine/WorkflowEngine.js.map +1 -1
- package/dist/core/workflow/engine/WorkflowRunLoop.d.ts +1 -0
- package/dist/core/workflow/engine/WorkflowRunLoop.d.ts.map +1 -1
- package/dist/core/workflow/engine/WorkflowRunLoop.js +26 -7
- package/dist/core/workflow/engine/WorkflowRunLoop.js.map +1 -1
- package/dist/core/workflow/observability/workflowSpans.d.ts +28 -0
- package/dist/core/workflow/observability/workflowSpans.d.ts.map +1 -0
- package/dist/core/workflow/observability/workflowSpans.js +107 -0
- package/dist/core/workflow/observability/workflowSpans.js.map +1 -0
- package/dist/core/workflow/permission-profile-resolution.d.ts.map +1 -1
- package/dist/core/workflow/permission-profile-resolution.js +1 -0
- package/dist/core/workflow/permission-profile-resolution.js.map +1 -1
- package/dist/core/workflow/phase-runner.d.ts +1 -3
- package/dist/core/workflow/phase-runner.d.ts.map +1 -1
- package/dist/core/workflow/phase-runner.js.map +1 -1
- package/dist/core/workflow/report-phase-runner.d.ts.map +1 -1
- package/dist/core/workflow/report-phase-runner.js +3 -2
- package/dist/core/workflow/report-phase-runner.js.map +1 -1
- package/dist/core/workflow/status-judgment-phase.d.ts.map +1 -1
- package/dist/core/workflow/status-judgment-phase.js +7 -3
- package/dist/core/workflow/status-judgment-phase.js.map +1 -1
- package/dist/core/workflow/system/system-step-effect-runner.d.ts.map +1 -1
- package/dist/core/workflow/system/system-step-effect-runner.js +16 -1
- package/dist/core/workflow/system/system-step-effect-runner.js.map +1 -1
- package/dist/core/workflow/types.d.ts +3 -1
- package/dist/core/workflow/types.d.ts.map +1 -1
- package/dist/features/interactive/assistantInitFiles.d.ts +2 -0
- package/dist/features/interactive/assistantInitFiles.d.ts.map +1 -0
- package/dist/features/interactive/assistantInitFiles.js +110 -0
- package/dist/features/interactive/assistantInitFiles.js.map +1 -0
- package/dist/features/interactive/conversationLoop.d.ts +5 -1
- package/dist/features/interactive/conversationLoop.d.ts.map +1 -1
- package/dist/features/interactive/conversationLoop.js +23 -3
- package/dist/features/interactive/conversationLoop.js.map +1 -1
- package/dist/features/interactive/interactive-summary.d.ts +1 -1
- package/dist/features/interactive/interactive-summary.d.ts.map +1 -1
- package/dist/features/interactive/interactive-summary.js +4 -3
- package/dist/features/interactive/interactive-summary.js.map +1 -1
- package/dist/features/interactive/interactive.d.ts +5 -3
- package/dist/features/interactive/interactive.d.ts.map +1 -1
- package/dist/features/interactive/interactive.js +4 -0
- package/dist/features/interactive/interactive.js.map +1 -1
- package/dist/features/interactive/promptSections.d.ts +2 -0
- package/dist/features/interactive/promptSections.d.ts.map +1 -1
- package/dist/features/interactive/promptSections.js +7 -1
- package/dist/features/interactive/promptSections.js.map +1 -1
- package/dist/features/interactive/slashCommandRegistry.d.ts.map +1 -1
- package/dist/features/interactive/slashCommandRegistry.js +1 -0
- package/dist/features/interactive/slashCommandRegistry.js.map +1 -1
- package/dist/features/tasks/execute/workflowExecution.d.ts.map +1 -1
- package/dist/features/tasks/execute/workflowExecution.js +12 -1
- package/dist/features/tasks/execute/workflowExecution.js.map +1 -1
- package/dist/features/tasks/execute/workflowExecutionBootstrap.d.ts +5 -1
- package/dist/features/tasks/execute/workflowExecutionBootstrap.d.ts.map +1 -1
- package/dist/features/tasks/execute/workflowExecutionBootstrap.js +6 -1
- package/dist/features/tasks/execute/workflowExecutionBootstrap.js.map +1 -1
- package/dist/infra/claude/executor.d.ts.map +1 -1
- package/dist/infra/claude/executor.js +27 -6
- package/dist/infra/claude/executor.js.map +1 -1
- package/dist/infra/claude/mcp-config.d.ts +7 -0
- package/dist/infra/claude/mcp-config.d.ts.map +1 -0
- package/dist/infra/claude/mcp-config.js +30 -0
- package/dist/infra/claude/mcp-config.js.map +1 -0
- package/dist/infra/claude-headless/client.d.ts.map +1 -1
- package/dist/infra/claude-headless/client.js +5 -40
- package/dist/infra/claude-headless/client.js.map +1 -1
- package/dist/infra/claude-headless/result-response.js +1 -1
- package/dist/infra/claude-headless/result-response.js.map +1 -1
- package/dist/infra/claude-terminal/client.d.ts +4 -0
- package/dist/infra/claude-terminal/client.d.ts.map +1 -0
- package/dist/infra/claude-terminal/client.js +314 -0
- package/dist/infra/claude-terminal/client.js.map +1 -0
- package/dist/infra/claude-terminal/command.d.ts +4 -0
- package/dist/infra/claude-terminal/command.d.ts.map +1 -0
- package/dist/infra/claude-terminal/command.js +50 -0
- package/dist/infra/claude-terminal/command.js.map +1 -0
- package/dist/infra/claude-terminal/response-normalizer.d.ts +14 -0
- package/dist/infra/claude-terminal/response-normalizer.d.ts.map +1 -0
- package/dist/infra/claude-terminal/response-normalizer.js +118 -0
- package/dist/infra/claude-terminal/response-normalizer.js.map +1 -0
- package/dist/infra/claude-terminal/tmux-backend.d.ts +7 -0
- package/dist/infra/claude-terminal/tmux-backend.d.ts.map +1 -0
- package/dist/infra/claude-terminal/tmux-backend.js +177 -0
- package/dist/infra/claude-terminal/tmux-backend.js.map +1 -0
- package/dist/infra/claude-terminal/transcript-reader.d.ts +13 -0
- package/dist/infra/claude-terminal/transcript-reader.d.ts.map +1 -0
- package/dist/infra/claude-terminal/transcript-reader.js +329 -0
- package/dist/infra/claude-terminal/transcript-reader.js.map +1 -0
- package/dist/infra/claude-terminal/types.d.ts +106 -0
- package/dist/infra/claude-terminal/types.d.ts.map +1 -0
- package/dist/infra/claude-terminal/types.js +2 -0
- package/dist/infra/claude-terminal/types.js.map +1 -0
- package/dist/infra/config/configNormalizers.d.ts +7 -1
- package/dist/infra/config/configNormalizers.d.ts.map +1 -1
- package/dist/infra/config/configNormalizers.js +31 -1
- package/dist/infra/config/configNormalizers.js.map +1 -1
- package/dist/infra/config/env/global-current-env-specs.d.ts.map +1 -1
- package/dist/infra/config/env/global-current-env-specs.js +5 -0
- package/dist/infra/config/env/global-current-env-specs.js.map +1 -1
- package/dist/infra/config/env/project-current-env-specs.d.ts.map +1 -1
- package/dist/infra/config/env/project-current-env-specs.js +5 -0
- package/dist/infra/config/env/project-current-env-specs.js.map +1 -1
- package/dist/infra/config/global/globalConfigCore.d.ts.map +1 -1
- package/dist/infra/config/global/globalConfigCore.js +2 -0
- package/dist/infra/config/global/globalConfigCore.js.map +1 -1
- package/dist/infra/config/global/globalConfigSerializer.d.ts.map +1 -1
- package/dist/infra/config/global/globalConfigSerializer.js +5 -0
- package/dist/infra/config/global/globalConfigSerializer.js.map +1 -1
- package/dist/infra/config/global/initialization.d.ts +1 -1
- package/dist/infra/config/global/initialization.d.ts.map +1 -1
- package/dist/infra/config/global/initialization.js +1 -0
- package/dist/infra/config/global/initialization.js.map +1 -1
- package/dist/infra/config/observabilityConfig.d.ts +13 -0
- package/dist/infra/config/observabilityConfig.d.ts.map +1 -0
- package/dist/infra/config/observabilityConfig.js +52 -0
- package/dist/infra/config/observabilityConfig.js.map +1 -0
- package/dist/infra/config/project/projectConfig.d.ts.map +1 -1
- package/dist/infra/config/project/projectConfig.js +19 -2
- package/dist/infra/config/project/projectConfig.js.map +1 -1
- package/dist/infra/config/providerOptions.d.ts +8 -2
- package/dist/infra/config/providerOptions.d.ts.map +1 -1
- package/dist/infra/config/providerOptions.js +49 -1
- package/dist/infra/config/providerOptions.js.map +1 -1
- package/dist/infra/config/providerOptionsContract.d.ts +3 -3
- package/dist/infra/config/providerOptionsContract.d.ts.map +1 -1
- package/dist/infra/config/providerOptionsContract.js +14 -0
- package/dist/infra/config/providerOptionsContract.js.map +1 -1
- package/dist/infra/config/resolveConfigValue.d.ts.map +1 -1
- package/dist/infra/config/resolveConfigValue.js +18 -0
- package/dist/infra/config/resolveConfigValue.js.map +1 -1
- package/dist/infra/config/resolvedConfig.d.ts +2 -1
- package/dist/infra/config/resolvedConfig.d.ts.map +1 -1
- package/dist/infra/config/traced/tracedConfigSchema.d.ts.map +1 -1
- package/dist/infra/config/traced/tracedConfigSchema.js +12 -0
- package/dist/infra/config/traced/tracedConfigSchema.js.map +1 -1
- package/dist/infra/git/format.d.ts.map +1 -1
- package/dist/infra/git/format.js +75 -8
- package/dist/infra/git/format.js.map +1 -1
- package/dist/infra/git/index.d.ts +1 -1
- package/dist/infra/git/index.d.ts.map +1 -1
- package/dist/infra/git/types.d.ts +5 -0
- package/dist/infra/git/types.d.ts.map +1 -1
- package/dist/infra/github/pr.d.ts.map +1 -1
- package/dist/infra/github/pr.js +174 -28
- package/dist/infra/github/pr.js.map +1 -1
- package/dist/infra/observability/otelFoundation.d.ts +6 -0
- package/dist/infra/observability/otelFoundation.d.ts.map +1 -0
- package/dist/infra/observability/otelFoundation.js +89 -0
- package/dist/infra/observability/otelFoundation.js.map +1 -0
- package/dist/infra/opencode/client.d.ts.map +1 -1
- package/dist/infra/opencode/client.js +19 -15
- package/dist/infra/opencode/client.js.map +1 -1
- package/dist/infra/providers/claude-terminal.d.ts +6 -0
- package/dist/infra/providers/claude-terminal.d.ts.map +1 -0
- package/dist/infra/providers/claude-terminal.js +70 -0
- package/dist/infra/providers/claude-terminal.js.map +1 -0
- package/dist/infra/providers/index.d.ts.map +1 -1
- package/dist/infra/providers/index.js +2 -0
- package/dist/infra/providers/index.js.map +1 -1
- package/dist/infra/providers/provider-capabilities.d.ts +1 -0
- package/dist/infra/providers/provider-capabilities.d.ts.map +1 -1
- package/dist/infra/providers/provider-capabilities.js +16 -0
- package/dist/infra/providers/provider-capabilities.js.map +1 -1
- package/dist/infra/rate-limit/detection.d.ts +2 -0
- package/dist/infra/rate-limit/detection.d.ts.map +1 -1
- package/dist/infra/rate-limit/detection.js +14 -1
- package/dist/infra/rate-limit/detection.js.map +1 -1
- package/dist/infra/task/clone-base-branch.d.ts +11 -0
- package/dist/infra/task/clone-base-branch.d.ts.map +1 -1
- package/dist/infra/task/clone-base-branch.js +34 -4
- package/dist/infra/task/clone-base-branch.js.map +1 -1
- package/dist/infra/task/clone.d.ts +1 -1
- package/dist/infra/task/clone.d.ts.map +1 -1
- package/dist/infra/task/clone.js +1 -1
- package/dist/infra/task/clone.js.map +1 -1
- package/dist/infra/task/index.d.ts +1 -1
- package/dist/infra/task/index.d.ts.map +1 -1
- package/dist/infra/task/index.js +1 -1
- package/dist/infra/task/index.js.map +1 -1
- package/dist/infra/workflow/system/system-enqueue-effect.d.ts +2 -2
- package/dist/infra/workflow/system/system-enqueue-effect.d.ts.map +1 -1
- package/dist/infra/workflow/system/system-enqueue-effect.js +5 -2
- package/dist/infra/workflow/system/system-enqueue-effect.js.map +1 -1
- package/dist/shared/constants.d.ts +1 -0
- package/dist/shared/constants.d.ts.map +1 -1
- package/dist/shared/constants.js +1 -0
- package/dist/shared/constants.js.map +1 -1
- package/dist/shared/i18n/labels_en.yaml +3 -1
- package/dist/shared/i18n/labels_ja.yaml +3 -1
- package/dist/shared/types/provider.d.ts +1 -1
- package/dist/shared/types/provider.d.ts.map +1 -1
- package/dist/shared/utils/debug.d.ts +2 -0
- package/dist/shared/utils/debug.d.ts.map +1 -1
- package/dist/shared/utils/debug.js +1 -0
- package/dist/shared/utils/debug.js.map +1 -1
- 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 —
|
|
5
|
+
**T**AKT **A**gent **K**oordination **T**opology — Orchestrate multiple AI agents with structured review loops, managed prompts, and guardrails.
|
|
6
6
|
|
|
7
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
26
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
142
|
-
| `backend
|
|
143
|
-
| `dual
|
|
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)
|
|
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
|
-
##
|
|
266
|
+
## Adopting Spec-Driven Development
|
|
247
267
|
|
|
248
|
-
|
|
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
|
-
|
|
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
|
-
|
|
255
|
-
|
|
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
|
-
| [
|
|
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
|
-
|
|
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
|
-
##
|
|
377
|
+
## Unfinished Code Detection
|
|
378
378
|
|
|
379
|
-
|
|
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
|
|
381
|
+
TODO/FIXME without an issue number, external blocker, and removal condition is REJECT.
|
|
382
382
|
|
|
383
383
|
```kotlin
|
|
384
|
-
// REJECT -
|
|
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
|
-
|
|
401
|
+
Acceptable TODO/FIXME cases:
|
|
402
402
|
|
|
403
403
|
| Condition | Example | Judgment |
|
|
404
404
|
|-----------|---------|----------|
|
|
405
|
-
| External dependency prevents implementation +
|
|
406
|
-
| Technical constraint prevents +
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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 |
|
|
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 |
|
|
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.),
|
|
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 |
|
|
@@ -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
|
-
- **
|
|
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,
|
|
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,
|
|
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
|
-
|
|
|
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
|
|
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
|
-
-
|
|
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
|
|
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 |
|