import { test } from 'node:test';
import assert from 'node:assert/strict';
import { execFileSync } from 'node:child_process';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const skillRoot = path.resolve(__dirname, '..');
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'archify-output-checks-'));
const checker = path.join(skillRoot, 'scripts/check-render-output.mjs');
function checkHtml(name, svgBody, profile = 'standard', viewBox = '0 0 240 160') {
const htmlPath = path.join(tmp, `${name}.html`);
fs.writeFileSync(htmlPath, `
`);
try {
const stdout = execFileSync('node', [checker, htmlPath], { encoding: 'utf8' });
return { code: 0, result: JSON.parse(stdout) };
} catch (err) {
return { code: err.status ?? 1, result: JSON.parse(String(err.stdout || '{}')) };
}
}
test('render output check: showcase rejects node copy that becomes illegible at 1440px', () => {
const { code, result } = checkHtml('showcase-desktop-readability', `
ToolRuntime
permissions and recovery
`, 'showcase', '0 0 1994 804');
assert.notEqual(code, 0);
const issue = result.composition.issues.find(
(item) => item.code === 'composition/desktop-readability',
);
assert.equal(issue?.severity, 'error');
assert.equal(issue?.viewportWidth, 1440);
assert.ok(issue?.projectedFontPx < issue?.minimumProjectedFontPx);
});
test('render output check: compares exact projected size before rounding diagnostics', () => {
const sourceFontPx = 8.1;
const viewBoxWidth = 1260;
assert.ok(sourceFontPx * 930 / viewBoxWidth < 6);
const { code, result } = checkHtml('showcase-desktop-readability-borderline', `
permissions and recovery
`, 'showcase', `0 0 ${viewBoxWidth} 804`);
assert.notEqual(code, 0);
const issue = result.composition.issues.find(
(item) => item.code === 'composition/desktop-readability',
);
assert.equal(issue?.severity, 'error');
assert.ok(issue?.projectedFontPx < issue?.minimumProjectedFontPx);
});
test('render output check: includes primary node labels in desktop readability', () => {
const { code, result } = checkHtml('showcase-primary-desktop-readability', `
Compact node
`, 'showcase', '0 0 1300 700');
assert.notEqual(code, 0);
const issue = result.composition.issues.find(
(item) => item.code === 'composition/desktop-readability',
);
assert.equal(issue?.text, 'Compact node');
assert.equal(issue?.detail, 'primary');
assert.equal(issue?.availableDiagramWidth, 930);
assert.ok(issue?.projectedFontPx < issue?.minimumProjectedFontPx);
});
test('render output check: includes semantic boundary labels in desktop readability', () => {
const { code, result } = checkHtml('showcase-boundary-desktop-readability', `
Disaster recovery boundary
`, 'showcase', '0 0 1376 728');
assert.notEqual(code, 0);
const issue = result.composition.issues.find(
(item) => item.code === 'composition/desktop-readability',
);
assert.equal(issue?.text, 'Disaster recovery boundary');
assert.equal(issue?.detail, 'boundary');
assert.ok(issue?.projectedFontPx < issue?.minimumProjectedFontPx);
});
test('render output check: accepts orthogonal arrows away from legend', () => {
const { code, result } = checkHtml('clean', `
Legend
Backend
`);
assert.equal(code, 0);
assert.equal(result.ok, true);
});
test('render output check: rejects two-point diagonal arrows', () => {
const { code, result } = checkHtml('diagonal', `
Legend
`);
assert.notEqual(code, 0);
const check = result.checks.find((item) => item.name === 'orthogonal_arrows');
assert.equal(check.ok, false);
assert.match(check.details[0], /path 1/);
});
test('render output check: rejects a diagonal segment inside a polyline', () => {
const { code, result } = checkHtml('polyline-diagonal', `
Legend
`);
assert.notEqual(code, 0);
const check = result.checks.find((item) => item.name === 'orthogonal_arrows');
assert.equal(check.ok, false);
assert.match(check.details[0], /path 1/);
assert.match(check.details[0], /segment 1/);
});
test('render output check: rejects arrows crossing legend text', () => {
const { code, result } = checkHtml('legend-crossing', `
Legend
Backend
`);
assert.notEqual(code, 0);
const check = result.checks.find((item) => item.name === 'legend_clearance');
assert.equal(check.ok, false);
assert.match(check.details[0], /Legend/);
});
test('render output check: ignores unmarked sequence lifelines near legend', () => {
const { code, result } = checkHtml('lifeline-near-legend', `
Legend
return
`);
assert.equal(code, 0);
assert.equal(result.ok, true);
});
test('render output check: standard records a proper X as a composition warning', () => {
const { code, result } = checkHtml('standard-crossing', `
`);
assert.equal(code, 0);
assert.equal(result.composition.profile, 'standard');
assert.deepEqual(result.composition.summary, { errors: 0, warnings: 1 });
assert.equal(result.composition.metrics.properCrossings, 1);
assert.equal(result.composition.issues[0].code, 'composition/proper-crossing');
assert.equal(result.composition.issues[0].severity, 'warning');
});
test('render output check: showcase rejects a proper X with semantic identities', () => {
const { code, result } = checkHtml('showcase-crossing', `
`, 'showcase');
assert.notEqual(code, 0);
const check = result.checks.find((item) => item.name === 'relationship_crossings');
assert.equal(check.ok, false);
assert.match(check.details[0], /\[composition\/proper-crossing\] showcase/);
assert.match(check.details[0], /relationship id "left"/);
assert.deepEqual(result.composition.summary, { errors: 1, warnings: 0 });
});
test('render output check: shared endpoints and endpoint touches pass showcase', () => {
const { code, result } = checkHtml('showcase-exemptions', `
`, 'showcase');
assert.equal(code, 0);
assert.equal(result.composition.metrics.properCrossings, 0);
assert.equal(result.composition.metrics.ambiguousCorridors, 0);
});
test('render output check: relationship labels cannot hide another shared-source route', () => {
for (const profile of ['standard', 'showcase']) {
const { code, result } = checkHtml(`label-route-${profile}`, `
approved replay
`, profile);
assert.equal(result.composition.metrics.labelRouteClearanceIssues, 1);
assert.equal(result.composition.metrics.minLabelRouteClearance, 0);
const issue = result.composition.issues.find((item) => item.code === 'composition/label-route-clearance');
assert.deepEqual(issue.labelRelationship, { id: 'approved', from: 'dlq', to: 'replay', label: 'approved replay', collectionIndex: 0, artifactIndex: 1 });
assert.deepEqual(issue.otherRelationship, { id: 'sample', from: 'dlq', to: 'ops', label: '', collectionIndex: 1, artifactIndex: 2 });
assert.equal(issue.segmentIndex, 0);
assert.deepEqual(issue.labelRect, { x: 80, y: 48, width: 60, height: 14 });
assert.equal(issue.clearance, 0);
assert.equal(issue.intersectionLength, 60);
assert.equal(issue.threshold, profile === 'showcase' ? 4 : 2);
const check = result.checks.find((item) => item.name === 'label_route_clearance');
if (profile === 'standard') {
assert.equal(code, 0);
assert.equal(check.ok, true);
assert.equal(issue.severity, 'warning');
assert.deepEqual(result.composition.summary, { errors: 0, warnings: 1 });
} else {
assert.notEqual(code, 0);
assert.equal(check.ok, false);
assert.match(check.details[0], /approved.*sample/);
assert.match(check.details[0], /labelAt.*labelDx.*labelDy.*labelSegment/);
assert.equal(issue.severity, 'error');
assert.deepEqual(result.composition.summary, { errors: 1, warnings: 0 });
}
}
});
test('render output check: repeated endpoint messages keep their own stable owner identity', () => {
const { code, result } = checkHtml('sequence-repeated-endpoints', `
`, 'showcase');
assert.notEqual(code, 0);
const issues = result.composition.issues.filter((item) => item.code === 'composition/label-route-clearance');
assert.equal(issues.length, 1);
assert.equal(issues[0].label, 'second request');
assert.equal(issues[0].labelRelationship.collectionIndex, 1);
assert.equal(issues[0].otherRelationship.collectionIndex, 2);
});
test('render output check: duplicate fragments of the owning relationship stay exempt', () => {
const { code, result } = checkHtml('label-owner-fragments', `
approved replay
`, 'showcase');
assert.equal(code, 0);
assert.equal(result.composition.metrics.labelRouteClearanceIssues, 0);
assert.equal(result.composition.metrics.minLabelRouteClearance, null);
});
test('render output check: duplicate fragments of another relationship count once', () => {
const { result } = checkHtml('label-other-fragments', `
approved replay
`, 'showcase');
assert.equal(result.composition.metrics.labelRouteClearanceIssues, 1);
});
test('render output check: label-route thresholds include exact 2px and 4px boundaries', () => {
const body = (otherY) => `
handoff
`;
const standardAtTwo = checkHtml('label-standard-two', body(64), 'standard');
assert.equal(standardAtTwo.code, 0);
assert.equal(standardAtTwo.result.composition.metrics.labelRouteClearanceIssues, 0);
assert.equal(standardAtTwo.result.composition.metrics.minLabelRouteClearance, 2);
const standardBelowTwo = checkHtml('label-standard-one-nine', body(63.9), 'standard');
assert.equal(standardBelowTwo.code, 0);
assert.equal(standardBelowTwo.result.composition.metrics.labelRouteClearanceIssues, 1);
assert.equal(standardBelowTwo.result.composition.summary.warnings, 1);
const showcaseAtTwo = checkHtml('label-showcase-two', body(64), 'showcase');
assert.notEqual(showcaseAtTwo.code, 0);
assert.equal(showcaseAtTwo.result.composition.metrics.labelRouteClearanceIssues, 1);
assert.equal(showcaseAtTwo.result.composition.issues.find((item) => item.code === 'composition/label-route-clearance').threshold, 4);
const showcaseAtFour = checkHtml('label-showcase-four', body(66), 'showcase');
assert.equal(showcaseAtFour.code, 0);
assert.equal(showcaseAtFour.result.composition.metrics.labelRouteClearanceIssues, 0);
assert.equal(showcaseAtFour.result.composition.metrics.minLabelRouteClearance, 4);
const showcaseBelowFour = checkHtml('label-showcase-three-nine', body(65.9), 'showcase');
assert.notEqual(showcaseBelowFour.code, 0);
assert.equal(showcaseBelowFour.result.composition.metrics.labelRouteClearanceIssues, 1);
assert.equal(showcaseBelowFour.result.composition.summary.errors, 1);
});
test('render output check: unrelated shared corridors warn in standard and fail showcase', () => {
for (const profile of ['standard', 'showcase']) {
const { code, result } = checkHtml(`corridor-${profile}`, `
`, profile);
assert.equal(result.composition.metrics.ambiguousCorridors, 1);
assert.equal(result.composition.issues[0].code, 'composition/ambiguous-corridor');
assert.equal(result.composition.issues[0].overlapLength, 80);
assert.deepEqual(result.composition.issues[0].from, [60, 60]);
assert.deepEqual(result.composition.issues[0].to, [140, 60]);
const check = result.checks.find((item) => item.name === 'relationship_corridors');
if (profile === 'standard') {
assert.equal(code, 0);
assert.equal(check.ok, true);
assert.deepEqual(result.composition.summary, { errors: 0, warnings: 1 });
assert.equal(result.composition.issues[0].severity, 'warning');
} else {
assert.notEqual(code, 0);
assert.equal(check.ok, false);
assert.match(check.details[0], /\[composition\/ambiguous-corridor\] showcase/);
assert.match(check.details[0], /relationship id "first".*relationship id "second"/);
assert.deepEqual(result.composition.summary, { errors: 1, warnings: 0 });
assert.equal(result.composition.issues[0].severity, 'error');
}
}
});
test('render output check: visible quadratic crossing is caught in showcase', () => {
const { code, result } = checkHtml('showcase-quadratic-crossing', `
`, 'showcase');
assert.notEqual(code, 0);
assert.equal(result.composition.metrics.properCrossings, 1);
assert.equal(result.composition.status, 'fail');
});
test('render output check: container border runs fail both profiles with frame identity', () => {
for (const profile of ['standard', 'showcase']) {
const { code, result } = checkHtml(`border-run-${profile}`, `
`, profile);
assert.notEqual(code, 0);
const check = result.checks.find((item) => item.name === 'container_border_runs');
assert.equal(check.ok, false);
assert.match(check.details[0], /\[composition\/container-border-run\].*relationship id "events"/);
assert.match(check.details[0], /stage "sources" top border for 90px/);
assert.equal(result.composition.summary.errors, 1);
assert.equal(result.composition.metrics.containerBorderRuns, 1);
assert.equal(result.composition.issues[0].code, 'composition/container-border-run');
}
});
test('render output check: perpendicular crossings, rounded-corner touches, and tangent Q curves pass', () => {
const { code, result } = checkHtml('border-run-exemptions', `
`, 'showcase');
assert.equal(code, 0);
assert.equal(result.composition.metrics.containerBorderRuns, 0);
});
test('render output check: a fully collinear quadratic primitive is a border run', () => {
const { code, result } = checkHtml('border-run-collinear-q', `
`);
assert.notEqual(code, 0);
assert.equal(result.composition.metrics.containerBorderRuns, 1);
});
test('render output check: composition receipt records neutral normalized route metrics', () => {
const { code, result } = checkHtml('route-metrics', `
`);
assert.equal(code, 0);
assert.equal(result.composition.metrics.maxBends, 3);
assert.equal(result.composition.metrics.routesOverSuggestedBends, 1);
assert.equal(result.composition.metrics.minSegmentPx, 8);
assert.equal(result.composition.metrics.shortSegmentCount, 1);
assert.equal(result.composition.metrics.shortInteriorSegmentCount, 1);
assert.equal(result.composition.metrics.shortEndpointSegmentCount, 0);
assert.equal(result.composition.metrics.microSegmentCount, 0);
assert.deepEqual(result.composition.suggestedLimits, { bendsPerRelationship: 2, stretch: 1.35, segmentPx: 16, microSegmentPx: 8 });
});
test('render output check: endpoint stubs from 8px pass while cramped interior turns are profile-aware', () => {
const clean = checkHtml('endpoint-stubs', `
`, 'showcase');
assert.equal(clean.code, 0);
assert.equal(clean.result.composition.metrics.shortEndpointSegmentCount, 2);
assert.equal(clean.result.composition.metrics.shortInteriorSegmentCount, 0);
const standard = checkHtml('short-turn-standard', `
`, 'standard');
assert.equal(standard.code, 0);
assert.deepEqual(standard.result.composition.summary, { errors: 0, warnings: 1 });
assert.equal(standard.result.composition.issues[0].code, 'composition/short-interior-segment');
assert.equal(standard.result.checks.find((item) => item.name === 'route_rhythm').ok, true);
const showcase = checkHtml('short-turn-showcase', `
`, 'showcase');
assert.notEqual(showcase.code, 0);
assert.deepEqual(showcase.result.composition.summary, { errors: 1, warnings: 0 });
const rhythm = showcase.result.checks.find((item) => item.name === 'route_rhythm');
assert.equal(rhythm.ok, false);
assert.match(rhythm.details[0], /\[composition\/short-interior-segment\] showcase relationship id "tight"/);
});
process.on('exit', () => fs.rmSync(tmp, { recursive: true, force: true }));