contentrain_validate
Validate content against model schemas to detect field violations, type mismatches, broken relations, secret leaks, and i18n issues. Optionally auto-fix structural problems like canonical sorting and missing locale files.
Instructions
Validate project content against model schemas. Detects required field violations, type mismatches, broken relations, secret leaks, i18n parity issues, and more. If fix:true, auto-fixes structural issues (canonical sort, orphan meta, missing locale files) — do NOT manually edit .contentrain/ files.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| model | No | Model ID to validate (omit for all models) | |
| fix | No | Auto-fix structural issues (canonical sort, orphan meta, missing locale files). Default: false |
Implementation Reference
- The handler for 'contentrain_validate' tool, which validates project content and optionally auto-fixes issues.
server.tool( 'contentrain_validate', 'Validate project content against model schemas. Detects required field violations, type mismatches, broken relations, secret leaks, i18n parity issues, and more. If fix:true, auto-fixes structural issues (canonical sort, orphan meta, missing locale files) — do NOT manually edit .contentrain/ files.', { model: z.string().optional().describe('Model ID to validate (omit for all models)'), fix: z.boolean().optional().describe('Auto-fix structural issues (canonical sort, orphan meta, missing locale files). Default: false'), }, async (input) => { const config = await readConfig(projectRoot) if (!config) { return { content: [{ type: 'text' as const, text: JSON.stringify({ error: 'Project not initialized. Run contentrain_init first.' }) }], isError: true, } } try { let result: Awaited<ReturnType<typeof validateProject>> | undefined if (input.fix) { // Branch health gate for fix mode (creates a branch) const fixHealth = await checkBranchHealth(projectRoot) if (fixHealth.blocked) { return { content: [{ type: 'text' as const, text: JSON.stringify({ error: fixHealth.message, action: 'blocked', hint: 'Merge or delete old contentrain/* branches before auto-fixing.', }, null, 2) }], isError: true, } } // Use git transaction for fixes const branch = buildBranchName('fix', 'validate') const tx = await createTransaction(projectRoot, branch) try { await tx.write(async (wt) => { result = await validateProject(wt, { model: input.model, fix: true }) }) if (result!.fixed > 0) { await tx.commit(`[contentrain] validate: auto-fix ${result!.fixed} issue(s)`) const gitResult = await tx.complete({ tool: 'contentrain_validate', model: input.model ?? '*', }) const nextSteps: string[] = [] if (result!.summary.errors > 0) nextSteps.push('Fix remaining errors manually') if (result!.summary.warnings > 0) nextSteps.push('Review warnings') nextSteps.push('Run contentrain_validate again to verify') return { content: [{ type: 'text' as const, text: JSON.stringify({ status: 'committed', message: `Validation complete. ${result!.fixed} issue(s) auto-fixed and committed to git. Do NOT manually edit .contentrain/ files.`, ...result!, git: { branch, action: gitResult.action, commit: gitResult.commit }, context_updated: true, next_steps: nextSteps, }, null, 2) }], } } else { // Nothing to fix, cleanup the branch await tx.cleanup() } } catch (error) { await tx.cleanup() throw error } finally { await tx.cleanup() } } // No fix or nothing was fixed — run read-only validation if (!result) { result = await validateProject(projectRoot, { model: input.model, fix: false }) } const nextSteps: string[] = [] if (result.summary.errors > 0) nextSteps.push('Fix errors in content using contentrain_content_save') if (result.summary.warnings > 0) nextSteps.push('Review warnings') if (result.valid) nextSteps.push('Run contentrain_submit to push changes') return { content: [{ type: 'text' as const, text: JSON.stringify({ status: 'validated', message: result.valid ? 'All validation checks passed.' : `Validation found ${result.summary.errors} error(s) and ${result.summary.warnings} warning(s).`, ...result, next_steps: nextSteps, }, null, 2) }], } } catch (error) { return { content: [{ type: 'text' as const, text: JSON.stringify({ error: `Validation failed: ${error instanceof Error ? error.message : String(error)}`, }) }], isError: true, } } }, )