From gilfoyle
Master coordinator for the Evaluate-Loop workflow v4. Supports GOAL-DRIVEN entry, PARALLEL execution via superpowers agents, BOARD OF DIRECTORS deliberation, and message bus coordination. Dispatches superpowers (writing-plans, executing-plans, systematic-debugging) as PRIMARY path with legacy loop agents as FALLBACK. Uses metadata.json v4 for parallel state tracking. Use when: '/gilfoyle <goal>', '/conductor run', 'start track', 'run the loop', 'orchestrate', 'automate track'.
npx claudepluginhub ahmedelhadarey/gilfoyle --plugin gilfoyleThis skill uses the workspace's default tool permissions.
The master coordinator that runs the Evaluate-Loop for any track. Version 4 unifies dispatch around **superpowers as the PRIMARY path** (writing-plans, executing-plans, systematic-debugging) with legacy loop agents as FALLBACK. Adds **goal-driven entry**, **parallel execution**, **Board of Directors deliberation**, and **message bus coordination**.
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
The master coordinator that runs the Evaluate-Loop for any track. Version 4 unifies dispatch around superpowers as the PRIMARY path (writing-plans, executing-plans, systematic-debugging) with legacy loop agents as FALLBACK. Adds goal-driven entry, parallel execution, Board of Directors deliberation, and message bus coordination.
/gilfoyle)The simplest entry point. User states their goal, the system handles everything.
/gilfoyle Add Stripe payment integration
/gilfoyle Fix the login bug
/gilfoyle Build an admin dashboard
async function processGoal(userGoal: string) {
// 1. GOAL ANALYSIS
const analysis = await analyzeGoal(userGoal);
/*
Returns:
- intent: "feature" | "bugfix" | "refactor" | "research"
- keywords: ["stripe", "payment", "checkout"]
- complexity: "minor" | "moderate" | "major"
- technical: boolean
*/
// 2. CHECK EXISTING TRACKS
const existingTrack = await findMatchingTrack(analysis.keywords);
if (existingTrack) {
// Resume existing track
console.log(`Found existing track: ${existingTrack.id}`);
return resumeOrchestration(existingTrack.id);
}
// 3. CREATE NEW TRACK
const trackId = await createTrackFromGoal(userGoal, analysis);
/*
Creates:
- conductor/tracks/{trackId}/
- conductor/tracks/{trackId}/spec.md (generated from goal)
- conductor/tracks/{trackId}/metadata.json (v4)
*/
// 4. RUN FULL LOOP
return runOrchestrationLoop(trackId);
}
async function analyzeGoal(goal: string) {
// Use context-explorer to understand codebase
const codebaseContext = await Task({
subagent_type: "Explore",
description: "Understand codebase for goal",
prompt: `Analyze codebase to understand context for: "${goal}"
Return:
1. Related files/components
2. Existing patterns to follow
3. Dependencies needed
4. Potential conflicts with existing code`
});
// Classify goal
const intent = classifyIntent(goal);
const keywords = extractKeywords(goal);
const complexity = estimateComplexity(goal, codebaseContext);
const technical = isTechnicalGoal(goal);
return { intent, keywords, complexity, technical, codebaseContext };
}
function classifyIntent(goal: string): string {
const lowerGoal = goal.toLowerCase();
if (lowerGoal.match(/fix|bug|error|broken|crash|issue/)) return "bugfix";
if (lowerGoal.match(/refactor|clean|optimize|improve|simplify/)) return "refactor";
if (lowerGoal.match(/research|investigate|analyze|understand/)) return "research";
return "feature";
}
async function findMatchingTrack(keywords: string[]): Track | null {
const tracks = await readTracksFile();
// Check in-progress tracks first
const inProgress = tracks.filter(t =>
t.status === 'IN_PROGRESS' || t.status === 'in_progress'
);
for (const track of inProgress) {
const trackKeywords = extractKeywords(track.name + ' ' + track.description);
const overlap = keywords.filter(k => trackKeywords.includes(k));
if (overlap.length >= 2) {
return track; // Good match
}
}
// Check planned tracks
const planned = tracks.filter(t =>
t.status === 'NOT_STARTED' || t.status === 'planned'
);
for (const track of planned) {
const trackKeywords = extractKeywords(track.name + ' ' + track.description);
const overlap = keywords.filter(k => trackKeywords.includes(k));
if (overlap.length >= 2) {
return track;
}
}
return null; // No match, create new track
}
async function generateSpecFromGoal(goal: string, analysis: GoalAnalysis): string {
const spec = await Task({
subagent_type: "Plan",
description: "Generate spec from goal",
prompt: `Generate a specification document for this goal:
GOAL: "${goal}"
CODEBASE CONTEXT:
${analysis.codebaseContext}
Create spec.md with:
1. Overview - what we're building/fixing
2. Requirements - specific deliverables
3. Acceptance Criteria - how to verify it works
4. Dependencies - what this needs
5. Out of Scope - what we're NOT doing
Be specific and actionable. Use the codebase context to identify:
- Existing patterns to follow
- Files that will be modified
- Tests that need to pass
Format as markdown.`
});
return spec.output;
}
// If goal is ambiguous, ask for clarification
if (analysis.ambiguous) {
return askUserQuestion({
questions: [{
question: "I need clarification on your goal. Which do you mean?",
header: "Clarify",
options: analysis.interpretations.map(i => ({
label: i.summary,
description: i.detail
})),
multiSelect: false
}]
});
}
// If multiple tracks match, ask which one
if (matchingTracks.length > 1) {
return askUserQuestion({
questions: [{
question: "This goal matches multiple existing tracks. Which one?",
header: "Track",
options: matchingTracks.map(t => ({
label: t.name,
description: `Status: ${t.status}`
})),
multiSelect: false
}]
});
}
loop_state.current_step from metadata.jsonsuperpowers:writing-plans, superpowers:executing-plans, superpowers:systematic-debugging are the default path for new tracksloop-planner, loop-executor, loop-fixer remain available as fallback if superpowers fail or are unavailableEXECUTE is the canonical step name (parallelism is an implementation detail inside EXECUTE, not a separate step)async function detectCurrentStep(trackId: string) {
const metadataPath = `conductor/tracks/${trackId}/metadata.json`;
const metadata = await readJSON(metadataPath);
// Migrate older versions to v4 if needed
if (!metadata.version || metadata.version < 4) {
metadata = await migrateToV4(trackId, metadata);
// NOTE: Write to metadata.json.tmp then rename to metadata.json for crash safety.
await writeJSON(metadataPath + '.tmp', metadata);
await rename(metadataPath + '.tmp', metadataPath);
}
const { current_step, step_status } = metadata.loop_state;
return { current_step, step_status, metadata };
}
PRIMARY dispatch uses superpowers. FALLBACK uses legacy loop agents if superpowers fail or are unavailable.
| Current Step | Step Status | Next Action |
|---|---|---|
PLAN | NOT_STARTED | Dispatch superpowers:writing-plans (PRIMARY) or loop-planner (FALLBACK) |
PLAN | IN_PROGRESS | Resume planning agent |
PLAN | PASSED | Advance to EVALUATE_PLAN |
EVALUATE_PLAN | NOT_STARTED | Dispatch loop-plan-evaluator + DAG validation |
EVALUATE_PLAN | BOARD_REVIEW | Invoke Board of Directors if major track |
EVALUATE_PLAN | PASSED | Advance to EXECUTE |
EVALUATE_PLAN | FAILED | Go back to PLAN with board conditions |
EXECUTE | NOT_STARTED | Dispatch superpowers:executing-plans (PRIMARY) or loop-executor (FALLBACK). Parallelism is handled internally. |
EXECUTE | IN_PROGRESS | Monitor workers via message bus |
EXECUTE | PASSED | Advance to EVALUATE_EXECUTION |
EXECUTE | PARTIAL_FAIL | Handle failures, continue independent tasks |
EVALUATE_EXECUTION | NOT_STARTED | Dispatch evaluators + quick board review |
EVALUATE_EXECUTION | PASSED | Check business_sync_required → BUSINESS_SYNC or COMPLETE |
EVALUATE_EXECUTION | FAILED | Advance to FIX |
FIX | NOT_STARTED | Check fix_cycle_count → dispatch superpowers:systematic-debugging (PRIMARY) or loop-fixer (FALLBACK) |
FIX | IN_PROGRESS | Resume fixer agent |
FIX | PASSED | Go back to EVALUATE_EXECUTION |
BUSINESS_SYNC | NOT_STARTED | Dispatch business-docs-sync |
BUSINESS_SYNC | PASSED | Advance to COMPLETE |
COMPLETE | — | Run retrospective, cleanup workers, report success |
| Any | BLOCKED | Check blockers, escalate to user |
| Any | ESCALATE | Board or lead escalated → user intervention |
Before escalating a decision to user, consult the appropriate Lead Engineer:
| Question Category | Lead to Consult | Skill Path |
|---|---|---|
| Architecture, patterns, component organization | Architecture Lead | .claude/skills/leads/architecture-lead/SKILL.md |
| Scope interpretation, requirements, copy | Product Lead | .claude/skills/leads/product-lead/SKILL.md |
| Implementation, dependencies, tooling | Tech Lead | .claude/skills/leads/tech-lead/SKILL.md |
| Testing, coverage, quality gates | QA Lead | .claude/skills/leads/qa-lead/SKILL.md |
async function handleDecision(question: Question) {
// 1. Check Authority Matrix
const authority = lookupAuthority(question.category);
// 2. USER_ONLY decisions go straight to user
if (authority === 'USER_ONLY') {
return escalateToUser(question);
}
// 3. LEAD_CONSULT decisions go to appropriate lead
if (authority === 'LEAD_CONSULT') {
const lead = getLeadForCategory(question.category);
// Dispatch lead agent via Task tool
const response = await Task({
subagent_type: "general-purpose",
description: `Consult ${lead} lead`,
prompt: `You are the ${lead}-lead agent.
Question: ${question.text}
Context: ${question.context}
Follow the ${lead}-lead skill instructions.
Output your decision in JSON format:
{
"lead": "${lead}",
"decision_made": true/false,
"decision": "...",
"reasoning": "...",
"authority_used": "...",
"escalate_to": null | "user" | "cto-advisor",
"escalation_reason": "..."
}`
});
const result = parseLeadResponse(response.output);
// Log consultation to metadata
await logConsultation(trackId, result);
if (result.decision_made) {
return result.decision;
}
// Lead escalated - follow their recommendation
return escalateTo(result.escalate_to, result.escalation_reason);
}
// 4. ORCHESTRATOR decisions are made autonomously
return makeAutonomousDecision(question);
}
See conductor/authority-matrix.md for the complete decision matrix.
Quick Reference — Always Escalate to User:
Quick Reference — Lead Can Decide:
Each agent dispatch includes instructions to update metadata.json. Atomic writes: Write to metadata.json.tmp then rename to metadata.json for crash safety.
// PRIMARY: Dispatching superpowers:executing-plans
// FALLBACK: Use loop-executor if superpowers unavailable
Task({
subagent_type: "general-purpose",
description: "Execute track tasks",
prompt: `You are the executing-plans agent for track ${trackId}.
METADATA STATE:
- Current step: EXECUTE
- Tasks completed: ${metadata.loop_state.checkpoints.EXECUTE.tasks_completed}
- Last task: ${metadata.loop_state.checkpoints.EXECUTE.last_task}
- Resume from: Next [ ] task after "${lastTask}"
Your task:
1. Read conductor/tracks/${trackId}/plan.md
2. Skip all [x] tasks - they are already done
3. Find first [ ] task after "${lastTask}"
4. Implement following superpowers:executing-plans skill
5. After EACH task completion:
- Mark [x] in plan.md with commit SHA
- Update metadata.json checkpoints.EXECUTE:
- tasks_completed++
- last_task = "Task X.Y"
- last_commit = "sha"
- Write to metadata.json.tmp then rename to metadata.json for crash safety.
6. Continue until all tasks complete
MANDATORY: Update metadata.json after every task for resumption support.
MANDATORY: Use atomic writes (write .tmp then rename) for metadata.json.`
})
PRIMARY dispatch uses superpowers. FALLBACK uses legacy loop agents.
| Step | PRIMARY Agent | FALLBACK Agent | Dispatch Prompt Key Points |
|---|---|---|---|
| PRE-PLAN | Knowledge Manager | — | Load patterns + errors for this track type |
| PLAN | superpowers:writing-plans | loop-planner | Create plan.md WITH DAG, update metadata |
| EVALUATE_PLAN | loop-plan-evaluator | — | Run 6 checks (+ DAG + Board), write verdict |
| EVALUATE_PLAN | board-of-directors | — | Full deliberation for major tracks |
| EXECUTE | superpowers:executing-plans | loop-executor / worker-templates/* | Parallel Task calls, parallelism handled internally |
| EVALUATE_EXECUTION | loop-execution-evaluator | — | Dispatch evaluators + quick board review |
| FIX | superpowers:systematic-debugging | loop-fixer | Check fix_cycle_count, implement fixes |
| BUSINESS_SYNC | business-docs-sync | — | Update Tier 1-3 docs if needed |
| POST-COMPLETE | retrospective-agent | — | Extract learnings, cleanup workers |
Parallel execution is an implementation detail inside the EXECUTE step. It is used when:
dag: block with parallel_groupsasync function stepExecute(trackId: string, metadata: dict) {
// 1. Initialize message bus
const busPath = await initMessageBus(`conductor/tracks/${trackId}`);
// 2. Parse DAG from plan.md
const dag = await parseDagFromPlan(trackId);
// 3. Import parallel dispatch utilities
const { execute_parallel_phase } = require('parallel-dispatch');
// 4. Execute all parallel groups
const result = await execute_parallel_phase(dag, trackId, busPath, metadata);
// 5. Update metadata with results
metadata.loop_state.parallel_state = {
total_workers_spawned: result.workers_spawned,
completed_workers: result.all_tasks_completed.length,
failed_workers: Object.keys(result.failed_tasks).length,
parallel_groups_completed: result.parallel_groups_executed
};
// NOTE: Write to metadata.json.tmp then rename to metadata.json for crash safety.
await writeJSON(metadataPath + '.tmp', metadata);
await rename(metadataPath + '.tmp', metadataPath);
// 6. Determine next step
if (result.success) {
return { next_step: 'EVALUATE_EXECUTION', status: 'PASSED' };
} else if (result.escalate) {
return { next_step: 'ESCALATE', reason: result.escalate_reason };
} else {
return { next_step: 'FIX', failures: result.failed_tasks };
}
}
Workers are dispatched using parallel Task calls:
// Dispatch 3 workers in parallel (single message, multiple tool calls)
await Promise.all([
Task({
subagent_type: "general-purpose",
description: "Execute Task 1.1: Create store",
prompt: workerPrompts["1.1"],
run_in_background: true
}),
Task({
subagent_type: "general-purpose",
description: "Execute Task 1.2: Build resolver",
prompt: workerPrompts["1.2"],
run_in_background: true
}),
Task({
subagent_type: "general-purpose",
description: "Execute Task 1.3: Add validation",
prompt: workerPrompts["1.3"],
run_in_background: true
})
]);
Monitor workers via message bus polling:
async function monitorWorkers(busPath: string, taskIds: string[]) {
const pending = new Set(taskIds);
const completed = new Set();
const failed = {};
while (pending.size > 0) {
// Check for completions
for (const taskId of pending) {
const eventFile = `${busPath}/events/TASK_COMPLETE_${taskId}.event`;
if (await exists(eventFile)) {
pending.delete(taskId);
completed.add(taskId);
}
const failFile = `${busPath}/events/TASK_FAILED_${taskId}.event`;
if (await exists(failFile)) {
pending.delete(taskId);
failed[taskId] = await getFailureReason(busPath, taskId);
}
}
// Check for stale workers
const stale = await checkStaleWorkers(busPath, thresholdMinutes=10);
for (const worker of stale) {
if (pending.has(worker.task_id)) {
failed[worker.task_id] = `Stale: no heartbeat for ${worker.minutes_stale}m`;
pending.delete(worker.task_id);
}
}
await sleep(5000);
}
return { completed: [...completed], failed };
}
| Checkpoint | Condition | Board Type |
|---|---|---|
| EVALUATE_PLAN | Major track (arch/integ/infra, 5+ tasks, P0) | Full meeting |
| EVALUATE_EXECUTION | Always | Quick review |
| PRE_LAUNCH | Production deploy | Security + Ops deep dive |
| CONFLICT | Evaluators disagree | Tie-breaker |
async function evaluatePlanWithBoard(trackId: string, metadata: dict) {
// 1. Run standard plan evaluation
const evalResult = await dispatchPlanEvaluator(trackId);
// 2. Check if board is needed
const needsBoard = isMajorTrack(metadata) || evalResult.recommends_board;
if (needsBoard) {
// 3. Invoke full board meeting
const boardResult = await invokeBoardMeeting(
busPath: `conductor/tracks/${trackId}/.message-bus`,
checkpoint: "EVALUATE_PLAN",
proposal: await readFile(`conductor/tracks/${trackId}/plan.md`),
context: { spec: metadata.spec_summary, dag: evalResult.dag }
);
// 4. Store board session
metadata.loop_state.board_sessions.push({
session_id: boardResult.session_id,
checkpoint: "EVALUATE_PLAN",
verdict: boardResult.verdict,
vote_summary: boardResult.votes,
conditions: boardResult.conditions,
timestamp: new Date().toISOString()
});
// 5. Handle board verdict
if (boardResult.verdict === "REJECTED") {
return {
next_step: "PLAN",
status: "FAILED",
reason: "Board rejected plan",
conditions: boardResult.conditions
};
}
// Carry forward conditions for EVALUATE_EXECUTION
metadata.board_conditions = boardResult.conditions;
}
return { next_step: "EXECUTE", status: "PASSED" };
}
async function evaluateExecutionWithBoard(trackId: string, metadata: dict) {
// 1. Run specialized evaluators
const evalResults = await dispatchSpecializedEvaluators(trackId);
// 2. Quick board review (no discussion phase)
const boardReview = await invokeBoardReview(
busPath: `conductor/tracks/${trackId}/.message-bus`,
proposal: summarizeExecutionResults(evalResults)
);
// 3. Verify board conditions from EVALUATE_PLAN were met
const conditionsMet = await verifyBoardConditions(
metadata.board_conditions,
evalResults
);
if (!conditionsMet.all_met) {
return {
next_step: "FIX",
status: "FAILED",
reason: `Board conditions not met: ${conditionsMet.unmet.join(", ")}`
};
}
return evalResults.all_passed
? { next_step: "BUSINESS_SYNC", status: "PASSED" }
: { next_step: "FIX", status: "FAILED" };
}
TRACK START
│
▼
┌──────────────────────────┐
│ KNOWLEDGE MANAGER │
│ (Load patterns) │
└────────────┬─────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ PLAN (with DAG) │
│ superpowers:writing-plans (PRIMARY) or loop-planner (FALLBACK) │
└──────────────────────────────────┬──────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ EVALUATE_PLAN + BOARD MEETING │
│ │
│ 1. DAG Validation (cycles, conflicts) │
│ 2. Standard checks (scope, overlap, deps, quality) │
│ 3. For MAJOR tracks → invoke /board-meeting │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ BOARD DELIBERATION │ │
│ │ Phase 1: All 5 directors ASSESS in parallel │ │
│ │ Phase 2: Directors DISCUSS via message bus │ │
│ │ Phase 3: Directors VOTE │ │
│ │ Phase 4: RESOLVE → APPROVED / REJECTED / CONDITIONS │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
│ PASS → Continue | FAIL → Back to PLAN with conditions │
└──────────────────────────────────┬──────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ EXECUTE (parallel internally) │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ MESSAGE BUS │ │
│ │ queue.jsonl | locks.json | worker-status.json | events/ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ superpowers:executing-plans (PRIMARY) or loop-executor (FALLBACK) │
│ For each parallel_group in DAG: │
│ 1. agent-factory creates specialized workers │
│ 2. Dispatch via parallel Task(run_in_background=true) │
│ 3. Workers coordinate via message bus: │
│ - FILE_LOCK / FILE_UNLOCK for shared files │
│ - PROGRESS updates every 5 min │
│ - TASK_COMPLETE / TASK_FAILED when done │
│ 4. Monitor for completion, handle failures │
│ 5. Cleanup ephemeral workers │
│ │
│ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │Worker│ │Worker│ │Worker│ (max 5 concurrent) │
│ │ 1.1 │ │ 1.2 │ │ 1.3 │ │
│ └──┬───┘ └──┬───┘ └──┬───┘ │
│ └────────┴────────┘ │
│ │ │
│ PASS → Continue | PARTIAL_FAIL → Isolate + Continue │
└──────────────────────────────────┬──────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ EVALUATE_EXECUTION + BOARD REVIEW │
│ │
│ 1. Specialized evaluators (UI, Code, Integration, Business) │
│ 2. Quick board review (no discussion) │
│ 3. Verify board conditions from EVALUATE_PLAN │
│ │
│ PASS → BUSINESS_SYNC? → COMPLETE │
│ FAIL → FIX (with specific failures) │
└──────────────────────────────────┬──────────────────────────────────────────┘
│
┌────┴────┐
│ │
PASS ▼ FAIL ▼
┌──────────┐ ┌──────────┐
│BUSINESS │ │ FIX │
│ SYNC │ │ (max 3x) │
└────┬─────┘ └────┬─────┘
│ │
▼ │
┌──────────┐ │
│ COMPLETE │◄──────┘
│ │ (after fix passes)
└────┬─────┘
│
▼
┌──────────────────────────┐
│ RETROSPECTIVE AGENT │
│ + Cleanup workers │
└──────────────────────────┘
When orchestrator starts, it resumes from exact state:
async function resumeOrchestration(trackId: string) {
const { current_step, step_status, metadata } = await detectCurrentStep(trackId);
switch (step_status) {
case 'NOT_STARTED':
// Start the step fresh
return dispatchAgent(current_step, metadata);
case 'IN_PROGRESS':
// Resume the step with checkpoint data
const checkpoint = metadata.loop_state.checkpoints[current_step];
return resumeAgent(current_step, checkpoint);
case 'PASSED':
// Move to next step
const nextStep = getNextStep(current_step, 'PASS');
await updateMetadata(trackId, { current_step: nextStep, step_status: 'NOT_STARTED' });
return dispatchAgent(nextStep, metadata);
case 'FAILED':
// Handle based on which step failed
if (current_step === 'EVALUATE_PLAN') {
// NOTE: Write to metadata.json.tmp then rename to metadata.json for crash safety.
await updateMetadata(trackId, { current_step: 'PLAN', step_status: 'NOT_STARTED' });
return dispatchAgent('PLAN', metadata);
}
if (current_step === 'EVALUATE_EXECUTION') {
// Check fix cycle limit
if (metadata.loop_state.fix_cycle_count >= 3) {
return escalateToUser('Fix cycle limit exceeded after 3 attempts');
}
// NOTE: Write to metadata.json.tmp then rename to metadata.json for crash safety.
await updateMetadata(trackId, {
current_step: 'FIX',
step_status: 'NOT_STARTED',
fix_cycle_count: metadata.loop_state.fix_cycle_count + 1
});
return dispatchAgent('FIX', metadata);
}
// Unhandled FAILED step — escalate rather than fall through
return escalateToUser(`Unexpected FAILED state at step: ${current_step}`);
case 'BLOCKED':
// Check if blocker is resolved
const activeBlockers = metadata.blockers.filter(b => b.status === 'ACTIVE');
if (activeBlockers.length > 0) {
return escalateToUser(`Track blocked: ${activeBlockers[0].description}`);
}
// Blocker resolved, continue
// NOTE: Write to metadata.json.tmp then rename to metadata.json for crash safety.
await updateMetadata(trackId, { step_status: 'NOT_STARTED' });
return dispatchAgent(current_step, metadata);
default:
// Unrecognized step+status combination — escalate to user
return escalateToUser(
`Unrecognized state: step=${current_step}, status=${step_status}. ` +
`Manual intervention required.`
);
}
}
| Step | Resumption Data | Action |
|---|---|---|
| PLAN | checkpoints.PLAN.plan_version | Re-run planner if revising |
| EXECUTE | checkpoints.EXECUTE.last_task | Skip completed tasks, continue from next |
| FIX | checkpoints.FIX.fixes_remaining | Continue with remaining fixes |
┌─────────────────────────────────────────────────────────────────┐
│ ORCHESTRATOR │
│ │
│ 1. Read metadata.json → detect current_step + step_status │
│ 2. Dispatch appropriate agent via Task tool │
│ 3. Agent updates metadata.json checkpoints │
│ 4. Agent returns → orchestrator reads new state │
│ 5. Continue to next step or handle failure │
│ 6. Loop until COMPLETE or escalation needed │
│ │
└─────────────────────────────────────────────────────────────────┘
PLAN ──► EVALUATE_PLAN ──► EXECUTE ──► EVALUATE_EXECUTION
▲ │ │
│ FAIL → back PASS → BUSINESS_SYNC? → COMPLETE
│ FAIL → FIX
│ │
└─────────────────────────────────────────────┘
(after fix, re-evaluate)
Escalate to user (stop the loop) when:
escalate_to: "user"## Orchestrator Paused — User Input Required
**Track**: [track-id]
**Current Step**: [step]
**Reason**: [escalation reason]
**Context**:
[What was happening when escalation triggered]
**Options**:
1. [Option 1]
2. [Option 2]
3. [Option 3 if applicable]
What would you like to do?
When current_step reaches COMPLETE:
{
"status": "complete",
"completed_at": "[timestamp]",
"loop_state": {
"current_step": "COMPLETE",
"step_status": "PASSED"
}
}
Update tracks.md — Move track to "Done" table with date
Update conductor/index.md — Update current status
Commit — docs: complete [track-id] - evaluation passed
Report to user
## Track Complete
**Track**: [track-id]
**Phases**: [count] completed
**Tasks**: [count] completed
**Evaluation**: PASS — all checks passed
**Lead Consultations**: [count] decisions made autonomously
**Commits**: [list of key commits]
**Next track**: [suggest from tracks.md]
For technical tracks, automatically include CTO review during EVALUATE_PLAN:
// Detect if track is technical
const technicalKeywords = [
'architecture', 'system design', 'integration', 'API', 'database',
'schema', 'migration', 'infrastructure', 'scalability', 'performance',
'security', 'authentication', 'authorization', 'deployment'
];
const isTechnical = technicalKeywords.some(keyword =>
spec.toLowerCase().includes(keyword) || plan.toLowerCase().includes(keyword)
);
if (isTechnical) {
// Include CTO review in plan evaluation
dispatchPrompt += `
This is a TECHNICAL track. Your evaluation must include:
1. Standard plan checks (scope, overlap, dependencies, clarity)
2. CTO technical review using cto-plan-reviewer skill
Both must PASS for plan evaluation to pass.`;
}
The orchestrator integrates the Knowledge Layer for continuous learning:
BEFORE dispatching the planner, run Knowledge Manager to load relevant patterns:
async function dispatchPlannerWithKnowledge(trackId: string) {
// 1. Run Knowledge Manager first
const knowledgeBrief = await Task({
subagent_type: "general-purpose",
description: "Load knowledge for track",
prompt: `You are the knowledge-manager agent.
Track: ${trackId}
Spec: ${await readFile(`conductor/tracks/${trackId}/spec.md`)}
1. Extract keywords from the spec
2. Search conductor/knowledge/patterns.md for matching patterns
3. Search conductor/knowledge/errors.json for relevant errors
4. Return a knowledge brief with:
- Relevant patterns to apply
- Known errors to avoid
- Similar previous tracks (if any)
Follow .claude/skills/knowledge/knowledge-manager/SKILL.md`
});
// 2. Dispatch planner WITH knowledge brief injected
// PRIMARY: superpowers:writing-plans. FALLBACK: loop-planner.
await Task({
subagent_type: "general-purpose",
description: "Create track plan",
prompt: `You are the writing-plans agent for track ${trackId}.
## KNOWLEDGE BRIEF (from previous tracks)
${knowledgeBrief.output}
## YOUR TASK
Create plan.md using the patterns above where applicable.
Avoid the known errors listed.
Follow superpowers:writing-plans skill (or .claude/skills/loop-planner/SKILL.md as fallback)`
});
}
AFTER a track reaches COMPLETE, run Retrospective Agent to extract learnings:
async function runPostCompletionRetrospective(trackId: string) {
await Task({
subagent_type: "general-purpose",
description: "Run track retrospective",
prompt: `You are the retrospective-agent.
Track: ${trackId}
1. Read conductor/tracks/${trackId}/plan.md (all tasks and fix cycles)
2. Read conductor/tracks/${trackId}/metadata.json (fix counts, consultations)
3. Analyze: What worked? What failed? What patterns emerged?
4. Update conductor/knowledge/patterns.md with new reusable solutions
5. Update conductor/knowledge/errors.json with new error patterns
6. Write retrospective to conductor/tracks/${trackId}/retrospective.md
7. Propose skill improvements if workflow issues found
Follow .claude/skills/knowledge/retrospective-agent/SKILL.md`
});
}
TRACK START
│
▼
┌──────────────────────────┐
│ KNOWLEDGE MANAGER │ ◄── NEW: Load patterns & errors
│ (Pre-planning intel) │
└────────────┬─────────────┘
│
▼
PLAN ──► EVALUATE_PLAN ──► EXECUTE ──► EVALUATE_EXECUTION
▲ │ │
│ FAIL → back PASS → BUSINESS_SYNC? → COMPLETE
│ FAIL → FIX │
│ │ │
└─────────────────────────────────────────────┘ │
▼
┌──────────────────────────┐
│ RETROSPECTIVE AGENT │ ◄── NEW
│ (Extract learnings) │
└────────────┬─────────────┘
│
▼
┌──────────────────────────┐
│ KNOWLEDGE BASE │
│ patterns.md + errors.json│
└──────────────────────────┘
│
▼
NEXT TRACK
(now smarter than before)
| File | Purpose | Updated By |
|---|---|---|
conductor/knowledge/patterns.md | Reusable solutions | Retrospective Agent |
conductor/knowledge/errors.json | Error → Fix registry | Retrospective Agent, Fixer |
conductor/tracks/[id]/retrospective.md | Track-specific learnings | Retrospective Agent |
The fixer (superpowers:systematic-debugging as PRIMARY, loop-fixer as FALLBACK) also uses the error registry:
// In the fixer, before attempting a fix
async function findKnownSolution(errorMessage: string) {
const errors = JSON.parse(await readFile('conductor/knowledge/errors.json'));
for (const error of errors.errors) {
if (new RegExp(error.pattern, 'i').test(errorMessage)) {
return {
found: true,
solution: error.solution,
code_fix: error.code_fix
};
}
}
return { found: false };
}
// After fixing a new error, log it
async function logNewError(pattern, solution, trackId) {
const errors = JSON.parse(await readFile('conductor/knowledge/errors.json'));
errors.errors.push({
id: `err-${String(errors.errors.length + 1).padStart(3, '0')}`,
pattern,
solution,
discovered_in: trackId,
last_seen: new Date().toISOString().split('T')[0]
});
await writeFile('conductor/knowledge/errors.json', JSON.stringify(errors, null, 2));
}
User: /conductor run
Orchestrator:
1. Read conductor/tracks.md → get active track
2. Read conductor/tracks/[track]/metadata.json → get loop_state
3. Determine current step and status
4. Dispatch appropriate agent
5. Loop until complete
| Data | Location | Purpose |
|---|---|---|
| Loop state | metadata.json → loop_state | Primary state machine |
| Task progress | plan.md markers | Human-readable progress |
| Lead decisions | metadata.json → lead_consultations | Decision audit trail |
| Blockers | metadata.json → blockers | Escalation tracking |
| Authority rules | conductor/authority-matrix.md | Decision boundaries |
conductor/tracks/[track]/metadata.json — State updates (Write to metadata.json.tmp then rename to metadata.json for crash safety.)conductor/tracks.md — Completion trackingconductor/index.md — Current status