统一执行引擎Skill unified-execute-with-file

这个技能是一个统一执行引擎,专为处理.task/*.json格式的任务文件而设计。它执行序列化任务,验证每个任务的收敛标准,并通过execution.md和execution-events.md文件跟踪执行进度。支持自动提交、干运行模式,适用于软件开发中的自动化工作流管理。关键词:任务自动化、JSON任务管理、收敛验证、执行跟踪、DevOps工具。

DevOps 0 次安装 2 次浏览 更新于 3/16/2026

name: unified-execute-with-file description: 统一执行引擎消费 .task/*.json 目录格式。序列任务执行带有收敛验证,通过 execution.md + execution-events.md 跟踪进度。 argument-hint: “PLAN="<路径/.task/>" [–auto-commit] [–dry-run]”

统一执行带文件工作流

快速启动

统一执行引擎消费 .task/*.json 目录并序列执行任务,带有收敛验证和进度跟踪。

# 从 lite-plan 输出执行
/codex:unified-execute-with-file PLAN=".workflow/.lite-plan/LPLAN-auth-2025-01-21/.task/"

# 从工作流会话输出执行
/codex:unified-execute-with-file PLAN=".workflow/active/WFS-xxx/.task/" --auto-commit

# 执行单个任务 JSON 文件
/codex:unified-execute-with-file PLAN=".workflow/active/WFS-xxx/.task/IMPL-001.json" --dry-run

# 从 .workflow/ 目录自动检测
/codex:unified-execute-with-file

核心工作流:扫描 .task/*.json → 验证 → 预执行分析 → 执行 → 验证收敛 → 跟踪进度

关键特性

  • 基于目录:消费包含单个任务 JSON 文件的 .task/ 目录
  • 收敛驱动:执行后验证每个任务的收敛标准
  • 序列执行:按拓扑顺序处理任务,带有依赖跟踪
  • 双重进度跟踪execution.md(概述) + execution-events.md(事件流)
  • 自动提交:可选的按任务常规提交
  • 干运行模式:模拟执行而不做更改
  • 灵活输入:接受 .task/ 目录路径或单个 .json 文件路径

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

概述

┌─────────────────────────────────────────────────────────────┐
│                   统一执行工作流                    │
├─────────────────────────────────────────────────────────────┤
│                                                               │
│  阶段 1: 加载与验证                                     │
│     ├─ 扫描 .task/*.json(每个文件一个任务)                   │
│     ├─ 验证模式(id、title、depends_on、convergence)   │
│     ├─ 检测循环,构建拓扑顺序                 │
│     └─ 初始化 execution.md + execution-events.md          │
│                                                               │
│  阶段 2: 预执行分析                              │
│     ├─ 检查文件冲突(多个任务 → 同一文件)      │
│     ├─ 验证文件存在性                                  │
│     ├─ 生成可行性报告                            │
│     └─ 用户确认(除非干运行)                     │
│                                                               │
│  阶段 3: 序列执行 + 收敛验证         │
│     对每个任务按拓扑顺序:                        │
│     ├─ 检查依赖满足                           │
│     ├─ 记录 START 事件                                     │
│     ├─ 直接执行(读取/编辑/写入/搜索/全局/Shell)      │
│     ├─ 验证 convergence.criteria[]                          │
│     ├─ 运行 convergence.verification 命令                   │
│     ├─ 记录 COMPLETE/FAIL 事件与验证结果   │
│     ├─ 在任务 JSON 文件中更新 _execution 状态               │
│     └─ 如果启用则自动提交                                 │
│                                                               │
│  阶段 4: 完成                                          │
│     ├─ 使用摘要统计完成 execution.md          │
│     ├─ 使用会话页脚完成 execution-events.md       │
│     ├─ 写回 .task/*.json 带有 _execution 状态          │
│     └─ 提供后续行动                                │
│                                                               │
└─────────────────────────────────────────────────────────────┘

输出结构

${projectRoot}/.workflow/.execution/EXEC-{slug}-{date}-{random}/
├── execution.md              # 计划概述 + 任务表 + 摘要
└── execution-events.md       # ⭐ 统一事件日志(单一真实来源)

此外,每个源 .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()

// 解析参数
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

// 如果未指定 PLAN 则自动检测
if (!planPath) {
  // 按顺序搜索(最近优先):
  //   .workflow/active/*/.task/
  //   .workflow/.lite-plan/*/.task/
  //   .workflow/.req-plan/*/.task/
  //   .workflow/.planning/*/.task/
  // 使用包含 *.json 文件的最远修改目录
}

// 解析路径
planPath = path.isAbsolute(planPath) ? planPath : `${projectRoot}/${planPath}`

// 生成会话 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/ 目录并解析任务文件

// 确定 planPath 是目录还是单个文件
const isDirectory = planPath.endsWith('/') || Bash(`test -d "${planPath}" && echo dir || echo file`).trim() === 'dir'

let taskFiles, tasks

if (isDirectory) {
  // 目录模式:扫描所有 *.json 文件
  taskFiles = Glob('*.json', planPath)
  if (taskFiles.length === 0) throw new Error(`在 ${planPath} 中未找到 .json 文件`)

  tasks = taskFiles.map(filePath => {
    try {
      const content = Read(filePath)
      const task = JSON.parse(content)
      task._source_file = filePath  // 跟踪源文件用于写回
      return task
    } catch (e) {
      throw new Error(`${path.basename(filePath)}: 无效 JSON - ${e.message}`)
    }
  })
} else {
  // 单个文件模式:解析一个任务 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)}: 无效 JSON - ${e.message}`)
  }
}

if (tasks.length === 0) throw new Error('未找到任务')

步骤 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) : `任务 ${i + 1}`

  // 必填字段(根据 task-schema.json)
  if (!task.id) errors.push(`${src}: 缺少 'id'`)
  if (!task.title) errors.push(`${src}: 缺少 'title'`)
  if (!task.description) errors.push(`${src}: 缺少 'description'`)
  if (!Array.isArray(task.depends_on)) errors.push(`${task.id || src}: 缺少 'depends_on' 数组`)

  // 上下文块(可选但如果存在则验证)
  if (task.context) {
    if (task.context.requirements && !Array.isArray(task.context.requirements))
      errors.push(`${task.id}: context.requirements 必须是数组`)
    if (task.context.acceptance && !Array.isArray(task.context.acceptance))
      errors.push(`${task.id}: context.acceptance 必须是数组`)
    if (task.context.focus_paths && !Array.isArray(task.context.focus_paths))
      errors.push(`${task.id}: context.focus_paths 必须是数组`)
  }

  // 收敛(执行验证必填)
  if (!task.convergence) {
    errors.push(`${task.id || src}: 缺少 'convergence'`)
  } else {
    if (!task.convergence.criteria?.length) errors.push(`${task.id}: 空的 convergence.criteria`)
    if (!task.convergence.verification) errors.push(`${task.id}: 缺少 convergence.verification`)
    if (!task.convergence.definition_of_done) errors.push(`${task.id}: 缺少 convergence.definition_of_done`)
  }

  // 流控制(可选但如果存在则验证)
  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 必须是数组`)
  }

  // 新统一模式字段(向后兼容添加)
  if (task.focus_paths && !Array.isArray(task.focus_paths))
    errors.push(`${task.id}: focus_paths 必须是数组`)
  if (task.implementation && !Array.isArray(task.implementation))
    errors.push(`${task.id}: implementation 必须是数组`)
  if (task.files && !Array.isArray(task.files))
    errors.push(`${task.id}: files 必须是数组`)
})

if (errors.length) {
  // 报告错误,停止执行
}

步骤 1.3: 构建执行顺序

// 1. 验证依赖引用
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}: 依赖于未知任务 '${dep}'`)
  })
})

// 2. 检测循环(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(`循环依赖: ${cycles.join('; ')}`)

// 3. 拓扑排序
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 = `# 执行概述

## 会话信息
- **会话 ID**: ${sessionId}
- **计划来源**: ${planPath}
- **开始时间**: ${getUtc8ISOString()}
- **总任务数**: ${tasks.length}
- **模式**: ${dryRun ? '干运行(无更改)' : '直接内联执行'}
- **自动提交**: ${autoCommit ? '启用' : '禁用'}

## 任务概述

| # | ID | 标题 | 类型 | 优先级 | 工作量 | 依赖 | 状态 |
|---|-----|-------|------|----------|--------|--------------|--------|
${tasks.map((t, i) => `| ${i+1} | ${t.id} | ${t.title} | ${t.type || '-'} | ${t.priority || '-'} | ${t.effort || '-'} | ${t.depends_on.join(', ') || '-'} | 待处理 |`).join('
')}

## 预执行分析
> 在阶段 2 中填充

## 执行时间线
> 随着任务完成更新

## 执行摘要
> 所有任务完成后更新
`
Write(`${sessionFolder}/execution.md`, executionMd)

// execution-events.md
Write(`${sessionFolder}/execution-events.md`, `# 执行事件

**会话**: ${sessionId}
**开始时间**: ${getUtc8ISOString()}
**来源**: ${planPath}

---

`)

阶段 2: 预执行分析

目标:在执行前验证可行性和识别问题。

步骤 2.1: 分析文件冲突

const fileTaskMap = new Map()  // 文件 → [任务IDs]
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: '按依赖顺序执行' })
  }
})

// 检查文件存在性
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

// 替换 "预执行分析" 部分为:
// - 文件冲突(列表或 "无冲突")
// - 缺失文件(列表或 "所有文件存在")
// - 依赖验证(错误或 "无问题")
// - 执行顺序(编号列表)

步骤 2.3: 用户确认

if (!dryRun) {
  AskUserQuestion({
    questions: [{
      question: `执行 ${tasks.length} 个任务?

${conflicts.length ? `⚠ ${conflicts.length} 个文件冲突
` : ''}执行顺序:
${executionOrder.map((id, i) => `  ${i+1}. ${id}: ${tasks.find(t => t.id === id).title}`).join('
')}`,
      header: "确认",
      multiSelect: false,
      options: [
        { label: "执行", description: "开始序列执行" },
        { label: "干运行", description: "模拟而不做更改" },
        { label: "取消", description: "中止执行" }
      ]
    }]
  })
}

阶段 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. 检查依赖
  const unmetDeps = task.depends_on.filter(dep => !completedTasks.has(dep))
  if (unmetDeps.length) {
    appendToEvents(task, 'BLOCKED', `未满足依赖: ${unmetDeps.join(', ')}`)
    skippedTasks.add(task.id)
    task._execution = { status: 'skipped', executed_at: startTime,
      result: { success: false, error: `被阻塞: ${unmetDeps.join(', ')}` } }
    continue
  }

  // 2. 记录 START 事件
  appendToEvents(`## ${getUtc8ISOString()} — ${task.id}: ${task.title}

**类型**: ${task.type || '-'} | **优先级**: ${task.priority || '-'} | **工作量**: ${task.effort || '-'}
**状态**: ⏳ 进行中
**文件**: ${(task.files || []).map(f => f.path).join(', ') || '待确定'}
**描述**: ${task.description}
**收敛标准**:
${task.convergence.criteria.map(c => `- [ ] ${c}`).join('
')}

### 执行日志
`)

  if (dryRun) {
    // 模拟:标记为完成而不做更改
    appendToEvents(`
**状态**: ⏭ 干运行(无更改)

---
`)
    task._execution = { status: 'completed', executed_at: startTime,
      result: { success: true, summary: '干运行 — 未做更改' } }
    completedTasks.add(task.id)
    continue
  }

  // 3. 直接执行任务
  //    - 读取任务中的每个文件(如果指定)
  //    - 分析满足 task.description + task.convergence.criteria 的更改
  //    - 如果 task.files 有详细更改,使用它们作为指导
  //    - 使用 Edit(首选)或 Write(新文件)应用更改
  //    - 如果需要,使用 Grep/Glob/mcp__ace-tool 进行发现
  //    - 使用 Bash 进行构建/测试命令

  // 双路径字段访问(支持统一和传统 6 字段模式)
  // 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. 验证收敛
  const convergenceResults = verifyConvergence(task)

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

  if (convergenceResults.allPassed) {
    // 5a. 记录成功
    appendToEvents(`
**状态**: ✅ 完成
**持续时间**: ${calculateDuration(startTime, endTime)}
**修改的文件**: ${filesModified.join(', ')}

#### 更改摘要
${changeSummary}

#### 收敛验证
${task.convergence.criteria.map((c, i) => `- [${convergenceResults.verified[i] ? 'x' : ' '}] ${c}`).join('
')}
- **验证**: ${convergenceResults.verificationOutput}
- **完成定义**: ${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. 记录失败
    handleTaskFailure(task, convergenceResults, startTime, endTime)
  }

  // 6. 如果启用则自动提交
  if (autoCommit && task._execution.status === 'completed') {
    autoCommitTask(task, filesModified)
  }
}

步骤 3.2: 收敛验证

function verifyConvergence(task) {
  const results = {
    verified: [],           // 每个标准的布尔数组
    verificationOutput: '', // 验证命令的输出
    allPassed: true
  }

  // 1. 检查每个标准
  //    对于 task.convergence.criteria 中的每个标准:
  //      - 如果引用可测试条件,则检查它
  //      - 如果是手动的,则基于所做的更改标记为已验证
  //      - 记录每个标准的真/假
  task.convergence.criteria.forEach(criterion => {
    const passed = evaluateCriterion(criterion, task)
    results.verified.push(passed)
    if (!passed) results.allPassed = false
  })

  // 2. 运行验证命令(如果可执行)
  const verification = task.convergence.verification
  if (isExecutableCommand(verification)) {
    try {
      const output = Bash(verification, { timeout: 120000 })
      results.verificationOutput = `${verification} → 通过`
    } catch (e) {
      results.verificationOutput = `${verification} → 失败: ${e.message}`
      results.allPassed = false
    }
  } else {
    results.verificationOutput = `手动: ${verification}`
  }

  return results
}

function isExecutableCommand(verification) {
  // 检测可执行模式:npm, npx, jest, tsc, curl, pytest, go test, 等。
  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(`
**状态**: ❌ 失败
**持续时间**: ${calculateDuration(startTime, endTime)}
**错误**: 收敛验证失败

#### 失败的标准
${task.convergence.criteria.map((c, i) => `- [${convergenceResults.verified[i] ? 'x' : ' '}] ${c}`).join('
')}
- **验证**: ${convergenceResults.verificationOutput}

---
`)

  task._execution = {
    status: 'failed', executed_at: endTime,
    result: {
      success: false,
      error: '收敛验证失败',
      convergence_verified: convergenceResults.verified
    }
  }
  failedTasks.add(task.id)

  // 询问用户
  AskUserQuestion({
    questions: [{
      question: `任务 ${task.id} 收敛验证失败。如何处理?`,
      header: "失败",
      multiSelect: false,
      options: [
        { label: "跳过并继续", description: "跳过此任务,继续下一个" },
        { label: "重试", description: "重试此任务" },
        { label: "接受", description: "尽管失败,标记为完成" },
        { label: "中止", description: "停止执行,保留进度" }
      ]
    }]
  })
}

步骤 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.id}
来源: ${path.basename(planPath)}
EOF
)"`)

  appendToEvents(`**提交**: \`${commitType}(${scope}): ${task.title}\`
`)
}

阶段 4: 完成

目标:完成所有工件,写回执行状态,提供后续行动。

步骤 4.1: 完成 execution.md

追加摘要统计到 execution.md

const summary = `
## 执行摘要

- **完成时间**: ${getUtc8ISOString()}
- **总任务数**: ${tasks.length}
- **成功**: ${completedTasks.size}
- **失败**: ${failedTasks.size}
- **跳过**: ${skippedTasks.size}
- **成功率**: ${Math.round(completedTasks.size / tasks.length * 100)}%

### 任务结果

| ID | 标题 | 状态 | 收敛 | 修改的文件 |
|----|-------|--------|-------------|----------------|
${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 || '待处理'} | ${convergenceStatus} | ${(ex.result?.files_modified || []).join(', ') || '-'} |`
}).join('
')}

${failedTasks.size > 0 ? `### 失败任务

${[...failedTasks].map(id => {
  const t = tasks.find(t => t.id === id)
  return `- **${t.id}**: ${t.title} — ${t._execution?.result?.error || '未知'}`
}).join('
')}
` : ''}
### 工件
- **计划来源**: ${planPath}
- **执行概述**: ${sessionFolder}/execution.md
- **执行事件**: ${sessionFolder}/execution-events.md
`
// 追加到 execution.md

步骤 4.2: 完成 execution-events.md

appendToEvents(`
---

# 会话摘要

- **会话**: ${sessionId}
- **完成时间**: ${getUtc8ISOString()}
- **任务**: ${completedTasks.size} 完成, ${failedTasks.size} 失败, ${skippedTasks.size} 跳过
- **总事件数**: ${completedTasks.size + failedTasks.size + skippedTasks.size}
`)

步骤 4.3: 写回 .task/*.json 带有 _execution

更新每个源任务 JSON 文件带有执行状态:

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

  // 读取当前文件以保留格式和非执行字段
  const current = JSON.parse(Read(filePath))

  // 更新 _execution 状态和结果
  current._execution = {
    status: task._execution?.status || 'pending',
    executed_at: task._execution?.executed_at || null,
    result: task._execution?.result || null
  }

  // 写回单个任务文件
  Write(filePath, JSON.stringify(current, null, 2))
})
// 每个任务 JSON 文件现在有 _execution: { status, executed_at, result }

步骤 4.4: 完成后选项

AskUserQuestion({
  questions: [{
    question: `执行完成: ${completedTasks.size}/${tasks.length} 成功(${Math.round(completedTasks.size / tasks.length * 100)}%)。
下一步:`,
    header: "后执行",
    multiSelect: false,
    options: [
      { label: "重试失败", description: `重新执行 ${failedTasks.size} 个失败任务` },
      { label: "查看事件", description: "显示 execution-events.md" },
      { label: "创建问题", description: "从失败任务创建问题" },
      { label: "完成", description: "结束工作流" }
    ]
  }]
})
选择 行动
重试失败 过滤任务 _execution.status === 'failed',重新执行,追加 [重试] 事件
查看事件 显示 execution-events.md 内容
创建问题 Skill(skill="issue:new", args="...") 从失败任务详情
完成 显示工件路径,结束工作流

配置

标志 默认 描述
PLAN="..." 自动检测 路径到 .task/ 目录或单个任务 .json 文件
--auto-commit false 每个成功任务后提交更改
--dry-run false 模拟执行而不做更改

计划自动检测顺序

当未指定 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