overseer.status
Check project status by analyzing phase files to determine current phases and their states for structured project management workflows.
Instructions
Get the current status of a project, including all phases and their states. Determines phase status from PHASES.md and PHASE-*.md files.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| repo_root | Yes | Root path of the repository |
Implementation Reference
- src/tools/status.ts:25-169 (handler)The `handleStatus` function implements the core logic of the 'overseer.status' tool. It resolves the repository path, reads the PHASES.md file, determines phase statuses by checking PHASE-*.md files, computes the current phase and summary statistics, and returns a structured status report.export async function handleStatus( args: { repo_root: string }, phaseManager: PhaseManager ): Promise<{ success: boolean; message: string; project_name: string; current_phase: string | null; phases: Array<{ id: string; name: string; status: string; description?: string; started_at?: string; completed_at?: string; }>; summary: { total: number; pending: number; active: number; in_progress: number; completed: number; locked: number; blocked: number; }; }> { try { // Resolve repo path let repoPath = args.repo_root; if (!repoPath.startsWith('/')) { repoPath = join(homedir(), 'dev', repoPath); } repoPath = FSUtils.expandPath(repoPath); // Extract repo name from path (for display purposes) const repoName = repoPath.split('/').pop() || 'unknown'; // Read PHASES.md using absolute path (handles paths with spaces) const repoHandler = new RepoHandler(); const projectPhases = repoHandler.readPhasesIndexFromPath(repoPath); if (!projectPhases) { return { success: false, message: `Project ${repoName} not found. Run plan_project first.`, project_name: repoName, current_phase: null, phases: [], summary: { total: 0, pending: 0, active: 0, in_progress: 0, completed: 0, locked: 0, blocked: 0, }, }; } // Determine current phase (first non-completed phase) let currentPhase: string | null = null; for (const phase of projectPhases.phases) { if (phase.status !== 'completed') { currentPhase = phase.id; break; } } // Enhance phase status by checking PHASE-*.md files const enhancedPhases = projectPhases.phases.map(phase => { let enhancedStatus = phase.status; // Try to read phase file to get more accurate status (handles paths with spaces) const phaseFilePath = repoHandler.getPhaseFileByIdFromPath(repoPath, phase.id); if (FSUtils.fileExists(phaseFilePath)) { try { const phaseContent = FSUtils.readFile(phaseFilePath); // Check for status markers in the file if (phaseContent.includes('**Status**: locked')) { enhancedStatus = 'locked'; } else if (phaseContent.includes('**Status**: in_progress')) { enhancedStatus = 'in_progress'; } else if (phaseContent.includes('**Status**: active')) { enhancedStatus = 'active'; } else if (phaseContent.includes('**Status**: completed')) { enhancedStatus = 'completed'; } else if (phaseContent.includes('**Status**: blocked')) { enhancedStatus = 'blocked'; } } catch { // If we can't read the file, use the status from PHASES.md } } return { id: phase.id, name: phase.name, status: enhancedStatus, description: phase.description, started_at: phase.started_at, completed_at: phase.completed_at, }; }); // Calculate summary const summary = { total: enhancedPhases.length, pending: enhancedPhases.filter(p => p.status === 'pending').length, active: enhancedPhases.filter(p => p.status === 'active').length, in_progress: enhancedPhases.filter(p => p.status === 'in_progress').length, completed: enhancedPhases.filter(p => p.status === 'completed').length, locked: enhancedPhases.filter(p => p.status === 'locked').length, blocked: enhancedPhases.filter(p => p.status === 'blocked').length, }; return { success: true, message: `Status retrieved for project ${projectPhases.project_name}`, project_name: projectPhases.project_name, current_phase: currentPhase, phases: enhancedPhases, summary, }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { success: false, message: `Failed to get status: ${errorMessage}`, project_name: 'unknown', current_phase: null, phases: [], summary: { total: 0, pending: 0, active: 0, in_progress: 0, completed: 0, locked: 0, blocked: 0, }, }; } }
- src/tools/status.ts:8-23 (schema)The `createStatusTool` function defines the tool metadata, including the name 'overseer.status', description, and input schema requiring 'repo_root'.export function createStatusTool(phaseManager: PhaseManager): Tool { return { name: 'overseer.status', description: 'Get the current status of a project, including all phases and their states. Determines phase status from PHASES.md and PHASE-*.md files.', inputSchema: { type: 'object', required: ['repo_root'], properties: { repo_root: { type: 'string', description: 'Root path of the repository', }, }, }, }; }
- src/tools/index.ts:22-41 (registration)The `createTools` function registers the 'overseer.status' tool by calling `createStatusTool` and including it in the array of available tools.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), ]; }
- src/tools/index.ts:61-62 (registration)In the `handleToolCall` dispatcher, the switch case for 'overseer.status' routes execution to the `handleStatus` handler.case 'overseer.status': return await handleStatus(args, context.phaseManager);