Token导航 LogoToken导航TokenDH.com
研究检索需要联网github未标认证来源可访问许可证需确认审计通过

plan-converter计划转换器

Agent Skill

plan-converter 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

346

周安装

14

GitHub Stars

1,907

下载量

109
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:plan-converter(计划转换器)
来源仓库:https://github.com/catlog22/claude-code-workflow
仓库路径:skills/plan-converter
安装命令:
npx skills add https://github.com/catlog22/claude-code-workflow --skill plan-converter
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/catlog22/claude-code-workflow --skill plan-converter

简介

用于在任务前查找、检索和筛选相关信息。

  • 适合根据关键词、任务场景或来源线索快速定位候选结果,支持多宿主环境协作。
  • 通过 npx skills add 命令从指定 GitHub 仓库安装,使用前需确认权限和维护状态。
  • 建议检查是否会触发联网、命令执行或文件读写操作,确保符合安全策略。
  • 可结合来源仓库和原始 README 进一步核验具体用法和适用边界。

SKILL.md

Plan Converter

Overview

Converts any planning artifact to **.task/*.json multi-file format** — the single standard consumed by unified-execute-with-file.

Schema: cat ~/.ccw/workflows/cli-templates/schemas/task-schema.json
# Auto-detect format, output to same directory .task/
/codex:plan-converter ".workflow/.req-plan/RPLAN-auth-2025-01-21/roadmap.jsonl"

# Specify output directory
/codex:plan-converter ".workflow/.planning/CPLAN-xxx/plan-note.md" -o .task/

# Convert brainstorm synthesis
/codex:plan-converter ".workflow/.brainstorm/BS-xxx/synthesis.json"

Supported inputs: roadmap.jsonl,.task/*.json (per-domain), plan-note.md, conclusions.json, synthesis.json

Output: .task/*.json (one file per task, in same directory's .task/ subfolder, or specified -o path)

Task JSON Schema

每个任务一个独立 JSON 文件 (.task/TASK-{id}.json),遵循统一 schema:

Schema 定义: cat ~/.ccw/workflows/cli-templates/schemas/task-schema.json

Producer 使用的字段集 (plan-converter 输出):

IDENTITY (必填):        id, title, description
CLASSIFICATION (可选):   type, priority, effort, action
SCOPE (可选):            scope, excludes, focus_paths
DEPENDENCIES (必填):     depends_on, parallel_group, inputs, outputs
CONVERGENCE (必填):      convergence.criteria, convergence.verification, convergence.definition_of_done
FILES (可选):            files[].path, files[].action, files[].changes, files[].change, files[].target, files[].conflict_risk
IMPLEMENTATION (可选):   implementation[], test.manual_checks, test.success_metrics
PLANNING (可选):         reference, rationale, risks
CONTEXT (可选):          source.tool, source.session_id, source.original_id, evidence, risk_items
RUNTIME (执行时填充):    status, executed_at, result

文件命名: TASK-{id}.json (保留原有 ID 前缀: L0-, T1-, IDEA- 等)

Target Input

$ARGUMENTS

Execution Process

Step 0: Parse arguments, resolve input path
Step 1: Detect input format
Step 2: Parse input → extract raw records
Step 3: Transform → unified task records
Step 4: Validate convergence quality
Step 5: Write .task/*.json output + display summary

Implementation

Step 0: Parse Arguments

const args = $ARGUMENTS
const outputMatch = args.match(/-o\s+(\S+)/)
const outputPath = outputMatch ? outputMatch[1] : null
const inputPath = args.replace(/-o\s+\S+/, '').trim()

// Resolve absolute path
const projectRoot = Bash(`git rev-parse --show-toplevel 2>/dev/null || pwd`).trim()
const resolvedInput = path.isAbsolute(inputPath) ? inputPath : `${projectRoot}/${inputPath}`

Step 1: Detect Format

const filename = path.basename(resolvedInput)
const content = Read(resolvedInput)

function detectFormat(filename, content) {
  if (filename === 'roadmap.jsonl')     return 'roadmap-jsonl'
  if (filename === 'tasks.jsonl')       return 'tasks-jsonl'    // legacy JSONL or per-domain
  if (filename === 'plan-note.md')      return 'plan-note-md'
  if (filename === 'conclusions.json')  return 'conclusions-json'
  if (filename === 'synthesis.json')    return 'synthesis-json'
  if (filename.endsWith('.jsonl'))      return 'generic-jsonl'
  if (filename.endsWith('.json')) {
    const parsed = JSON.parse(content)
    if (parsed.top_ideas)               return 'synthesis-json'
    if (parsed.recommendations && parsed.key_conclusions) return 'conclusions-json'
    if (parsed.tasks && parsed.focus_area) return 'domain-plan-json'
    return 'unknown-json'
  }
  if (filename.endsWith('.md'))         return 'plan-note-md'
  return 'unknown'
}

Format Detection Table:

FilenameFormat IDSource Tool
roadmap.jsonlroadmap-jsonlreq-plan-with-file
tasks.jsonl (legacy) / .task/*.jsontasks-jsonl / task-jsoncollaborative-plan-with-file
plan-note.mdplan-note-mdcollaborative-plan-with-file
conclusions.jsonconclusions-jsonanalyze-with-file
synthesis.jsonsynthesis-jsonbrainstorm-with-file

Step 2: Parse Input

roadmap-jsonl (req-plan-with-file)

function parseRoadmapJsonl(content) {
  return content.split('\n')
    .filter(line => line.trim())
    .map(line => JSON.parse(line))
}
// Records have: id (L0/T1), name/title, goal/scope, convergence, depends_on, etc.

plan-note-md (collaborative-plan-with-file)

function parsePlanNoteMd(content) {
  const tasks = []
  // 1. Extract YAML frontmatter for session metadata
  const frontmatter = extractYamlFrontmatter(content)

  // 2. Find all "## 任务池 - {Domain}" sections
  const taskPoolSections = content.match(/## 任务池 - .+/g) || []

  // 3. For each section, extract tasks matching:
  //    ### TASK-{ID}: {Title} [{domain}]
  //    - **状态**: pending
  //    - **复杂度**: Medium
  //    - **依赖**: TASK-xxx
  //    - **范围**: ...
  //    - **修改点**: `file:location`: change summary
  //    - **冲突风险**: Low
  taskPoolSections.forEach(section => {
    const sectionContent = extractSectionContent(content, section)
    const taskPattern = /### (TASK-\d+):\s+(.+?)\s+\[(.+?)\]/g
    let match
    while ((match = taskPattern.exec(sectionContent)) !== null) {
      const [_, id, title, domain] = match
      const taskBlock = extractTaskBlock(sectionContent, match.index)
      tasks.push({
        id, title, domain,
        ...parseTaskDetails(taskBlock)
      })
    }
  })
  return { tasks, frontmatter }
}

conclusions-json (analyze-with-file)

function parseConclusionsJson(content) {
  const conclusions = JSON.parse(content)
  // Extract from: conclusions.recommendations[]
  //   { action, rationale, priority }
  // Also available: conclusions.key_conclusions[]
  return conclusions
}

synthesis-json (brainstorm-with-file)

function parseSynthesisJson(content) {
  const synthesis = JSON.parse(content)
  // Extract from: synthesis.top_ideas[]
  //   { title, description, score, feasibility, next_steps, key_strengths, main_challenges }
  // Also available: synthesis.recommendations
  return synthesis
}

Step 3: Transform to Unified Records

roadmap-jsonl → unified

function transformRoadmap(records, sessionId) {
  return records.map(rec => {
    // roadmap.jsonl now uses unified field names (title, description, source)
    // Passthrough is mostly direct
    return {
      id: rec.id,
      title: rec.title,
      description: rec.description,
      type: rec.type || 'feature',
      effort: rec.effort,
      scope: rec.scope,
      excludes: rec.excludes,
      depends_on: rec.depends_on || [],
      parallel_group: rec.parallel_group,
      inputs: rec.inputs,
      outputs: rec.outputs,
      convergence: rec.convergence,  // already unified format
      risk_items: rec.risk_items,
      source: rec.source || {
        tool: 'req-plan-with-file',
        session_id: sessionId,
        original_id: rec.id
      }
    }
  })
}

plan-note-md → unified

function transformPlanNote(parsed) {
  const { tasks, frontmatter } = parsed
  return tasks.map(task => ({
    id: task.id,
    title: task.title,
    description: task.scope || task.title,
    type: task.type || inferTypeFromTitle(task.title),
    priority: task.priority || inferPriorityFromEffort(task.effort),
    effort: task.effort || 'medium',
    scope: task.scope,
    depends_on: task.depends_on || [],
    convergence: task.convergence || generateConvergence(task),  // plan-note now has convergence
    files: task.files?.map(f => ({
      path: f.path || f.file,
      action: f.action || 'modify',
      changes: f.changes || (f.change ? [f.change] : undefined),
      change: f.change,
      target: f.target,
      conflict_risk: f.conflict_risk
    })),
    source: {
      tool: 'collaborative-plan-with-file',
      session_id: frontmatter.session_id,
      original_id: task.id
    }
  }))
}

// Generate convergence from task details when source lacks it (legacy fallback)
function generateConvergence(task) {
  return {
    criteria: [
      // Derive testable conditions from scope and files
      // e.g., "Modified files compile without errors"
      // e.g., scope-derived: "API endpoint returns expected response"
    ],
    verification: '// Derive from files — e.g., test commands',
    definition_of_done: '// Derive from scope — business language summary'
  }
}

conclusions-json → unified

function transformConclusions(conclusions) {
  return conclusions.recommendations.map((rec, index) => ({
    id: `TASK-${String(index + 1).padStart(3, '0')}`,
    title: rec.action,
    description: rec.rationale,
    type: inferTypeFromAction(rec.action),
    priority: rec.priority,
    depends_on: [],
    convergence: {
      criteria: generateCriteriaFromAction(rec),
      verification: generateVerificationFromAction(rec),
      definition_of_done: generateDoDFromRationale(rec)
    },
    evidence: conclusions.key_conclusions.map(c => c.point),
    source: {
      tool: 'analyze-with-file',
      session_id: conclusions.session_id
    }
  }))
}

function inferTypeFromAction(action) {
  const lower = action.toLowerCase()
  if (/fix|resolve|repair|修复/.test(lower)) return 'fix'
  if (/refactor|restructure|extract|重构/.test(lower)) return 'refactor'
  if (/add|implement|create|新增|实现/.test(lower)) return 'feature'
  if (/improve|optimize|enhance|优化/.test(lower)) return 'enhancement'
  if (/test|coverage|validate|测试/.test(lower)) return 'testing'
  return 'feature'
}

synthesis-json → unified

function transformSynthesis(synthesis) {
  return synthesis.top_ideas
    .filter(idea => idea.score >= 6)  // Only viable ideas (score ≥ 6)
    .map((idea, index) => ({
      id: `IDEA-${String(index + 1).padStart(3, '0')}`,
      title: idea.title,
      description: idea.description,
      type: 'feature',
      priority: idea.score >= 8 ? 'high' : idea.score >= 6 ? 'medium' : 'low',
      effort: idea.feasibility >= 4 ? 'small' : idea.feasibility >= 2 ? 'medium' : 'large',
      depends_on: [],
      convergence: {
        criteria: idea.next_steps || [`${idea.title} implemented and functional`],
        verification: 'Manual validation of feature functionality',
        definition_of_done: idea.description
      },
      risk_items: idea.main_challenges || [],
      source: {
        tool: 'brainstorm-with-file',
        session_id: synthesis.session_id,
        original_id: `idea-${index + 1}`
      }
    }))
}

Step 4: Validate Convergence Quality

All records must pass convergence quality checks before output.

function validateConvergence(records) {
  const vaguePatterns = /正常|正确|好|可以|没问题|works|fine|good|correct/i
  const technicalPatterns = /compile|build|lint|npm|npx|jest|tsc|eslint/i
  const issues = []

  records.forEach(record => {
    const c = record.convergence
    if (!c) {
      issues.push({ id: record.id, field: 'convergence', issue: 'Missing entirely' })
      return
    }
    if (!c.criteria?.length) {
      issues.push({ id: record.id, field: 'criteria', issue: 'Empty criteria array' })
    }
    c.criteria?.forEach((criterion, i) => {
      if (vaguePatterns.test(criterion) && criterion.length < 15) {
        issues.push({ id: record.id, field: `criteria[${i}]`, issue: `Too vague: "${criterion}"` })
      }
    })
    if (!c.verification || c.verification.length < 10) {
      issues.push({ id: record.id, field: 'verification', issue: 'Too short or missing' })
    }
    if (technicalPatterns.test(c.definition_of_done)) {
      issues.push({ id: record.id, field: 'definition_of_done', issue: 'Should be business language' })
    }
  })

  return issues
}

// Auto-fix strategy:
// | Issue                | Fix                                          |
// |----------------------|----------------------------------------------|
// | Missing convergence  | Generate from title + description + files     |
// | Vague criteria       | Replace with specific condition from context  |
// | Short verification   | Expand with file-based test suggestion        |
// | Technical DoD        | Rewrite in business language                  |

Step 5: Write.task/*.json Output & Summary

// Determine output directory
const outputDir = outputPath
  || `${path.dirname(resolvedInput)}/.task`

// Create output directory
Bash(`mkdir -p ${outputDir}`)

// Clean records: remove undefined/null optional fields
const cleanedRecords = records.map(rec => {
  const clean = { ...rec }
  Object.keys(clean).forEach(key => {
    if (clean[key] === undefined || clean[key] === null) delete clean[key]
    if (Array.isArray(clean[key]) && clean[key].length === 0 && key !== 'depends_on') delete clean[key]
  })
  return clean
})

// Write individual task JSON files
cleanedRecords.forEach(record => {
  const filename = `${record.id}.json`
  Write(`${outputDir}/${filename}`, JSON.stringify(record, null, 2))
})

// Display summary
// | Source          | Format            | Records | Issues |
// |-----------------|-------------------|---------|--------|
// | roadmap.jsonl   | roadmap-jsonl     | 4       | 0      |
//
// Output: .workflow/.req-plan/RPLAN-xxx/.task/ (4 files)
// Records: 4 tasks with convergence criteria
// Quality: All convergence checks passed

Conversion Matrix

SourceSource ToolID PatternHas ConvergenceHas FilesHas PriorityHas Source
roadmap.jsonl (progressive)req-planL0-L3YesNoNoYes
roadmap.jsonl (direct)req-planT1-TNYesNoNoYes
.task/TASK-*.json (per-domain)collaborative-planTASK-NNNYesYes (detailed)OptionalYes
plan-note.mdcollaborative-planTASK-NNNGenerateYes (from 修改文件)From effortNo
conclusions.jsonanalyzeTASK-NNNGenerateNoYesNo
synthesis.jsonbrainstormIDEA-NNNGenerateNoFrom scoreNo

Legend: Yes = source already has it, Generate = converter produces it, No = not available

Error Handling

SituationAction
Input file not foundReport error, suggest checking path
Unknown formatReport error, list supported formats
Empty inputReport error, no output file created
Convergence validation failsAuto-fix where possible, report remaining issues
Partial parse failureConvert valid records, report skipped items
Output file existsOverwrite with warning message
plan-note.md has empty sectionsSkip empty domains, report in summary

Now execute plan-converter for: $ARGUMENTS

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

36.08%
按下载量换算39

Claude

32.49%
按下载量换算35

Cursor

17.56%
按下载量换算19

Gemini CLI

9.43%
按下载量换算10

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills