Skip to main content
Glama

overseer.check_compliance

Validate repository structure against sentinel.yml conventions to ensure compliance with expected directories and key files.

Instructions

Validates repository structure against sentinel.yml conventions. Checks for expected directories and key files.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
repo_rootYesRoot path of the repository
phase_idNoOptional: Specific phase ID to check
strictNoIf true, all checks must pass. If false, warns about missing items.

Implementation Reference

  • The core handler function implementing the overseer.check_compliance tool logic. It validates the repository against conventions from sentinel.yml, checking directories, key files, PHASES.md, phase-specific structures, and naming.
    export async function handleCheckCompliance( args: { repo_root: string; phase_id?: string; strict?: boolean; }, phaseManager: PhaseManager ): Promise<{ success: boolean; compliant: boolean; phase_id?: string; checks: Array<{ check_type: 'directory' | 'file' | 'convention' | 'phase_structure'; passed: boolean; message: string; details?: Record<string, unknown>; }>; summary: { total_checks: number; passed: number; failed: number; }; }> { const checks: Array<{ check_type: 'directory' | 'file' | 'convention' | 'phase_structure'; passed: boolean; message: string; details?: Record<string, unknown>; }> = []; try { // Resolve repo path let repoPath = args.repo_root; if (!repoPath.startsWith('/')) { repoPath = join(homedir(), 'dev', repoPath); } repoPath = FSUtils.expandPath(repoPath); if (!FSUtils.dirExists(repoPath)) { return { success: false, compliant: false, checks: [{ check_type: 'directory', passed: false, message: 'Repository directory does not exist', }], summary: { total_checks: 1, passed: 0, failed: 1, }, }; } // Load config to get conventions const configLoader = new ConfigLoader(); const config = configLoader.getConfig(); const conventions = config.conventions; // Check PHASES.md exists const phasesPath = join(repoPath, conventions.phases_index.file); if (FSUtils.fileExists(phasesPath)) { checks.push({ check_type: 'file', passed: true, message: `${conventions.phases_index.file} exists`, }); } else { checks.push({ check_type: 'file', passed: false, message: `${conventions.phases_index.file} is missing`, }); } // Check for common expected directories based on conventions const expectedDirs = ['src', 'config', 'docs']; for (const dir of expectedDirs) { const dirPath = join(repoPath, dir); if (FSUtils.dirExists(dirPath)) { checks.push({ check_type: 'directory', passed: true, message: `${dir}/ directory exists`, }); } else { checks.push({ check_type: 'directory', passed: false, message: `${dir}/ directory is missing`, }); } } // Check for key files const keyFiles = ['README.md', 'package.json', '.gitignore']; for (const file of keyFiles) { const filePath = join(repoPath, file); if (FSUtils.fileExists(filePath)) { checks.push({ check_type: 'file', passed: true, message: `${file} exists`, }); } else { checks.push({ check_type: 'file', passed: false, message: `${file} is missing`, }); } } // If phase_id provided, check phase-specific structure if (args.phase_id) { const phaseId = args.phase_id.padStart(2, '0'); const phaseFilePath = join(repoPath, `PHASE-${phaseId}.md`); if (FSUtils.fileExists(phaseFilePath)) { const phaseContent = FSUtils.readFile(phaseFilePath); // Check for required sections const requiredSections = ['Description', 'Deliverables', 'Done Criteria', 'Progress']; for (const section of requiredSections) { if (phaseContent.includes(`## ${section}`)) { checks.push({ check_type: 'phase_structure', passed: true, message: `PHASE-${phaseId}.md has ${section} section`, }); } else { checks.push({ check_type: 'phase_structure', passed: false, message: `PHASE-${phaseId}.md missing ${section} section`, }); } } } else { checks.push({ check_type: 'phase_structure', passed: false, message: `PHASE-${phaseId}.md file is missing`, }); } } // Check naming conventions const repoName = repoPath.split('/').pop() || ''; const namingConvention = conventions.naming.phase_names; // Use phase_names as proxy for repo naming if (namingConvention === 'kebab-case') { const isValidKebabCase = /^[a-z0-9]+(-[a-z0-9]+)*$/.test(repoName); checks.push({ check_type: 'convention', passed: isValidKebabCase, message: `Repository name follows kebab-case convention`, details: { repo_name: repoName, expected_format: 'kebab-case' }, }); } // Calculate summary const passed = checks.filter(c => c.passed).length; const failed = checks.filter(c => !c.passed).length; const compliant = args.strict ? failed === 0 : true; // In strict mode, all must pass return { success: true, compliant, phase_id: args.phase_id, checks, summary: { total_checks: checks.length, passed, failed, }, }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { success: false, compliant: false, checks: [{ check_type: 'convention', passed: false, message: `Error checking compliance: ${errorMessage}`, }], summary: { total_checks: 1, passed: 0, failed: 1, }, }; } }
  • Defines the tool specification including name, description, and detailed inputSchema for parameters repo_root (required), phase_id (optional), strict (optional boolean).
    export function createCheckComplianceTool(phaseManager: PhaseManager): Tool { return { name: 'overseer.check_compliance', description: 'Validates repository structure against sentinel.yml conventions. Checks for expected directories and key files.', inputSchema: { type: 'object', required: ['repo_root'], properties: { repo_root: { type: 'string', description: 'Root path of the repository', }, phase_id: { type: 'string', description: 'Optional: Specific phase ID to check', }, strict: { type: 'boolean', default: false, description: 'If true, all checks must pass. If false, warns about missing items.', }, }, }, }; }
  • Tool factory function that registers the overseer.check_compliance tool by calling createCheckComplianceTool 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), ]; }
  • Central tool dispatcher that routes calls to 'overseer.check_compliance' to the handleCheckCompliance function with context.
    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}`); } }

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