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,250 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import fs from "node:fs";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import { spawnSync } from "node:child_process";
|
|
6
|
-
import { fileURLToPath } from "node:url";
|
|
7
|
-
import { copyTreeNoSymlinks, testPromotionBoundaries } from "./promotion-boundary-test-contract.mjs";
|
|
8
|
-
|
|
9
|
-
const repositoryRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
10
|
-
const fixtureRoot = path.join(repositoryRoot, "consumer-reference/fixtures/promotion");
|
|
11
|
-
const validator = path.join(repositoryRoot, "scripts/validate-promotion-rfc.mjs");
|
|
12
|
-
|
|
13
|
-
function readJson(relative) {
|
|
14
|
-
return JSON.parse(fs.readFileSync(path.join(fixtureRoot, relative), "utf8"));
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function runArguments(args) {
|
|
18
|
-
const child = spawnSync(process.execPath, [validator, ...args], { cwd: repositoryRoot, encoding: "utf8" });
|
|
19
|
-
let report = { failures: [], ok: false, parse_error: true };
|
|
20
|
-
try {
|
|
21
|
-
report = JSON.parse(child.stdout);
|
|
22
|
-
} catch (error) {
|
|
23
|
-
if (!(error instanceof SyntaxError)) throw error;
|
|
24
|
-
report = { failures: [], ok: false, parse_error: true };
|
|
25
|
-
}
|
|
26
|
-
return { report, status: child.status };
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function run(file, profileRepositoryRoot) {
|
|
30
|
-
const args = ["--file", file, "--json"];
|
|
31
|
-
if (profileRepositoryRoot) args.push("--profile-repository-root", profileRepositoryRoot);
|
|
32
|
-
return runArguments(args);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function runPolicy(file) {
|
|
36
|
-
return runArguments(["--policy", file, "--json"]);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function writeMutation(name, source, mutate) {
|
|
40
|
-
const value = structuredClone(readJson(source));
|
|
41
|
-
mutate(value);
|
|
42
|
-
const file = path.join(tempRoot, `${name}.json`);
|
|
43
|
-
fs.writeFileSync(file, `${JSON.stringify(value, null, 2)}\n`);
|
|
44
|
-
return file;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function writePolicyMutation(root, name, mutate) {
|
|
48
|
-
const value = JSON.parse(fs.readFileSync(path.join(repositoryRoot, "consumer-reference/policies/shared-experimental.json"), "utf8"));
|
|
49
|
-
mutate(value);
|
|
50
|
-
const file = path.join(root, `${name}.json`);
|
|
51
|
-
fs.writeFileSync(file, `${JSON.stringify(value, null, 2)}\n`);
|
|
52
|
-
return file;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function copyProfileRepository(name) {
|
|
56
|
-
const root = path.join(tempRoot, name);
|
|
57
|
-
const source = path.join(repositoryRoot, "design-engineering/reference-profiles/governed-local");
|
|
58
|
-
const target = path.join(root, "design-engineering/reference-profiles/governed-local");
|
|
59
|
-
copyTreeNoSymlinks(source, target);
|
|
60
|
-
return root;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function editProfileJson(root, relative, mutate) {
|
|
64
|
-
const file = path.join(root, relative);
|
|
65
|
-
const value = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
66
|
-
mutate(value);
|
|
67
|
-
fs.writeFileSync(file, `${JSON.stringify(value, null, 2)}\n`);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const fixtureManifest = JSON.parse(fs.readFileSync(path.join(fixtureRoot, "manifest.json"), "utf8"));
|
|
71
|
-
const invalidCases = fixtureManifest.invalid_records.map((entry) => [entry.file.replace(/\.json$/, ""), entry.file, entry.expected_code]);
|
|
72
|
-
|
|
73
|
-
const tempRoot = fs.mkdtempSync(path.join(repositoryRoot, ".tmp-pr6-promotion-"));
|
|
74
|
-
const repositoryTempRoot = fs.mkdtempSync(path.join(repositoryRoot, ".tmp-pr6-profile-"));
|
|
75
|
-
const results = [];
|
|
76
|
-
try {
|
|
77
|
-
for (const [name, relative, expected] of invalidCases) {
|
|
78
|
-
const child = run(path.join(fixtureRoot, relative));
|
|
79
|
-
const codes = child.report.failures.map((failure) => failure.code);
|
|
80
|
-
results.push({ actual: { codes, scaffold: child.report.scaffold === true, status: child.status }, expected, name, ok: child.status > 0 && codes.includes(expected) && child.report.scaffold !== true });
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const editorial = writeMutation("editorial_counted", "valid-deferred-example.json", (value) => {
|
|
84
|
-
value.attestations = [{ attested_by: "Synthetic owner", context_id: "editorial", consumer_id: "editorial-reference-profile", count_toward_gate: true, organization_id: "stylegallery", profile_record: "design-engineering/reference-profiles/governed-local/editorial/profile.json", relationship: "independent" }];
|
|
85
|
-
});
|
|
86
|
-
const terminal = writeMutation("terminal_counted", "valid-deferred-example.json", (value) => {
|
|
87
|
-
value.attestations = [{ attested_by: "Synthetic owner", context_id: "terminal", consumer_id: "terminal-reference-profile", count_toward_gate: true, organization_id: "stylegallery", profile_record: "design-engineering/reference-profiles/governed-local/terminal/profile.json", relationship: "independent" }];
|
|
88
|
-
});
|
|
89
|
-
const booleanReview = writeMutation("boolean_review", "valid-deferred-example.json", (value) => { value.review_independence = false; });
|
|
90
|
-
const fakeIndependence = writeMutation("fake_independence", "valid-deferred-example.json", (value) => {
|
|
91
|
-
value.attestations = [
|
|
92
|
-
{ attested_by: "Synthetic owner", context_id: "one", consumer_id: "consumer-one", count_toward_gate: true, organization_id: "same-org", relationship: "independent" },
|
|
93
|
-
{ attested_by: "Synthetic owner", context_id: "two", consumer_id: "consumer-two", count_toward_gate: true, organization_id: "same-org", relationship: "independent" }
|
|
94
|
-
];
|
|
95
|
-
});
|
|
96
|
-
const duplicateIdentity = writeMutation("duplicate_identity", "valid-deferred-example.json", (value) => {
|
|
97
|
-
const attestation = { attested_by: "Synthetic owner", context_id: "same", consumer_id: "same-consumer", count_toward_gate: true, organization_id: "same-org", relationship: "independent" };
|
|
98
|
-
value.attestations = [attestation, structuredClone(attestation)];
|
|
99
|
-
});
|
|
100
|
-
const duplicateConsumer = writeMutation("duplicate_consumer", "valid-deferred-example.json", (value) => {
|
|
101
|
-
value.attestations = [
|
|
102
|
-
{ attested_by: "Synthetic owner A", context_id: "one", consumer_id: "same-consumer", count_toward_gate: true, organization_id: "organization-a", relationship: "independent" },
|
|
103
|
-
{ attested_by: "Synthetic owner B", context_id: "two", consumer_id: "same-consumer", count_toward_gate: true, organization_id: "organization-b", relationship: "independent" }
|
|
104
|
-
];
|
|
105
|
-
});
|
|
106
|
-
const unknownConsumers = writeMutation("unknown_consumers", "valid-deferred-example.json", (value) => {
|
|
107
|
-
value.attestations = [
|
|
108
|
-
{ attested_by: "Synthetic owner A", context_id: "one", consumer_id: "unknown-one", count_toward_gate: true, organization_id: "organization-a", relationship: "independent" },
|
|
109
|
-
{ attested_by: "Synthetic owner B", context_id: "two", consumer_id: "unknown-two", count_toward_gate: true, organization_id: "organization-b", relationship: "independent" }
|
|
110
|
-
];
|
|
111
|
-
});
|
|
112
|
-
const forgedOne = path.join(repositoryTempRoot, "forged-one.json");
|
|
113
|
-
const forgedTwo = path.join(repositoryTempRoot, "forged-two.json");
|
|
114
|
-
fs.writeFileSync(forgedOne, '{"fixture_independence":"independent","id":"forged-one"}\n');
|
|
115
|
-
fs.writeFileSync(forgedTwo, '{"fixture_independence":"independent","id":"forged-two"}\n');
|
|
116
|
-
const forgedProfiles = writeMutation("forged_profiles", "valid-deferred-example.json", (value) => {
|
|
117
|
-
value.attestations = [
|
|
118
|
-
{ attested_by: "Synthetic owner A", context_id: "one", consumer_id: "forged-one", count_toward_gate: true, organization_id: "organization-a", profile_record: path.relative(repositoryRoot, forgedOne), relationship: "independent" },
|
|
119
|
-
{ attested_by: "Synthetic owner B", context_id: "two", consumer_id: "forged-two", count_toward_gate: true, organization_id: "organization-b", profile_record: path.relative(repositoryRoot, forgedTwo), relationship: "independent" }
|
|
120
|
-
];
|
|
121
|
-
});
|
|
122
|
-
const copiedProfileRoot = path.join(repositoryTempRoot, "copied");
|
|
123
|
-
copyTreeNoSymlinks(path.join(repositoryRoot, "design-engineering/reference-profiles/governed-local/editorial"), copiedProfileRoot);
|
|
124
|
-
const copiedUnregistered = writeMutation("copied_unregistered", "valid-deferred-example.json", (value) => {
|
|
125
|
-
value.attestations = [{ attested_by: "Synthetic owner", context_id: "copied", consumer_id: "editorial-reference-profile", count_toward_gate: true, organization_id: "copied-org", profile_record: path.relative(repositoryRoot, path.join(copiedProfileRoot, "profile.json")), relationship: "independent" }];
|
|
126
|
-
});
|
|
127
|
-
const invalidRegisteredRoot = copyProfileRepository("invalid-registered-root");
|
|
128
|
-
editProfileJson(invalidRegisteredRoot, "design-engineering/reference-profiles/governed-local/editorial/profile.json", (value) => { delete value.owner; });
|
|
129
|
-
const invalidRegistered = writeMutation("invalid_registered", "valid-deferred-example.json", (value) => {
|
|
130
|
-
value.attestations = [{ attested_by: "Synthetic owner", context_id: "invalid", consumer_id: "editorial-reference-profile", count_toward_gate: true, organization_id: "invalid-org", profile_record: "design-engineering/reference-profiles/governed-local/editorial/profile.json", relationship: "independent" }];
|
|
131
|
-
});
|
|
132
|
-
const duplicateRegistryRoot = copyProfileRepository("duplicate-registry-root");
|
|
133
|
-
editProfileJson(duplicateRegistryRoot, "design-engineering/reference-profiles/governed-local/terminal/profile.json", (value) => { value.id = "editorial-reference-profile"; });
|
|
134
|
-
const duplicateRegistryIdentity = writeMutation("duplicate_registry_identity", "valid-deferred-example.json", (value) => {
|
|
135
|
-
value.attestations = [{ attested_by: "Synthetic owner", context_id: "duplicate", consumer_id: "editorial-reference-profile", count_toward_gate: true, organization_id: "duplicate-org", profile_record: "design-engineering/reference-profiles/governed-local/editorial/profile.json", relationship: "independent" }];
|
|
136
|
-
});
|
|
137
|
-
const silentRelabel = writeMutation("silent_relabel", "valid-deferred-example.json", (value) => {
|
|
138
|
-
value.transition = { from: "stable", to: "shared_experimental" };
|
|
139
|
-
});
|
|
140
|
-
const pathEscape = writeMutation("path_escape", "valid-deferred-example.json", (value) => {
|
|
141
|
-
value.attestations = [{ attested_by: "Synthetic owner", context_id: "escape", consumer_id: "escape", count_toward_gate: true, organization_id: "escape", profile_record: "../outside.json", relationship: "independent" }];
|
|
142
|
-
});
|
|
143
|
-
const profileMismatch = writeMutation("profile_mismatch", "valid-deferred-example.json", (value) => {
|
|
144
|
-
value.attestations = [{ attested_by: "Synthetic owner", context_id: "editorial", consumer_id: "different-profile", count_toward_gate: true, organization_id: "stylegallery", profile_record: "design-engineering/reference-profiles/governed-local/editorial/profile.json", relationship: "independent" }];
|
|
145
|
-
});
|
|
146
|
-
const profileLink = path.join(repositoryTempRoot, "profile.json");
|
|
147
|
-
fs.symlinkSync(path.join(repositoryRoot, "design-engineering/reference-profiles/governed-local/editorial/profile.json"), profileLink);
|
|
148
|
-
const profileSymlink = writeMutation("profile_symlink", "valid-deferred-example.json", (value) => {
|
|
149
|
-
value.attestations = [{ attested_by: "Synthetic owner", context_id: "editorial", consumer_id: "editorial-reference-profile", count_toward_gate: true, organization_id: "stylegallery", profile_record: path.relative(repositoryRoot, profileLink), relationship: "independent" }];
|
|
150
|
-
});
|
|
151
|
-
const schemaExtra = writeMutation("schema_extra", "valid-deferred-example.json", (value) => { value.unexpected_promotion = true; });
|
|
152
|
-
const acceptedDecision = writeMutation("accepted_decision", "valid-deferred-example.json", (value) => { value.decision = "accepted"; });
|
|
153
|
-
const aestheticPromotion = writeMutation("aesthetic_promotion", "valid-deferred-example.json", (value) => { value.scope.aesthetic = true; });
|
|
154
|
-
const breakingWithoutMigration = writeMutation("breaking_without_migration", "valid-deferred-example.json", (value) => { value.compatibility.breaking = true; value.migration.required = false; });
|
|
155
|
-
const normativeWithoutRollback = writeMutation("normative_without_rollback", "valid-normative-bypass.json", (value) => { delete value.rollback; });
|
|
156
|
-
const normativeEndedSupport = writeMutation("normative_ended_support", "valid-normative-bypass.json", (value) => {
|
|
157
|
-
value.support = { capacity: "No active support capacity", status: "ended" };
|
|
158
|
-
});
|
|
159
|
-
const normativeMissingSupport = writeMutation("normative_missing_support", "valid-normative-bypass.json", (value) => { delete value.support; });
|
|
160
|
-
const normativeMissingCapacity = writeMutation("normative_missing_capacity", "valid-normative-bypass.json", (value) => { delete value.support.capacity; });
|
|
161
|
-
const weakCapacityCases = ["0", "Not available", "Absent", "Lapsed", "Negative capacity"].map((capacity, index) => [
|
|
162
|
-
`weak_capacity_${index + 1}`,
|
|
163
|
-
writeMutation(`weak_capacity_${index + 1}`, "valid-deferred-example.json", (value) => { value.support.capacity = capacity; }),
|
|
164
|
-
"promotion_support_required",
|
|
165
|
-
]);
|
|
166
|
-
const stableWithoutCount = writeMutation("stable_without_count", "valid-deferred-example.json", (value) => {
|
|
167
|
-
value.transition = { from: "shared_experimental", to: "stable" };
|
|
168
|
-
value.stable_scope_decision = true;
|
|
169
|
-
value.provenance.debt_resolved = true;
|
|
170
|
-
});
|
|
171
|
-
const stableWithoutEvidence = writeMutation("stable_without_evidence", "valid-deferred-example.json", (value) => {
|
|
172
|
-
value.transition = { from: "shared_experimental", to: "stable" };
|
|
173
|
-
value.stable_scope_decision = true;
|
|
174
|
-
value.provenance.debt_resolved = true;
|
|
175
|
-
value.evidence = [{ id: "regression", kind: "regression", reference: "synthetic-fixture:regression", status: "failed" }];
|
|
176
|
-
});
|
|
177
|
-
const duplicateKey = path.join(tempRoot, "duplicate_key.json");
|
|
178
|
-
fs.writeFileSync(duplicateKey, fs.readFileSync(path.join(fixtureRoot, "valid-deferred-example.json"), "utf8").replace('"decision": "deferred",', '"decision": "deferred",\n "decision": "rejected",'));
|
|
179
|
-
for (const [name, file, expected, profileRepositoryRoot] of [
|
|
180
|
-
["editorial_counted", editorial, "promotion_related_consumer_counted"],
|
|
181
|
-
["terminal_counted", terminal, "promotion_related_consumer_counted"],
|
|
182
|
-
["boolean_review", booleanReview, "review_independence_boolean"],
|
|
183
|
-
["fake_independence", fakeIndependence, "promotion_independence_unproven"],
|
|
184
|
-
["duplicate_identity", duplicateIdentity, "promotion_attestation_duplicate"],
|
|
185
|
-
["duplicate_consumer", duplicateConsumer, "promotion_attestation_duplicate"],
|
|
186
|
-
["unknown_consumers", unknownConsumers, "promotion_independence_unproven"],
|
|
187
|
-
["forged_profiles", forgedProfiles, "promotion_independence_unproven"],
|
|
188
|
-
["copied_unregistered", copiedUnregistered, "promotion_independence_unproven"],
|
|
189
|
-
["invalid_registered", invalidRegistered, "promotion_independence_unproven", invalidRegisteredRoot],
|
|
190
|
-
["duplicate_registry_identity", duplicateRegistryIdentity, "promotion_independence_unproven", duplicateRegistryRoot],
|
|
191
|
-
["silent_relabel", silentRelabel, "promotion_stable_relabel_forbidden"],
|
|
192
|
-
["path_escape", pathEscape, "promotion_profile_path_invalid"],
|
|
193
|
-
["profile_mismatch", profileMismatch, "promotion_profile_identity_mismatch"],
|
|
194
|
-
["profile_symlink", profileSymlink, "promotion_profile_path_symlink"],
|
|
195
|
-
["schema_extra", schemaExtra, "promotion_schema_invalid"],
|
|
196
|
-
["accepted_decision", acceptedDecision, "promotion_schema_invalid"],
|
|
197
|
-
["aesthetic_promotion", aestheticPromotion, "promotion_schema_invalid"],
|
|
198
|
-
["breaking_without_migration", breakingWithoutMigration, "promotion_migration_required"],
|
|
199
|
-
["normative_without_rollback", normativeWithoutRollback, "promotion_schema_invalid"],
|
|
200
|
-
["normative_ended_support", normativeEndedSupport, "promotion_support_required"],
|
|
201
|
-
["normative_missing_support", normativeMissingSupport, "promotion_support_required"],
|
|
202
|
-
["normative_missing_capacity", normativeMissingCapacity, "promotion_support_required"],
|
|
203
|
-
["duplicate_key", duplicateKey, "promotion_json_invalid"],
|
|
204
|
-
["stable_without_evidence", stableWithoutEvidence, "promotion_stable_evidence_required"],
|
|
205
|
-
...weakCapacityCases,
|
|
206
|
-
]) {
|
|
207
|
-
const child = run(file, profileRepositoryRoot);
|
|
208
|
-
const codes = child.report.failures.map((failure) => failure.code);
|
|
209
|
-
results.push({ actual: { codes, scaffold: child.report.scaffold === true, status: child.status }, expected, name, ok: child.status > 0 && codes.includes(expected) && child.report.scaffold !== true });
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
for (const relative of ["valid-deferred-example.json", "valid-normative-bypass.json"]) {
|
|
213
|
-
const child = run(path.join(fixtureRoot, relative));
|
|
214
|
-
results.push({ actual: { scaffold: child.report.scaffold === true, status: child.status }, expected: "ok:true", name: relative, ok: child.status === 0 && child.report.ok === true && child.report.scaffold !== true });
|
|
215
|
-
}
|
|
216
|
-
const stable = run(stableWithoutCount);
|
|
217
|
-
results.push({ actual: { scaffold: stable.report.scaffold === true, status: stable.status }, expected: "stable_without_numeric_threshold", name: "stable_without_count", ok: stable.status === 0 && stable.report.ok === true && stable.report.scaffold !== true });
|
|
218
|
-
const canonicalPolicy = runPolicy(path.join(repositoryRoot, "consumer-reference/policies/shared-experimental.json"));
|
|
219
|
-
results.push({ actual: { status: canonicalPolicy.status }, expected: "canonical_policy_valid", name: "canonical_policy", ok: canonicalPolicy.status === 0 && canonicalPolicy.report.ok === true });
|
|
220
|
-
results.push(...testPromotionBoundaries({ fixtureRoot, repositoryRoot, runArguments, tempRoot }));
|
|
221
|
-
for (const [name, file, expected] of [
|
|
222
|
-
["stable_numeric_count", writePolicyMutation(tempRoot, "stable_numeric_count", (value) => { value.gateway.stable_numeric_threshold = 2; }), "promotion_stable_numeric_threshold_forbidden"],
|
|
223
|
-
["bypass_overreach", writePolicyMutation(tempRoot, "bypass_overreach", (value) => { value.normative_bypass.waives.push("regression_proof"); }), "promotion_normative_bypass_overreach"],
|
|
224
|
-
["fake_promotion_claim", writePolicyMutation(tempRoot, "fake_promotion_claim", (value) => { value.claims.promotion_occurred = true; }), "promotion_claim_forbidden"],
|
|
225
|
-
["policy_unknown_field", writePolicyMutation(tempRoot, "policy_unknown_field", (value) => { value.accepted = true; }), "promotion_policy_shape_invalid"],
|
|
226
|
-
["policy_nested_unknown", writePolicyMutation(tempRoot, "policy_nested_unknown", (value) => { value.gateway.stable_by_count = true; }), "promotion_policy_shape_invalid"],
|
|
227
|
-
["policy_promotes_palette", writePolicyMutation(tempRoot, "policy_promotes_palette", (value) => { value.boundaries.promoted_content.push("palette"); }), "promotion_aesthetic_boundary_required"],
|
|
228
|
-
["policy_promotes_alias", writePolicyMutation(tempRoot, "policy_promotes_alias", (value) => { value.boundaries.promoted_content.push("brand_identity"); }), "promotion_aesthetic_boundary_required"],
|
|
229
|
-
["policy_promoted_non_string", writePolicyMutation(tempRoot, "policy_promoted_non_string", (value) => { value.boundaries.promoted_content = [42]; }), "promotion_aesthetic_boundary_required"],
|
|
230
|
-
["policy_normative_aesthetic", writePolicyMutation(tempRoot, "policy_normative_aesthetic", (value) => { value.normative_bypass.categories = ["aesthetic"]; }), "promotion_normative_bypass_overreach"],
|
|
231
|
-
["policy_lifecycle_incomplete", writePolicyMutation(tempRoot, "policy_lifecycle_incomplete", (value) => { value.lifecycle.failure_actions = ["deprecate_with_migration"]; }), "promotion_lifecycle_invalid"],
|
|
232
|
-
["policy_excluded_non_string", writePolicyMutation(tempRoot, "policy_excluded_non_string", (value) => { value.boundaries.excluded_content.push(42); }), "promotion_aesthetic_boundary_required"],
|
|
233
|
-
["policy_retains_non_string", writePolicyMutation(tempRoot, "policy_retains_non_string", (value) => { value.normative_bypass.retains.push(42); }), "promotion_normative_bypass_overreach"],
|
|
234
|
-
["policy_verified_owner", writePolicyMutation(tempRoot, "policy_verified_owner", (value) => { value.owner.enforcement = "verified"; }), "promotion_policy_owner_invalid"],
|
|
235
|
-
["policy_promoted_status", writePolicyMutation(tempRoot, "policy_promoted_status", (value) => { value.status = "promoted"; }), "promotion_claim_forbidden"],
|
|
236
|
-
["policy_generated_mode", writePolicyMutation(tempRoot, "policy_generated_mode", (value) => { value.artifact_mode = "generated"; }), "promotion_policy_identity_invalid"],
|
|
237
|
-
]) {
|
|
238
|
-
const child = runPolicy(file);
|
|
239
|
-
const codes = child.report.failures.map((failure) => failure.code);
|
|
240
|
-
results.push({ actual: { codes, status: child.status }, expected, name, ok: child.status > 0 && codes.includes(expected) });
|
|
241
|
-
}
|
|
242
|
-
} finally {
|
|
243
|
-
fs.rmSync(tempRoot, { force: true, recursive: true });
|
|
244
|
-
fs.rmSync(repositoryTempRoot, { force: true, recursive: true });
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
const failures = results.filter((result) => !result.ok).map((result) => `missing_semantic:${result.name}:${result.expected}`);
|
|
248
|
-
const report = { failures, ok: failures.length === 0, results };
|
|
249
|
-
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
250
|
-
if (!report.ok) process.exitCode = 1;
|
|
@@ -1,170 +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 repositoryRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
10
|
-
const validator = path.join(repositoryRoot, "scripts", "validate-consumer-reference.mjs");
|
|
11
|
-
const profilePath = "design-engineering/reference-profiles/governed-local/editorial/profile.json";
|
|
12
|
-
const terminalProfilePath = "design-engineering/reference-profiles/governed-local/terminal/profile.json";
|
|
13
|
-
const aliasProfilePath = "design-engineering/reference-profiles/governed-local/alias/profile.json";
|
|
14
|
-
const layoutSha = "775430bbaf4ee208a642220f440f6926d79c90a3";
|
|
15
|
-
|
|
16
|
-
const baseProfile = {
|
|
17
|
-
artifact_mode: "governed_local",
|
|
18
|
-
component_records: ["components/button.component.json"],
|
|
19
|
-
default: false,
|
|
20
|
-
environment_assumptions: {
|
|
21
|
-
reset: { body_margin: "0", box_sizing: "border-box", figure_margin: "0" },
|
|
22
|
-
user_agent_styles: "Preserve browser defaults except for the declared reset.",
|
|
23
|
-
},
|
|
24
|
-
example_only: true,
|
|
25
|
-
evidence_records: ["evidence/button.evidence.json"],
|
|
26
|
-
fixture_records: ["fixtures/button.fixture.json"],
|
|
27
|
-
fixture_independence: "related",
|
|
28
|
-
handoff: { record: profilePath, status: "declared" },
|
|
29
|
-
generated_records: ["generated/evidence-coverage.md", "generated/keyboard-matrix.md", "generated/state-matrix.md"],
|
|
30
|
-
id: "editorial-reference-profile",
|
|
31
|
-
layout_source_sha: layoutSha,
|
|
32
|
-
local_foundations: "local-foundations.json",
|
|
33
|
-
maturity: "experimental",
|
|
34
|
-
owner: { enforcement: "placeholder", name: "Design Engineering owner" },
|
|
35
|
-
profile_kind: "governed_local",
|
|
36
|
-
related_fixture_set_id: "layout-identity-adversarial-pair",
|
|
37
|
-
review_independence: "single_account",
|
|
38
|
-
schema_version: "1.0",
|
|
39
|
-
selection: { method: "profile_path", required: true },
|
|
40
|
-
state_records: ["states/button.states.json"],
|
|
41
|
-
support: { status: "active" },
|
|
42
|
-
tokens: "tokens.dtcg.json",
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const tokens = {
|
|
46
|
-
color: {
|
|
47
|
-
$type: "color",
|
|
48
|
-
accent: { $value: { alpha: 1, colorSpace: "srgb", components: [0.55, 0.18, 0.1] } },
|
|
49
|
-
},
|
|
50
|
-
space: { $type: "dimension", page: { $value: { unit: "rem", value: 1.5 } } },
|
|
51
|
-
};
|
|
52
|
-
const terminalTokens = {
|
|
53
|
-
color: {
|
|
54
|
-
$type: "color",
|
|
55
|
-
accent: { $value: { alpha: 1, colorSpace: "srgb", components: [0.1, 0.9, 0.5] } },
|
|
56
|
-
},
|
|
57
|
-
space: { $type: "dimension", page: { $value: { unit: "rem", value: 1 } } },
|
|
58
|
-
};
|
|
59
|
-
const editorialFoundations = { bindings: { accent: "{color.accent}" }, identity: "Warm editorial", profile_id: "editorial-reference-profile" };
|
|
60
|
-
const terminalFoundations = { bindings: { accent: "{color.accent}" }, identity: "Dark terminal", profile_id: "terminal-reference-profile" };
|
|
61
|
-
|
|
62
|
-
const cases = [
|
|
63
|
-
{ name: "valid_governed_local_profile" },
|
|
64
|
-
{ expect: "profile_artifact_mode_governed_local", name: "local_as_external", mutate: (item) => { item.artifact_mode = "external_consumer"; } },
|
|
65
|
-
{ expect: "profile_default_forbidden", name: "implicit_default", mutate: (item) => { item.default = true; } },
|
|
66
|
-
{ expect: "profile_layout_source_sha_required", name: "missing_layout_sha", mutate: (item) => { delete item.layout_source_sha; } },
|
|
67
|
-
{ expect: "profile_ua_assumption_required", name: "missing_ua_assumption", mutate: (item) => { delete item.environment_assumptions.user_agent_styles; } },
|
|
68
|
-
{ expect: "profile_reset_assumptions_required", name: "missing_reset_assumptions", mutate: (item) => { delete item.environment_assumptions.reset; } },
|
|
69
|
-
{ expect: "profile_explicit_selection_required", name: "implicit_selection", mutate: (item) => { item.selection.required = false; } },
|
|
70
|
-
{ expect: "fixture_independence_related", name: "independence_independent", mutate: (item) => { item.fixture_independence = "independent"; } },
|
|
71
|
-
{ expect: "reverse_import", name: "reverse_profile_import", patternData: "export const related_fixture_set_id = 'layout-identity-adversarial-pair';\n" },
|
|
72
|
-
{ expect: "external_adaptation_record_forbidden", externalRecord: true, name: "durable_external_adopter" },
|
|
73
|
-
{ equalTokens: true, expect: "profile_tokens_not_distinct", name: "single_profile_equal_pair_tokens" },
|
|
74
|
-
{ equalFoundations: true, expect: "profile_foundations_not_distinct", name: "single_profile_equal_pair_foundations" },
|
|
75
|
-
{ equalIdentity: true, expect: "profile_identity_not_distinct", name: "single_profile_equal_pair_identity" },
|
|
76
|
-
{ expect: "profile_related_set_mismatch", name: "single_profile_related_set_mismatch", mutateTerminal: (item) => { item.related_fixture_set_id = "unrelated-terminal-set"; } },
|
|
77
|
-
{ expect: "profile_tokens_symlink_escape", linkedArtifact: "tokens", name: "linked_outside_tokens" },
|
|
78
|
-
{ expect: "profile_foundations_symlink_escape", linkedArtifact: "foundations", name: "linked_outside_foundations" },
|
|
79
|
-
{ expect: "profile_environment_property_unknown", name: "unknown_environment_field", mutate: (item) => { item.environment_assumptions.viewport = "wide"; } },
|
|
80
|
-
{ expect: "profile_reset_property_unknown", name: "unknown_reset_field", mutate: (item) => { item.environment_assumptions.reset.list_margin = "0"; } },
|
|
81
|
-
{ expect: "profile_selection_property_unknown", name: "unknown_selection_field", mutate: (item) => { item.selection.fallback = "editorial"; } },
|
|
82
|
-
{ expect: "item_property_unknown", name: "unknown_profile_top_level", mutate: (item) => { item.profile_fallback = true; } },
|
|
83
|
-
{
|
|
84
|
-
equalTokens: true,
|
|
85
|
-
expect: "profile_tokens_not_distinct",
|
|
86
|
-
name: "normalized_equivalent_selector_loads_pair",
|
|
87
|
-
selector: "design-engineering/reference-profiles/governed-local/editorial/../editorial/profile.json",
|
|
88
|
-
},
|
|
89
|
-
{ absoluteSelector: true, expect: "item_unresolved", name: "absolute_profile_selector_rejected" },
|
|
90
|
-
{ expect: "item_unresolved", name: "scheme_profile_selector_rejected", selector: "https://example.com/editorial/profile.json" },
|
|
91
|
-
{ expect: "item_unresolved", name: "network_profile_selector_rejected", selector: "//server/editorial/profile.json" },
|
|
92
|
-
{ expect: "item_unresolved", name: "escaping_profile_selector_rejected", selector: "../editorial/profile.json" },
|
|
93
|
-
{ aliasSelector: true, expect: "item_redirect", name: "symlink_alias_profile_selector_rejected" },
|
|
94
|
-
];
|
|
95
|
-
|
|
96
|
-
function writeFixture(testCase) {
|
|
97
|
-
const root = fs.mkdtempSync(path.join(os.tmpdir(), `stylegallery-reference-profile-${testCase.name}-`));
|
|
98
|
-
const profile = structuredClone(baseProfile);
|
|
99
|
-
const terminalProfile = structuredClone(baseProfile);
|
|
100
|
-
terminalProfile.handoff.record = terminalProfilePath;
|
|
101
|
-
terminalProfile.id = "terminal-reference-profile";
|
|
102
|
-
testCase.mutate?.(profile);
|
|
103
|
-
testCase.mutateTerminal?.(terminalProfile);
|
|
104
|
-
const terminalFoundation = structuredClone(terminalFoundations);
|
|
105
|
-
if (testCase.equalIdentity) terminalFoundation.identity = editorialFoundations.identity;
|
|
106
|
-
const files = {
|
|
107
|
-
"CATALOG.md": "# Catalog\n",
|
|
108
|
-
[profilePath]: `${JSON.stringify(profile, null, 2)}\n`,
|
|
109
|
-
"design-engineering/reference-profiles/governed-local/editorial/local-foundations.json": `${JSON.stringify(editorialFoundations)}\n`,
|
|
110
|
-
"design-engineering/reference-profiles/governed-local/editorial/tokens.dtcg.json": `${JSON.stringify(tokens, null, 2)}\n`,
|
|
111
|
-
[terminalProfilePath]: `${JSON.stringify(terminalProfile, null, 2)}\n`,
|
|
112
|
-
"design-engineering/reference-profiles/governed-local/terminal/local-foundations.json": `${JSON.stringify(testCase.equalFoundations ? editorialFoundations : terminalFoundation)}\n`,
|
|
113
|
-
"design-engineering/reference-profiles/governed-local/terminal/tokens.dtcg.json": `${JSON.stringify(testCase.equalTokens ? tokens : terminalTokens, null, 2)}\n`,
|
|
114
|
-
"layout/index.md": "# Layout\n",
|
|
115
|
-
"patterns/index.md": "# Patterns\n",
|
|
116
|
-
"quality/handoff.md": "Implementation handoff:\nConsumer reference: not_applicable\nConsumer reference reason: This fixture has no consumer-specific reference record.\n",
|
|
117
|
-
"scripts/pattern-data.mjs": testCase.patternData ?? "export const patterns = [];\n",
|
|
118
|
-
};
|
|
119
|
-
if (testCase.externalRecord) files["design-engineering/reference-profiles/external-adaptation/adopter.json"] = "{}\n";
|
|
120
|
-
for (const [relative, content] of Object.entries(files)) {
|
|
121
|
-
const target = path.join(root, relative);
|
|
122
|
-
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
123
|
-
fs.writeFileSync(target, content);
|
|
124
|
-
}
|
|
125
|
-
let externalRoot;
|
|
126
|
-
if (testCase.linkedArtifact) {
|
|
127
|
-
externalRoot = fs.mkdtempSync(path.join(os.tmpdir(), "stylegallery-reference-profile-outside-"));
|
|
128
|
-
const filename = testCase.linkedArtifact === "tokens" ? "tokens.dtcg.json" : "local-foundations.json";
|
|
129
|
-
const target = path.join(root, path.posix.dirname(profilePath), filename);
|
|
130
|
-
const external = path.join(externalRoot, filename);
|
|
131
|
-
fs.writeFileSync(external, files[path.posix.join(path.posix.dirname(profilePath), filename)]);
|
|
132
|
-
fs.rmSync(target);
|
|
133
|
-
fs.symlinkSync(external, target);
|
|
134
|
-
}
|
|
135
|
-
let selector = testCase.selector ?? profilePath;
|
|
136
|
-
if (testCase.absoluteSelector) selector = path.join(root, profilePath);
|
|
137
|
-
if (testCase.aliasSelector) {
|
|
138
|
-
const alias = path.join(root, aliasProfilePath);
|
|
139
|
-
fs.mkdirSync(path.dirname(alias), { recursive: true });
|
|
140
|
-
fs.symlinkSync(path.join(root, profilePath), alias);
|
|
141
|
-
selector = aliasProfilePath;
|
|
142
|
-
}
|
|
143
|
-
return { externalRoot, root, selector };
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
function runCase(testCase) {
|
|
147
|
-
const fixture = writeFixture(testCase);
|
|
148
|
-
try {
|
|
149
|
-
const child = spawnSync(process.execPath, [validator, "--profile", fixture.selector, "--json"], { cwd: fixture.root, encoding: "utf8" });
|
|
150
|
-
const output = JSON.parse(child.stdout);
|
|
151
|
-
const codes = Array.isArray(output.failures) ? output.failures.map((failure) => failure.code) : [];
|
|
152
|
-
const accepted = child.status === 0 && output.ok === true && output.scaffold !== true;
|
|
153
|
-
const rejected = child.status !== 0 && output.ok === false && codes.includes(testCase.expect);
|
|
154
|
-
return {
|
|
155
|
-
actual: { codes, ok: output.ok, status: child.status },
|
|
156
|
-
expected: testCase.expect ?? "ok:true and exit:0",
|
|
157
|
-
name: testCase.name,
|
|
158
|
-
ok: testCase.expect ? rejected : accepted,
|
|
159
|
-
};
|
|
160
|
-
} finally {
|
|
161
|
-
fs.rmSync(fixture.root, { force: true, recursive: true });
|
|
162
|
-
if (fixture.externalRoot) fs.rmSync(fixture.externalRoot, { force: true, recursive: true });
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const results = cases.map(runCase);
|
|
167
|
-
const failures = results.filter((result) => !result.ok).map((result) => `missing_semantic:${result.name}:${result.expected}`);
|
|
168
|
-
const report = { failures, ok: failures.length === 0, results };
|
|
169
|
-
console.log(JSON.stringify(report, null, 2));
|
|
170
|
-
process.exitCode = report.ok ? 0 : 1;
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
|
-
import os from "node:os";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import { spawnSync } from "node:child_process";
|
|
6
|
-
|
|
7
|
-
const root = path.resolve(import.meta.dirname, "..");
|
|
8
|
-
const validator = path.join(root, "scripts", "validate-unity-org-wiki.mjs");
|
|
9
|
-
|
|
10
|
-
function run(cwd) {
|
|
11
|
-
return spawnSync(process.execPath, [validator, "--json"], { cwd, encoding: "utf8" });
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
async function main() {
|
|
15
|
-
const inventoryPath = path.join(root, "game-ui", "unity", "data", "unity-technologies-public-repositories.json");
|
|
16
|
-
const mapPath = path.join(root, "game-ui", "unity", "repository-map.md");
|
|
17
|
-
const wikiPath = path.join(root, "game-ui", "unity", "org-wiki.md");
|
|
18
|
-
const inventoryText = await readFile(inventoryPath, "utf8");
|
|
19
|
-
const inventory = JSON.parse(inventoryText);
|
|
20
|
-
const map = await readFile(mapPath, "utf8");
|
|
21
|
-
const wiki = await readFile(wikiPath, "utf8");
|
|
22
|
-
const tempRoot = await mkdtemp(path.join(os.tmpdir(), "unity-org-wiki-validator-"));
|
|
23
|
-
|
|
24
|
-
try {
|
|
25
|
-
await writeFile(path.join(tempRoot, "inventory.json"), inventoryText);
|
|
26
|
-
await writeFile(path.join(tempRoot, "map.md"), map);
|
|
27
|
-
await writeFile(path.join(tempRoot, "wiki.md"), wiki);
|
|
28
|
-
const fixtures = [
|
|
29
|
-
["wrong count", inventory.slice(1), map, wiki, "expected 804 repositories"],
|
|
30
|
-
["duplicate repository", [...inventory.slice(0, -1), inventory[0]], map, wiki, "duplicate repository identity"],
|
|
31
|
-
["NGUI inside org", [...inventory.slice(0, -1), { ...inventory.at(-1), id: 999999999, full_name: "tasharen/ngui", html_url: "https://github.com/tasharen/ngui" }], map, wiki, "NGUI must remain external"],
|
|
32
|
-
["invalid cluster", [{ ...inventory[0], primary_cluster: "unverified" }, ...inventory.slice(1)], map, wiki, "invalid primary_cluster"],
|
|
33
|
-
["absolute path", inventory, map, `${wiki}\n/Users/example/private\n`, "absolute home path"],
|
|
34
|
-
["wiki data drift", inventory, map, wiki.replaceAll("**804**", "**803**"), "wiki must state the 804-row boundary"],
|
|
35
|
-
["repository map count drift", inventory, map.replace("804 classified rows", "803 classified rows"), wiki, "repository map must state the 804-row boundary"],
|
|
36
|
-
["repository map hash drift", inventory, map.replaceAll("b1438e6e8d438bab3eff2ff02f5a10e9374fdfb89b0581ffb936a42920fa2e05", "0000000000000000000000000000000000000000000000000000000000000000"), wiki, "repository map tracked inventory hash drift"],
|
|
37
|
-
["tracked inventory hash drift", [{ ...inventory[0], stargazers_count: inventory[0].stargazers_count + 1 }, ...inventory.slice(1)], map, wiki, "tracked inventory SHA-256 mismatch"],
|
|
38
|
-
];
|
|
39
|
-
|
|
40
|
-
for (const [name, candidateInventory, candidateMap, candidateWiki, expected] of fixtures) {
|
|
41
|
-
await writeFile(path.join(tempRoot, "inventory.json"), candidateInventory === inventory ? inventoryText : JSON.stringify(candidateInventory));
|
|
42
|
-
await writeFile(path.join(tempRoot, "map.md"), candidateMap);
|
|
43
|
-
await writeFile(path.join(tempRoot, "wiki.md"), candidateWiki);
|
|
44
|
-
const result = spawnSync(process.execPath, [validator, "--json", "--inventory", path.join(tempRoot, "inventory.json"), "--map", path.join(tempRoot, "map.md"), "--wiki", path.join(tempRoot, "wiki.md")], { cwd: root, encoding: "utf8" });
|
|
45
|
-
assert.notEqual(result.status, 0, `${name} fixture unexpectedly passed`);
|
|
46
|
-
assert.match(`${result.stdout}${result.stderr}`, new RegExp(expected.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")), `${name} fixture failed for the wrong reason`);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const result = run(root);
|
|
50
|
-
assert.equal(result.status, 0, result.stderr || result.stdout);
|
|
51
|
-
console.log("Unity org wiki validator fixtures passed: 9 negative, 1 positive.");
|
|
52
|
-
} finally {
|
|
53
|
-
await rm(tempRoot, { recursive: true, force: true });
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
await main();
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import assert from "node:assert/strict";
|
|
4
|
-
import fs from "node:fs";
|
|
5
|
-
import os from "node:os";
|
|
6
|
-
import path from "node:path";
|
|
7
|
-
import { spawnSync } from "node:child_process";
|
|
8
|
-
|
|
9
|
-
const root = path.resolve(import.meta.dirname, "..");
|
|
10
|
-
const validator = path.join(root, "scripts", "validate-unity-source-contracts.mjs");
|
|
11
|
-
const documents = [
|
|
12
|
-
"game-ui/unity/architecture.md",
|
|
13
|
-
"game-ui/unity/cli-loop.md",
|
|
14
|
-
"game-ui/unity/org-wiki.md",
|
|
15
|
-
"game-ui/unity/repository-map.md",
|
|
16
|
-
"game-ui/unity/ui-systems.md",
|
|
17
|
-
];
|
|
18
|
-
const originals = Object.fromEntries(documents.map((relative) => [relative, fs.readFileSync(path.join(root, relative), "utf8")]));
|
|
19
|
-
const fixtures = [
|
|
20
|
-
{
|
|
21
|
-
name: "missing CLI license attribution",
|
|
22
|
-
relative: "game-ui/unity/cli-loop.md",
|
|
23
|
-
mutate: (content) => content.replace(/- Source license:.*\n/, ""),
|
|
24
|
-
expected: "game-ui/unity/cli-loop.md: missing pinned source license",
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
name: "mutable CLI body citation",
|
|
28
|
-
relative: "game-ui/unity/cli-loop.md",
|
|
29
|
-
mutate: (content) => content.replace("https://github.com/hatayama/unity-cli-loop/blob/61a0fe6d7da0aa9d0bcbc6d95944dd069c483ff0/README.md", "https://github.com/hatayama/unity-cli-loop/blob/main/README.md"),
|
|
30
|
-
expected: "game-ui/unity/cli-loop.md: GitHub body citation must use a non-zero 40-character revision: hatayama/unity-cli-loop",
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
name: "zeroed uGUI body revisions",
|
|
34
|
-
relative: "game-ui/unity/ui-systems.md",
|
|
35
|
-
mutate: (content) => content.replaceAll("9edb4420267b6652090ece4c28c38bd98746a68e", "0000000000000000000000000000000000000000"),
|
|
36
|
-
expected: "game-ui/unity/ui-systems.md: GitHub body citation must use a non-zero 40-character revision: Unity-Technologies/uGUI",
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
name: "invalid reviewed date",
|
|
40
|
-
relative: "game-ui/unity/architecture.md",
|
|
41
|
-
mutate: (content) => content.replace("reviewed_on: 2026-07-14", "reviewed_on: never"),
|
|
42
|
-
expected: "game-ui/unity/architecture.md: reviewed_on must be an ISO calendar date",
|
|
43
|
-
},
|
|
44
|
-
];
|
|
45
|
-
|
|
46
|
-
function writeFixture(fixture) {
|
|
47
|
-
const directory = fs.mkdtempSync(path.join(os.tmpdir(), "unity-source-contracts-"));
|
|
48
|
-
for (const [relative, content] of Object.entries(originals)) {
|
|
49
|
-
const target = path.join(directory, relative);
|
|
50
|
-
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
51
|
-
fs.writeFileSync(target, relative === fixture.relative ? fixture.mutate(content) : content);
|
|
52
|
-
}
|
|
53
|
-
return directory;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
for (const fixture of fixtures) {
|
|
57
|
-
const directory = writeFixture(fixture);
|
|
58
|
-
const result = spawnSync(process.execPath, [validator, "--json", "--root", directory], { encoding: "utf8" });
|
|
59
|
-
fs.rmSync(directory, { force: true, recursive: true });
|
|
60
|
-
assert.notEqual(result.status, 0, `${fixture.name} unexpectedly passed`);
|
|
61
|
-
const output = JSON.parse(result.stdout);
|
|
62
|
-
assert(output.failures.includes(fixture.expected), `${fixture.name} failed for the wrong reason: ${result.stdout}`);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const positive = spawnSync(process.execPath, [validator, "--json"], { cwd: root, encoding: "utf8" });
|
|
66
|
-
assert.equal(positive.status, 0, positive.stderr || positive.stdout);
|
|
67
|
-
console.log("Unity source contract fixtures passed: 4 negative, 1 positive.");
|