Skip to main content

workflow-lite-execute

Lightweight execution engine - multi-mode input, task grouping, batch execution, chain to workflow-lite-test-review

소스 정보

저장소
catlog22/Claude-Code-Workflow
최근 소스 활동
2026년 5월 14일 15:44
감지된 SKILL.md 언어
영어
스타
2,128
포크
166

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
workflow-lite-execute
description
Lightweight execution engine - multi-mode input, task grouping, batch execution, chain to workflow-lite-test-review
allowed-tools
Skill, Agent, AskUserQuestion, TodoWrite, Read, Write, Edit, Bash, Glob, Grep
# Workflow-Lite-Execute Execution engine for workflow-lite-plan handoff and standalone task execution. --- ## Usage ``` <input> Task description string, or path to file (required) ``` | Flag | Description | |------|-------------| | `--in-memory` | Mode 1: Use executionContext from workflow-lite-plan handoff (via Skill({ skill: "workflow-lite-execute", args: "--in-memory" }) | ## Input Modes ### Mode 1: In-Memory Plan **Trigger**: `--in-memory` flag or `executionContext` global variable available **Input Source**: `executionContext` global variable set by workflow-lite-plan **Behavior**: Skip execution method/code review selection (already chosen in LP-Phase 4), directly proceed with full context (exploration, clarifications, plan artifacts all available) > **Note**: LP-Phase 4 is the single confirmation gate. Mode 1 invocation means user already approved — no further prompts. ### Mode 2: Prompt Description **Trigger**: User calls with task description string (e.g., "Add unit tests for auth module") **Behavior**: Store prompt as `originalUserInput` → create simple execution plan → run `selectExecutionOptions()` → proceed ### Mode 3: File Content **Trigger**: User calls with file path (ends with .md/.json/.txt) ```javascript fileContent = Read(filePath) try { jsonData = JSON.parse(fileContent) // plan.json detection: two-layer format with task_ids[] if (jsonData.summary && jsonData.approach && jsonData.task_ids) { planObject = jsonData originalUserInput = jsonData.summary isPlanJson = true const planDir = filePath.replace(/[/\\][^/\\]+$/, '') planObject._loadedTasks = loadTaskFiles(planDir, jsonData.task_ids) } else { originalUserInput = fileContent isPlanJson = false } } catch { originalUserInput = fileContent isPlanJson = false } ``` - `isPlanJson === true`: Use `planObject` directly → run `selectExecutionOptions()` - `isPlanJson === false`: Treat as prompt (same as Mode 2) ### User Selection (Mode 2/3 shared) ```javascript function selectExecutionOptions() { // autoYes: set by -y flag (standalone only; Mode 1 never reaches here) const autoYes = workflowPreferences?.autoYes ?? false if (autoYes) { return { execution_method: "Auto", code_review_tool: "Skip", convergence_review_tool: "Skip" } } return AskUserQuestion({ questions: [ { question: "Select execution method:", header: "Execution", multiSelect: false, options: [ { label: "Agent", description: "@code-developer agent" }, { label: "Codex", description: "codex CLI tool" }, { label: "Auto", description: "Auto-select based on complexity" } ] }, { question: "Code review after execution? (runs here in lite-execute)", header: "Code Review", multiSelect: false, options: [ { label: "Gemini Review", description: "Gemini CLI: git diff quality review" }, { label: "Codex Review", description: "Codex CLI: prompt-based code quality review (--mode analysis)" }, { label: "Agent Review", description: "@code-reviewer agent" }, { label: "Skip", description: "No code review" } ] }, { question: "Convergence review in workflow-lite-test-review phase?", header: "Convergence Review", multiSelect: false, options: [ { label: "Agent", description: "Agent: verify convergence criteria" }, { label: "Gemini", description: "Gemini CLI: convergence verification" }, { label: "Codex", description: "Codex CLI: convergence verification" }, { label: "Skip", description: "Skip convergence review, run tests only" } ] } ] }) } ``` ## Execution Steps ### Step 1: Initialize & Echo Strategy ```javascript previousExecutionResults = [] // Mode 1: echo strategy for transparency if (executionContext) { console.log(` Execution Strategy (from lite-plan): Method: ${executionContext.executionMethod} Code Review: ${executionContext.codeReviewTool} Convergence Review: ${executionContext.convergenceReviewTool} Tasks: ${getTasks(executionContext.planObject).length} Complexity: ${executionContext.planObject.complexity} ${executionContext.executorAssignments ? ` Assignments: ${JSON.stringify(executionContext.executorAssignments)}` : ''} `) } // Helper: load .task/*.json files (two-layer format) function loadTaskFiles(planDir, taskIds) { return taskIds.map(id => JSON.parse(Read(`${planDir}/.task/${id}.json`))) } function getTasks(planObject) { return planObject._loadedTasks || [] } ``` ### Step 2: Task Grouping & Batch Creation ```javascript // Dependency extraction: explicit depends_on only (no file/keyword inference) function extractDependencies(tasks) { const taskIdToIndex = {} tasks.forEach((t, i) => { taskIdToIndex[t.id] = i }) return tasks.map((task, i) => { const deps = (task.depends_on || []) .map(depId => taskIdToIndex[depId]) .filter(idx => idx !== undefined && idx < i) return { ...task, taskIndex: i, dependencies: deps } }) } // Executor resolution: executorAssignments[taskId] > executionMethod > Auto fallback function getTaskExecutor(task) { const assignments = executionContext?.executorAssignments || {} if (assignments[task.id]) return assignments[task.id].executor // 'gemini' | 'codex' | 'agent' const method = executionContext?.executionMethod || 'Auto' if (method === 'Agent') return 'agent' if (method === 'Codex') return 'codex' return planObject.complexity === 'Low' ? 'agent' : 'codex' // Auto fallback } function groupTasksByExecutor(tasks) { const groups = { gemini: [], codex: [], agent: [] } tasks.forEach(task => { groups[getTaskExecutor(task)].push(task) }) return groups } // Batch creation: independent → per-executor parallel, dependent → sequential phases function createExecutionCalls(tasks, executionMethod) { const tasksWithDeps = extractDependencies(tasks) const processed = new Set() const calls = [] // Phase 1: Independent tasks → per-executor parallel batches const independentTasks = tasksWithDeps.filter(t => t.dependencies.length === 0) if (independentTasks.length > 0) { const executorGroups = groupTasksByExecutor(independentTasks) let parallelIndex = 1 for (const [executor, tasks] of Object.entries(executorGroups)) { if (tasks.length === 0) continue tasks.forEach(t => processed.add(t.taskIndex)) calls.push({ method: executionMethod, executor, executionType: "parallel", groupId: `P${parallelIndex++}`, taskSummary: tasks.map(t => t.title).join(' | '), tasks }) } } // Phase 2+: Dependent tasks → respect dependency order let sequentialIndex = 1 let remaining = tasksWithDeps.filter(t => !processed.has(t.taskIndex)) while (remaining.length > 0) { let ready = remaining.filter(t => t.dependencies.every(d => processed.has(d))) if (ready.length === 0) { console.warn('Circular dependency detected, forcing remaining'); ready = [...remaining] } if (ready.length > 1) { const executorGroups = groupTasksByExecutor(ready) for (const [executor, tasks] of Object.entries(executorGroups)) { if (tasks.length === 0) continue tasks.forEach(t => processed.add(t.taskIndex)) calls.push({ method: executionMethod, executor, executionType: "parallel", groupId: `P${calls.length + 1}`, taskSummary: tasks.map(t => t.title).join(' | '), tasks }) } } else { ready.forEach(t => processed.add(t.taskIndex)) calls.push({ method: executionMethod, executor: getTaskExecutor(ready[0]), executionType: "sequential", groupId: `S${sequentialIndex++}`, taskSummary: ready[0].title, tasks: ready }) } remaining = remaining.filter(t => !processed.has(t.taskIndex)) } return calls } executionCalls = createExecutionCalls(getTasks(planObject), executionMethod).map(c => ({ ...c, id: `[${c.groupId}]` })) TodoWrite({ todos: executionCalls.map((c, i) => ({ content: `${c.executionType === "parallel" ? "⚡" : `→ [${i+1}/${executionCalls.filter(x=>x.executionType==="sequential").length}]`} ${c.id} [${c.executor}] ${c.tasks.map(t=>t.id).join(', ')}`, status: "pending", activeForm: `Waiting: ${c.tasks.length} task(s) via ${c.executor}` })) }) ``` ### Step 3: Launch Execution & Track Progress > **CHECKPOINT**: Verify Phase 2 execution protocol (Step 3-5) is in active memory. If only a summary remains, re-read `phases/02-lite-execute.md` now. **Batch Routing** (by `batch.executor` field): ```javascript function executeBatch(batch) { const executor = batch.executor || getTaskExecutor(batch.tasks[0]) const sessionId = executionContext?.session?.id || 'standalone' const fixedId = `${sessionId}-${batch.groupId}` if (executor === 'agent') { return Agent({ subagent_type: "code-developer", run_in_background: false, description: batch.taskSummary, prompt: buildExecutionPrompt(batch) }) } else { // CLI execution (codex/gemini): background with fixed ID const tool = executor // 'codex' | 'gemini' const mode = executor === 'gemini' ? 'analysis' : 'write' const previousCliId = batch.resumeFromCliId || null const cmd = previousCliId ? `ccw cli -p "${buildExecutionPrompt(batch)}" --tool ${tool} --mode ${mode} --id ${fixedId} --resume ${previousCliId}` : `ccw cli -p "${buildExecutionPrompt(batch)}" --tool ${tool} --mode ${mode} --id ${fixedId}` return Bash(cmd, { run_in_background: true }) // STOP - wait for task hook callback } } ``` **Parallel execution rules**: - Each batch = one independent CLI instance or Agent call - Parallel = multiple Bash(run_in_background=true) or multiple Agent() in single message - Never merge independent tasks into one CLI prompt - Agent: run_in_background=false, but multiple Agent() calls can be concurrent in single message **Execution Flow**: Parallel batches concurrently → Sequential batches in order ```javascript const parallel = executionCalls.filter(c => c.executionType === "parallel") const sequential = executionCalls.filter(c => c.executionType === "sequential") // Phase 1: All parallel batches (single message, multiple tool calls) if (parallel.length > 0) { TodoWrite({ todos: executionCalls.map(c => ({ status: c.executionType === "parallel" ? "in_progress" : "pending", activeForm: c.executionType === "parallel" ? `Running [${c.executor}]: ${c.tasks.map(t=>t.id).join(', ')}` : `Blocked by parallel phase` })) }) parallelResults = await Promise.all(parallel.map(c => executeBatch(c))) previousExecutionResults.push(...parallelResults) TodoWrite({ todos: executionCalls.map(c => ({ status: parallel.includes(c) ? "completed" : "pending", activeForm: parallel.includes(c) ? `Done [${c.executor}]` : `Ready` })) }) } // Phase 2: Sequential batches one by one for (const call of sequential) { TodoWrite({ todos: executionCalls.map(c => ({ status: c === call ? "in_progress" : (c.status === "completed" ? "completed" : "pending"), activeForm: c === call ? `Running [${c.executor}]: ${c.tasks.map(t=>t.id).join(', ')}` : undefined
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기