mcpField
U
unified-execute-with-file

unified-execute-with-file

github.com/catlog22エージェントワークフロー2.1k54 回インストール19 週間前に更新
リポジトリ

unified-execute-with-file について

タスク JSON の計画を依存順に実行する開発ワークフロー用スキルです。実行後の収束条件確認と進捗記録を行い、ディレクトリまたは単一 JSON ファイルを受け付けます。

主な機能

  1. 01依存関係順の逐次実行
  2. 02実行後の収束条件チェック
  3. 03概要とイベントログの記録
  4. 04ドライランと自動コミット
  5. 05ディレクトリまたは単一ファイル入力

活用シーン

  1. 01複数タスクからなる開発計画の実行
  2. 02実行前の依存関係とファイル競合の確認
  3. 03ファイルを変更せずに計画をシミュレーション

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/catlog22/claude-code-workflow --skill unified-execute-with-file

インストール後、Claude Code で/unified-execute-with-fileを入力して読み込まれたか確認します。

詳細

Unified-Execute-With-File ワークフロー

クイックスタート

.task/*.json ディレクトリを読み込み、収束の検証と進捗の追跡を行いながらタスクを順次実行する汎用実行エンジンです。

# Execute from lite-plan output
/codex:unified-execute-with-file PLAN=".workflow/.lite-plan/LPLAN-auth-2025-01-21/.task/"

# Execute from workflow session output
/codex:unified-execute-with-file PLAN=".workflow/active/WFS-xxx/.task/" --auto-commit

# Execute a single task JSON file
/codex:unified-execute-with-file PLAN=".workflow/active/WFS-xxx/.task/IMPL-001.json" --dry-run

# Auto-detect from .workflow/ directories
/codex:unified-execute-with-file

主なワークフロー:.task/*.json をスキャン → 検証 → 実行前分析 → 実行 → 収束の検証 → 進捗の追跡

主な機能:

  • ディレクトリベース:個別のタスク JSON ファイルを含む .task/ ディレクトリを読み込みます
  • 収束を重視:実行後に各タスクの収束条件を検証します
  • 逐次実行:依存関係を追跡しながら、トポロジカル順序でタスクを処理します
  • 二重の進捗追跡:execution.md(概要)と execution-events.md(イベントストリーム)
  • 自動コミット:タスクごとに任意で Conventional Commits 形式のコミットを行います
  • ドライランモード:変更を加えずに実行をシミュレートします
  • 柔軟な入力:.task/ ディレクトリのパス、または単一の .json ファイルのパスを受け付けます

入力形式:各タスクは .task/ ディレクトリ内の独立した JSON ファイルです(例:IMPL-001.json)。ほかの形式を .task/*.json に変換するには、あらかじめ plan-converter を使用してください。

概要

┌─────────────────────────────────────────────────────────────┐
│                   UNIFIED EXECUTE WORKFLOW                    │
├─────────────────────────────────────────────────────────────┤
│                                                               │
│  Phase 1: Load & Validate                                     │
│     ├─ Scan .task/*.json (one task per file)                   │
│     ├─ Validate schema (id, title, depends_on, convergence)   │
│     ├─ Detect cycles, build topological order                 │
│     └─ Initialize execution.md + execution-events.md          │
│                                                               │
│  Phase 2: Pre-Execution Analysis                              │
│     ├─ Check file conflicts (multiple tasks → same file)      │
│     ├─ Verify file existence                                  │
│     ├─ Generate feasibility report                            │
│     └─ User confirmation (unless dry-run)                     │
│                                                               │
│  Phase 3: Serial Execution + Convergence Verification         │
│     For each task in topological order:                        │
│     ├─ Check dependencies satisfied                           │
│     ├─ Record START event                                     │
│     ├─ Execute directly (Read/Edit/Write/Grep/Glob/Bash)      │
│     ├─ Verify convergence.criteria[]                          │
│     ├─ Run convergence.verification command                   │
│     ├─ Record COMPLETE/FAIL event with verification results   │
│     ├─ Update _execution state in task JSON file               │
│     └─ Auto-commit if enabled                                 │
│                                                               │
│  Phase 4: Completion                                          │
│     ├─ Finalize execution.md with summary statistics          │
│     ├─ Finalize execution-events.md with session footer       │
│     ├─ Write back .task/*.json with _execution states          │
│     └─ Offer follow-up actions                                │
│                                                               │
└─────────────────────────────────────────────────────────────┘

出力構成

${projectRoot}/.workflow/.execution/EXEC-{slug}-{date}-{random}/
├── execution.md              # Plan overview + task table + summary
└── execution-events.md       # ⭐ Unified event log (single source of truth)

さらに、各ソース .task/*.json ファイルは _execution の状態でインプレース更新されます。


実装の詳細

セッションの初期化
ステップ 0:セッションを初期化
const getUtc8ISOString = () => new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString()
const projectRoot = Bash(`git rev-parse --show-toplevel 2>/dev/null || pwd`).trim()

// Parse arguments
const autoCommit = $ARGUMENTS.includes('--auto-commit')
const dryRun = $ARGUMENTS.includes('--dry-run')
const planMatch = $ARGUMENTS.match(/PLAN="([^"]+)"/) || $ARGUMENTS.match(/PLAN=(\S+)/)
let planPath = planMatch ? planMatch[1] : null

// Auto-detect if no PLAN specified
if (!planPath) {
  // Search in order (most recent first):
  //   .workflow/active/*/.task/
  //   .workflow/.lite-plan/*/.task/
  //   .workflow/.req-plan/*/.task/
  //   .workflow/.planning/*/.task/
  // Use most recently modified directory containing *.json files
}

// Resolve path
planPath = path.isAbsolute(planPath) ? planPath : `${projectRoot}/${planPath}`

// Generate session ID
const slug = path.basename(path.dirname(planPath)).toLowerCase().substring(0, 30)
const dateStr = getUtc8ISOString().substring(0, 10)
const random = Math.random().toString(36).substring(2, 9)
const sessionId = `EXEC-${slug}-${dateStr}-${random}`
const sessionFolder = `${projectRoot}/.workflow/.execution/${sessionId}`

Bash(`mkdir -p ${sessionFolder}`)

フェーズ 1:読み込みと検証

目的:.task/ ディレクトリをスキャンし、個別のタスク JSON ファイルを解析して、スキーマと依存関係を検証し、実行順序を構築します。

ステップ 1.1:.task/ ディレクトリをスキャンし、タスクファイルを解析
// Determine if planPath is a directory or single file
const isDirectory = planPath.endsWith('/') || Bash(`test -d "${planPath}" && echo dir || echo file`).trim() === 'dir'

let taskFiles, tasks

if (isDirectory) {
  // Directory mode: scan for all *.json files
  taskFiles = Glob('*.json', planPath)
  if (taskFiles.length === 0) throw new Error(`No .json files found in ${planPath}`)

  tasks = taskFiles.map(filePath => {
    try {
      const content = Read(filePath)
      const task = JSON.parse(content)
      task._source_file = filePath  // Track source file for write-back
      return task
    } catch (e) {
      throw new Error(`${path.basename(filePath)}: Invalid JSON - ${e.message}`)
    }
  })
} else {
  // Single file mode: parse one task JSON
  try {
    const content = Read(planPath)
    const task = JSON.parse(content)
    task._source_file = planPath
    tasks = [task]
  } catch (e) {
    throw new Error(`${path.basename(planPath)}: Invalid JSON - ${e.message}`)
  }
}

if (tasks.length === 0) throw new Error('No tasks found')
ステップ 1.2:スキーマを検証

統合タスクスキーマに照らして検証します:~/.ccw/workflows/cli-templates/schemas/task-schema.json

const errors = []
tasks.forEach((task, i) => {
  const src = task._source_file ? path.basename(task._source_file) : `Task ${i + 1}`

  // Required fields (per task-schema.json)
  if (!task.id) errors.push(`${src}: missing 'id'`)
  if (!task.title) errors.push(`${src}: missing 'title'`)
  if (!task.description) errors.push(`${src}: missing 'description'`)
  if (!Array.isArray(task.depends_on)) errors.push(`${task.id || src}: missing 'depends_on' array`)

  // Context block (optional but validated if present)
  if (task.context) {
    if (task.context.requirements && !Array.isArray(task.context.requirements))
      errors.push(`${task.id}: context.requirements must be array`)
    if (task.context.acceptance && !Array.isArray(task.context.acceptance))
      errors.push(`${task.id}: context.acceptance must be array`)
    if (task.context.focus_paths && !Array.isArray(task.context.focus_paths))
      errors.push(`${task.id}: context.focus_paths must be array`)
  }

  // Convergence (required for execution verification)
  if (!task.convergence) {
    errors.push(`${task.id || src}: missing 'convergence'`)
  } else {
    if (!task.convergence.criteria?.length) errors.push(`${task.id}: empty convergence.criteria`)
    if (!task.convergence.verification) errors.push(`${task.id}: missing convergence.verification`)
    if (!task.convergence.definition_of_done) errors.push(`${task.id}: missing convergence.definition_of_done`)
  }

  // Flow control (optional but validated if present)
  if (task.flow_control) {
    if (task.flow_control.target_files && !Array.isArray(task.flow_control.target_files))
      errors.push(`${task.id}: flow_control.target_files must be array`)
  }

  // New unified schema fields (backward compatible addition)
  if (task.focus_paths && !Array.isArray(task.focus_paths))
    errors.push(`${task.id}: focus_paths must be array`)
  if (task.implementation && !Array.isArray(task.implementation))
    errors.push(`${task.id}: implementation must be array`)
  if (task.files && !Array.isArray(task.files))
    errors.push(`${task.id}: files must be array`)
})

if (errors.length) {
  // Report errors, stop execution
}
ステップ 1.3:実行順序を構築
// 1. Validate dependency references
const taskIds = new Set(tasks.map(t => t.id))
tasks.forEach(task => {
  task.depends_on.forEach(dep => {
    if (!taskIds.has(dep)) errors.push(`${task.id}: depends on unknown task '${dep}'`)
  })
})

// 2. Detect cycles (DFS)
function detectCycles(tasks) {
  const graph = new Map(tasks.map(t => [t.id, t.depends_on || []]))
  const visited = new Set(), inStack = new Set(), cycles = []
  function dfs(node, path) {
    if (inStack.has(node)) { cycles.push([...path, node].join(' → ')); return }
    if (visited.has(node)) return
    visited.add(node); inStack.add(node)
    ;(graph.get(node) || []).forEach(dep => dfs(dep, [...path, node]))
    inStack.delete(node)
  }
  tasks.forEach(t => { if (!visited.has(t.id)) dfs(t.id, []) })
  return cycles
}
const cycles = detectCycles(tasks)
if (cycles.length) errors.push(`Circular dependencies: ${cycles.join('; ')}`)

// 3. Topological sort
function topoSort(tasks) {
  const inDegree = new Map(tasks.map(t => [t.id, 0]))
  tasks.forEach(t => t.depends_on.forEach(dep => {
    inDegree.set(t.id, (inDegree.get(t.id) || 0) + 1)
  }))
  const queue = tasks.filter(t => inDegree.get(t.id) === 0).map(t => t.id)
  const order = []
  while (queue.length) {
    const id = queue.shift()
    order.push(id)
    tasks.forEach(t => {
      if (t.depends_on.includes(id)) {
        inDegree.set(t.id, inDegree.get(t.id) - 1)
        if (inDegree.get(t.id) === 0) queue.push(t.id)
      }
    })
  }
  return order
}
const executionOrder = topoSort(tasks)
ステップ 1.4:実行アーティファクトを初期化
// execution.md
const executionMd = `# Execution Overview

## Session Info
- **Session ID**: ${sessionId}
- **Plan Source**: ${planPath}
- **Started**: ${getUtc8ISOString()}
- **Total Tasks**: ${tasks.length}
- **Mode**: ${dryRun ? 'Dry-run (no changes)' : 'Direct inline execution'}
- **Auto-Commit**: ${autoCommit ? 'Enabled' : 'Disabled'}

## Task Overview

| # | ID | Title | Type | Priority | Effort | Dependencies | Status |
|---|-----|-------|------|----------|--------|--------------|--------|
${tasks.map((t, i) => `| ${i+1} | ${t.id} | ${t.title} | ${t.type || '-'} | ${t.priority || '-'} | ${t.effort || '-'} | ${t.depends_on.join(', ') || '-'} | pending |`).join('\n')}

## Pre-Execution Analysis
> Populated in Phase 2

## Execution Timeline
> Updated as tasks complete

## Execution Summary
> Updated after all tasks complete
`
Write(`${sessionFolder}/execution.md`, executionMd)

// execution-events.md
Write(`${sessionFolder}/execution-events.md`, `# Execution Events

**Session**: ${sessionId}
**Started**: ${getUtc8ISOString()}
**Source**: ${planPath}

---

`)

フェーズ 2:実行前分析

目的:実行前に実現可能性を検証し、問題を特定します。

ステップ 2.1:ファイルの競合を分析
const fileTaskMap = new Map()  // file → [taskIds]
tasks.forEach(task => {
  (task.files || []).forEach(f => {
    const key = f.path
    if (!fileTaskMap.has(key)) fileTaskMap.set(key, [])
    fileTaskMap.get(key).push(task.id)
  })
})

const conflicts = []
fileTaskMap.forEach((taskIds, file) => {
  if (taskIds.length > 1) {
    conflicts.push({ file, tasks: taskIds, resolution: 'Execute in dependency order' })
  }
})

// Check file existence
const missingFiles = []
tasks.forEach(task => {
  (task.files || []).forEach(f => {
    if (f.action !== 'create' && !file_exists(f.path)) {
      missingFiles.push({ file: f.path, task: task.id })
    }
  })
})
ステップ 2.2:execution.md に追記
// Replace "Pre-Execution Analysis" section with:
// - File Conflicts (list or "No conflicts")
// - Missing Files (list or "All files exist")
// - Dependency Validation (errors or "No issues")
// - Execution Order (numbered list)
ステップ 2.3:ユーザーの確認
if (!dryRun) {
  request_user_input({
    questions: [{
      header: "Confirm",
      id: "confirm_execute",
      question: `Execute ${tasks.length} tasks?`,
      options: [
        { label: "Execute (Recommended)", description: "Start serial execution" },
        { label: "Dry Run", description: "Simulate without changes" },
        { label: "Cancel", description: "Abort execution" }
      ]
    }]
  })
  // answer.answers.confirm_execute.answers[0] → selected label
}

フェーズ 3:逐次実行と収束の検証

目的:タスクを順番に実行し、各タスクの実行後に収束を検証して、すべての状態を追跡します。

実行モデル:インラインで直接実行します。メインプロセスがファイルを直接読み取り、編集し、書き込みます。CLI への委譲は行いません。

ステップ 3.1:実行ループ
const completedTasks = new Set()
const failedTasks = new Set()
const skippedTasks = new Set()

for (const taskId of executionOrder) {
  const task = tasks.find(t => t.id === taskId)
  const startTime = getUtc8ISOString()

  // 1. Check dependencies
  const unmetDeps = task.depends_on.filter(dep => !completedTasks.has(dep))
  if (unmetDeps.length) {
    appendToEvents(task, 'BLOCKED', `Unmet dependencies: ${unmetDeps.join(', ')}`)
    skippedTasks.add(task.id)
    task._execution = { status: 'skipped', executed_at: startTime,
      result: { success: false, error: `Blocked by: ${unmetDeps.join(', ')}` } }
    continue
  }

  // 2. Record START event
  appendToEvents(`## ${getUtc8ISOString()} — ${task.id}: ${task.title}

**Type**: ${task.type || '-'} | **Priority**: ${task.priority || '-'} | **Effort**: ${task.effort || '-'}
**Status**: ⏳ IN PROGRESS
**Files**: ${(task.files || []).map(f => f.path).join(', ') || 'To be determined'}
**Description**: ${task.description}
**Convergence Criteria**:
${task.convergence.criteria.map(c => `- [ ] ${c}`).join('\n')}

### Execution Log
`)

  if (dryRun) {
    // Simulate: mark as completed without changes
    appendToEvents(`\n**Status**: ⏭ DRY RUN (no changes)\n\n---\n`)
    task._execution = { status: 'completed', executed_at: startTime,
      result: { success: true, summary: 'Dry run — no changes made' } }
    completedTasks.add(task.id)
    continue
  }

  // 3. Execute task directly
  //    - Read each file in task.files (if specified)
  //    - Analyze what changes satisfy task.description + task.convergence.criteria
  //    - If task.files has detailed changes, use them as guidance
  //    - Apply changes using Edit (preferred) or Write (for new files)
  //    - Use Grep/Glob/mcp__ace-tool for discovery if needed
  //    - Use Bash for build/test commands

  // Dual-path field access (supports both unified and legacy 6-field schema)
  // const targetFiles = task.files?.map(f => f.path) || task.flow_control?.target_files || []
  // const acceptanceCriteria = task.convergence?.criteria || task.context?.acceptance || []
  // const requirements = task.implementation || task.context?.requirements || []
  // const focusPaths = task.focus_paths || task.context?.focus_paths || []

  // 4. Verify convergence
  const convergenceResults = verifyConvergence(task)

  const endTime = getUtc8ISOString()
  const filesModified = getModifiedFiles()

  if (convergenceResults.allPassed) {
    // 5a. Record SUCCESS
    appendToEvents(`
**Status**: ✅ COMPLETED
**Duration**: ${calculateDuration(startTime, endTime)}
**Files Modified**: ${filesModified.join(', ')}

#### Changes Summary
${changeSummary}

#### Convergence Verification
${task.convergence.criteria.map((c, i) => `- [${convergenceResults.verified[i] ? 'x' : ' '}] ${c}`).join('\n')}
- **Verification**: ${convergenceResults.verificationOutput}
- **Definition of Done**: ${task.convergence.definition_of_done}

---
`)
    task._execution = {
      status: 'completed', executed_at: endTime,
      result: {
        success: true,
        files_modified: filesModified,
        summary: changeSummary,
        convergence_verified: convergenceResults.verified
      }
    }
    completedTasks.add(task.id)
  } else {
    // 5b. Record FAILURE
    handleTaskFailure(task, convergenceResults, startTime, endTime)
  }

  // 6. Auto-commit if enabled
  if (autoCommit && task._execution.status === 'completed') {
    autoCommitTask(task, filesModified)
  }
}
ステップ 3.2:収束の検証
function verifyConvergence(task) {
  const results = {
    verified: [],           // boolean[] per criterion
    verificationOutput: '', // output of verification command
    allPassed: true
  }

  // 1. Check each criterion
  //    For each criterion in task.convergence.criteria:
  //      - If it references a testable condition, check it
  //      - If it's manual, mark as verified based on changes made
  //      - Record true/false per criterion
  task.convergence.criteria.forEach(criterion => {
    const passed = evaluateCriterion(criterion, task)
    results.verified.push(passed)
    if (!passed) results.allPassed = false
  })

  // 2. Run verification command (if executable)
  const verification = task.convergence.verification
  if (isExecutableCommand(verification)) {
    try {
      const output = Bash(verification, { timeout: 120000 })
      results.verificationOutput = `${verification} → PASS`
    } catch (e) {
      results.verificationOutput = `${verification} → FAIL: ${e.message}`
      results.allPassed = false
    }
  } else {
    results.verificationOutput = `Manual: ${verification}`
  }

  return results
}

function isExecutableCommand(verification) {
  // Detect executable patterns: npm, npx, jest, tsc, curl, pytest, go test, etc.
  return /^(npm|npx|jest|tsc|eslint|pytest|go\s+test|cargo\s+test|curl|make)/.test(verification.trim())
}
ステップ 3.3:失敗時の処理
function handleTaskFailure(task, convergenceResults, startTime, endTime) {
  appendToEvents(`
**Status**: ❌ FAILED
**Duration**: ${calculateDuration(startTime, endTime)}
**Error**: Convergence verification failed

#### Failed Criteria
${task.convergence.criteria.map((c, i) => `- [${convergenceResults.verified[i] ? 'x' : ' '}] ${c}`).join('\n')}
- **Verification**: ${convergenceResults.verificationOutput}

---
`)

  task._execution = {
    status: 'failed', executed_at: endTime,
    result: {
      success: false,
      error: 'Convergence verification failed',
      convergence_verified: convergenceResults.verified
    }
  }
  failedTasks.add(task.id)

  // Ask user
  request_user_input({
    questions: [{
      header: "Failure",
      id: "handle_failure",
      question: `Task ${task.id} failed convergence verification. How to proceed?`,
      options: [
        { label: "Skip & Continue (Recommended)", description: "Skip this task, continue with next" },
        { label: "Retry", description: "Retry this task" },
        { label: "Abort", description: "Stop execution, keep progress" }
      ]
    }]
  })
  // answer.answers.handle_failure.answers[0] → selected label
}
ステップ 3.4:自動コミット
function autoCommitTask(task, filesModified) {
  Bash(`git add ${filesModified.join(' ')}`)

  const commitType = {
    fix: 'fix', refactor: 'refactor', feature: 'feat',
    enhancement: 'feat', testing: 'test', infrastructure: 'chore'
  }[task.type] || 'chore'

  const scope = inferScope(filesModified)

  Bash(`git commit -m "$(cat <<'EOF'
${commitType}(${scope}): ${task.title}

Task: ${task.id}
Source: ${path.basename(planPath)}
EOF
)"`)

  appendToEvents(`**Commit**: \`${commitType}(${scope}): ${task.title}\`\n`)
}

フェーズ 4:完了

目的:すべてのアーティファクトを確定し、実行状態を書き戻して、後続の操作を提示します。

ステップ 4.1:execution.md を確定

execution.md に概要統計を追記します:

const summary = `
## Execution Summary

- **Completed**: ${getUtc8ISOString()}
- **Total Tasks**: ${tasks.length}
- **Succeeded**: ${completedTasks.size}
- **Failed**: ${failedTasks.size}
- **Skipped**: ${skippedTasks.size}
- **Success Rate**: ${Math.round(completedTasks.size / tasks.length * 100)}%

### Task Results

| ID | Title | Status | Convergence | Files Modified |
|----|-------|--------|-------------|----------------|
${tasks.map(t => {
  const ex = t._execution || {}
  const convergenceStatus = ex.result?.convergence_verified
    ? `${ex.result.convergence_verified.filter(v => v).length}/${ex.result.convergence_verified.length}`
    : '-'
  return `| ${t.id} | ${t.title} | ${ex.status || 'pending'} | ${convergenceStatus} | ${(ex.result?.files_modified || []).join(', ') || '-'} |`
}).join('\n')}

${failedTasks.size > 0 ? `### Failed Tasks

${[...failedTasks].map(id => {
  const t = tasks.find(t => t.id === id)
  return `- **${t.id}**: ${t.title} — ${t._execution?.result?.error || 'Unknown'}`
}).join('\n')}
` : ''}
### Artifacts
- **Plan Source**: ${planPath}
- **Execution Overview**: ${sessionFolder}/execution.md
- **Execution Events**: ${sessionFolder}/execution-events.md
`
// Append to execution.md
ステップ 4.2:execution-events.md を確定
appendToEvents(`
---

# Session Summary

- **Session**: ${sessionId}
- **Completed**: ${getUtc8ISOString()}
- **Tasks**: ${completedTasks.size} completed, ${failedTasks.size} failed, ${skippedTasks.size} skipped
- **Total Events**: ${completedTasks.size + failedTasks.size + skippedTasks.size}
`)
ステップ 4.3:_execution を使って .task/*.json に書き戻す

各ソースタスク JSON ファイルを実行状態で更新します:

tasks.forEach(task => {
  const filePath = task._source_file
  if (!filePath) return

  // Read current file to preserve formatting and non-execution fields
  const current = JSON.parse(Read(filePath))

  // Update _execution status and result
  current._execution = {
    status: task._execution?.status || 'pending',
    executed_at: task._execution?.executed_at || null,
    result: task._execution?.result || null
  }

  // Write back individual task file
  Write(filePath, JSON.stringify(current, null, 2))
})
// Each task JSON file now has _execution: { status, executed_at, result }
ステップ 4.4:完了後のオプション
request_user_input({
  questions: [{
    header: "Post Execute",
    id: "post_execute",
    question: `Execution complete: ${completedTasks.size}/${tasks.length} succeeded. Next step?`,
    options: [
      { label: "Done (Recommended)", description: "End workflow" },
      { label: "Retry Failed", description: `Re-execute ${failedTasks.size} failed tasks` },
      { label: "Create Issue", description: "Create issue from failed tasks" }
    ]
  }]
})
// answer.answers.post_execute.answers[0] → selected label
選択項目アクション
失敗したタスクを再試行_execution.status === 'failed' のタスクを抽出して再実行し、[RETRY] イベントを追記します
イベントを表示execution-events.md の内容を表示します
Issue を作成失敗したタスクの詳細から Skill(skill="issue:new", args="...") を実行します
完了アーティファクトのパスを表示し、セッション状態を同期して、ワークフローを終了します
ステップ 4.5:セッション状態を同期

完了後(ユーザーの選択にかかわらず)、--dry-run が指定されていない場合:

$session-sync -y "Execution complete: {completed}/{total} tasks succeeded"

実行で得られた知見で specs/*.md を更新し、project-tech.json に開発インデックスのエントリーを追加します。


設定

フラグデフォルト説明
PLAN="..."自動検出.task/ ディレクトリ、または単一のタスク .json ファイルへのパス
--auto-commitfalseタスクの成功後に変更をコミットします
--dry-runfalse変更を加えずに実行をシミュレートします
プランの自動検出順序

PLAN が指定されていない場合は、次の順序で .task/ ディレクトリを検索します(最新のものが先):

  1. .workflow/active/*/.task/
  2. .workflow/.lite-plan/*/.task/
  3. .workflow/.req-plan/*/.task/
  4. .workflow/.planning/*/.task/

ソースが .task/*.json ではない場合:まず plan-converter を実行して .task/ ディレクトリを生成します。


エラー処理と復旧

状況対応復旧方法
.task/ ディレクトリが見つからないパスを含むエラーを報告パスを確認し、plan-converter を実行
タスクファイルの JSON が無効ファイル名とエラーを報告タスク JSON ファイルを手動で修正
収束条件が不足している検証エラーを報告plan-converter を実行して収束条件を追加
循環依存停止し、循環パスを報告タスク JSON の依存関係を修正
タスクの実行に失敗events に記録し、ユーザーに確認再試行、スキップ、承認、または中止
収束検証に失敗タスクを失敗としてマークし、ユーザーに確認コードを修正して再試行するか、承認
検証コマンドがタイムアウト未検証としてマーク手動での検証が必要
実行中にファイルの競合が発生events に記録依存関係の順序で解決
すべてのタスクに失敗報告し、プランの見直しを提案再分析または手動での介入

ベストプラクティス

実行前
  1. プランを検証:まず --dry-run を使用して、プランの実行可能性を確認します
  2. 収束条件を確認:すべてのタスクに意味のある収束基準があることを確認します
  3. 依存関係を確認:実行順序が妥当であることを確認します
  4. バックアップ:開始前に保留中の変更をコミットします
  5. 先に変換:ソースが .task/ 形式ではない場合は plan-converter を使用します
実行中
  1. イベントを監視:リアルタイムの進捗を確認するには、execution-events.md を確認します
  2. 失敗に対応:判断を下す前に、収束の失敗を慎重に確認します
  3. コミットを確認:有効になっている場合は、自動コミットが正しいことを確認します
実行後
  1. 概要を確認:execution.md の統計情報と失敗したタスクを確認します
  2. 変更を検証:変更されたファイルが想定どおりであることを確認します
  3. タスクファイルを確認:.task/*.json ファイル内の _execution 状態を確認します
  4. 次のステップ:完了オプションを使用して後続の処理を行います

次に unified-execute-with-file を実行します:$PLAN

コメント