stylegallery 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -1
- package/DOMAINS.md +2 -6
- package/GOVERNANCE.md +10 -9
- package/README.md +29 -127
- package/consumer-reference/agent-native/v2/admission-policy.json +646 -0
- package/consumer-reference/agent-native/v2/material-registry.json +1 -0
- package/consumer-reference/agent-native/v2/schema/admission-policy.schema.json +50 -0
- package/consumer-reference/agent-native/v2/schema/material-manifest.schema.json +17 -0
- package/consumer-reference/agent-native/v2/schema/material-record.schema.json +20 -0
- package/consumer-reference/contract.md +1 -1
- package/consumer-reference/index.md +5 -3
- package/layout/index.md +124 -0
- package/log.md +57 -0
- package/package.json +183 -22
- package/scripts/agent-native/v2/experimental-extension-registry.mjs +143 -0
- package/scripts/agent-native/v2/extensions/a2a-projection.mjs +264 -0
- package/scripts/agent-native/v2/extensions/agui-projection.mjs +191 -0
- package/scripts/agent-native/v2/material-admission.mjs +295 -0
- package/scripts/agent-native/v2/material-cli-adapter.mjs +134 -0
- package/scripts/agent-native/v2/material-context.mjs +251 -0
- package/scripts/agent-native/v2/material-identity.mjs +71 -0
- package/scripts/agent-native/v2/material-mcp-adapter.mjs +253 -0
- package/scripts/agent-native/v2/material-operation-registry.mjs +123 -0
- package/scripts/agent-native/v2/material-queries.mjs +398 -0
- package/scripts/agent-native/v2/material-registry.mjs +319 -0
- package/scripts/sg-material-mcp.mjs +98 -0
- package/scripts/sg-material.mjs +27 -0
- package/consumer-reference/adapters/style-dictionary.config.mjs +0 -36
- package/consumer-reference/baselines/calibration.json +0 -260
- package/consumer-reference/baselines/manifest.json +0 -21
- package/consumer-reference/fixtures/consumer-conformance/e2e-fixture.mjs +0 -282
- package/consumer-reference/fixtures/consumer-conformance/manifest.json +0 -102
- package/consumer-reference/fixtures/consumer-conformance/runtime-proof.mjs +0 -32
- package/consumer-reference/fixtures/consumer-conformance/valid-migration-result.json +0 -18
- package/consumer-reference/fixtures/consumer-conformance/valid-migration.json +0 -142
- package/consumer-reference/fixtures/invalid-stable-ended-support.json +0 -19
- package/consumer-reference/fixtures/promotion/invalid-blocking-evidence.json +0 -26
- package/consumer-reference/fixtures/promotion/invalid-count-only.json +0 -29
- package/consumer-reference/fixtures/promotion/invalid-missing-owner-migration.json +0 -25
- package/consumer-reference/fixtures/promotion/invalid-normative-bypass-no-regression.json +0 -25
- package/consumer-reference/fixtures/promotion/invalid-related-counted-independent.json +0 -45
- package/consumer-reference/fixtures/promotion/invalid-stable-ended-support.json +0 -26
- package/consumer-reference/fixtures/promotion/manifest.json +0 -15
- package/consumer-reference/fixtures/promotion/valid-deferred-example.json +0 -67
- package/consumer-reference/fixtures/promotion/valid-normative-bypass.json +0 -67
- package/consumer-reference/fixtures/token-portability/invalid-cycle.json +0 -7
- package/consumer-reference/fixtures/token-portability/invalid-dangling-alias.json +0 -6
- package/consumer-reference/fixtures/token-portability/invalid-extends.json +0 -4
- package/consumer-reference/fixtures/token-portability/invalid-json-pointer.json +0 -7
- package/consumer-reference/fixtures/token-portability/invalid-resolver.json +0 -9
- package/consumer-reference/fixtures/token-portability/invalid-type-mismatch.json +0 -10
- package/consumer-reference/fixtures/token-portability/invalid-unknown-reserved.json +0 -6
- package/consumer-reference/fixtures/token-portability/invalid-untested-type.json +0 -6
- package/consumer-reference/fixtures/token-portability/valid-border.json +0 -14
- package/consumer-reference/fixtures/token-portability/valid-reference.json +0 -32
- package/consumer-reference/fixtures/token-portability/valid-whole-alias.json +0 -7
- package/consumer-reference/fixtures/valid-deprecated.json +0 -21
- package/consumer-reference/fixtures/valid-experimental.json +0 -19
- package/consumer-reference/generated/manifest.json +0 -40
- package/consumer-reference/generated/tokens.css +0 -12
- package/consumer-reference/policies/shared-experimental.json +0 -37
- package/consumer-reference/schema/ax-evidence.schema.json +0 -30
- package/consumer-reference/schema/baseline-manifest.schema.json +0 -55
- package/consumer-reference/schema/calibration-record.schema.json +0 -190
- package/consumer-reference/schema/capture-session.schema.json +0 -161
- package/consumer-reference/schema/component-state.schema.json +0 -150
- package/consumer-reference/schema/consumer-conformance-record.schema.json +0 -365
- package/consumer-reference/schema/dom-evidence.schema.json +0 -38
- package/consumer-reference/schema/evidence-record.schema.json +0 -81
- package/consumer-reference/schema/fixture-manifest.schema.json +0 -32
- package/consumer-reference/schema/item.schema.json +0 -188
- package/consumer-reference/schema/page-evidence-manifest.schema.json +0 -216
- package/consumer-reference/schema/page-evidence-session.schema.json +0 -119
- package/consumer-reference/schema/portable-tokens.schema.json +0 -104
- package/consumer-reference/schema/promotion-rfc.schema.json +0 -219
- package/consumer-reference/schema/runtime-evidence-manifest.schema.json +0 -33
- package/consumer-reference/schema/visual-evidence.schema.json +0 -31
- package/design-engineering/consumer-migration-readiness.md +0 -124
- package/design-engineering/interface-craft.md +0 -107
- package/design-engineering/reference-profiles/external-adaptation/index.md +0 -12
- package/design-engineering/reference-profiles/governed-local/editorial/components/button.component.json +0 -125
- package/design-engineering/reference-profiles/governed-local/editorial/evidence/button.evidence.json +0 -3504
- package/design-engineering/reference-profiles/governed-local/editorial/fixtures/button.fixture.json +0 -65
- package/design-engineering/reference-profiles/governed-local/editorial/generated/evidence-coverage.md +0 -23
- package/design-engineering/reference-profiles/governed-local/editorial/generated/keyboard-matrix.md +0 -19
- package/design-engineering/reference-profiles/governed-local/editorial/generated/state-matrix.md +0 -21
- package/design-engineering/reference-profiles/governed-local/editorial/local-foundations.json +0 -12
- package/design-engineering/reference-profiles/governed-local/editorial/states/button.states.json +0 -195
- package/design-engineering/reference-profiles/governed-local/editorial/tokens.dtcg.json +0 -17
- package/design-engineering/reference-profiles/governed-local/terminal/components/button.component.json +0 -125
- package/design-engineering/reference-profiles/governed-local/terminal/evidence/button.evidence.json +0 -3504
- package/design-engineering/reference-profiles/governed-local/terminal/fixtures/button.fixture.json +0 -65
- package/design-engineering/reference-profiles/governed-local/terminal/generated/evidence-coverage.md +0 -23
- package/design-engineering/reference-profiles/governed-local/terminal/generated/keyboard-matrix.md +0 -19
- package/design-engineering/reference-profiles/governed-local/terminal/generated/state-matrix.md +0 -21
- package/design-engineering/reference-profiles/governed-local/terminal/local-foundations.json +0 -12
- package/design-engineering/reference-profiles/governed-local/terminal/profile.json +0 -43
- package/design-engineering/reference-profiles/governed-local/terminal/states/button.states.json +0 -195
- package/design-engineering/reference-profiles/governed-local/terminal/tokens.dtcg.json +0 -17
- package/game-ui/classification.md +0 -82
- package/game-ui/reference-record.md +0 -62
- package/game-ui/screen-hierarchy.md +0 -107
- package/game-ui/unity/architecture.md +0 -166
- package/game-ui/unity/cli-loop.md +0 -84
- package/game-ui/unity/data/unity-technologies-public-repositories.json +0 -26654
- package/game-ui/unity/org-wiki.md +0 -146
- package/game-ui/unity/repository-map.md +0 -102
- package/game-ui/unity/ui-systems.md +0 -85
- package/motion/practice-reference.md +0 -145
- package/motion/review-workflow.md +0 -86
- package/motion/vocabulary.md +0 -82
- package/platform-guides/apple-interaction.md +0 -89
- package/scripts/agent-native/events.mjs +0 -113
- package/scripts/agent-native/immutable-store.mjs +0 -102
- package/scripts/artifact-metadata.mjs +0 -20
- package/scripts/audit-evidence-freshness.mjs +0 -308
- package/scripts/baseline-contract.mjs +0 -189
- package/scripts/baseline-schema-parity.mjs +0 -40
- package/scripts/build-reference-artifacts.mjs +0 -127
- package/scripts/calibration-raw-contract.mjs +0 -172
- package/scripts/capture-session-contract.mjs +0 -187
- package/scripts/component-state-artifact-fixture.mjs +0 -44
- package/scripts/component-state-contract.mjs +0 -99
- package/scripts/component-state-semantics.mjs +0 -128
- package/scripts/component-state-workflow-contract.mjs +0 -67
- package/scripts/component-state-workflow-negative-cases.mjs +0 -64
- package/scripts/consumer-conformance-contract.mjs +0 -198
- package/scripts/consumer-evidence-governance-contract.mjs +0 -210
- package/scripts/consumer-reference-case-runner.mjs +0 -93
- package/scripts/consumer-reference-schema.mjs +0 -155
- package/scripts/create-component-state-session.mjs +0 -100
- package/scripts/create-page-evidence-session.mjs +0 -139
- package/scripts/domain-document-boundaries.mjs +0 -40
- package/scripts/domain-validation-checks.mjs +0 -141
- package/scripts/evidence-artifact-contract.mjs +0 -191
- package/scripts/finalize-component-state-evidence.mjs +0 -165
- package/scripts/finalize-page-evidence.mjs +0 -197
- package/scripts/generate-consumer-reference-evidence.mjs +0 -154
- package/scripts/generate-patterns.mjs +0 -218
- package/scripts/governance-matrix-contract.mjs +0 -73
- package/scripts/governance-matrix-negative-cases.mjs +0 -114
- package/scripts/governance-policy-contract.mjs +0 -49
- package/scripts/governance-test-fixture.mjs +0 -321
- package/scripts/governance-workflow-negative-cases.mjs +0 -241
- package/scripts/governed-profile-registry.mjs +0 -125
- package/scripts/json-schema-formats.mjs +0 -31
- package/scripts/markdown-structure.mjs +0 -45
- package/scripts/page-artifact-metadata.mjs +0 -124
- package/scripts/page-evidence-contract.mjs +0 -297
- package/scripts/page-evidence-fixture.mjs +0 -271
- package/scripts/pattern-data.mjs +0 -325
- package/scripts/profile-record-contract.mjs +0 -140
- package/scripts/promotion-attestation-contract.mjs +0 -91
- package/scripts/promotion-boundary-test-contract.mjs +0 -92
- package/scripts/promotion-fixture-inventory.mjs +0 -109
- package/scripts/promotion-governance-contract.mjs +0 -28
- package/scripts/reference-artifact-path-contract.mjs +0 -28
- package/scripts/reference-profile-contract.mjs +0 -114
- package/scripts/reference-token-contract.mjs +0 -156
- package/scripts/run-consumer-page-evidence-ci.mjs +0 -170
- package/scripts/summarize-sentinel-calibration.mjs +0 -98
- package/scripts/test-agent-adapter-conformance.mjs +0 -250
- package/scripts/test-agent-conformance-receipt.mjs +0 -106
- package/scripts/test-agent-events.mjs +0 -81
- package/scripts/test-agent-execution-effects.mjs +0 -114
- package/scripts/test-agent-execution-fixtures.mjs +0 -140
- package/scripts/test-agent-execution-kernel.mjs +0 -39
- package/scripts/test-agent-execution-learning.mjs +0 -130
- package/scripts/test-agent-execution-lifecycle.mjs +0 -143
- package/scripts/test-agent-execution-safety.mjs +0 -158
- package/scripts/test-agent-execution-views.mjs +0 -117
- package/scripts/test-agent-identity-integrity-cases.mjs +0 -160
- package/scripts/test-agent-knowledge-kernel.mjs +0 -183
- package/scripts/test-agent-learning.mjs +0 -246
- package/scripts/test-agent-mcp.mjs +0 -246
- package/scripts/test-agent-native-schemas.mjs +0 -215
- package/scripts/test-agent-projections.mjs +0 -249
- package/scripts/test-agent-registry-mcp-integrity.mjs +0 -215
- package/scripts/test-agent-registry-mutations.mjs +0 -110
- package/scripts/test-audit-evidence-freshness.mjs +0 -177
- package/scripts/test-component-state-sentinel.mjs +0 -35
- package/scripts/test-component-state-source-contract.mjs +0 -83
- package/scripts/test-consumer-conformance-sentinel.mjs +0 -165
- package/scripts/test-consumer-reference-sentinel.mjs +0 -31
- package/scripts/test-generate-consumer-reference-evidence.mjs +0 -124
- package/scripts/test-json-cli-output.mjs +0 -151
- package/scripts/test-json-schema-formats.mjs +0 -40
- package/scripts/test-reference-adapters.mjs +0 -199
- package/scripts/test-renderer-purity.mjs +0 -34
- package/scripts/test-sg-cli.mjs +0 -129
- package/scripts/test-summarize-sentinel-calibration.mjs +0 -226
- package/scripts/test-validate-baseline-manifest.mjs +0 -234
- package/scripts/test-validate-component-state-artifacts.mjs +0 -243
- package/scripts/test-validate-component-state.mjs +0 -106
- package/scripts/test-validate-consumer-conformance.mjs +0 -427
- package/scripts/test-validate-consumer-reference-cli.mjs +0 -69
- package/scripts/test-validate-consumer-reference.mjs +0 -263
- package/scripts/test-validate-domains.mjs +0 -357
- package/scripts/test-validate-governance.mjs +0 -292
- package/scripts/test-validate-ia.mjs +0 -262
- package/scripts/test-validate-okf.mjs +0 -73
- package/scripts/test-validate-page-evidence.mjs +0 -302
- package/scripts/test-validate-patterns.mjs +0 -157
- package/scripts/test-validate-promotion-rfc.mjs +0 -250
- package/scripts/test-validate-reference-profiles.mjs +0 -170
- package/scripts/test-validate-unity-org-wiki.mjs +0 -57
- package/scripts/test-validate-unity-source-contracts.mjs +0 -67
- package/scripts/test-validate-vocabulary.mjs +0 -174
- package/scripts/test-validate-webpage-workflow.mjs +0 -293
- package/scripts/validate-baseline-manifest.mjs +0 -44
- package/scripts/validate-catalog.mjs +0 -65
- package/scripts/validate-component-state.mjs +0 -141
- package/scripts/validate-consumer-conformance.mjs +0 -477
- package/scripts/validate-consumer-reference.mjs +0 -288
- package/scripts/validate-domains.mjs +0 -237
- package/scripts/validate-governance.mjs +0 -248
- package/scripts/validate-ia.mjs +0 -136
- package/scripts/validate-links.mjs +0 -66
- package/scripts/validate-okf.mjs +0 -104
- package/scripts/validate-page-evidence.mjs +0 -191
- package/scripts/validate-patterns.mjs +0 -246
- package/scripts/validate-promotion-rfc.mjs +0 -224
- package/scripts/validate-reference-artifacts.mjs +0 -125
- package/scripts/validate-renderer-purity.mjs +0 -56
- package/scripts/validate-unity-org-wiki.mjs +0 -146
- package/scripts/validate-unity-source-contracts.mjs +0 -107
- package/scripts/validate-vocabulary.mjs +0 -115
- package/scripts/validate-webpage-workflow.mjs +0 -254
- package/scripts/visual-expectation-contract.mjs +0 -20
- package/scripts/workflow-action-contract.mjs +0 -163
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import fs from "node:fs";
|
|
4
|
-
import os from "node:os";
|
|
5
|
-
import path from "node:path";
|
|
6
|
-
import { execFileSync } from "node:child_process";
|
|
7
|
-
import { MAX_ARTIFACT_FILE_BYTES } from "./page-artifact-metadata.mjs";
|
|
8
|
-
import { canonicalSourceManifest } from "./page-evidence-contract.mjs";
|
|
9
|
-
import {
|
|
10
|
-
completeSession,
|
|
11
|
-
corruptPngCrc,
|
|
12
|
-
createConformance,
|
|
13
|
-
declareCapturedArtifact,
|
|
14
|
-
finalizeSession,
|
|
15
|
-
isolated,
|
|
16
|
-
pngWithTrailingBytes,
|
|
17
|
-
pngWithInvalidImageData,
|
|
18
|
-
pngWithTrailingImageData,
|
|
19
|
-
receiptFor,
|
|
20
|
-
reuseSetup,
|
|
21
|
-
rewriteCompletedCapture,
|
|
22
|
-
rewriteCompletedArtifact,
|
|
23
|
-
semanticEnvironment,
|
|
24
|
-
startSession,
|
|
25
|
-
started,
|
|
26
|
-
truncatedPng,
|
|
27
|
-
validateSession,
|
|
28
|
-
writeJson,
|
|
29
|
-
writeRunner,
|
|
30
|
-
} from "./page-evidence-fixture.mjs";
|
|
31
|
-
|
|
32
|
-
const requested = [];
|
|
33
|
-
let json = false;
|
|
34
|
-
for (let index = 2; index < process.argv.length; index += 1) {
|
|
35
|
-
const argument = process.argv[index];
|
|
36
|
-
if (argument === "--json") json = true;
|
|
37
|
-
else if (argument === "--case") {
|
|
38
|
-
const value = process.argv[index + 1];
|
|
39
|
-
if (value) { requested.push(value); index += 1; }
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function codes(child) {
|
|
44
|
-
return child?.report?.failures?.map((failure) => failure.code) ?? [];
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function outcome(name, expected, child, observe = {}) {
|
|
48
|
-
const actualCodes = codes(child);
|
|
49
|
-
const valid = expected === "ok:true";
|
|
50
|
-
const ok = valid ? child?.status === 0 && child.report.ok === true : child?.status !== 0 && actualCodes.includes(expected);
|
|
51
|
-
return { actual: { codes: actualCodes, status: child?.status, ...observe }, expected, name, ok };
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const cases = {
|
|
55
|
-
"complete-session": () => isolated((fixture) => {
|
|
56
|
-
const completed = completeSession(fixture);
|
|
57
|
-
return outcome("complete-session", "ok:true", completed.validate, {
|
|
58
|
-
finalized: completed.finalize?.report.ok === true,
|
|
59
|
-
scenarioCount: completed.validate?.report.scenarioCount,
|
|
60
|
-
started: completed.start?.report.ok === true,
|
|
61
|
-
});
|
|
62
|
-
}),
|
|
63
|
-
"dirty-relevant-source": () => isolated((fixture) => {
|
|
64
|
-
const session = createConformance(fixture);
|
|
65
|
-
fs.appendFileSync(path.join(fixture.root, fixture.relevantSources[0]), "// dirty\n");
|
|
66
|
-
return outcome("dirty-relevant-source", "page_evidence_source_dirty", startSession(fixture, session));
|
|
67
|
-
}),
|
|
68
|
-
"untracked-relevant-source": () => isolated((fixture) => {
|
|
69
|
-
const session = createConformance(fixture);
|
|
70
|
-
const untracked = "src/untracked.js";
|
|
71
|
-
fs.writeFileSync(path.join(fixture.root, untracked), "export const untracked = true;\n");
|
|
72
|
-
const record = JSON.parse(fs.readFileSync(session.recordFile));
|
|
73
|
-
record.consumer.relevant_sources.push(untracked);
|
|
74
|
-
const sourceFailures = [];
|
|
75
|
-
const source = canonicalSourceManifest(fixture.root, record.consumer.relevant_sources, sourceFailures);
|
|
76
|
-
record.scenarios[0].source_digest = source.sha256;
|
|
77
|
-
writeJson(session.recordFile, record);
|
|
78
|
-
return outcome("untracked-relevant-source", "page_evidence_source_dirty", startSession(fixture, session));
|
|
79
|
-
}),
|
|
80
|
-
"source-drift-after-start": () => isolated((fixture) => {
|
|
81
|
-
const session = started(fixture);
|
|
82
|
-
const runner = writeRunner(fixture, session);
|
|
83
|
-
fs.appendFileSync(path.join(fixture.root, fixture.relevantSources[0]), "// drift\n");
|
|
84
|
-
return outcome("source-drift-after-start", "page_evidence_source_drift", finalizeSession(fixture, session, runner));
|
|
85
|
-
}),
|
|
86
|
-
"cross-revision": () => isolated((fixture) => {
|
|
87
|
-
const session = started(fixture);
|
|
88
|
-
const runner = writeRunner(fixture, session, { revision: "0".repeat(40), runRevision: "0".repeat(40) });
|
|
89
|
-
return outcome("cross-revision", "page_evidence_revision_mismatch", finalizeSession(fixture, session, runner));
|
|
90
|
-
}),
|
|
91
|
-
"cross-run": () => isolated((fixture) => {
|
|
92
|
-
const session = started(fixture);
|
|
93
|
-
const runner = writeRunner(fixture, session, { runId: "different-run" });
|
|
94
|
-
return outcome("cross-run", "page_evidence_run_mismatch", finalizeSession(fixture, session, runner));
|
|
95
|
-
}),
|
|
96
|
-
"cross-session-replay": () => isolated((fixture) => {
|
|
97
|
-
const target = started(fixture, { artifactName: "target" });
|
|
98
|
-
const alternate = started(fixture, { artifactName: "alternate" });
|
|
99
|
-
const targetRunner = writeRunner(fixture, target);
|
|
100
|
-
const alternateRunner = writeRunner(fixture, alternate);
|
|
101
|
-
fs.copyFileSync(alternateRunner.runnerFile, targetRunner.runnerFile);
|
|
102
|
-
fs.copyFileSync(path.join(alternate.artifactRoot, alternateRunner.artifactReference), path.join(target.artifactRoot, targetRunner.artifactReference));
|
|
103
|
-
return outcome("cross-session-replay", "page_evidence_session_mismatch", finalizeSession(fixture, target, targetRunner));
|
|
104
|
-
}),
|
|
105
|
-
"failed-runner": () => isolated((fixture) => {
|
|
106
|
-
const session = started(fixture);
|
|
107
|
-
const runner = writeRunner(fixture, session, { status: "failed" });
|
|
108
|
-
return outcome("failed-runner", "page_evidence_runner_failed", finalizeSession(fixture, session, runner));
|
|
109
|
-
}),
|
|
110
|
-
"finalize-runner-control-collision": () => isolated((fixture) => {
|
|
111
|
-
const session = started(fixture);
|
|
112
|
-
const runner = writeRunner(fixture, session);
|
|
113
|
-
const declared = declareCapturedArtifact(session, runner, runner.runnerReference);
|
|
114
|
-
return outcome("finalize-runner-control-collision", "page_evidence_artifact_control_collision", finalizeSession(fixture, session, declared));
|
|
115
|
-
}),
|
|
116
|
-
"finalize-receipt-control-collision": () => isolated((fixture) => {
|
|
117
|
-
const session = started(fixture);
|
|
118
|
-
const runner = writeRunner(fixture, session);
|
|
119
|
-
const declared = declareCapturedArtifact(session, runner, "page-evidence-session.json");
|
|
120
|
-
return outcome("finalize-receipt-control-collision", "page_evidence_artifact_control_collision", finalizeSession(fixture, session, declared));
|
|
121
|
-
}),
|
|
122
|
-
"unmanifested-png": () => isolated((fixture) => {
|
|
123
|
-
const session = started(fixture);
|
|
124
|
-
const runner = writeRunner(fixture, session);
|
|
125
|
-
fs.writeFileSync(path.join(session.artifactRoot, "rogue.png"), "rogue");
|
|
126
|
-
return outcome("unmanifested-png", "page_evidence_artifact_unmanifested", finalizeSession(fixture, session, runner));
|
|
127
|
-
}),
|
|
128
|
-
"artifact-tree-depth-limit": () => isolated((fixture) => {
|
|
129
|
-
const session = started(fixture);
|
|
130
|
-
const runner = writeRunner(fixture, session);
|
|
131
|
-
fs.mkdirSync(path.join(session.artifactRoot, ...Array.from({ length: 18 }, (_, index) => `depth-${index}`)), { recursive: true });
|
|
132
|
-
return outcome("artifact-tree-depth-limit", "page_evidence_artifact_limit", finalizeSession(fixture, session, runner));
|
|
133
|
-
}),
|
|
134
|
-
"artifact-entry-limit": () => isolated((fixture) => {
|
|
135
|
-
const session = started(fixture);
|
|
136
|
-
const runner = writeRunner(fixture, session);
|
|
137
|
-
for (let index = 0; index < 4097; index += 1) fs.writeFileSync(path.join(session.artifactRoot, `entry-${index}.txt`), "");
|
|
138
|
-
return outcome("artifact-entry-limit", "page_evidence_artifact_limit", finalizeSession(fixture, session, runner));
|
|
139
|
-
}),
|
|
140
|
-
"artifact-file-byte-limit": () => isolated((fixture) => {
|
|
141
|
-
const session = started(fixture);
|
|
142
|
-
const runner = writeRunner(fixture, session);
|
|
143
|
-
fs.truncateSync(path.join(session.artifactRoot, runner.artifactReference), MAX_ARTIFACT_FILE_BYTES + 1);
|
|
144
|
-
return outcome("artifact-file-byte-limit", "page_evidence_artifact_limit", finalizeSession(fixture, session, runner));
|
|
145
|
-
}),
|
|
146
|
-
"artifact-packet-byte-limit": () => isolated((fixture) => {
|
|
147
|
-
const session = started(fixture);
|
|
148
|
-
const runner = writeRunner(fixture, session);
|
|
149
|
-
for (let index = 0; index < 5; index += 1) {
|
|
150
|
-
const file = path.join(session.artifactRoot, `packet-${index}.bin`);
|
|
151
|
-
fs.closeSync(fs.openSync(file, "w"));
|
|
152
|
-
fs.truncateSync(file, 60 * 1024 * 1024);
|
|
153
|
-
}
|
|
154
|
-
return outcome("artifact-packet-byte-limit", "page_evidence_artifact_limit", finalizeSession(fixture, session, runner));
|
|
155
|
-
}),
|
|
156
|
-
"missing-artifact": () => isolated((fixture) => {
|
|
157
|
-
const session = started(fixture);
|
|
158
|
-
const runner = writeRunner(fixture, session);
|
|
159
|
-
fs.rmSync(path.join(session.artifactRoot, runner.artifactReference));
|
|
160
|
-
return outcome("missing-artifact", "page_evidence_artifact_missing", finalizeSession(fixture, session, runner));
|
|
161
|
-
}),
|
|
162
|
-
"truncated-png": () => isolated((fixture) => {
|
|
163
|
-
const session = started(fixture);
|
|
164
|
-
const runner = writeRunner(fixture, session, { artifactBytes: truncatedPng() });
|
|
165
|
-
return outcome("truncated-png", "page_evidence_png_invalid", finalizeSession(fixture, session, runner));
|
|
166
|
-
}),
|
|
167
|
-
"corrupt-png-crc": () => isolated((fixture) => {
|
|
168
|
-
const session = started(fixture);
|
|
169
|
-
const runner = writeRunner(fixture, session, { artifactBytes: corruptPngCrc() });
|
|
170
|
-
return outcome("corrupt-png-crc", "page_evidence_png_invalid", finalizeSession(fixture, session, runner));
|
|
171
|
-
}),
|
|
172
|
-
"trailing-png-bytes": () => isolated((fixture) => {
|
|
173
|
-
const session = started(fixture);
|
|
174
|
-
const runner = writeRunner(fixture, session, { artifactBytes: pngWithTrailingBytes() });
|
|
175
|
-
return outcome("trailing-png-bytes", "page_evidence_png_invalid", finalizeSession(fixture, session, runner));
|
|
176
|
-
}),
|
|
177
|
-
"invalid-png-image-data-finalize": () => isolated((fixture) => {
|
|
178
|
-
const session = started(fixture);
|
|
179
|
-
const runner = writeRunner(fixture, session, { artifactBytes: pngWithInvalidImageData() });
|
|
180
|
-
return outcome("invalid-png-image-data-finalize", "page_evidence_png_invalid", finalizeSession(fixture, session, runner));
|
|
181
|
-
}),
|
|
182
|
-
"invalid-png-image-data-validate": () => isolated((fixture) => {
|
|
183
|
-
const completed = completeSession(fixture);
|
|
184
|
-
rewriteCompletedArtifact(completed.session, completed.runner, pngWithInvalidImageData());
|
|
185
|
-
return outcome("invalid-png-image-data-validate", "page_evidence_png_invalid", validateSession(fixture, completed.session));
|
|
186
|
-
}),
|
|
187
|
-
"trailing-png-image-data-finalize": () => isolated((fixture) => {
|
|
188
|
-
const session = started(fixture);
|
|
189
|
-
const runner = writeRunner(fixture, session, { artifactBytes: pngWithTrailingImageData() });
|
|
190
|
-
return outcome("trailing-png-image-data-finalize", "page_evidence_png_invalid", finalizeSession(fixture, session, runner));
|
|
191
|
-
}),
|
|
192
|
-
"hash-substitution": () => isolated((fixture) => {
|
|
193
|
-
const completed = completeSession(fixture);
|
|
194
|
-
fs.appendFileSync(path.join(completed.session.artifactRoot, completed.runner.artifactReference), "substitution");
|
|
195
|
-
return outcome("hash-substitution", "page_evidence_artifact_integrity", validateSession(fixture, completed.session));
|
|
196
|
-
}),
|
|
197
|
-
"validate-runner-control-collision": () => isolated((fixture) => {
|
|
198
|
-
const completed = completeSession(fixture);
|
|
199
|
-
rewriteCompletedCapture(completed.session, completed.runner, completed.runner.runnerReference);
|
|
200
|
-
return outcome("validate-runner-control-collision", "page_evidence_artifact_control_collision", validateSession(fixture, completed.session));
|
|
201
|
-
}),
|
|
202
|
-
"validate-receipt-control-collision": () => isolated((fixture) => {
|
|
203
|
-
const completed = completeSession(fixture);
|
|
204
|
-
rewriteCompletedCapture(completed.session, completed.runner, "page-evidence-session.json");
|
|
205
|
-
return outcome("validate-receipt-control-collision", "page_evidence_artifact_control_collision", validateSession(fixture, completed.session));
|
|
206
|
-
}),
|
|
207
|
-
"validate-manifest-control-collision": () => isolated((fixture) => {
|
|
208
|
-
const completed = completeSession(fixture);
|
|
209
|
-
rewriteCompletedCapture(completed.session, completed.runner, "page-evidence-manifest.json");
|
|
210
|
-
return outcome("validate-manifest-control-collision", "page_evidence_artifact_control_collision", validateSession(fixture, completed.session));
|
|
211
|
-
}),
|
|
212
|
-
"artifact-symlink": () => isolated((fixture) => {
|
|
213
|
-
const session = started(fixture);
|
|
214
|
-
const runner = writeRunner(fixture, session);
|
|
215
|
-
const artifact = path.join(session.artifactRoot, runner.artifactReference);
|
|
216
|
-
fs.rmSync(artifact);
|
|
217
|
-
fs.symlinkSync("/etc/hosts", artifact);
|
|
218
|
-
return outcome("artifact-symlink", "page_evidence_artifact_symlink", finalizeSession(fixture, session, runner));
|
|
219
|
-
}),
|
|
220
|
-
"artifact-redirect": () => isolated((fixture) => {
|
|
221
|
-
const completed = completeSession(fixture);
|
|
222
|
-
const realRoot = `${completed.session.artifactRoot}-real`;
|
|
223
|
-
fs.renameSync(completed.session.artifactRoot, realRoot);
|
|
224
|
-
fs.symlinkSync(realRoot, completed.session.artifactRoot);
|
|
225
|
-
return outcome("artifact-redirect", "page_evidence_artifact_redirect", validateSession(fixture, completed.session));
|
|
226
|
-
}),
|
|
227
|
-
"parent-escape": () => isolated((fixture) => {
|
|
228
|
-
const session = started(fixture);
|
|
229
|
-
const runner = writeRunner(fixture, session, { artifactPath: "../outside.png" });
|
|
230
|
-
return outcome("parent-escape", "page_evidence_artifact_escape", finalizeSession(fixture, session, runner));
|
|
231
|
-
}),
|
|
232
|
-
"capture-outside-session": () => isolated((fixture) => {
|
|
233
|
-
const session = started(fixture);
|
|
234
|
-
const runner = writeRunner(fixture, session, { recordedAt: "2000-01-01T00:00:00Z" });
|
|
235
|
-
return outcome("capture-outside-session", "page_evidence_capture_outside_session", finalizeSession(fixture, session, runner));
|
|
236
|
-
}),
|
|
237
|
-
"missing-start-receipt": () => isolated((fixture) => {
|
|
238
|
-
const completed = completeSession(fixture);
|
|
239
|
-
fs.rmSync(path.join(completed.session.artifactRoot, "page-evidence-session.json"));
|
|
240
|
-
return outcome("missing-start-receipt", "page_evidence_session_missing", validateSession(fixture, completed.session));
|
|
241
|
-
}),
|
|
242
|
-
"safe-reuse": () => isolated((fixture) => {
|
|
243
|
-
const setup = reuseSetup(fixture);
|
|
244
|
-
const runner = writeRunner(fixture, setup.current, { evidence: setup.evidence, writeArtifact: false });
|
|
245
|
-
const finalized = finalizeSession(fixture, setup.current, runner, setup.priorManifest);
|
|
246
|
-
const validated = finalized.status === 0 ? validateSession(fixture, setup.current, setup.priorManifest) : finalized;
|
|
247
|
-
return outcome("safe-reuse", "ok:true", validated, { finalized: finalized.report.ok === true });
|
|
248
|
-
}),
|
|
249
|
-
"unsafe-reuse": () => isolated((fixture) => {
|
|
250
|
-
const setup = reuseSetup(fixture);
|
|
251
|
-
setup.evidence.prior_manifest_sha256 = "0".repeat(64);
|
|
252
|
-
const runner = writeRunner(fixture, setup.current, { evidence: setup.evidence, writeArtifact: false });
|
|
253
|
-
return outcome("unsafe-reuse", "page_evidence_reuse_manifest_mismatch", finalizeSession(fixture, setup.current, runner, setup.priorManifest));
|
|
254
|
-
}),
|
|
255
|
-
"reuse-source-mismatch": () => isolated((fixture) => {
|
|
256
|
-
const setup = reuseSetup(fixture, { beforeCurrent: (consumer) => {
|
|
257
|
-
fs.appendFileSync(path.join(consumer.root, consumer.relevantSources[0]), "// next revision\n");
|
|
258
|
-
execFileSync("git", ["add", consumer.relevantSources[0]], { cwd: consumer.root });
|
|
259
|
-
execFileSync("git", ["commit", "-m", "next fixture revision"], { cwd: consumer.root });
|
|
260
|
-
consumer.revision = execFileSync("git", ["rev-parse", "HEAD"], { cwd: consumer.root, encoding: "utf8" }).trim();
|
|
261
|
-
} });
|
|
262
|
-
const runner = writeRunner(fixture, setup.current, { evidence: setup.evidence, writeArtifact: false });
|
|
263
|
-
return outcome("reuse-source-mismatch", "page_evidence_reuse_source_mismatch", finalizeSession(fixture, setup.current, runner, setup.priorManifest));
|
|
264
|
-
}),
|
|
265
|
-
"reuse-scenario-mismatch": () => isolated((fixture) => {
|
|
266
|
-
const setup = reuseSetup(fixture, { currentOptions: { scenarioId: "different-scenario" } });
|
|
267
|
-
const runner = writeRunner(fixture, setup.current, { evidence: setup.evidence, writeArtifact: false });
|
|
268
|
-
return outcome("reuse-scenario-mismatch", "page_evidence_reuse_scenario_mismatch", finalizeSession(fixture, setup.current, runner, setup.priorManifest));
|
|
269
|
-
}),
|
|
270
|
-
"reuse-environment-mismatch": () => isolated((fixture) => {
|
|
271
|
-
const setup = reuseSetup(fixture);
|
|
272
|
-
const changedEnvironment = { ...semanticEnvironment, viewport: { ...semanticEnvironment.viewport, width: 375 } };
|
|
273
|
-
const runner = writeRunner(fixture, setup.current, { evidence: setup.evidence, semanticEnvironment: changedEnvironment, writeArtifact: false });
|
|
274
|
-
return outcome("reuse-environment-mismatch", "page_evidence_reuse_environment_mismatch", finalizeSession(fixture, setup.current, runner, setup.priorManifest));
|
|
275
|
-
}),
|
|
276
|
-
"downloaded-unchanged-session": () => isolated((fixture) => {
|
|
277
|
-
const completed = completeSession(fixture);
|
|
278
|
-
const download = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), "stylegallery-page-download-")));
|
|
279
|
-
try {
|
|
280
|
-
fs.cpSync(fixture.root, download, { recursive: true });
|
|
281
|
-
const downloadedFixture = { ...fixture, root: download };
|
|
282
|
-
const downloadedSession = { ...completed.session, artifactRoot: completed.session.artifactRoot.replace(fixture.root, download), recordFile: completed.session.recordFile.replace(fixture.root, download) };
|
|
283
|
-
return outcome("downloaded-unchanged-session", "ok:true", validateSession(downloadedFixture, downloadedSession));
|
|
284
|
-
} finally { fs.rmSync(download, { force: true, recursive: true }); }
|
|
285
|
-
}),
|
|
286
|
-
"past-review-by-advisory": () => isolated((fixture) => {
|
|
287
|
-
const completed = completeSession(fixture);
|
|
288
|
-
const manifestFile = path.join(completed.session.artifactRoot, "page-evidence-manifest.json");
|
|
289
|
-
const manifest = JSON.parse(fs.readFileSync(manifestFile));
|
|
290
|
-
manifest.review_by = "2000-01-01T00:00:00Z";
|
|
291
|
-
writeJson(manifestFile, manifest);
|
|
292
|
-
return outcome("past-review-by-advisory", "ok:true", validateSession(fixture, completed.session));
|
|
293
|
-
}),
|
|
294
|
-
};
|
|
295
|
-
|
|
296
|
-
const selected = requested.length > 0 ? requested : Object.keys(cases);
|
|
297
|
-
const results = selected.map((name) => cases[name]?.() ?? ({ actual: { codes: [], status: null }, expected: "known-case", name, ok: false }));
|
|
298
|
-
const failures = results.filter((result) => !result.ok).map((result) => `${result.name}:${result.expected}`);
|
|
299
|
-
const report = { adversarial: results.filter((result) => result.expected !== "ok:true").length, failures, ok: failures.length === 0, results };
|
|
300
|
-
if (json) process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
301
|
-
else process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
302
|
-
if (!report.ok) process.exitCode = 1;
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import fs from "node:fs";
|
|
4
|
-
import os from "node:os";
|
|
5
|
-
import path from "node:path";
|
|
6
|
-
import { spawnSync } from "node:child_process";
|
|
7
|
-
import { fileURLToPath } from "node:url";
|
|
8
|
-
|
|
9
|
-
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
10
|
-
const validator = path.join(root, "scripts", "validate-patterns.mjs");
|
|
11
|
-
const cases = [
|
|
12
|
-
{
|
|
13
|
-
name: "missing_metadata",
|
|
14
|
-
file: "patterns/stacking/bad.md",
|
|
15
|
-
content: "# Bad\n\n## HTML\n\n```html\n<div></div>\n```\n\n## CSS\n\n```css\n.bad {\n display: grid;\n}\n```\n\n## Failure Mode\n\nBad.\n\n## Accessibility Notes\n\nBad.\n",
|
|
16
|
-
expect: "missing frontmatter",
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
name: "unsorted_css",
|
|
20
|
-
file: "patterns/stacking/bad.md",
|
|
21
|
-
content: pattern("bad", "Stacking", ".bad {\n width: 100%;\n display: grid;\n}"),
|
|
22
|
-
expect: "declarations are not alphabetical",
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
name: "forbidden_property",
|
|
26
|
-
file: "patterns/stacking/bad.md",
|
|
27
|
-
content: pattern("bad", "Stacking", ".bad {\n background: red;\n display: grid;\n}"),
|
|
28
|
-
expect: "forbidden decorative property",
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
name: "id_selector",
|
|
32
|
-
file: "patterns/stacking/bad.md",
|
|
33
|
-
content: pattern("bad", "Stacking", "#bad {\n display: grid;\n}"),
|
|
34
|
-
expect: "selector uses id",
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
name: "missing_html_block",
|
|
38
|
-
file: "patterns/stacking/bad.md",
|
|
39
|
-
content: pattern("bad", "Stacking", ".bad {\n display: grid;\n}", ""),
|
|
40
|
-
expect: "missing html code block",
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
name: "missing_css_block",
|
|
44
|
-
file: "patterns/stacking/bad.md",
|
|
45
|
-
content: pattern("bad", "Stacking", "", "<section class=\"bad\"></section>"),
|
|
46
|
-
expect: "missing css code block",
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
name: "missing_css_hook_in_html",
|
|
50
|
-
file: "patterns/stacking/bad.md",
|
|
51
|
-
content: pattern("bad", "Stacking", ".bad {\n display: grid;\n}\n\n.bad_item {\n display: grid;\n}"),
|
|
52
|
-
expect: "is missing from HTML block",
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
name: "missing_contract_section",
|
|
56
|
-
file: "patterns/stacking/bad.md",
|
|
57
|
-
content: legacyPattern("bad", "Stacking", ".bad {\n display: grid;\n}"),
|
|
58
|
-
expect: "missing Core Properties section",
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
name: "missing_accessibility_risk_details",
|
|
62
|
-
file: "patterns/stacking/bad.md",
|
|
63
|
-
content: pattern("bad", "Stacking", ".bad {\n display: grid;\n}").replace("- DOM order expectation: Keep semantic order.\n", ""),
|
|
64
|
-
expectWarning: "missing recommended accessibility detail DOM order expectation:",
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
name: "contract_sections_inside_code_block",
|
|
68
|
-
file: "patterns/stacking/bad.md",
|
|
69
|
-
content: legacyPattern(
|
|
70
|
-
"bad",
|
|
71
|
-
"Stacking",
|
|
72
|
-
".bad {\n display: grid;\n}\n\n/*\n## Core Properties\n## Properties That Break The Layout If Removed\n## Constraints And Change Points\n## Scroll Ownership\n## Accessibility And Source Order Notes\n## Browser And Fallback Notes\n## Composition Notes\n## Anti-patterns\n*/",
|
|
73
|
-
),
|
|
74
|
-
expect: "missing Core Properties section",
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
name: "reflow_without_reflow_mechanic",
|
|
78
|
-
file: "patterns/split-sidebar/bad.md",
|
|
79
|
-
content: pattern("bad", "Split / Sidebar", ".bad {\n display: grid;\n grid-template-columns: 16rem minmax(0, 1fr);\n}", "<section class=\"bad\"><article>Customer queue</article><article>Selected customer</article></section>", "reflow"),
|
|
80
|
-
expect: "responsiveness reflow requires",
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
name: "reflow_tokens_inside_css_comment",
|
|
84
|
-
file: "patterns/split-sidebar/bad.md",
|
|
85
|
-
content: pattern("bad", "Split / Sidebar", ".bad {\n display: grid;\n grid-template-columns: 24rem 24rem;\n}\n\n/* auto-fit 100% */", "<section class=\"bad\"><article>Customer queue</article><article>Selected customer</article></section>", "reflow"),
|
|
86
|
-
expect: "responsiveness reflow requires",
|
|
87
|
-
},
|
|
88
|
-
{
|
|
89
|
-
name: "unused_html_class",
|
|
90
|
-
file: "patterns/stacking/bad.md",
|
|
91
|
-
content: pattern("bad", "Stacking", ".bad {\n display: grid;\n}", "<section class=\"bad\"><div class=\"bad_extra\"></div></section>"),
|
|
92
|
-
expect: "has no CSS rule",
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
name: "placeholder_html",
|
|
96
|
-
file: "patterns/stacking/bad.md",
|
|
97
|
-
content: pattern("bad", "Stacking", ".bad {\n display: grid;\n}", "<section class=\"bad\"><article>First item</article></section>"),
|
|
98
|
-
expect: "placeholder sample phrase",
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
name: "success_path",
|
|
102
|
-
file: "patterns/stacking/good.md",
|
|
103
|
-
content: pattern("good", "Stacking", ".good {\n display: grid;\n gap: 1rem;\n}", "<section class=\"good\"><article>Quarterly review</article></section>"),
|
|
104
|
-
expect: null,
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
name: "default_min_count",
|
|
108
|
-
file: "patterns/stacking/good.md",
|
|
109
|
-
content: pattern("good", "Stacking", ".good {\n display: grid;\n gap: 1rem;\n}", "<section class=\"good\"><article>Quarterly review</article></section>"),
|
|
110
|
-
expect: null,
|
|
111
|
-
useDefaultMinCount: true,
|
|
112
|
-
},
|
|
113
|
-
];
|
|
114
|
-
|
|
115
|
-
function legacyPattern(name, category, css, html = `<section class="${name}"></section>`, responsiveness = "fluid") {
|
|
116
|
-
const cssBlock = css ? `\n\`\`\`css\n${css}\n\`\`\`\n` : "\n";
|
|
117
|
-
return `---\nname: ${name}\ncategory: ${category}\nprimary_spatial_problem: Test spatial problem.\nsecondary_spatial_problems: none\nlayout_axis: block\ncontent_shape: mixed\nresponsiveness: ${responsiveness}\nconstraints: Test constraints.\nscroll_ownership: No internal scroll container.\nsource_lineage: test\n---\n\n# ${name}\n\n## When To Use\n\nUse for validation tests.\n\n## HTML\n\n\`\`\`html\n${html}\n\`\`\`\n\n## CSS\n${cssBlock}\n## Failure Mode\n\nBad layout.\n\n## Accessibility Notes\n\nKeep semantic order.\n`;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function pattern(name, category, css, html = `<section class="${name}"></section>`, responsiveness = "fluid") {
|
|
121
|
-
const cssBlock = css ? `\n\`\`\`css\n${css}\n\`\`\`\n` : "\n";
|
|
122
|
-
return `---\nname: ${name}\ncategory: ${category}\nprimary_spatial_problem: Test spatial problem.\nsecondary_spatial_problems: none\nlayout_axis: block\ncontent_shape: mixed\nresponsiveness: ${responsiveness}\nconstraints: Test constraints.\nscroll_ownership: No internal scroll container.\nsource_lineage: test\n---\n\n# ${name}\n\n## When To Use\n\nUse for validation tests.\n\n## HTML\n\n\`\`\`html\n${html}\n\`\`\`\n\n## CSS\n${cssBlock}\n## Core Properties\n\n- \`display\` establishes the layout context.\n\n## Properties That Break The Layout If Removed\n\n- Removing \`display\` removes the layout behavior.\n\n## Constraints And Change Points\n\nTest constraints.\n\n## Scroll Ownership\n\nNo internal scroll container.\n\n## Accessibility And Source Order Notes\n\n- Semantic role expectation: Preserve the element roles already present in the HTML sample.\n- DOM order expectation: Keep semantic order.\n- Focus risk: Keep focus order aligned with DOM order.\n- Scroll expectation: No internal scroll container.\n- Cognitive risk: Low when the pattern does not reorder meaning or hide controls.\n\n## Browser And Fallback Notes\n\nUse a simpler block fallback when needed.\n\n## Composition Notes\n\nCompose with semantic regions.\n\n## Anti-patterns\n\nDo not use for unrelated visual styling.\n`;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function runCase(testCase) {
|
|
126
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), `layout-gallery-${testCase.name}-`));
|
|
127
|
-
const absolute = path.join(dir, testCase.file);
|
|
128
|
-
fs.mkdirSync(path.dirname(absolute), { recursive: true });
|
|
129
|
-
fs.writeFileSync(absolute, testCase.content);
|
|
130
|
-
const args = testCase.useDefaultMinCount ? [validator, "--json"] : [validator, "--min-count", "1", "--json"];
|
|
131
|
-
const result = spawnSync(process.execPath, args, {
|
|
132
|
-
cwd: dir,
|
|
133
|
-
encoding: "utf8",
|
|
134
|
-
});
|
|
135
|
-
fs.rmSync(dir, { force: true, recursive: true });
|
|
136
|
-
const output = JSON.parse(result.stdout);
|
|
137
|
-
const passed = testCase.expectWarning
|
|
138
|
-
? output.ok && output.warnings?.some((warning) => warning.includes(testCase.expectWarning))
|
|
139
|
-
: testCase.expect
|
|
140
|
-
? !output.ok && output.failures.some((failure) => failure.includes(testCase.expect))
|
|
141
|
-
: output.ok && (!testCase.useDefaultMinCount || output.minCount === 1);
|
|
142
|
-
return {
|
|
143
|
-
name: testCase.name,
|
|
144
|
-
ok: passed,
|
|
145
|
-
expected: testCase.expectWarning ?? testCase.expect ?? "ok:true",
|
|
146
|
-
actual: output,
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const results = cases.map(runCase);
|
|
151
|
-
const report = {
|
|
152
|
-
ok: results.every((result) => result.ok),
|
|
153
|
-
results,
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
console.log(JSON.stringify(report, null, 2));
|
|
157
|
-
process.exitCode = report.ok ? 0 : 1;
|