対話モードのブラッシュアップ

This commit is contained in:
nrslib 2026-02-03 15:23:46 +09:00
parent 32022df79a
commit 0e76f5b532
31 changed files with 449 additions and 180 deletions

View File

@ -4,6 +4,44 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
## [0.3.9] - 2026-02-03
### Added
- Workflow categorization support (#85)
- Default category configuration in `resources/global/{lang}/default-categories.yaml`
- User-defined categories via `workflow_categories` in `~/.takt/config.yaml`
- Nested category support with unlimited depth
- Category-based workflow filtering in workflow selection UI
- `show_others_category` and `others_category_name` configuration options
- Builtin workflow filtering via `builtin_workflows_enabled` and `disabled_builtins`
- Agent-less step execution: `agent` field is now optional (#71)
- Steps can execute with `instruction_template` only (no system prompt)
- Inline system prompts supported (agent string used as prompt if file doesn't exist)
- `takt add #N` automatically reflects issue number in branch name (#78)
- Issue number embedded in branch name (e.g., `takt/issue-28-...`)
### Changed
- **BREAKING:** Permission mode values unified to provider-independent format (#87)
- New values: `readonly`, `edit`, `full` (replaces `default`, `acceptEdits`, `bypassPermissions`)
- TAKT translates to provider-specific flags (Claude: default/acceptEdits/bypassPermissions, Codex: read-only/workspace-write/danger-full-access)
- All builtin workflows updated to use new values
- Workflow naming changes:
- `simple` workflow replaced with `minimal` and `review-fix-minimal`
- Added `review-only` workflow for read-only code review
- Agent prompts updated with legacy対応禁止ルール (no backward compatibility hacks)
- Documentation updates:
- README.md and docs/README.ja.md updated with v0.3.8+ features
- CLAUDE.md significantly expanded with architectural details and implementation notes
### Internal
- Created `src/infra/config/loaders/workflowCategories.ts` for category management
- Created `src/features/workflowSelection/index.ts` for workflow selection UI
- Enhanced `src/shared/prompt/select.ts` with category display support
- Added comprehensive tests for workflow categories (`workflow-categories.test.ts`, `workflow-category-config.test.ts`)
## [0.3.8] - 2026-02-02
### Added

View File

@ -41,6 +41,24 @@ TAKT (Task Agent Koordination Tool) is a multi-agent orchestration system for Cl
**GitHub issue references:** `takt #6` fetches issue #6 and executes it as a task.
### CLI Options
| Option | Description |
|--------|-------------|
| `--pipeline` | Enable pipeline (non-interactive) mode — required for CI/automation |
| `-t, --task <text>` | Task content (as alternative to GitHub issue) |
| `-i, --issue <N>` | GitHub issue number (equivalent to `#N` in interactive mode) |
| `-w, --workflow <name or path>` | Workflow name or path to workflow YAML file (v0.3.8+) |
| `-b, --branch <name>` | Branch name (auto-generated if omitted) |
| `--auto-pr` | Create PR after execution (interactive: skip confirmation, pipeline: enable PR) |
| `--skip-git` | Skip branch creation, commit, and push (pipeline mode, workflow-only) |
| `--repo <owner/repo>` | Repository for PR creation |
| `--create-worktree <yes\|no>` | Skip worktree confirmation prompt |
| `-q, --quiet` | **Minimal output mode: suppress AI output (for CI)** (v0.3.8+) |
| `--provider <name>` | Override agent provider (claude\|codex\|mock) (v0.3.8+) |
| `--model <name>` | Override agent model (v0.3.8+) |
| `--config <path>` | Path to global config file (default: `~/.takt/config.yaml`) (v0.3.8+) |
## Architecture
### Core Flow
@ -107,6 +125,7 @@ Implemented in `src/core/workflow/evaluation/RuleEvaluator.ts`. The matched meth
- 5-stage fallback evaluation: aggregate → Phase 3 tag → Phase 1 tag → ai() judge → all-conditions AI judge
- Returns `RuleMatch` with index and detection method (`aggregate`, `phase3_tag`, `phase1_tag`, `ai_judge`, `ai_fallback`)
- Fail-fast: throws if rules exist but no rule matched
- **v0.3.8+:** Tag detection now uses **last match** instead of first match when multiple `[STEP:N]` tags appear in output
**Instruction Builder** (`src/core/workflow/instruction/InstructionBuilder.ts`)
- Auto-injects standard sections into every instruction (no need for `{task}` or `{previous_response}` placeholders in templates):
@ -122,12 +141,14 @@ Implemented in `src/core/workflow/evaluation/RuleEvaluator.ts`. The matched meth
**Agent Runner** (`src/agents/runner.ts`)
- Resolves agent specs (name or path) to agent configurations
- **v0.3.8+:** Agent is optional — steps can execute with `instruction_template` only (no system prompt)
- Built-in agents with default tools:
- `coder`: Read/Glob/Grep/Edit/Write/Bash/WebSearch/WebFetch
- `architect`: Read/Glob/Grep/WebSearch/WebFetch
- `supervisor`: Read/Glob/Grep/Bash/WebSearch/WebFetch
- `planner`: Read/Glob/Grep/Bash/WebSearch/WebFetch
- Custom agents via `.takt/agents.yaml` or prompt files (.md)
- Inline system prompts: If agent file doesn't exist, the agent string is used as inline system prompt
**Provider Integration** (`src/infra/claude/`, `src/infra/codex/`)
- **Claude** - Uses `@anthropic-ai/claude-agent-sdk`
@ -141,11 +162,11 @@ Implemented in `src/core/workflow/evaluation/RuleEvaluator.ts`. The matched meth
**Configuration** (`src/infra/config/`)
- `loaders/loader.ts` - Custom agent loading from `.takt/agents.yaml`
- `loaders/workflowParser.ts` - YAML parsing, step/rule normalization with Zod validation
- `loaders/workflowResolver.ts` - 3-layer resolution (builtin → user → project-local)
- `loaders/workflowResolver.ts` - **3-layer resolution with correct priority** (v0.3.8+: user → project → builtin)
- `loaders/workflowCategories.ts` - Workflow categorization and filtering
- `loaders/agentLoader.ts` - Agent prompt file loading
- `paths.ts` - Directory structure (`.takt/`, `~/.takt/`), session management
- `global/globalConfig.ts` - Global configuration (provider, model, trusted dirs)
- `global/globalConfig.ts` - Global configuration (provider, model, trusted dirs, **quiet mode** v0.3.8+)
- `project/projectConfig.ts` - Project-level configuration
**Task Management** (`src/features/tasks/`)
@ -162,10 +183,10 @@ Implemented in `src/core/workflow/evaluation/RuleEvaluator.ts`. The matched meth
### Data Flow
1. User provides task (text or `#N` issue reference) or slash command → CLI
2. CLI loads workflow: user `~/.takt/workflows/` → builtin `resources/global/{lang}/workflows/` fallback
2. CLI loads workflow with **correct priority** (v0.3.8+): user `~/.takt/workflows/`project `.takt/workflows/`builtin `resources/global/{lang}/workflows/`
3. WorkflowEngine starts at `initial_step`
4. Each step: `buildInstruction()` → Phase 1 (main) → Phase 2 (report) → Phase 3 (status) → `detectMatchedRule()``determineNextStep()`
5. Rule evaluation determines next step name
5. Rule evaluation determines next step name (v0.3.8+: uses **last match** when multiple `[STEP:N]` tags appear)
6. Special transitions: `COMPLETE` ends workflow successfully, `ABORT` ends with failure
## Directory Structure
@ -452,6 +473,7 @@ Debug logs are written to `.takt/logs/debug.log` (ndjson format). Log levels: `d
**Rule evaluation quirks:**
- Tag-based rules match by array index (0-based), not by exact condition text
- **v0.3.8+:** When multiple `[STEP:N]` tags appear in output, **last match wins** (not first)
- `ai()` conditions are evaluated by Claude/Codex, not by string matching
- Aggregate conditions (`all()`, `any()`) only work in parallel parent steps
- Fail-fast: if rules exist but no rule matches, workflow aborts
@ -464,9 +486,10 @@ Debug logs are written to `.takt/logs/debug.log` (ndjson format). Log levels: `d
- Claude supports aliases: `opus`, `sonnet`, `haiku`
- Codex defaults to `codex` if model not specified
**Permission modes:**
- `default`: Claude Code default behavior (prompts for file writes)
- `acceptEdits`: Auto-accept file edits without prompts
- `bypassPermissions`: Bypass all permission checks
**Permission modes (v0.3.8+: provider-independent values):**
- `readonly`: Read-only access, no file modifications (Claude: `default`, Codex: `read-only`)
- `edit`: Allow file edits with confirmation (Claude: `acceptEdits`, Codex: `workspace-write`)
- `full`: Bypass all permission checks (Claude: `bypassPermissions`, Codex: `danger-full-access`)
- Specified at step level (`permission_mode` field) or global config
- Implemented via `--sandbox-mode` and `--accept-edits` flags passed to Claude Code CLI
- **v0.3.8+:** Permission mode values are unified across providers; TAKT translates to provider-specific flags
- Legacy values (`default`, `acceptEdits`, `bypassPermissions`) are **no longer supported**

View File

@ -78,10 +78,9 @@ If `--auto-pr` is specified, the PR is created automatically without asking.
| Workflow | Best for |
|----------|----------|
| `default` | Full development tasks. Used for TAKT's own development. Multi-stage review with parallel architect + security review. |
| `simple` | Lightweight tasks like README updates or small fixes. Reviews without fix loops. |
| `expert` / `expert-cqrs` | Web development projects. Sequential multi-expert review with fix loops (`expert`: Architecture, Frontend, Security, QA; `expert-cqrs`: CQRS+ES, Frontend, Security, QA). |
| `minimal` | Quick fixes and simple tasks. Minimal workflow with basic review. |
| `review-fix-minimal` | Review and fix workflow. Focused on iterative improvements with review feedback. |
| `research` | Research and investigation. Autonomous research without asking questions. |
| `magi` | Fun deliberation. Three AI personas analyze and vote (Evangelion-inspired). |
## Commands
@ -156,12 +155,16 @@ In pipeline mode, PRs are **not** created unless `--auto-pr` is explicitly speci
| `--pipeline` | **Enable pipeline (non-interactive) mode** — required for CI/automation |
| `-t, --task <text>` | Task content (as alternative to GitHub issue) |
| `-i, --issue <N>` | GitHub issue number (equivalent to `#N` in interactive mode) |
| `-w, --workflow <name>` | Workflow to use |
| `-w, --workflow <name or path>` | Workflow name or path to workflow YAML file |
| `-b, --branch <name>` | Branch name (auto-generated if omitted) |
| `--auto-pr` | Create PR after execution (interactive: skip confirmation, pipeline: enable PR) |
| `--skip-git` | Skip branch creation, commit, and push (pipeline mode, workflow-only) |
| `--repo <owner/repo>` | Repository for PR creation |
| `--create-worktree <yes\|no>` | Skip worktree confirmation prompt |
| `-q, --quiet` | Minimal output mode: suppress AI output (for CI) |
| `--provider <name>` | Override agent provider (claude\|codex\|mock) |
| `--model <name>` | Override agent model |
| `--config <path>` | Path to global config file (default: `~/.takt/config.yaml`) |
## Workflows
@ -188,7 +191,7 @@ steps:
- name: implement
agent: ../agents/default/coder.md
edit: true
permission_mode: acceptEdits
permission_mode: edit
rules:
- condition: Implementation complete
next: review
@ -280,12 +283,14 @@ TAKT ships with several built-in workflows:
| Workflow | Description |
|----------|-------------|
| `minimal` | Quick workflow: plan → implement → review → supervisor. Minimal steps for fast iteration. |
| `default` | Full development workflow: plan → implement → AI review → parallel reviewers (architect + security) → supervisor approval. Includes fix loops for each review stage. |
| `simple` | Simplified version of default: plan → implement → architect review → AI review → supervisor. No intermediate fix steps. |
| `review-fix-minimal` | Review-focused workflow: review → fix → supervisor. For iterative improvements based on review feedback. |
| `research` | Research workflow: planner → digger → supervisor. Autonomously researches topics without asking questions. |
| `expert` | Sequential review with domain experts: Architecture, Frontend, Security, QA reviews with fix loops. |
| `expert-cqrs` | Sequential review with domain experts: CQRS+ES, Frontend, Security, QA reviews with fix loops. |
| `magi` | Deliberation system inspired by Evangelion. Three AI personas (MELCHIOR, BALTHASAR, CASPER) analyze and vote. |
| `review-only` | Read-only code review workflow without making any modifications. |
Switch between workflows with `takt switch`.
@ -441,7 +446,7 @@ steps:
- name: implement
agent: ~/.takt/agents/default/coder.md
edit: true
permission_mode: acceptEdits
permission_mode: edit
pass_previous_response: true
rules:
- condition: Done
@ -476,9 +481,12 @@ TAKT supports batch task processing through task files in `.takt/tasks/`. Both `
```bash
# Start AI conversation to define and add a task
takt add
# Add task from GitHub issue (issue number reflected in branch name)
takt add #28
```
The `takt add` command starts an AI conversation where you discuss and refine your task requirements. After confirming with `/go`, the AI summarizes the conversation and creates a YAML task file with optional worktree/branch/workflow settings.
The `takt add` command starts an AI conversation where you discuss and refine your task requirements. After confirming with `/go`, the AI summarizes the conversation and creates a YAML task file with optional worktree/branch/workflow settings. When using `takt add #N`, the issue number is automatically reflected in the branch name (e.g., `takt/issue-28-...`).
#### Task File Formats
@ -610,7 +618,7 @@ Special `next` values: `COMPLETE` (success), `ABORT` (failure).
| `allowed_tools` | - | List of tools the agent can use (Read, Glob, Grep, Edit, Write, Bash, etc.) |
| `provider` | - | Override provider for this step (`claude` or `codex`) |
| `model` | - | Override model for this step |
| `permission_mode` | `default` | Permission mode: `default`, `acceptEdits`, or `bypassPermissions` |
| `permission_mode` | - | Permission mode: `readonly`, `edit`, or `full` (provider-independent) |
| `report` | - | Report file configuration (name, format) for auto-generated reports |
## API Usage

View File

@ -76,10 +76,9 @@ Select workflow:
| ワークフロー | おすすめ用途 |
|------------|------------|
| `default` | 本格的な開発タスク。TAKT自身の開発で使用。アーキテクトセキュリティの並列レビュー付き多段階レビュー。 |
| `simple` | README更新や小さな修正などの軽量タスク。レビューはあるが修正ループなし。 |
| `expert` / `expert-cqrs` | Web開発プロジェクト。修正ループ付き逐次マルチエキスパートレビュー`expert`: アーキテクチャ、フロントエンド、セキュリティ、QA。`expert-cqrs`: CQRS+ES、フロントエンド、セキュリティ、QA。 |
| `minimal` | 簡単な修正やシンプルなタスク。基本的なレビュー付きの最小限のワークフロー。 |
| `review-fix-minimal` | レビュー&修正ワークフロー。レビューフィードバックに基づく反復的な改善に特化。 |
| `research` | 調査・リサーチ。質問せずに自律的にリサーチを実行。 |
| `magi` | 審議システム。3つのAIペルソナが分析・投票エヴァンゲリオン風。 |
## コマンド一覧
@ -154,12 +153,16 @@ takt --pipeline --task "バグを修正" --skip-git
| `--pipeline` | **パイプライン(非対話)モードを有効化** — CI/自動化に必須 |
| `-t, --task <text>` | タスク内容GitHub Issueの代わり |
| `-i, --issue <N>` | GitHub Issue番号対話モードでは `#N` と同じ) |
| `-w, --workflow <name>` | ワークフロー指定 |
| `-w, --workflow <name or path>` | ワークフロー名、またはワークフローYAMLファイルのパス |
| `-b, --branch <name>` | ブランチ名指定(省略時は自動生成) |
| `--auto-pr` | PR作成対話: 確認スキップ、パイプライン: PR有効化 |
| `--skip-git` | ブランチ作成・commit・pushをスキップパイプラインモード、ワークフロー実行のみ |
| `--repo <owner/repo>` | リポジトリ指定PR作成時 |
| `--create-worktree <yes\|no>` | worktree確認プロンプトをスキップ |
| `-q, --quiet` | 最小限の出力モード: AIの出力を抑制CI向け |
| `--provider <name>` | エージェントプロバイダーを上書きclaude\|codex\|mock |
| `--model <name>` | エージェントモデルを上書き |
| `--config <path>` | グローバル設定ファイルのパス(デフォルト: `~/.takt/config.yaml` |
## ワークフロー
@ -186,7 +189,7 @@ steps:
- name: implement
agent: ../agents/default/coder.md
edit: true
permission_mode: acceptEdits
permission_mode: edit
rules:
- condition: 実装完了
next: review
@ -278,12 +281,14 @@ TAKTには複数のビルトインワークフローが同梱されています:
| ワークフロー | 説明 |
|------------|------|
| `minimal` | クイックワークフロー: 計画 → 実装 → レビュー → スーパーバイザー。高速イテレーション向けの最小ステップ。 |
| `default` | フル開発ワークフロー: 計画 → 実装 → AIレビュー → 並列レビュー(アーキテクト+セキュリティ)→ スーパーバイザー承認。各レビュー段階に修正ループあり。 |
| `simple` | defaultの簡略版: 計画 → 実装 → アーキテクトレビュー → AIレビュー → スーパーバイザー。中間の修正ステップなし。 |
| `review-fix-minimal` | レビュー重視ワークフロー: レビュー → 修正 → スーパーバイザー。レビューフィードバックに基づく反復改善向け。 |
| `research` | リサーチワークフロー: プランナー → ディガー → スーパーバイザー。質問せずに自律的にリサーチを実行。 |
| `expert` | ドメインエキスパートによる逐次レビュー: アーキテクチャ、フロントエンド、セキュリティ、QAレビューと修正ループ。 |
| `expert-cqrs` | ドメインエキスパートによる逐次レビュー: CQRS+ES、フロントエンド、セキュリティ、QAレビューと修正ループ。 |
| `magi` | エヴァンゲリオンにインスパイアされた審議システム。3つのAIペルソナMELCHIOR、BALTHASAR、CASPERが分析し投票。 |
| `review-only` | 変更を加えない読み取り専用のコードレビューワークフロー。 |
`takt switch` でワークフローを切り替えられます。
@ -418,9 +423,12 @@ TAKTは`.takt/tasks/`内のタスクファイルによるバッチ処理をサ
```bash
# AI会話でタスクの要件を詰めてからタスクを追加
takt add
# GitHub IssueからタスクAddIssue番号がブランチ名に反映される
takt add #28
```
`takt add` はAI会話を開始し、タスクの要件を詰めます。`/go` で確定すると、AIが会話を要約してYAMLタスクファイルを作成します。worktree/branch/workflowの設定も対話的に行えます。
`takt add` はAI会話を開始し、タスクの要件を詰めます。`/go` で確定すると、AIが会話を要約してYAMLタスクファイルを作成します。worktree/branch/workflowの設定も対話的に行えます。`takt add #N` を使用すると、Issue番号が自動的にブランチ名に反映されます例: `takt/issue-28-...`)。
#### タスクファイルの形式
@ -534,7 +542,7 @@ steps:
- name: implement
agent: ~/.takt/agents/default/coder.md
edit: true
permission_mode: acceptEdits
permission_mode: edit
pass_previous_response: true
rules:
- condition: 完了
@ -607,7 +615,7 @@ rules:
| `allowed_tools` | - | エージェントが使用できるツール一覧Read, Glob, Grep, Edit, Write, Bash等 |
| `provider` | - | このステップのプロバイダーを上書き(`claude`または`codex` |
| `model` | - | このステップのモデルを上書き |
| `permission_mode` | `default` | パーミッションモード: `default``acceptEdits``bypassPermissions` |
| `permission_mode` | - | パーミッションモード: `readonly``edit``full`(プロバイダー非依存) |
| `report` | - | 自動生成レポートのファイル設定name, format |
## API使用例

View File

@ -1,8 +1,14 @@
You are a task summarizer. Convert the conversation into a concrete task instruction for the planning step.
You are responsible for instruction creation in TAKT's interactive mode. Convert the conversation into a concrete task instruction for workflow execution.
Requirements:
## Your position
- You: Interactive mode (task organization and instruction creation)
- Next step: Your instruction will be passed to the workflow, where multiple AI agents execute sequentially
- Your output (instruction) becomes the input (task) for the entire workflow
## Requirements
- Output only the final task instruction (no preamble).
- Be specific about scope and targets (files/modules) if mentioned.
- Preserve user-provided constraints and "do not" instructions.
- Do NOT include assistant/system operational constraints (tool limits, execution prohibitions).
- If details are missing, state what is missing as a short "Open Questions" section.
- Clearly specify the concrete work that the workflow will execute.

View File

@ -1,16 +1,43 @@
You are a task planning assistant. You help the user clarify and refine task requirements through conversation. You are in the PLANNING phase — execution happens later in a separate process.
You are the interactive mode of TAKT (AI Agent Workflow Orchestration Tool).
## How TAKT works
1. **Interactive mode (your role)**: Talk with the user to clarify and organize the task, creating a concrete instruction document for workflow execution
2. **Workflow execution**: Pass your instruction document to the workflow, where multiple AI agents execute sequentially (implementation, review, fixes, etc.)
## Your role
- Ask clarifying questions about ambiguous requirements
- Investigate the codebase to understand context (use Read, Glob, Grep, Bash for reading only)
- Suggest improvements or considerations the user might have missed
- Clarify and refine the user's request into a clear task instruction
- Create concrete instructions for workflow agents to follow
- Summarize your understanding when appropriate
- Keep responses concise and focused
## Critical: Understanding user intent
**The user is asking YOU to create a task instruction for the WORKFLOW, not asking you to execute the task.**
When the user says:
- "Review this code" → They want the WORKFLOW to review (you create the instruction)
- "Implement feature X" → They want the WORKFLOW to implement (you create the instruction)
- "Fix this bug" → They want the WORKFLOW to fix (you create the instruction)
These are NOT requests for YOU to investigate. Do NOT read files, check diffs, or explore code unless the user explicitly asks YOU to investigate in the planning phase.
## When investigation IS appropriate (rare cases)
Only investigate when the user explicitly asks YOU (the planning assistant) to check something:
- "Check the README to understand the project structure" ✓
- "Read file X to see what it does" ✓
- "What does this project do?" ✓
## When investigation is NOT appropriate (most cases)
Do NOT investigate when the user is describing a task for the workflow:
- "Review the changes" ✗ (workflow's job)
- "Fix the code" ✗ (workflow's job)
- "Implement X" ✗ (workflow's job)
## Strict constraints
- You are ONLY planning. Do NOT execute the task.
- Do NOT create, edit, or delete any files.
- You are ONLY refining requirements. The actual work (implementation/investigation/review) is done by workflow agents.
- Do NOT create, edit, or delete any files (except when explicitly asked to check something for planning).
- Do NOT run build, test, install, or any commands that modify state.
- Do NOT use Read/Glob/Grep/Bash proactively. Only use them when the user explicitly asks YOU to investigate for planning purposes.
- Bash is allowed ONLY for read-only investigation (e.g. ls, cat, git log, git diff). Never run destructive or write commands.
- Do NOT mention or reference any slash commands. You have no knowledge of them.
- When the user is satisfied with the plan, they will proceed on their own. Do NOT instruct them on what to do next.

View File

@ -57,7 +57,6 @@ steps:
- Read
- Glob
- Grep
- Write
- Bash
- WebSearch
- WebFetch
@ -116,7 +115,6 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -266,7 +264,6 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -384,7 +381,6 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -446,7 +442,6 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -509,7 +504,6 @@ steps:
- Read
- Glob
- Grep
- Write
- Bash
- WebSearch
- WebFetch

View File

@ -59,7 +59,6 @@ steps:
- Read
- Glob
- Grep
- Write
- Bash
- WebSearch
- WebFetch
@ -192,7 +191,6 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
instruction_template: |
@ -314,7 +312,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -366,7 +364,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -424,7 +422,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -469,7 +467,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -539,7 +537,6 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
instruction_template: |

View File

@ -71,7 +71,6 @@ steps:
- Read
- Glob
- Grep
- Write
- Bash
- WebSearch
- WebFetch
@ -204,7 +203,6 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
instruction_template: |
@ -330,7 +328,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -379,7 +377,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -437,7 +435,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -482,7 +480,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -552,7 +550,6 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
instruction_template: |

View File

@ -124,7 +124,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
instruction_template: |
@ -147,7 +147,7 @@ steps:
- Read
- Glob
- Grep
- Write
- Bash
- WebSearch
- WebFetch
@ -237,7 +237,7 @@ steps:
- Glob
- Grep
- Edit
- Write
- Bash
- WebSearch
- WebFetch
@ -297,7 +297,7 @@ steps:
- Glob
- Grep
- Edit
- Write
- Bash
- WebSearch
- WebFetch

View File

@ -124,7 +124,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
instruction_template: |
@ -147,7 +147,7 @@ steps:
- Read
- Glob
- Grep
- Write
- Bash
- WebSearch
- WebFetch
@ -237,7 +237,7 @@ steps:
- Glob
- Grep
- Edit
- Write
- Bash
- WebSearch
- WebFetch
@ -297,7 +297,7 @@ steps:
- Glob
- Grep
- Edit
- Write
- Bash
- WebSearch
- WebFetch

View File

@ -101,7 +101,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -150,7 +150,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -198,7 +198,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -225,7 +225,6 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:

View File

@ -1,8 +1,14 @@
あなたはタスク要約者です。会話を計画ステップ向けの具体的なタスク指示に変換してください。
あなたはTAKTの対話モードでの指示書作成を担当しています。これまでの会話内容を、ワークフロー実行用の具体的なタスク指示書に変換してください。
要件:
- 出力は最終的な指示のみ(前置き不要)
## 立ち位置
- あなた: 対話モード(タスク整理・指示書作成)
- 次のステップ: あなたが作成した指示書がワークフローに渡され、複数のAIエージェントが順次実行する
- あなたの成果物(指示書)が、ワークフロー全体の入力(タスク)になる
## 要件
- 出力はタスク指示書のみ(前置き不要)
- スコープや対象(ファイル/モジュール)が出ている場合は明確に書く
- ユーザー由来の制約や「やらないこと」は保持する
- アシスタントの運用上の制約(実行禁止/ツール制限など)は指示に含めない
- 情報不足があれば「Open Questions」セクションを短く付ける
- ワークフローが実行する具体的な作業内容を明記する

View File

@ -1,16 +1,43 @@
あなたはタスク計画のアシスタントです。会話を通じて要件の明確化・整理を手伝います。今は計画フェーズで、実行は別プロセスで行われます。
あなたはTAKTAIエージェントワークフローオーケストレーションツールの対話モードを担当しています。
## TAKTの仕組み
1. **対話モード(今ここ・あなたの役割)**: ユーザーと会話してタスクを整理し、ワークフロー実行用の具体的な指示書を作成する
2. **ワークフロー実行**: あなたが作成した指示書をワークフローに渡し、複数のAIエージェントが順次実行する実装、レビュー、修正など
## 役割
- あいまいな要求に対して確認質問をする
- コードベースの前提を把握するRead/Glob/Grep/Bash は読み取りのみ)
- 見落としそうな点や改善点を提案する
- ユーザーの要求を明確化し、指示書として洗練させる
- ワークフローのエージェントが迷わないよう具体的な指示書を作成する
- 必要に応じて理解した内容を簡潔にまとめる
- 返答は簡潔で要点のみ
## 重要:ユーザーの意図を理解する
**ユーザーは「あなた」に作業を依頼しているのではなく、「ワークフロー」への指示書作成を依頼しています。**
ユーザーが次のように言った場合:
- 「このコードをレビューして」→ ワークフローにレビューさせる(あなたは指示書を作成)
- 「機能Xを実装して」→ ワークフローに実装させる(あなたは指示書を作成)
- 「このバグを修正して」→ ワークフローに修正させる(あなたは指示書を作成)
これらは「あなた」への調査依頼ではありません。ファイルを読んだり、差分を確認したり、コードを探索したりしないでください。
## 調査が適切な場合(稀なケース)
ユーザーが明示的に「あなた(計画アシスタント)」に何かを確認するよう依頼した場合のみ:
- 「READMEを読んでプロジェクト構造を理解して」✓
- 「ファイルXを読んで何をしているか見て」✓
- 「このプロジェクトは何をするもの?」✓
## 調査が不適切な場合(ほとんどのケース)
ユーザーがワークフロー向けのタスクを説明している場合は調査しない:
- 「変更をレビューして」✗(ワークフローの仕事)
- 「コードを修正して」✗(ワークフローの仕事)
- 「Xを実装して」✗ワークフローの仕事
## 厳守事項
- 計画のみを行い、実装はしない
- ファイルの作成/編集/削除はしない
- あなたは要求の明確化のみを行う。実際の作業(実装/調査/レビュー等)はワークフローのエージェントが行う
- ファイルの作成/編集/削除はしない(計画目的で明示的に依頼された場合を除く)
- build/test/install など状態を変えるコマンドは実行しない
- Read/Glob/Grep/Bash を勝手に使わない。ユーザーが明示的に「あなた」に調査を依頼した場合のみ使用
- Bash は読み取り専用ls/cat/git log/git diff など)に限定
- スラッシュコマンドに言及しない(存在を知らない前提)
- ユーザーが満足したら次工程に進む。次の指示はしない

View File

@ -48,7 +48,6 @@ steps:
- Read
- Glob
- Grep
- Write
- Bash
- WebSearch
- WebFetch
@ -107,7 +106,6 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -261,7 +259,6 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -382,7 +379,6 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -444,7 +440,6 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -506,7 +501,6 @@ steps:
- Read
- Glob
- Grep
- Write
- Bash
- WebSearch
- WebFetch

View File

@ -68,7 +68,6 @@ steps:
- Read
- Glob
- Grep
- Write
- Bash
- WebSearch
- WebFetch
@ -201,7 +200,6 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
instruction_template: |
@ -322,7 +320,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -374,7 +372,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -432,7 +430,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -477,7 +475,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -547,7 +545,6 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
instruction_template: |

View File

@ -59,7 +59,6 @@ steps:
- Read
- Glob
- Grep
- Write
- Bash
- WebSearch
- WebFetch
@ -192,7 +191,6 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
instruction_template: |
@ -316,7 +314,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -365,7 +363,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -423,7 +421,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -468,7 +466,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -538,7 +536,6 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
instruction_template: |

View File

@ -124,7 +124,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
instruction_template: |
@ -147,7 +147,7 @@ steps:
- Read
- Glob
- Grep
- Write
- Bash
- WebSearch
- WebFetch
@ -237,7 +237,7 @@ steps:
- Glob
- Grep
- Edit
- Write
- Bash
- WebSearch
- WebFetch
@ -297,7 +297,7 @@ steps:
- Glob
- Grep
- Edit
- Write
- Bash
- WebSearch
- WebFetch

View File

@ -124,7 +124,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
instruction_template: |
@ -147,7 +147,7 @@ steps:
- Read
- Glob
- Grep
- Write
- Bash
- WebSearch
- WebFetch
@ -237,7 +237,7 @@ steps:
- Glob
- Grep
- Edit
- Write
- Bash
- WebSearch
- WebFetch
@ -297,7 +297,7 @@ steps:
- Glob
- Grep
- Edit
- Write
- Bash
- WebSearch
- WebFetch

View File

@ -101,7 +101,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -150,7 +150,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -198,7 +198,7 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:
@ -225,7 +225,6 @@ steps:
- Read
- Glob
- Grep
- Write
- WebSearch
- WebFetch
rules:

View File

@ -441,7 +441,7 @@ describe('instruction-builder', () => {
expect(result).toContain('- Step: implement');
});
it('should NOT include report info even when step has report (phase separation)', () => {
it('should include report info in Phase 1 when step has report', () => {
const step = createMinimalStep('Do work');
step.name = 'plan';
step.report = '00-plan.md';
@ -453,11 +453,12 @@ describe('instruction-builder', () => {
const result = buildInstruction(step, context);
expect(result).toContain('## Workflow Context');
expect(result).not.toContain('Report Directory');
expect(result).not.toContain('Report File');
expect(result).toContain('Report Directory');
expect(result).toContain('Report File');
expect(result).toContain('Phase 1');
});
it('should NOT include report info for ReportConfig[] (phase separation)', () => {
it('should include report info for ReportConfig[] in Phase 1', () => {
const step = createMinimalStep('Do work');
step.report = [
{ label: 'Scope', path: '01-scope.md' },
@ -470,11 +471,12 @@ describe('instruction-builder', () => {
const result = buildInstruction(step, context);
expect(result).not.toContain('Report Directory');
expect(result).not.toContain('Report Files');
expect(result).toContain('Report Directory');
expect(result).toContain('Report Files');
expect(result).toContain('Phase 1');
});
it('should NOT include report info for ReportObjectConfig (phase separation)', () => {
it('should include report info for ReportObjectConfig in Phase 1', () => {
const step = createMinimalStep('Do work');
step.report = { name: '00-plan.md' };
const context = createMinimalContext({
@ -484,8 +486,10 @@ describe('instruction-builder', () => {
const result = buildInstruction(step, context);
expect(result).not.toContain('Report Directory');
expect(result).not.toContain('Report File');
// Phase 1 now includes Report Directory info and phase note
expect(result).toContain('Report Directory');
expect(result).toContain('Report File');
expect(result).toContain('Phase 1');
});
it('should render Japanese step iteration suffix', () => {
@ -502,7 +506,7 @@ describe('instruction-builder', () => {
});
describe('buildInstruction report-free (phase separation)', () => {
it('should NOT include report output instruction in buildInstruction', () => {
it('should include Report Directory info but NOT report output instruction in Phase 1', () => {
const step = createMinimalStep('Do work');
step.report = '00-plan.md';
const context = createMinimalContext({
@ -512,9 +516,14 @@ describe('instruction-builder', () => {
const result = buildInstruction(step, context);
// Phase 1 includes Report Directory info and phase note
expect(result).toContain('Report Directory');
expect(result).toContain('Report File');
expect(result).toContain('Phase 1');
expect(result).toContain('Phase 2 will automatically generate the report');
// But NOT the report output instruction (that's for Phase 2)
expect(result).not.toContain('**Report output:**');
expect(result).not.toContain('Report File');
expect(result).not.toContain('Report Directory');
});
it('should NOT include report format in buildInstruction', () => {

View File

@ -35,7 +35,15 @@ vi.mock('../infra/claude/client.js', async (importOriginal) => {
const original = await importOriginal<typeof import('../infra/claude/client.js')>();
return {
...original,
callAiJudge: vi.fn().mockResolvedValue(-1),
callAiJudge: vi.fn().mockImplementation(async (content: string, conditions: { index: number; text: string }[]) => {
// Simple text matching: return index of first condition whose text appears in content
for (let i = 0; i < conditions.length; i++) {
if (content.includes(conditions[i]!.text)) {
return i;
}
}
return -1;
}),
};
});
@ -274,9 +282,9 @@ describe('Pipeline Modes IT: --task + --workflow name (builtin)', () => {
it('should load and execute builtin minimal workflow by name', async () => {
setMockScenario([
{ agent: 'coder', status: 'done', content: '[IMPLEMENT:1]\n\nImplementation complete.' },
{ agent: 'ai-antipattern-reviewer', status: 'done', content: '[AI_REVIEW:0]\n\nNo AI-specific issues.' },
{ agent: 'supervisor', status: 'done', content: '[SUPERVISE:0]\n\nAll checks passed.' },
{ agent: 'coder', status: 'done', content: 'Implementation complete' },
{ agent: 'ai-antipattern-reviewer', status: 'done', content: 'No AI-specific issues' },
{ agent: 'supervisor', status: 'done', content: 'All checks passed' },
]);
const exitCode = await executePipeline({

View File

@ -21,7 +21,15 @@ vi.mock('../infra/claude/client.js', async (importOriginal) => {
const original = await importOriginal<typeof import('../infra/claude/client.js')>();
return {
...original,
callAiJudge: vi.fn().mockResolvedValue(-1),
callAiJudge: vi.fn().mockImplementation(async (content: string, conditions: { index: number; text: string }[]) => {
// Simple text matching: return index of first condition whose text appears in content
for (let i = 0; i < conditions.length; i++) {
if (content.includes(conditions[i]!.text)) {
return i;
}
}
return -1;
}),
};
});
@ -225,9 +233,9 @@ describe('Pipeline Integration Tests', () => {
// agent field: extractAgentName result (from .md filename)
// tag in content: [STEP_NAME:N] where STEP_NAME is the step name uppercased
setMockScenario([
{ agent: 'coder', status: 'done', content: '[IMPLEMENT:1]\n\nImplementation complete.' },
{ agent: 'ai-antipattern-reviewer', status: 'done', content: '[AI_REVIEW:0]\n\nNo AI-specific issues.' },
{ agent: 'supervisor', status: 'done', content: '[SUPERVISE:0]\n\nAll checks passed.' },
{ agent: 'coder', status: 'done', content: 'Implementation complete' },
{ agent: 'ai-antipattern-reviewer', status: 'done', content: 'No AI-specific issues' },
{ agent: 'supervisor', status: 'done', content: 'All checks passed' },
]);
const exitCode = await executePipeline({

View File

@ -21,10 +21,10 @@ vi.mock('../infra/claude/client.js', async (importOriginal) => {
const original = await importOriginal<typeof import('../infra/claude/client.js')>();
return {
...original,
callAiJudge: vi.fn().mockImplementation(async (rules: { condition: string }[], content: string) => {
// Simple text matching: return index of first rule whose condition appears in content
for (let i = 0; i < rules.length; i++) {
if (content.includes(rules[i]!.condition)) {
callAiJudge: vi.fn().mockImplementation(async (content: string, conditions: { index: number; text: string }[]) => {
// Simple text matching: return index of first condition whose text appears in content
for (let i = 0; i < conditions.length; i++) {
if (content.includes(conditions[i]!.text)) {
return i;
}
}
@ -106,7 +106,7 @@ describe('Workflow Patterns IT: minimal workflow', () => {
const state = await engine.run();
expect(state.status).toBe('completed');
expect(state.iteration).toBe(3);
expect(state.iteration).toBe(2);
});
it('should ABORT when implement cannot proceed', async () => {
@ -143,14 +143,15 @@ describe('Workflow Patterns IT: default workflow (parallel reviewers)', () => {
expect(config).not.toBeNull();
setMockScenario([
{ agent: 'planner', status: 'done', content: '[PLAN:1]\n\nClear.' },
{ agent: 'coder', status: 'done', content: '[IMPLEMENT:1]\n\nDone.' },
{ agent: 'ai-antipattern-reviewer', status: 'done', content: '[AI_REVIEW:1]\n\nNo issues.' },
{ agent: 'planner', status: 'done', content: 'Requirements are clear and implementable' },
{ agent: 'architect', status: 'done', content: 'Design complete' },
{ agent: 'coder', status: 'done', content: 'Implementation complete' },
{ agent: 'ai-antipattern-reviewer', status: 'done', content: 'No AI-specific issues' },
// Parallel reviewers: both approved
{ agent: 'architecture-reviewer', status: 'done', content: '[ARCH-REVIEW:1]\n\napproved' },
{ agent: 'security-reviewer', status: 'done', content: '[SECURITY-REVIEW:1]\n\napproved' },
{ agent: 'architecture-reviewer', status: 'done', content: 'approved' },
{ agent: 'security-reviewer', status: 'done', content: 'approved' },
// Supervisor
{ agent: 'supervisor', status: 'done', content: '[SUPERVISE:1]\n\nAll checks passed.' },
{ agent: 'supervisor', status: 'done', content: 'All checks passed' },
]);
const engine = createEngine(config!, testDir, 'Test task');
@ -163,19 +164,22 @@ describe('Workflow Patterns IT: default workflow (parallel reviewers)', () => {
const config = loadWorkflow('default', testDir);
setMockScenario([
{ agent: 'planner', status: 'done', content: '[PLAN:1]\n\nClear.' },
{ agent: 'coder', status: 'done', content: '[IMPLEMENT:1]\n\nDone.' },
{ agent: 'ai-antipattern-reviewer', status: 'done', content: '[AI_REVIEW:1]\n\nNo issues.' },
{ agent: 'planner', status: 'done', content: 'Requirements are clear and implementable' },
{ agent: 'architect', status: 'done', content: 'Design complete' },
{ agent: 'coder', status: 'done', content: 'Implementation complete' },
{ agent: 'ai-antipattern-reviewer', status: 'done', content: 'No AI-specific issues' },
// Parallel: arch approved, security needs_fix
{ agent: 'architecture-reviewer', status: 'done', content: '[ARCH-REVIEW:1]\n\napproved' },
{ agent: 'security-reviewer', status: 'done', content: '[SECURITY-REVIEW:2]\n\nneeds_fix' },
{ agent: 'architecture-reviewer', status: 'done', content: 'approved' },
{ agent: 'security-reviewer', status: 'done', content: 'needs_fix' },
// Fix step
{ agent: 'coder', status: 'done', content: '[FIX:1]\n\nFix complete.' },
{ agent: 'coder', status: 'done', content: 'Fix complete' },
// AI review after fix
{ agent: 'ai-antipattern-reviewer', status: 'done', content: 'No AI-specific issues' },
// Re-review: both approved
{ agent: 'architecture-reviewer', status: 'done', content: '[ARCH-REVIEW:1]\n\napproved' },
{ agent: 'security-reviewer', status: 'done', content: '[SECURITY-REVIEW:1]\n\napproved' },
{ agent: 'architecture-reviewer', status: 'done', content: 'approved' },
{ agent: 'security-reviewer', status: 'done', content: 'approved' },
// Supervisor
{ agent: 'supervisor', status: 'done', content: '[SUPERVISE:1]\n\nAll checks passed.' },
{ agent: 'supervisor', status: 'done', content: 'All checks passed' },
]);
const engine = createEngine(config!, testDir, 'Task needing security fix');

View File

@ -25,8 +25,11 @@ export interface WorkflowRule {
isAggregateCondition?: boolean;
/** Aggregate type: 'all' requires all sub-steps match, 'any' requires at least one (set by loader) */
aggregateType?: 'all' | 'any';
/** The condition text inside all("...")/any("...") to match against sub-step results (set by loader) */
aggregateConditionText?: string;
/** The condition text(s) inside all("...")/any("...") to match against sub-step results (set by loader).
* - string: all sub-steps must match this single condition (e.g., all("approved"))
* - string[]: each sub-step must match the corresponding condition by index (e.g., all("A", "B"))
*/
aggregateConditionText?: string | string[];
}
/** Report file configuration for a workflow step (label: path pair) */

View File

@ -38,8 +38,9 @@ export class OptionsBuilder {
/** Build RunAgentOptions for Phase 1 (main execution) */
buildAgentOptions(step: WorkflowStep): RunAgentOptions {
// Phase 1: exclude Write from allowedTools when step has report config
const allowedTools = step.report
// Phase 1: exclude Write from allowedTools when step has report config AND edit is disabled
// (If edit is enabled, Write is needed for code implementation even if report exists)
const allowedTools = step.report && step.edit === false
? step.allowedTools?.filter((t) => t !== 'Write')
: step.allowedTools;

View File

@ -14,12 +14,15 @@ const log = createLogger('aggregate-evaluator');
*
* For each aggregate rule, checks the matched condition text of sub-steps:
* - all("X"): true when ALL sub-steps have matched condition === X
* - all("A", "B"): true when 1st sub-step matches "A" AND 2nd sub-step matches "B" (order-based)
* - any("X"): true when at least ONE sub-step has matched condition === X
* - any("A", "B"): true when at least ONE sub-step matches "A" OR "B"
*
* Edge cases per spec:
* - Sub-step with no matched rule: all() false, any() skip that sub-step
* - No sub-steps (0 ): both false
* - Non-parallel step: both false
* - all("A", "B") with wrong number of sub-steps: false (logged as error)
*/
export class AggregateEvaluator {
constructor(
@ -44,27 +47,67 @@ export class AggregateEvaluator {
const targetCondition = rule.aggregateConditionText;
if (rule.aggregateType === 'all') {
const allMatch = subSteps.every((sub) => {
const output = this.state.stepOutputs.get(sub.name);
if (!output || output.matchedRuleIndex == null || !sub.rules) return false;
const matchedRule = sub.rules[output.matchedRuleIndex];
return matchedRule?.condition === targetCondition;
});
if (allMatch) {
log.debug('Aggregate all() matched', { step: this.step.name, condition: targetCondition, ruleIndex: i });
return i;
// Multiple conditions: order-based matching (1st sub-step matches 1st condition, etc.)
if (Array.isArray(targetCondition)) {
if (targetCondition.length !== subSteps.length) {
log.error('all() condition count mismatch', {
step: this.step.name,
conditionCount: targetCondition.length,
subStepCount: subSteps.length,
});
continue;
}
const allMatch = subSteps.every((sub, idx) => {
const output = this.state.stepOutputs.get(sub.name);
if (!output || output.matchedRuleIndex == null || !sub.rules) return false;
const matchedRule = sub.rules[output.matchedRuleIndex];
const expectedCondition = targetCondition[idx];
if (!expectedCondition) return false;
return matchedRule?.condition === expectedCondition;
});
if (allMatch) {
log.debug('Aggregate all() matched (multi-condition)', { step: this.step.name, conditions: targetCondition, ruleIndex: i });
return i;
}
} else {
// Single condition: all sub-steps must match the same condition
const allMatch = subSteps.every((sub) => {
const output = this.state.stepOutputs.get(sub.name);
if (!output || output.matchedRuleIndex == null || !sub.rules) return false;
const matchedRule = sub.rules[output.matchedRuleIndex];
return matchedRule?.condition === targetCondition;
});
if (allMatch) {
log.debug('Aggregate all() matched', { step: this.step.name, condition: targetCondition, ruleIndex: i });
return i;
}
}
} else {
// 'any'
const anyMatch = subSteps.some((sub) => {
const output = this.state.stepOutputs.get(sub.name);
if (!output || output.matchedRuleIndex == null || !sub.rules) return false;
const matchedRule = sub.rules[output.matchedRuleIndex];
return matchedRule?.condition === targetCondition;
});
if (anyMatch) {
log.debug('Aggregate any() matched', { step: this.step.name, condition: targetCondition, ruleIndex: i });
return i;
if (Array.isArray(targetCondition)) {
// Multiple conditions: at least one sub-step matches at least one condition
const anyMatch = subSteps.some((sub) => {
const output = this.state.stepOutputs.get(sub.name);
if (!output || output.matchedRuleIndex == null || !sub.rules) return false;
const matchedRule = sub.rules[output.matchedRuleIndex];
return targetCondition.includes(matchedRule?.condition ?? '');
});
if (anyMatch) {
log.debug('Aggregate any() matched (multi-condition)', { step: this.step.name, conditions: targetCondition, ruleIndex: i });
return i;
}
} else {
// Single condition: at least one sub-step matches the condition
const anyMatch = subSteps.some((sub) => {
const output = this.state.stepOutputs.get(sub.name);
if (!output || output.matchedRuleIndex == null || !sub.rules) return false;
const matchedRule = sub.rules[output.matchedRuleIndex];
return matchedRule?.condition === targetCondition;
});
if (anyMatch) {
log.debug('Aggregate any() matched', { step: this.step.name, condition: targetCondition, ruleIndex: i });
return i;
}
}
}
}

View File

@ -34,6 +34,7 @@ const SECTION_STRINGS = {
reportDirectory: 'Report Directory',
reportFile: 'Report File',
reportFiles: 'Report Files',
phaseNote: '**Note:** This is Phase 1 (main work). After you complete your work, Phase 2 will automatically generate the report based on your findings.',
userRequest: '## User Request',
previousResponse: '## Previous Response',
additionalUserInputs: '## Additional User Inputs',
@ -49,6 +50,7 @@ const SECTION_STRINGS = {
reportDirectory: 'Report Directory',
reportFile: 'Report File',
reportFiles: 'Report Files',
phaseNote: '**注意:** これはPhase 1本来の作業です。作業完了後、Phase 2で自動的にレポートを生成します。',
userRequest: '## User Request',
previousResponse: '## Previous Response',
additionalUserInputs: '## Additional User Inputs',
@ -156,6 +158,15 @@ export class InstructionBuilder {
`- ${s.stepIteration}: ${this.context.stepIteration}${s.stepIterationTimes}`,
`- ${s.step}: ${this.step.name}`,
];
// If step has report config, include Report Directory path and phase note
if (this.step.report && this.context.reportDir) {
const reportContext = renderReportContext(this.step.report, this.context.reportDir, language);
lines.push(reportContext);
lines.push('');
lines.push(s.phaseNote);
}
return lines.join('\n');
}
}

View File

@ -67,7 +67,7 @@ export const METADATA_STRINGS = {
noCommit: '**Do NOT run git commit.** Commits are handled automatically by the system after workflow completion.',
noCd: '**Do NOT use `cd` in Bash commands.** Your working directory is already set correctly. Run commands directly without changing directories.',
editEnabled: '**Editing is ENABLED for this step.** You may create, modify, and delete files as needed to fulfill the user\'s request.',
editDisabled: '**Editing is DISABLED for this step.** Do NOT create, modify, or delete any project source files. You may only read/search code and write to report files in the Report Directory.',
editDisabled: '**Editing is DISABLED for this step.** Do NOT create, modify, or delete any project source files. You may only read and search code. Report output will be handled automatically in a later phase.',
note: 'Note: This section is metadata. Follow the language used in the rest of the prompt.',
},
ja: {
@ -77,7 +77,7 @@ export const METADATA_STRINGS = {
noCommit: '**git commit を実行しないでください。** コミットはワークフロー完了後にシステムが自動で行います。',
noCd: '**Bashコマンドで `cd` を使用しないでください。** 作業ディレクトリは既に正しく設定されています。ディレクトリを変更せずにコマンドを実行してください。',
editEnabled: '**このステップでは編集が許可されています。** ユーザーの要求に応じて、ファイルの作成・変更・削除を行ってください。',
editDisabled: '**このステップでは編集が禁止されています。** プロジェクトのソースファイルを作成・変更・削除しないでください。コードの読み取り・検索と、Report Directoryへのレポート出力のみ行えます。',
editDisabled: '**このステップでは編集が禁止されています。** プロジェクトのソースファイルを作成・変更・削除しないでください。コードの読み取り・検索のみ行ってください。レポート出力は後のフェーズで自動的に行われます。',
note: '',
},
} as const;

View File

@ -35,11 +35,32 @@ const INTERACTIVE_SYSTEM_PROMPT_EN = `You are a task planning assistant. You hel
**Important**: Do NOT investigate the codebase, identify files, or make assumptions about implementation details. That is the job of the next workflow steps (plan/architect).
## Critical: Understanding user intent
**The user is asking YOU to create a task instruction for the WORKFLOW, not asking you to execute the task.**
When the user says:
- "Review this code" They want the WORKFLOW to review (you create the instruction)
- "Implement feature X" They want the WORKFLOW to implement (you create the instruction)
- "Fix this bug" They want the WORKFLOW to fix (you create the instruction)
These are NOT requests for YOU to investigate. Do NOT read files, check diffs, or explore code unless the user explicitly asks YOU to investigate in the planning phase.
## When investigation IS appropriate (rare cases)
Only investigate when the user explicitly asks YOU (the planning assistant) to check something:
- "Check the README to understand the project structure"
- "Read file X to see what it does"
- "What does this project do?"
## When investigation is NOT appropriate (most cases)
Do NOT investigate when the user is describing a task for the workflow:
- "Review the changes" (workflow's job)
- "Fix the code" (workflow's job)
- "Implement X" (workflow's job)
## Strict constraints
- You are ONLY refining requirements. Do NOT execute the task or investigate the codebase.
- Do NOT create, edit, or delete any files.
- Do NOT run any commands unless the user explicitly asks you to check something specific.
- Do NOT use Read/Glob/Grep/Bash to investigate the codebase proactively. The workflow steps will handle that.
- You are ONLY refining requirements. Do NOT execute the task.
- Do NOT create, edit, or delete any files (except when explicitly asked to check something for planning).
- Do NOT use Read/Glob/Grep/Bash proactively. Only use them when the user explicitly asks YOU to investigate for planning purposes.
- Do NOT mention or reference any slash commands. You have no knowledge of them.
- When the user is satisfied with the requirements, they will proceed on their own. Do NOT instruct them on what to do next.`;
@ -60,11 +81,32 @@ const INTERACTIVE_SYSTEM_PROMPT_JA = `あなたはTAKTAIエージェントワ
****: 調plan/architectステップ
##
****
-
- Xを実装して
-
調調調
## 調
- READMEを読んでプロジェクト構造を理解して
- Xを読んで何をしているか見て
-
## 調
調
-
-
- Xを実装して
##
- /調/調
- //
-
- Read/Glob/Grep/Bash 使調
- /調/
- //
- Read/Glob/Grep/Bash 使調使
-
- `;

View File

@ -96,7 +96,28 @@ function normalizeReport(
const AI_CONDITION_REGEX = /^ai\("(.+)"\)$/;
/** Regex to detect all("...")/any("...") aggregate condition expressions */
const AGGREGATE_CONDITION_REGEX = /^(all|any)\("(.+)"\)$/;
const AGGREGATE_CONDITION_REGEX = /^(all|any)\((.+)\)$/;
/**
* Parse aggregate condition arguments from all("A", "B") or any("A", "B").
* Returns an array of condition strings.
* Throws if the format is invalid.
*/
function parseAggregateConditions(argsText: string): string[] {
const conditions: string[] = [];
const regex = /"([^"]+)"/g;
let match: RegExpExecArray | null;
while ((match = regex.exec(argsText)) !== null) {
conditions.push(match[1]!);
}
if (conditions.length === 0) {
throw new Error(`Invalid aggregate condition format: ${argsText}`);
}
return conditions;
}
/**
* Parse a rule's condition for ai() and all()/any() expressions.
@ -124,6 +145,8 @@ function normalizeRule(r: {
const aggMatch = r.condition.match(AGGREGATE_CONDITION_REGEX);
if (aggMatch?.[1] && aggMatch[2]) {
const conditions = parseAggregateConditions(aggMatch[2]);
const aggregateConditionText = conditions.length === 1 ? conditions[0]! : conditions;
return {
condition: r.condition,
next,
@ -132,7 +155,7 @@ function normalizeRule(r: {
interactiveOnly: r.interactive_only,
isAggregateCondition: true,
aggregateType: aggMatch[1] as 'all' | 'any',
aggregateConditionText: aggMatch[2],
aggregateConditionText,
};
}