mcpField
U
unified-execute-with-file

unified-execute-with-file

github.com/catlog22Agent 工作流2.1k54 次安装19 周前更新
代码仓库

关于 unified-execute-with-file

用于按序执行任务 JSON 计划的工作流技能,面向需要验证任务收敛状态并跟踪进度的开发流程。支持目录或单个 JSON 文件输入、试运行及逐任务提交。

主要功能

  1. 01按依赖拓扑顺序串行执行
  2. 02执行后验证收敛条件
  3. 03记录概览与事件日志
  4. 04支持试运行和自动提交
  5. 05接受目录或单个 JSON 文件

适用场景

  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确认已加载。

详细介绍

统一执行文件工作流

快速开始

通用执行引擎,读取 .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(事件流)
  • 自动提交:可选择为每个任务创建符合约定的提交
  • 试运行模式:模拟执行,不进行更改
  • 灵活输入:接受 .task/ 目录路径或单个 .json 文件路径

输入格式:每个任务都是 .task/ 目录中的独立 JSON 文件(例如 IMPL-001.json)。请先使用 plan-converter 将其他格式转换为 .task/*.json。

概述

┌─────────────────────────────────────────────────────────────┐
│                   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:将执行状态写回 .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 内容
创建议题根据失败任务详情执行 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 中的依赖关系
任务执行失败记录到事件中并询问用户重试、跳过、接受或中止
收敛验证失败将任务标记为失败并询问用户修复代码后重试,或接受
验证命令超时标记为未经验证需要手动验证
执行期间发生文件冲突记录到事件中按依赖顺序解决
所有任务均失败报告问题并建议审查计划重新分析或手动干预

最佳实践

执行前
  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

评论

支持 Markdown