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, `${svgBody}`); 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 }));