stylegallery 0.1.0 → 0.1.1
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 +23 -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 +51 -0
- package/package.json +181 -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,288 +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 Ajv2020 from "ajv/dist/2020.js";
|
|
8
|
-
import { isPlainObject, validateItemSchema } from "./consumer-reference-schema.mjs";
|
|
9
|
-
import { canonicalGovernedProfilePaths } from "./governed-profile-registry.mjs";
|
|
10
|
-
import { validateReferenceProfile, validateReferenceProfileSet } from "./reference-profile-contract.mjs";
|
|
11
|
-
|
|
12
|
-
const root = process.cwd();
|
|
13
|
-
const repositoryRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
14
|
-
const conformanceValidator = path.join(repositoryRoot, "scripts", "validate-consumer-conformance.mjs");
|
|
15
|
-
const schema = JSON.parse(fs.readFileSync(path.join(repositoryRoot, "consumer-reference", "schema", "item.schema.json"), "utf8"));
|
|
16
|
-
const validateFullItemSchema = new Ajv2020({ allErrors: true, strict: false }).compile(schema);
|
|
17
|
-
const failures = [];
|
|
18
|
-
const warnings = [];
|
|
19
|
-
const canonicalProfilePaths = canonicalGovernedProfilePaths;
|
|
20
|
-
const defaultItems = [
|
|
21
|
-
"consumer-reference/fixtures/valid-experimental.json",
|
|
22
|
-
"consumer-reference/fixtures/valid-deprecated.json",
|
|
23
|
-
...canonicalProfilePaths,
|
|
24
|
-
];
|
|
25
|
-
const reverseMarkers = ["consumerreference", "designengineeringreferenceprofiles", "profilejson", "tokensdtcgjson", "relatedfixturesetid"];
|
|
26
|
-
const profileSummaries = [];
|
|
27
|
-
let checkedMigrationRecords = 0;
|
|
28
|
-
|
|
29
|
-
function addFailure(code, relative, message) {
|
|
30
|
-
failures.push({ code, message, path: relative });
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function canonicalProfileIdentity(selected) {
|
|
34
|
-
if (selected.startsWith("//")
|
|
35
|
-
|| selected.startsWith("\\\\")
|
|
36
|
-
|| path.posix.isAbsolute(selected)
|
|
37
|
-
|| path.win32.isAbsolute(selected)
|
|
38
|
-
|| /^[A-Za-z][A-Za-z\d+.-]*:/.test(selected)
|
|
39
|
-
|| selected.includes("\\")
|
|
40
|
-
|| selected.includes("?")
|
|
41
|
-
|| selected.includes("#")) return null;
|
|
42
|
-
const normalized = path.posix.normalize(selected);
|
|
43
|
-
if (normalized === ".." || normalized.startsWith("../") || !isInside(root, path.resolve(root, normalized))) return null;
|
|
44
|
-
return canonicalProfilePaths.includes(normalized) ? normalized : null;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function isInside(base, target) {
|
|
48
|
-
const relative = path.relative(base, target);
|
|
49
|
-
return relative === "" || (!relative.startsWith(`..${path.sep}`) && relative !== ".." && !path.isAbsolute(relative));
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function parseArguments() {
|
|
53
|
-
const items = [];
|
|
54
|
-
let json = false;
|
|
55
|
-
for (let index = 2; index < process.argv.length; index += 1) {
|
|
56
|
-
const argument = process.argv[index];
|
|
57
|
-
if (argument === "--json") {
|
|
58
|
-
json = true;
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
if (argument === "--item" || argument === "--profile") {
|
|
62
|
-
const value = process.argv[index + 1];
|
|
63
|
-
if (!value || value.startsWith("--")) {
|
|
64
|
-
addFailure("argument_value_required", "<cli>", `${argument} requires a repository-relative JSON path`);
|
|
65
|
-
} else {
|
|
66
|
-
items.push(value);
|
|
67
|
-
index += 1;
|
|
68
|
-
}
|
|
69
|
-
continue;
|
|
70
|
-
}
|
|
71
|
-
addFailure("argument_unknown", "<cli>", `unsupported argument ${argument}`);
|
|
72
|
-
}
|
|
73
|
-
const selected = items.length > 0 ? items : defaultItems;
|
|
74
|
-
const canonicalized = selected.map((item) => canonicalProfileIdentity(item) ?? item);
|
|
75
|
-
const requiresCanonicalPair = canonicalized.some((item) => canonicalProfilePaths.includes(item));
|
|
76
|
-
return { items: requiresCanonicalPair ? [...new Set([...canonicalized, ...canonicalProfilePaths])] : canonicalized, json };
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function validateRecordPath(record, itemPath, prefix = "record") {
|
|
80
|
-
const reject = (suffix, message) => addFailure(`${prefix}_${suffix}`, itemPath, message);
|
|
81
|
-
if (typeof record !== "string" || record.length === 0) {
|
|
82
|
-
reject("required", "declared handoff requires record");
|
|
83
|
-
return undefined;
|
|
84
|
-
}
|
|
85
|
-
if (record.startsWith("//") || record.startsWith("\\\\")) {
|
|
86
|
-
reject("network_path", "record must not use a network path");
|
|
87
|
-
return undefined;
|
|
88
|
-
}
|
|
89
|
-
if (path.posix.isAbsolute(record) || path.win32.isAbsolute(record)) {
|
|
90
|
-
reject("absolute", "record must be repository-relative");
|
|
91
|
-
return undefined;
|
|
92
|
-
}
|
|
93
|
-
if (/^[A-Za-z][A-Za-z\d+.-]*:/.test(record)) {
|
|
94
|
-
reject("uri_scheme", "record must not use a URI scheme");
|
|
95
|
-
return undefined;
|
|
96
|
-
}
|
|
97
|
-
if (record.split(/[\\/]/).includes("..")) {
|
|
98
|
-
reject("parent_segment", "record must not contain a parent segment");
|
|
99
|
-
return undefined;
|
|
100
|
-
}
|
|
101
|
-
if (record.includes("\\") || record.includes("?") || record.includes("#") || path.posix.normalize(record) !== record || record.startsWith("./")) {
|
|
102
|
-
reject("not_normalized", "record must be a normalized POSIX repository path");
|
|
103
|
-
return undefined;
|
|
104
|
-
}
|
|
105
|
-
if (!record.endsWith(".json")) {
|
|
106
|
-
reject("not_json", "record must target a JSON file");
|
|
107
|
-
return undefined;
|
|
108
|
-
}
|
|
109
|
-
const target = path.resolve(root, record);
|
|
110
|
-
if (!isInside(root, target)) {
|
|
111
|
-
reject("escape", "record resolves outside the repository root");
|
|
112
|
-
return undefined;
|
|
113
|
-
}
|
|
114
|
-
if (!fs.existsSync(target) || !fs.statSync(target).isFile()) {
|
|
115
|
-
reject("unresolved", `record does not resolve: ${record}`);
|
|
116
|
-
return undefined;
|
|
117
|
-
}
|
|
118
|
-
const realRoot = fs.realpathSync(root);
|
|
119
|
-
const realTarget = fs.realpathSync(target);
|
|
120
|
-
if (!isInside(realRoot, realTarget)) {
|
|
121
|
-
reject("symlink_escape", "record resolves through a symlink outside the repository root");
|
|
122
|
-
return undefined;
|
|
123
|
-
}
|
|
124
|
-
if (realTarget !== path.join(realRoot, record)) {
|
|
125
|
-
reject("redirect", "record must not resolve through a filesystem redirect");
|
|
126
|
-
return undefined;
|
|
127
|
-
}
|
|
128
|
-
try {
|
|
129
|
-
return { record, value: JSON.parse(fs.readFileSync(realTarget, "utf8")) };
|
|
130
|
-
} catch (error) {
|
|
131
|
-
if (error instanceof SyntaxError) {
|
|
132
|
-
reject("invalid_json", `record is not valid JSON: ${record}`);
|
|
133
|
-
return undefined;
|
|
134
|
-
}
|
|
135
|
-
throw error;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function runMigrationConformance(packet, relative) {
|
|
140
|
-
const args = [conformanceValidator, "--root", root, "--record", packet.record];
|
|
141
|
-
const manifest = packet.value?.page_evidence?.status === "applicable" ? packet.value.page_evidence.manifest : undefined;
|
|
142
|
-
if (typeof manifest === "string") args.push("--artifact-root", path.posix.dirname(manifest));
|
|
143
|
-
args.push("--json");
|
|
144
|
-
checkedMigrationRecords += 1;
|
|
145
|
-
const child = spawnSync(process.execPath, args, { cwd: repositoryRoot, encoding: "utf8" });
|
|
146
|
-
let report;
|
|
147
|
-
try { report = JSON.parse(child.stdout); }
|
|
148
|
-
catch (error) {
|
|
149
|
-
addFailure("migration_conformance_validator_output_invalid", relative, error instanceof Error ? error.message : String(error));
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
const childFailures = Array.isArray(report.failures) ? report.failures : [];
|
|
153
|
-
for (const failure of childFailures) {
|
|
154
|
-
addFailure(
|
|
155
|
-
typeof failure?.code === "string" ? failure.code : "migration_conformance_validator_output_invalid",
|
|
156
|
-
typeof failure?.path === "string" ? failure.path : relative,
|
|
157
|
-
typeof failure?.message === "string" ? failure.message : "consumer conformance validator returned a malformed finding",
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
if (child.status !== 0 && childFailures.length === 0) addFailure("migration_conformance_validator_failed", relative, "consumer conformance validator exited without a finding");
|
|
161
|
-
if (child.status === 0 && report.ok !== true) addFailure("migration_conformance_validator_output_invalid", relative, "consumer conformance validator exited zero without ok:true");
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
function validateHandoff(item, relative) {
|
|
165
|
-
if (isPlainObject(item.handoff) && item.handoff.status === "declared") validateRecordPath(item.handoff.record, relative);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
function validateItem(relative) {
|
|
169
|
-
const absolute = path.resolve(root, relative);
|
|
170
|
-
if (path.isAbsolute(relative) || path.win32.isAbsolute(relative) || !isInside(root, absolute) || !relative.endsWith(".json") || !fs.existsSync(absolute)) {
|
|
171
|
-
addFailure("item_unresolved", relative, "item must be an existing repository-relative JSON file");
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
const realRoot = fs.realpathSync(root);
|
|
175
|
-
const realAbsolute = fs.realpathSync(absolute);
|
|
176
|
-
if (!isInside(realRoot, realAbsolute)) {
|
|
177
|
-
addFailure("item_symlink_escape", relative, "item resolves through a symlink outside the repository root");
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
if (realAbsolute !== path.join(realRoot, relative)) {
|
|
181
|
-
addFailure("item_redirect", relative, "item must not resolve through a filesystem redirect");
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
let item;
|
|
185
|
-
try {
|
|
186
|
-
item = JSON.parse(fs.readFileSync(realAbsolute, "utf8"));
|
|
187
|
-
} catch (error) {
|
|
188
|
-
if (error instanceof SyntaxError) {
|
|
189
|
-
addFailure("item_invalid_json", relative, "item must contain valid JSON");
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
throw error;
|
|
193
|
-
}
|
|
194
|
-
if (!validateFullItemSchema(item)) {
|
|
195
|
-
for (const error of validateFullItemSchema.errors ?? []) addFailure("item_schema_invalid", relative, `${error.instancePath || "/"} ${error.message}`);
|
|
196
|
-
}
|
|
197
|
-
for (const finding of validateItemSchema(item, schema)) addFailure(finding.code, relative, finding.message);
|
|
198
|
-
if (!isPlainObject(item)) return;
|
|
199
|
-
validateHandoff(item, relative);
|
|
200
|
-
if (/^design-engineering\/reference-profiles\/governed-local\/[^/]+\/profile\.json$/.test(relative)) {
|
|
201
|
-
const result = validateReferenceProfile({ item, relative, root });
|
|
202
|
-
for (const finding of result.failures) addFailure(finding.code, finding.path, finding.message);
|
|
203
|
-
if (result.summary) profileSummaries.push(result.summary);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
function walkFiles(relative) {
|
|
208
|
-
const absolute = path.join(root, relative);
|
|
209
|
-
if (!fs.existsSync(absolute)) return [];
|
|
210
|
-
if (fs.statSync(absolute).isFile()) return [relative];
|
|
211
|
-
return fs.readdirSync(absolute, { withFileTypes: true }).flatMap((entry) => {
|
|
212
|
-
if ([".git", ".omo", "node_modules"].includes(entry.name)) return [];
|
|
213
|
-
return walkFiles(path.join(relative, entry.name));
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
function rejectReverseImports() {
|
|
218
|
-
const guarded = ["layout", "patterns", "scripts/pattern-data.mjs", "CATALOG.md"];
|
|
219
|
-
for (const relative of guarded.flatMap(walkFiles)) {
|
|
220
|
-
const compact = fs.readFileSync(path.join(root, relative), "utf8").toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
221
|
-
if (reverseMarkers.some((marker) => compact.includes(marker))) {
|
|
222
|
-
addFailure("reverse_import", relative, "Layout and generated corpus must not import consumer reference artifacts");
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
function rejectExternalAdaptationRecords() {
|
|
228
|
-
const directory = "design-engineering/reference-profiles/external-adaptation";
|
|
229
|
-
for (const relative of walkFiles(directory).filter((file) => file.endsWith(".json"))) {
|
|
230
|
-
addFailure("external_adaptation_record_forbidden", relative, "external adaptation has documentation and synthetic validator coverage only");
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
function isSentence(reason) {
|
|
235
|
-
const variants = schema.properties.handoff.oneOf;
|
|
236
|
-
const definition = variants.find((candidate) => candidate.properties.status.const === "not_applicable").properties.reason;
|
|
237
|
-
return reason.length >= definition.minLength && new RegExp(definition.pattern).test(reason);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
function validateHandoffCoverage() {
|
|
241
|
-
let checked = 0;
|
|
242
|
-
for (const relative of walkFiles(".").filter((file) => file.endsWith(".md"))) {
|
|
243
|
-
const lines = fs.readFileSync(path.join(root, relative), "utf8").split("\n");
|
|
244
|
-
for (let index = 0; index < lines.length; index += 1) {
|
|
245
|
-
if (!/Implementation handoff:/i.test(lines[index])) continue;
|
|
246
|
-
checked += 1;
|
|
247
|
-
const window = lines.slice(index, index + 7).join("\n").replaceAll("`", "");
|
|
248
|
-
const status = window.match(/Consumer reference:\s*(declared|not_applicable)/i)?.[1];
|
|
249
|
-
if (!status) {
|
|
250
|
-
addFailure("handoff_consumer_reference_required", relative, `implementation handoff at line ${index + 1} requires Consumer reference`);
|
|
251
|
-
} else if (status === "not_applicable") {
|
|
252
|
-
const reason = window.match(/Consumer reference reason:\s*([^\n]+)/i)?.[1]?.trim();
|
|
253
|
-
if (!reason || !isSentence(reason)) addFailure("handoff_consumer_reason_sentence", relative, `not_applicable handoff at line ${index + 1} requires a sentence reason`);
|
|
254
|
-
} else if (!/Consumer reference record:\s*\S+\.json/i.test(window)) {
|
|
255
|
-
addFailure("handoff_consumer_record_required", relative, `declared handoff at line ${index + 1} requires one JSON record`);
|
|
256
|
-
}
|
|
257
|
-
const migrationDeclarations = [...window.matchAll(/^Consumer migration conformance:\s*(\S+)\s*$/gim)];
|
|
258
|
-
const migrationRecords = [...window.matchAll(/^Consumer migration conformance record:\s*([^\n]+)\s*$/gim)];
|
|
259
|
-
if (migrationDeclarations.length === 0 && migrationRecords.length > 0) {
|
|
260
|
-
addFailure("migration_conformance_declaration_required", relative, `migration record at line ${index + 1} requires an exact declared conformance field`);
|
|
261
|
-
} else if (migrationDeclarations.length > 0) {
|
|
262
|
-
if (migrationDeclarations.length !== 1 || migrationDeclarations[0][1].toLowerCase() !== "declared") {
|
|
263
|
-
addFailure("migration_conformance_status_invalid", relative, `migration handoff at line ${index + 1} accepts exactly one declared status`);
|
|
264
|
-
} else if (migrationRecords.length !== 1) {
|
|
265
|
-
addFailure("migration_conformance_record_required", relative, `declared migration handoff at line ${index + 1} requires exactly one JSON record`);
|
|
266
|
-
} else {
|
|
267
|
-
const packet = validateRecordPath(migrationRecords[0][1].trim(), relative, "migration_conformance_record");
|
|
268
|
-
if (packet) runMigrationConformance(packet, relative);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
return checked;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
const options = parseArguments();
|
|
277
|
-
for (const item of options.items) validateItem(item);
|
|
278
|
-
rejectReverseImports();
|
|
279
|
-
rejectExternalAdaptationRecords();
|
|
280
|
-
for (const finding of validateReferenceProfileSet(profileSummaries)) addFailure(finding.code, finding.path, finding.message);
|
|
281
|
-
const checkedHandoffs = validateHandoffCoverage();
|
|
282
|
-
|
|
283
|
-
const uniqueFailures = [...new Map(failures.map((failure) => [`${failure.code}:${failure.path}:${failure.message}`, failure])).values()];
|
|
284
|
-
const result = { checkedHandoffs, checkedItems: options.items.length, checkedMigrationRecords, failures: uniqueFailures, ok: uniqueFailures.length === 0, profiles: profileSummaries, warnings };
|
|
285
|
-
if (options.json) console.log(JSON.stringify(result, null, 2));
|
|
286
|
-
else if (result.ok) console.log(`ok: ${result.checkedItems} consumer reference items`);
|
|
287
|
-
else console.error(result.failures.map((failure) => `${failure.code}: ${failure.path}: ${failure.message}`).join("\n"));
|
|
288
|
-
process.exitCode = result.ok ? 0 : 1;
|
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import fs from "node:fs";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import { fileURLToPath } from "node:url";
|
|
6
|
-
import { collectDomainBoundaryFailures } from "./domain-document-boundaries.mjs";
|
|
7
|
-
import { createDomainValidationChecks } from "./domain-validation-checks.mjs";
|
|
8
|
-
import { structuralMarkdown } from "./markdown-structure.mjs";
|
|
9
|
-
|
|
10
|
-
const repository = "https://github.com/emilkowalski/skills";
|
|
11
|
-
const revision = "220e8607c90b17337d210125777b7b695f26c221";
|
|
12
|
-
const revisionPattern = /^[0-9a-f]{40}$/;
|
|
13
|
-
const referenceDocuments = [
|
|
14
|
-
"design-engineering/reference-profiles/index.md",
|
|
15
|
-
"design-engineering/reference-profiles/governed-local/index.md",
|
|
16
|
-
"design-engineering/reference-profiles/external-adaptation/index.md",
|
|
17
|
-
];
|
|
18
|
-
const requiredCrossDomainStrings = [
|
|
19
|
-
{
|
|
20
|
-
relative: "guides/vocabulary.md",
|
|
21
|
-
required: "Use for: Layout, Motion, Design Engineering, Game UI, Platform Guides, root routing, and `domain` frontmatter on governed leaves.",
|
|
22
|
-
failure: "guides/vocabulary.md: missing canonical five-domain vocabulary list",
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
relative: "quality/index.md",
|
|
26
|
-
required: "`quality/` is shared StyleGallery infrastructure for deciding whether Layout, Motion, Design Engineering, Game UI, and Platform Guides claims are admissible.",
|
|
27
|
-
failure: "quality/index.md: missing canonical five-domain quality scope",
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
relative: "README.md",
|
|
31
|
-
required: "without owning profiles, visual values, components, or a sixth domain",
|
|
32
|
-
failure: "README.md: missing canonical Consumer Reference boundary",
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
relative: "quality/index.md",
|
|
36
|
-
required: "without classifying it as a sixth domain",
|
|
37
|
-
failure: "quality/index.md: missing canonical Consumer Reference boundary",
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
relative: "quality/evidence/executable-evidence.md",
|
|
41
|
-
required: "Five governed domains and their declared leaves are reachable and attributed.",
|
|
42
|
-
failure: "quality/evidence/executable-evidence.md: missing canonical five-domain validator coverage",
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
relative: "quality/index.md",
|
|
46
|
-
required: "| Find the authority route for uGUI, UI Toolkit, or NGUI. | [README](../README.md) | [Unity UI Systems](../game-ui/unity/ui-systems.md) | The first selected route is Game UI, and the system-specific source and version boundary is reached within three hops. |",
|
|
47
|
-
failure: "quality/index.md: missing Game UI findability QA scenario",
|
|
48
|
-
},
|
|
49
|
-
];
|
|
50
|
-
|
|
51
|
-
export const canonicalDomains = [
|
|
52
|
-
{ slug: "layout", label: "Layout", leaves: [] },
|
|
53
|
-
{
|
|
54
|
-
slug: "motion",
|
|
55
|
-
label: "Motion",
|
|
56
|
-
leaves: [
|
|
57
|
-
{ path: "motion/vocabulary.md", provenance: "external", sourcePath: "skills/animation-vocabulary/SKILL.md" },
|
|
58
|
-
{ path: "motion/review-workflow.md", provenance: "external", sourcePath: "skills/review-animations/SKILL.md" },
|
|
59
|
-
{ path: "motion/practice-reference.md", provenance: "external", sourcePath: "skills/review-animations/STANDARDS.md" },
|
|
60
|
-
],
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
slug: "design-engineering",
|
|
64
|
-
label: "Design Engineering",
|
|
65
|
-
leaves: [
|
|
66
|
-
{ path: "design-engineering/interface-craft.md", provenance: "external", sourcePath: "skills/emil-design-eng/SKILL.md" },
|
|
67
|
-
{ path: "design-engineering/consumer-migration-readiness.md", provenance: "local" },
|
|
68
|
-
],
|
|
69
|
-
referenceDocuments,
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
slug: "game-ui",
|
|
73
|
-
label: "Game UI",
|
|
74
|
-
leaves: [
|
|
75
|
-
{ path: "game-ui/classification.md", provenance: "repository" },
|
|
76
|
-
{ path: "game-ui/screen-hierarchy.md", provenance: "repository" },
|
|
77
|
-
{ path: "game-ui/reference-record.md", provenance: "repository" },
|
|
78
|
-
{ path: "game-ui/unity/architecture.md", provenance: "external", sourcePath: "README.md" },
|
|
79
|
-
{ path: "game-ui/unity/ui-systems.md", provenance: "repository" },
|
|
80
|
-
{ path: "game-ui/unity/cli-loop.md", provenance: "external", sourcePath: "README.md" },
|
|
81
|
-
{ path: "game-ui/unity/repository-map.md", provenance: "repository" },
|
|
82
|
-
{ path: "game-ui/unity/org-wiki.md", provenance: "repository" },
|
|
83
|
-
],
|
|
84
|
-
},
|
|
85
|
-
{ slug: "platform-guides", label: "Platform Guides", leaves: [{ path: "platform-guides/apple-interaction.md", provenance: "external", sourcePath: "skills/apple-design/SKILL.md" }] },
|
|
86
|
-
];
|
|
87
|
-
export const domainRegistry = canonicalDomains;
|
|
88
|
-
|
|
89
|
-
let domains = canonicalDomains;
|
|
90
|
-
let root = process.cwd();
|
|
91
|
-
let failures = [];
|
|
92
|
-
|
|
93
|
-
const sourceOverrides = {
|
|
94
|
-
"game-ui/unity/architecture.md": {
|
|
95
|
-
repository: "https://github.com/annulusgames/UGUIAnimationSamples",
|
|
96
|
-
revision: "343c8110e5683be209cc01ccb4cb986175e61643",
|
|
97
|
-
},
|
|
98
|
-
"game-ui/unity/cli-loop.md": {
|
|
99
|
-
repository: "https://github.com/hatayama/unity-cli-loop",
|
|
100
|
-
revision: "61a0fe6d7da0aa9d0bcbc6d95944dd069c483ff0",
|
|
101
|
-
},
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
const requiredLeafSections = [
|
|
105
|
-
"Repository Boundary",
|
|
106
|
-
"Reusable Method",
|
|
107
|
-
"Opinionated Guidance",
|
|
108
|
-
"Platform-Specific Guidance",
|
|
109
|
-
"Unsupported Absolutes",
|
|
110
|
-
"Verification Contract",
|
|
111
|
-
"Source, License, And Attribution",
|
|
112
|
-
"IA Navigation",
|
|
113
|
-
];
|
|
114
|
-
|
|
115
|
-
function read(relative) {
|
|
116
|
-
const target = path.join(root, relative);
|
|
117
|
-
if (!fs.existsSync(target)) {
|
|
118
|
-
failures.push(`${relative}: missing file`);
|
|
119
|
-
return "";
|
|
120
|
-
}
|
|
121
|
-
return fs.readFileSync(target, "utf8");
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function requireRootRoutes() {
|
|
125
|
-
for (const relative of ["README.md", "index.md"]) {
|
|
126
|
-
const content = structuralMarkdown(read(relative));
|
|
127
|
-
for (const domain of domains) {
|
|
128
|
-
const route = `[${domain.label}](${domain.slug}/index.md)`;
|
|
129
|
-
if (!content.includes(route)) failures.push(`${relative}: missing ${route}`);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function requireCrossDomainConsistency() {
|
|
135
|
-
for (const check of requiredCrossDomainStrings) {
|
|
136
|
-
const content = structuralMarkdown(read(check.relative));
|
|
137
|
-
if (!content.includes(check.required)) failures.push(check.failure);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function checkManifest() {
|
|
142
|
-
const relative = "DOMAINS.md";
|
|
143
|
-
const content = structuralMarkdown(read(relative));
|
|
144
|
-
const section = (heading) => content.split(`${heading}\n`)[1]?.split("\n## ")[0] ?? "";
|
|
145
|
-
const tableRows = (body) => {
|
|
146
|
-
const rows = body.split("\n").filter((line) => /^\s*\|.*\|\s*$/.test(line)).map((line) => line.trim().slice(1, -1).split("|").map((cell) => cell.trim()));
|
|
147
|
-
return rows.filter((row) => !row.every((cell) => /^:?-+:?$/.test(cell))).slice(1);
|
|
148
|
-
};
|
|
149
|
-
const domainRows = tableRows(section("## Domain Contract"));
|
|
150
|
-
const pageRows = tableRows(section("## Page Manifest"));
|
|
151
|
-
const expectedLabels = new Set(domains.map((domain) => domain.label));
|
|
152
|
-
const exactLabels = (rows) => rows.length === domains.length && new Set(rows.map((row) => row[0])).size === domains.length && rows.every((row) => expectedLabels.has(row[0]));
|
|
153
|
-
let valid = exactLabels(domainRows)
|
|
154
|
-
&& exactLabels(pageRows)
|
|
155
|
-
&& content.includes(`snapshot \`${revision}\``)
|
|
156
|
-
&& content.includes("## Shared Non-Domain Infrastructure")
|
|
157
|
-
&& content.includes("[Consumer Reference](consumer-reference/index.md)")
|
|
158
|
-
&& content.includes("infrastructure outside the five-domain contract")
|
|
159
|
-
&& content.includes("cannot add a sixth domain row");
|
|
160
|
-
|
|
161
|
-
for (const domain of domains) {
|
|
162
|
-
const domainRow = domainRows.find((row) => row[0] === domain.label);
|
|
163
|
-
const pageRow = pageRows.find((row) => row[0] === domain.label);
|
|
164
|
-
const expectedLifecycle = domain.slug === "layout" ? "`stable` and `generated`" : "`experimental`";
|
|
165
|
-
const expectedHub = `[${domain.label}](${domain.slug}/index.md)`;
|
|
166
|
-
const expectedManualHub = `\`${domain.slug}/index.md\``;
|
|
167
|
-
if (!domainRow || domainRow[1] !== expectedHub || domainRow[2] !== expectedLifecycle) valid = false;
|
|
168
|
-
if (!pageRow || pageRow[1] !== expectedManualHub) valid = false;
|
|
169
|
-
if (domain.leaves.length > 0 && pageRow) {
|
|
170
|
-
const declaredLeaves = [...pageRow[2].matchAll(/`([^`]+\.md)`/g)].map((match) => match[1]).sort();
|
|
171
|
-
const expectedLeaves = [...domain.leaves.map((leaf) => leaf.path), ...(domain.referenceDocuments ?? [])].sort();
|
|
172
|
-
if (JSON.stringify(declaredLeaves) !== JSON.stringify(expectedLeaves)) valid = false;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
if (!valid) {
|
|
177
|
-
failures.push(`${relative}: missing canonical domain contract`);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
function boundaryRegistry(registry) {
|
|
182
|
-
return registry.map((domain) => ({
|
|
183
|
-
...domain,
|
|
184
|
-
leaves: domain.leaves.map((leaf) => [leaf.path, leaf.sourcePath]),
|
|
185
|
-
}));
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
export function validateDomains({ root: nextRoot = process.cwd(), domains: nextDomains = canonicalDomains } = {}) {
|
|
189
|
-
const previousRoot = root;
|
|
190
|
-
const previousDomains = domains;
|
|
191
|
-
const previousFailures = failures;
|
|
192
|
-
root = nextRoot;
|
|
193
|
-
domains = nextDomains;
|
|
194
|
-
failures = [];
|
|
195
|
-
const { checkIndex, checkLeaf, checkReferenceDocuments, checkPromotionBoundary } = createDomainValidationChecks({
|
|
196
|
-
domains,
|
|
197
|
-
failures,
|
|
198
|
-
read,
|
|
199
|
-
referenceDocuments,
|
|
200
|
-
repository,
|
|
201
|
-
revision,
|
|
202
|
-
revisionPattern,
|
|
203
|
-
requiredLeafSections,
|
|
204
|
-
sourceOverrides,
|
|
205
|
-
});
|
|
206
|
-
checkManifest();
|
|
207
|
-
read("quality/claim-records/stylegallery-multidomain-scope.md");
|
|
208
|
-
requireRootRoutes();
|
|
209
|
-
requireCrossDomainConsistency();
|
|
210
|
-
const titles = new Set();
|
|
211
|
-
let checkedLeaves = 0;
|
|
212
|
-
for (const domain of domains) {
|
|
213
|
-
checkIndex(domain);
|
|
214
|
-
for (const leaf of domain.leaves) {
|
|
215
|
-
checkedLeaves += 1;
|
|
216
|
-
checkLeaf(domain, leaf, titles);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
failures.push(...collectDomainBoundaryFailures(root, boundaryRegistry(domains)));
|
|
220
|
-
checkReferenceDocuments();
|
|
221
|
-
checkPromotionBoundary();
|
|
222
|
-
|
|
223
|
-
const result = { ok: failures.length === 0, checkedDomains: domains.length, checkedLeaves, failures: [...new Set(failures)] };
|
|
224
|
-
root = previousRoot;
|
|
225
|
-
domains = previousDomains;
|
|
226
|
-
failures = previousFailures;
|
|
227
|
-
return result;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
const isMainModule = process.argv[1] && path.resolve(process.argv[1]) === path.resolve(fileURLToPath(import.meta.url));
|
|
231
|
-
if (isMainModule) {
|
|
232
|
-
const result = validateDomains();
|
|
233
|
-
if (process.argv.includes("--json")) console.log(JSON.stringify(result, null, 2));
|
|
234
|
-
else if (result.ok) console.log(`ok: ${result.checkedDomains} domains, ${result.checkedLeaves} governed leaves`);
|
|
235
|
-
else console.error(result.failures.join("\n"));
|
|
236
|
-
process.exitCode = result.ok ? 0 : 1;
|
|
237
|
-
}
|