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
آخر نشاط في المصدر
١٤ مايو ٢٠٢٦ في ١٥:٤٤
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٢٬١٢٨
التفرعات
١٦٦

خيارات التثبيت

يُحدَّد 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