How Archify's Validation System Works: Schema Checks and Composition Checks Explained
Archify validates every architecture diagram in two independent stages—schema validation against a JSON-IR type system, followed by geometric composition checks on the rendered SVG—producing a validation receipt that powers CI gates and proof galleries.
Archify's validation system ensures that authored diagrams meet both structural and visual quality standards before they reach production. The system is implemented across archify/renderers/shared/validator.mjs and archify/renderers/shared/geometry.mjs, with the CLI at archify/bin/archify.mjs orchestrating the full pipeline. This article breaks down how both validation stages work and what each composition check evaluates.
Schema Validation: Type-Safe JSON-IR Verification
The first stage ensures your diagram data conforms to the expected structure for its type. This check is fail-closed: any schema error aborts the pipeline immediately.
How Schema Validation Runs
- Load the validator –
validateSchema(diagramType, data)imports the pre-compiled AJV function fromarchify/renderers/shared/generated-validators.mjs. - Execute AJV – The validator runs against your diagram's JSON-IR. If
validate(data)returns false, AJV populatesvalidate.errors. - Format diagnostics –
formatErrorsbuilds human-readable messages, whileannotatedPathenriches JSON pointers with node identifiers (e.g.,/nodes/3 (id: "router")/label). - Abort on failure –
throwDiagnosticErrorcreates a structured diagnostic object withcode,severity,subject,evidence, andsupportedFixes, then halts execution.
The schema validator is deterministic and environment-independent—it is compiled ahead of time and bundled with the package.
Running Schema Validation Programmatically
import { validateSchema } from './archify/renderers/shared/validator.mjs';
import fs from 'fs';
const diagram = JSON.parse(fs.readFileSync('my-diagram.json'));
try {
validateSchema('workflow', diagram); // throws on any schema error
console.log('✅ Schema OK');
} catch (err) {
console.error('❌ Schema validation failed:', err.diagnostics);
}
Composition Checks: Geometric Quality Validation
After the deterministic renderer produces SVG geometry, Archify extracts attributes like data-composition-points and data-composition-frame-* to run geometric composition checks. These evaluate visual quality and structural soundness. All checks are implemented in archify/renderers/shared/geometry.mjs.
The Eight Composition Checks
| Check | Measurement | Severity Behavior |
|---|---|---|
| Proper crossing | X-shaped edge intersections | Warning in showcase profile, error in standard |
| Ambiguous corridor | Overlapping parallel edge segments that create indistinguishable paths | Warning or error depending on profile |
| Label route clearance | Minimum distance between relationship label routes and intersecting components | Warning or error |
| Container-border runs | Edge crossings of structural frame borders (regions, groups, lanes) | Warning or error when excessive |
| Short interior segment | Edge segments shorter than segmentPx threshold |
Warning or error |
| Micro segment | Sub-pixel segments below microSegmentPx that cause rendering artifacts |
Warning only |
| Bend count & stretch | Route complexity metrics—maximum bends, routes over suggested bend count, overall stretch | Used for rhythm profile |
| Metrics aggregation | Normalized summary via routeBudgetMetrics including all counts and suggestedLimits per profile |
Summary output |
Key Functions in geometry.mjs
collectAmbiguousCorridors()→cleanAmbiguousCorridorProblems()collectBorderRuns()→cleanBorderRunProblems()collectLabelRouteClearance()→cleanLabelRouteClearanceProblems()routeBudgetMetrics()– returns aggregate statistics and threshold guidance
Each collect* function gathers raw geometry; each clean*Problems function transforms that data into structured issue objects with code, severity, message, and optional threshold.
Running Composition Checks Programmatically
import {
collectAmbiguousCorridors,
cleanAmbiguousCorridorProblems,
collectBorderRuns,
cleanBorderRunProblems,
collectLabelRouteClearance,
cleanLabelRouteClearanceProblems,
routeBudgetMetrics
} from './archify/renderers/shared/geometry.mjs';
const svg = parseSVG(fs.readFileSync('my-diagram.svg'));
const composition = {};
composition.ambiguousCorridors = cleanAmbiguousCorridorProblems(
collectAmbiguousCorridors(svg)
);
composition.containerBorderRuns = cleanBorderRunProblems(
collectBorderRuns(svg)
);
composition.labelRouteClearance = cleanLabelRouteClearanceProblems(
collectLabelRouteClearance(svg)
);
composition.metrics = routeBudgetMetrics(svg);
console.log('Composition summary:', composition);
The Validation Receipt: Merging Results
The CLI merges schema and composition results into a single validation receipt (receipt.validation) written alongside each rendered artifact.
Receipt Structure
{
ok: boolean, // true if both stages pass
checksPassed: number,
checkCount: number,
compositionProfile: 'showcase' | 'standard' | 'rhythm',
compositionStatus: 'pass' | 'fail', // pass = warnings only, no errors
composition: {
issues: [/* issue objects */],
metrics: { /* routeBudgetMetrics output */ }
}
}
Status determination: compositionStatus is pass only when every issue has "warning" severity. Any "error" flips it to fail. The compositionProfile is derived from the rendering profile.
CLI Output Example
9/9 artifact checks; composition showcase: PASS·SHA256 a1b2c3…
Gallery Integration
scripts/build-gallery.mjs injects receipt data into HTML proof galleries:
<div class="receipt-cell">
<span class="receipt-label">Composition</span>
<span class="receipt-value ok"
title="1 crossings · 0 border runs · 0 micro segments · 0 cramped turns">
SHOWCASE · PASS
</span>
</div>
Full Validation Pipeline in Code
This illustrates what archify/bin/archify.mjs executes internally:
import { validateSchema } from './archify/renderers/shared/validator.mjs';
import { runCompositionChecks } from './archify/renderers/shared/geometry.mjs';
function createReceipt(diagramType, diagram, renderedSvg) {
// 1️⃣ Schema validation
try {
validateSchema(diagramType, diagram);
} catch (e) {
return { ok: false, schema: e.diagnostics };
}
// 2️⃣ Composition validation
const composition = runCompositionChecks(renderedSvg);
// 3️⃣ Aggregate receipt
const checksPassed = composition.issues.filter(i => i.severity === 'warning').length;
const checkCount = composition.issues.length;
return {
ok: composition.status === 'pass',
checksPassed,
checkCount,
compositionProfile: composition.profile,
compositionStatus: composition.status,
composition,
};
}
Profile-Based Severity Mapping
| Profile | Purpose | Strictness |
|---|---|---|
| showcase | Highest visual quality, publication-ready | Warnings for most issues |
| standard | Production diagrams | Errors for crossings, corridors, clearance |
| rhythm | Emphasizes clean routing cadence | Errors for excessive bends or stretch |
The routeBudgetMetrics function provides suggestedLimits objects describing thresholds for each profile, enabling profile-aware CI gates.
Summary
- Schema validation in
archify/renderers/shared/validator.mjsprovides fail-closed type checking using pre-compiled AJV validators fromgenerated-validators.mjs. - Composition checks in
archify/renderers/shared/geometry.mjsevaluate eight geometric quality criteria including crossings, corridors, label clearance, and border runs. - Validation receipts merge both stages into
receipt.validation, consumed by the CLI, gallery scripts (scripts/build-gallery.mjs), and CI gates (scripts/package-smoke.mjs). - Profile-driven severity allows
showcase,standard, andrhythmmodes to tune strictness for different output contexts.
Frequently Asked Questions
What happens if schema validation fails?
The pipeline aborts immediately. throwDiagnosticError creates structured diagnostics with annotated JSON pointers, and no SVG is rendered. This fail-closed design prevents invalid data from reaching composition checks.
How does Archify detect ambiguous corridors?
The collectAmbiguousCorridors function in geometry.mjs identifies overlapping parallel edge segments that create visually indistinguishable paths. cleanAmbiguousCorridorProblems converts these into issue objects with severity determined by the active composition profile.
Can I run validation without using the CLI?
Yes. Import validateSchema and the composition helpers directly from archify/renderers/shared/validator.mjs and geometry.mjs to build custom pipelines. The receipt format documented above is stable for下游 tooling.
What's the difference between warnings and errors in composition checks?
Errors fail the composition stage (compositionStatus: 'fail'), while warnings allow it to pass. The threshold for each check varies by profile—standard and rhythm promote more warnings to errors than showcase.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →