Skip to main content
Glama

overseer.run_phase

Execute project phases by reading task files, checking completion status, and generating TODO items for incomplete tasks to maintain structured workflow progress.

Instructions

Execute a specific phase of a project. Reads tasks from PHASE-XX.md, checks completion status, and creates TODOs/stubs for incomplete tasks.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
repo_rootYesRoot path of the repository
phase_idYesPhase ID (e.g., "01", "02")
aggression_levelNoHow aggressively to create files and make changesnormal

Implementation Reference

  • Main execution handler for overseer.run_phase tool. Processes PHASE-XX.md, checks/completes tasks, creates stubs/TODOs based on aggression_level, updates status and checklists.
    export async function handleRunPhase( args: { repo_root: string; phase_id: string; aggression_level?: 'bossmode' | 'normal' | 'conservative'; }, phaseManager: PhaseManager ): Promise<{ success: boolean; message: string; phase_id: string; completed_tasks: Array<{ task: string; type: 'deliverable' | 'done_criterion'; evidence: string; }>; pending_tasks: Array<{ task: string; type: 'deliverable' | 'done_criterion'; action_taken: string; }>; changed_files: string[]; status: 'in_progress' | 'potentially_complete'; }> { const completedTasks: Array<{ task: string; type: 'deliverable' | 'done_criterion'; evidence: string }> = []; const pendingTasks: Array<{ task: string; type: 'deliverable' | 'done_criterion'; action_taken: string }> = []; const changedFiles: string[] = []; try { // Resolve repo path let repoPath = args.repo_root; if (!repoPath.startsWith('/')) { repoPath = join(homedir(), 'dev', repoPath); } repoPath = FSUtils.expandPath(repoPath); const phaseId = args.phase_id.padStart(2, '0'); const aggressionLevel = args.aggression_level || 'normal'; // Read PHASES.md using absolute path (handles paths with spaces) const repoName = repoPath.split('/').pop() || 'unknown'; const repoHandler = new RepoHandler(); const projectPhases = repoHandler.readPhasesIndexFromPath(repoPath); if (!projectPhases) { return { success: false, message: 'Project not found. Run plan_project first.', phase_id: phaseId, completed_tasks: [], pending_tasks: [], changed_files: [], status: 'in_progress', }; } // Find the phase const phase = projectPhases.phases.find(p => p.id === phaseId); if (!phase) { return { success: false, message: `Phase ${phaseId} not found`, phase_id: phaseId, completed_tasks: [], pending_tasks: [], changed_files: [], status: 'in_progress', }; } // Read PHASE-XX.md (handles paths with spaces) const phaseFilePath = repoHandler.getPhaseFileByIdFromPath(repoPath, phaseId); if (!FSUtils.fileExists(phaseFilePath)) { return { success: false, message: `Phase file PHASE-${phaseId}.md not found`, phase_id: phaseId, completed_tasks: [], pending_tasks: [], changed_files: [], status: 'in_progress', }; } let phaseContent = FSUtils.readFile(phaseFilePath); // Parse deliverables and done_criteria from phase file const deliverables: string[] = []; const doneCriteria: string[] = []; // Extract deliverables const deliverablesMatch = phaseContent.match(/## Deliverables\s*\n((?:- \[[ x]\] .+\n?)+)/); if (deliverablesMatch) { const items = deliverablesMatch[1].match(/- \[[ x]\] (.+)/g); if (items) { items.forEach(item => { const text = item.replace(/- \[[ x]\] /, '').trim(); if (text) deliverables.push(text); }); } } // Extract done criteria const doneCriteriaMatch = phaseContent.match(/## Done Criteria\s*\n((?:- \[[ x]\] .+\n?)+)/); if (doneCriteriaMatch) { const items = doneCriteriaMatch[1].match(/- \[[ x]\] (.+)/g); if (items) { items.forEach(item => { const text = item.replace(/- \[[ x]\] /, '').trim(); if (text) doneCriteria.push(text); }); } } // Check each deliverable for (const deliverable of deliverables) { const checked = checkTaskCompletion(deliverable, repoPath, aggressionLevel); if (checked.completed) { completedTasks.push({ task: deliverable, type: 'deliverable', evidence: checked.evidence, }); // Update checklist in phase file phaseContent = updateChecklistItem(phaseContent, deliverable, true, 'Deliverables'); } else { pendingTasks.push({ task: deliverable, type: 'deliverable', action_taken: checked.actionTaken, }); // Create stub/TODO if aggression level allows if (aggressionLevel !== 'conservative' && checked.filePath) { createStubFile(checked.filePath, deliverable, aggressionLevel); changedFiles.push(checked.filePath); } // Update checklist in phase file phaseContent = updateChecklistItem(phaseContent, deliverable, false, 'Deliverables'); } } // Check each done criterion for (const criterion of doneCriteria) { const checked = checkTaskCompletion(criterion, repoPath, aggressionLevel); if (checked.completed) { completedTasks.push({ task: criterion, type: 'done_criterion', evidence: checked.evidence, }); phaseContent = updateChecklistItem(phaseContent, criterion, true, 'Done Criteria'); } else { pendingTasks.push({ task: criterion, type: 'done_criterion', action_taken: checked.actionTaken, }); phaseContent = updateChecklistItem(phaseContent, criterion, false, 'Done Criteria'); } } // Update phase status to in_progress if not already if (phase.status === 'pending') { phase.status = 'in_progress'; phase.started_at = new Date().toISOString(); repoHandler.writePhasesIndexToPath(repoPath, projectPhases); changedFiles.push(join(repoPath, 'PHASES.md')); } // Update phase file phaseContent = updatePhaseStatus(phaseContent, 'in_progress'); FSUtils.writeFile(phaseFilePath, phaseContent); changedFiles.push(phaseFilePath); // Determine overall status const allComplete = completedTasks.length === deliverables.length + doneCriteria.length; const status = allComplete ? 'potentially_complete' : 'in_progress'; return { success: true, message: `Phase ${phaseId} execution completed. ${completedTasks.length} tasks complete, ${pendingTasks.length} pending.`, phase_id: phaseId, completed_tasks: completedTasks, pending_tasks: pendingTasks, changed_files: changedFiles, status, }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { success: false, message: `Failed to run phase: ${errorMessage}`, phase_id: args.phase_id, completed_tasks: [], pending_tasks: [], changed_files: [], status: 'in_progress', }; } }
  • Tool schema definition including name, description, and input schema parameters for overseer.run_phase.
    export function createRunPhaseTool(phaseManager: PhaseManager): Tool { return { name: 'overseer.run_phase', description: 'Execute a specific phase of a project. Reads tasks from PHASE-XX.md, checks completion status, and creates TODOs/stubs for incomplete tasks.', inputSchema: { type: 'object', required: ['repo_root', 'phase_id'], properties: { repo_root: { type: 'string', description: 'Root path of the repository', }, phase_id: { type: 'string', description: 'Phase ID (e.g., "01", "02")', }, aggression_level: { type: 'string', enum: ['bossmode', 'normal', 'conservative'], default: 'normal', description: 'How aggressively to create files and make changes', }, }, }, }; }
  • Registration of overseer.run_phase tool via createRunPhaseTool in the tools array returned by createTools.
    export function createTools(context: ToolContext): Tool[] { return [ // Planning tools createPlanProjectTool(context.phaseManager), createInferPhasesTool(context.configLoader), createUpdatePhasesTool(context.phaseManager), // Execution tools createRunPhaseTool(context.phaseManager), createAdvancePhaseTool(context.phaseManager), createStatusTool(context.phaseManager), // QA tools createLintRepoTool(context.configLoader), createSyncDocsTool(context.phaseManager), createCheckComplianceTool(context.phaseManager), // Environment tools createEnvMapTool(context.phaseManager), createGenerateCiTool(context.phaseManager), createSecretsTemplateTool(context.phaseManager), ]; }
  • Dispatcher in handleToolCall that routes 'overseer.run_phase' calls to the handleRunPhase function.
    export async function handleToolCall( name: string, args: any, context: ToolContext ): Promise<any> { switch (name) { // Planning tools case 'overseer.plan_project': return await handlePlanProject(args, context.phaseManager); case 'overseer.infer_phases': return await handleInferPhases(args, context.configLoader); case 'overseer.update_phases': return await handleUpdatePhases(args, context.phaseManager); // Execution tools case 'overseer.run_phase': return await handleRunPhase(args, context.phaseManager); case 'overseer.advance_phase': return await handleAdvancePhase(args, context.phaseManager); case 'overseer.status': return await handleStatus(args, context.phaseManager); // QA tools case 'overseer.lint_repo': return await handleLintRepo(args, context.configLoader); case 'overseer.sync_docs': return await handleSyncDocs(args, context.phaseManager); case 'overseer.check_compliance': return await handleCheckCompliance(args, context.phaseManager); // Environment tools case 'overseer.env_map': return await handleEnvMap(args, context.phaseManager); case 'overseer.generate_ci': return await handleGenerateCi(args, context.phaseManager); case 'overseer.secrets_template': return await handleSecretsTemplate(args, context.phaseManager); default: throw new Error(`Unknown tool: ${name}`); } }
  • Supporting helper functions for task checking, file stubbing, checklist updates, etc.
    } function checkTaskCompletion(

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/freqkflag/PROJECT-OVERSEER-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server