@usefragments/core 1.10.2 → 1.11.0
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/dist/{chunk-MZ4SW3TP.js → chunk-3IOWHECM.js} +8 -1
- package/dist/{chunk-MZ4SW3TP.js.map → chunk-3IOWHECM.js.map} +1 -1
- package/dist/chunk-7ULGH74M.js +66 -0
- package/dist/chunk-7ULGH74M.js.map +1 -0
- package/dist/{chunk-YF65VYRY.js → chunk-ML5S6QNU.js} +191 -169
- package/dist/chunk-ML5S6QNU.js.map +1 -0
- package/dist/chunk-PWIJMOI4.js +202 -0
- package/dist/chunk-PWIJMOI4.js.map +1 -0
- package/dist/{chunk-XN3LSDPY.js → chunk-RPSEABY3.js} +622 -344
- package/dist/chunk-RPSEABY3.js.map +1 -0
- package/dist/chunk-RYFULE43.js +578 -0
- package/dist/chunk-RYFULE43.js.map +1 -0
- package/dist/codes/index.d.ts +2 -2
- package/dist/codes/index.js +3 -2
- package/dist/compiled-types/index.d.ts +327 -2
- package/dist/compiled-types/index.js +1 -1
- package/dist/generate/index.d.ts +3 -2
- package/dist/{governance-CLk_wkP9.d.ts → governance-BAsy1k2H.d.ts} +472 -513
- package/dist/governance-telemetry.d.ts +6 -0
- package/dist/governance-telemetry.js +1 -1
- package/dist/{index-_sxhUNqx.d.ts → index-C8bcXVav.d.ts} +448 -448
- package/dist/index.d.ts +9165 -1297
- package/dist/index.js +3041 -350
- package/dist/index.js.map +1 -1
- package/dist/manifest.d.ts +228 -0
- package/dist/manifest.js +24 -0
- package/dist/manifest.js.map +1 -0
- package/dist/preview/index.js +45 -1
- package/dist/preview/index.js.map +1 -1
- package/dist/preview-runtime.d.ts +1 -2
- package/dist/preview-runtime.js +150 -14
- package/dist/preview-runtime.js.map +1 -1
- package/dist/react-types.d.ts +1 -2
- package/dist/registry.d.ts +1412 -203
- package/dist/registry.js +30 -3
- package/dist/schemas/index.d.ts +1 -1
- package/dist/schemas/index.js +3 -2
- package/dist/storyAdapter.d.ts +1 -2
- package/dist/storyAdapter.js +11 -49
- package/dist/storyAdapter.js.map +1 -1
- package/dist/test-utils.d.ts +3 -2
- package/package.json +8 -2
- package/src/__tests__/contract-parser.test.ts +318 -277
- package/src/__tests__/preview-runtime-hook.test.tsx +315 -0
- package/src/__tests__/preview-runtime.test.tsx +30 -8
- package/src/__tests__/schema.test.ts +191 -14
- package/src/analysis-plan/analysis-plan-v1.test.ts +320 -0
- package/src/analysis-plan/coverage.ts +181 -0
- package/src/analysis-plan/digest.ts +141 -0
- package/src/analysis-plan/index.ts +34 -0
- package/src/analysis-plan/types.ts +207 -0
- package/src/codes/__tests__/codes.test.ts +9 -0
- package/src/codes/codes.ts +30 -0
- package/src/compiled-types/index.ts +640 -39
- package/src/compiled-types/parse.test.ts +145 -4
- package/src/component-contract.ts +95 -53
- package/src/composition.ts +7 -13
- package/src/constants.ts +3 -6
- package/src/contract/hash.test.ts +20 -0
- package/src/contract/hash.ts +66 -9
- package/src/contract/index.ts +24 -1
- package/src/contract/manifest.test.ts +94 -0
- package/src/contract/manifest.ts +68 -0
- package/src/contract/preimage.test.ts +219 -1
- package/src/contract/preimage.ts +326 -6
- package/src/contract/stamp.test.ts +3 -0
- package/src/contract/stamp.ts +1 -1
- package/src/contract-parser.ts +54 -30
- package/src/defineFragment.test.ts +476 -91
- package/src/defineFragment.ts +204 -114
- package/src/domain-ids.test.ts +52 -0
- package/src/domain-ids.ts +106 -0
- package/src/evaluation/evaluate.test.ts +522 -0
- package/src/evaluation/evaluate.ts +680 -0
- package/src/evaluation/evaluation-v2-receipt-v1.test.ts +760 -0
- package/src/evaluation/index.ts +58 -0
- package/src/evaluation/receipt.ts +753 -0
- package/src/evaluation/types.ts +406 -0
- package/src/facts/builders.ts +2 -0
- package/src/facts/compile.ts +29 -6
- package/src/facts/fact-index.ts +13 -3
- package/src/facts/fact-integrity-v1.test.ts +172 -0
- package/src/facts/facts.test.ts +15 -0
- package/src/facts/ids.ts +46 -3
- package/src/facts/index.ts +14 -1
- package/src/facts/integrity.ts +134 -0
- package/src/facts/types.ts +36 -0
- package/src/feature-plan/digest.ts +217 -0
- package/src/feature-plan/feature-plan-v1.test.ts +529 -0
- package/src/feature-plan/index.ts +65 -0
- package/src/feature-plan/types.ts +628 -0
- package/src/governance-integrity.test.ts +1 -0
- package/src/governance-integrity.ts +5 -3
- package/src/governance-telemetry.ts +8 -0
- package/src/governance.ts +52 -8
- package/src/index.ts +299 -37
- package/src/preview/validation.test.ts +62 -0
- package/src/preview/validation.ts +48 -2
- package/src/preview-runtime.tsx +227 -20
- package/src/registry-install-plan.ts +200 -109
- package/src/registry-shards.test.ts +263 -0
- package/src/registry.ts +237 -0
- package/src/repository-binding.test.ts +50 -0
- package/src/repository-binding.ts +96 -0
- package/src/rules/families.test.ts +36 -0
- package/src/rules/finding.ts +7 -2
- package/src/rules/index.ts +17 -1
- package/src/rules/rule-config.test.ts +66 -0
- package/src/rules/rule-config.ts +73 -0
- package/src/rules/rules.test.ts +26 -0
- package/src/rules/tokens-css-vars-must-be-defined.test.ts +51 -2
- package/src/rules/tokens-css-vars-must-be-defined.ts +34 -1
- package/src/schema.ts +293 -113
- package/src/schemas/index.ts +1 -1
- package/src/storyAdapter.test.ts +68 -12
- package/src/storyAdapter.ts +44 -75
- package/src/types.ts +258 -37
- package/dist/chunk-RANPUC6C.js +0 -72
- package/dist/chunk-RANPUC6C.js.map +0 -1
- package/dist/chunk-XN3LSDPY.js.map +0 -1
- package/dist/chunk-YF65VYRY.js.map +0 -1
- package/src/fragment-types.ts +0 -214
- package/src/react-create-element.test.ts +0 -22
- package/src/react-create-element.ts +0 -12
- package/src/storyFilters.test.ts +0 -350
- package/src/storyFilters.ts +0 -253
package/dist/index.js
CHANGED
|
@@ -1,15 +1,80 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FRAGMENTS_MANIFEST_FILENAME,
|
|
3
|
+
FRAGMENTS_MANIFEST_SCHEMA_VERSION,
|
|
4
|
+
FRAGMENTS_MANIFEST_TOKEN_RULE,
|
|
5
|
+
fragmentsManifestFcid,
|
|
6
|
+
fragmentsManifestGrammarSchema,
|
|
7
|
+
fragmentsManifestPatternSchema,
|
|
8
|
+
fragmentsManifestPrimitiveSchema,
|
|
9
|
+
fragmentsManifestSchema,
|
|
10
|
+
parseFragmentsManifest
|
|
11
|
+
} from "./chunk-7ULGH74M.js";
|
|
12
|
+
import {
|
|
13
|
+
REGISTRY_ARTIFACT_SCHEMA_VERSION,
|
|
14
|
+
REGISTRY_INDEX_SCHEMA_VERSION,
|
|
15
|
+
REGISTRY_INSTALL_RECEIPT_SCHEMA_VERSION,
|
|
16
|
+
REGISTRY_MANIFEST_SCHEMA_VERSION,
|
|
17
|
+
REGISTRY_POINTER_SCHEMA_VERSION,
|
|
18
|
+
REGISTRY_SHARD_SCHEMA_VERSION,
|
|
19
|
+
assembleRegistryArtifact,
|
|
20
|
+
assertValidRegistryArtifact,
|
|
21
|
+
buildRegistryArtifact,
|
|
22
|
+
buildRegistryFile,
|
|
23
|
+
buildRegistryPointer,
|
|
24
|
+
computeRegistryHash,
|
|
25
|
+
defaultRegistryShardPath,
|
|
26
|
+
finalizeRegistryManifest,
|
|
27
|
+
hashRegistryFileContent,
|
|
28
|
+
registryArtifactDigest,
|
|
29
|
+
registryArtifactSchema,
|
|
30
|
+
registryComponentExportSchema,
|
|
31
|
+
registryComponentSchema,
|
|
32
|
+
registryDependencySchema,
|
|
33
|
+
registryDependencyTypeSchema,
|
|
34
|
+
registryEntrypointSchema,
|
|
35
|
+
registryFileContentSchema,
|
|
36
|
+
registryFileRoleSchema,
|
|
37
|
+
registryFileSchema,
|
|
38
|
+
registryFileSize,
|
|
39
|
+
registryIndexSchema,
|
|
40
|
+
registryInstallProfileSchema,
|
|
41
|
+
registryInstallReceiptComponentSchema,
|
|
42
|
+
registryInstallReceiptFileSchema,
|
|
43
|
+
registryInstallReceiptSchema,
|
|
44
|
+
registryManifestCanonicalPreimage,
|
|
45
|
+
registryManifestDraftSchema,
|
|
46
|
+
registryManifestFileMetadata,
|
|
47
|
+
registryManifestFilePaths,
|
|
48
|
+
registryManifestSchema,
|
|
49
|
+
registryPointerSchema,
|
|
50
|
+
registryShardSchema,
|
|
51
|
+
registryShardsForPaths,
|
|
52
|
+
registrySourceSchema,
|
|
53
|
+
shardRegistryArtifact
|
|
54
|
+
} from "./chunk-ML5S6QNU.js";
|
|
55
|
+
import {
|
|
56
|
+
GOVERNANCE_TELEMETRY_FIELDS,
|
|
57
|
+
GOVERNANCE_TELEMETRY_SOURCE_DISCLOSURE,
|
|
58
|
+
GOVERNANCE_TELEMETRY_TOP_LEVEL_FIELDS
|
|
59
|
+
} from "./chunk-3IOWHECM.js";
|
|
1
60
|
import {
|
|
2
61
|
CompiledFragmentsFileValidationError,
|
|
3
62
|
parseCompiledFragmentsFile
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import {
|
|
6
|
-
generateContext
|
|
7
|
-
} from "./chunk-X34IA4LR.js";
|
|
63
|
+
} from "./chunk-RYFULE43.js";
|
|
8
64
|
import {
|
|
9
65
|
ComponentGraphEngine
|
|
10
66
|
} from "./chunk-SH4KPIYH.js";
|
|
67
|
+
import {
|
|
68
|
+
resolveArea
|
|
69
|
+
} from "./chunk-3LLRNCPX.js";
|
|
70
|
+
import {
|
|
71
|
+
generateContext
|
|
72
|
+
} from "./chunk-X34IA4LR.js";
|
|
11
73
|
import {
|
|
12
74
|
AGENT_FORMAT_SCHEMA_VERSION,
|
|
75
|
+
CANONICAL_FACT_MAX_CONFLICTS_V1,
|
|
76
|
+
CANONICAL_FACT_MAX_PROVENANCE_PER_VALUE_V1,
|
|
77
|
+
CANONICAL_FACT_MAX_VALUES_PER_CONFLICT_V1,
|
|
13
78
|
CODES,
|
|
14
79
|
EXPLAIN_URL_BASE,
|
|
15
80
|
FactIndex,
|
|
@@ -19,12 +84,18 @@ import {
|
|
|
19
84
|
agentFormatSchema,
|
|
20
85
|
agentIntegritySchema,
|
|
21
86
|
agentOutputSchema,
|
|
87
|
+
analysisPlanIdFromDigest,
|
|
88
|
+
analysisPlanIdSchema,
|
|
89
|
+
analysisPlanIdStringSchema,
|
|
22
90
|
asComponentId,
|
|
23
91
|
bridgeSourceViolation,
|
|
24
92
|
bridgeSourceViolations,
|
|
25
93
|
byCode,
|
|
26
94
|
byRuleId,
|
|
27
95
|
canonicalBridgeV1Schema,
|
|
96
|
+
canonicalFactConflictV1Schema,
|
|
97
|
+
canonicalFactConflictValueV1Schema,
|
|
98
|
+
canonicalFactIntegrityV1Schema,
|
|
28
99
|
canonicalJson,
|
|
29
100
|
compileComponentFacts,
|
|
30
101
|
compileGlobalGovernanceFacts,
|
|
@@ -32,11 +103,22 @@ import {
|
|
|
32
103
|
componentGovernanceRecordsSchema,
|
|
33
104
|
componentId,
|
|
34
105
|
describePolicyExclude,
|
|
106
|
+
digestHexSchema,
|
|
107
|
+
digestHexStringSchema,
|
|
108
|
+
evaluationReceiptIdFromDigest,
|
|
109
|
+
evaluationReceiptIdSchema,
|
|
110
|
+
evaluationReceiptIdStringSchema,
|
|
35
111
|
excludeGlobToRegExp,
|
|
36
112
|
explainUrlForCode,
|
|
37
113
|
factEvidenceSchema,
|
|
38
114
|
factId,
|
|
39
115
|
factLocationSchema,
|
|
116
|
+
featurePlanIdFromEntropy,
|
|
117
|
+
featurePlanIdSchema,
|
|
118
|
+
featurePlanIdStringSchema,
|
|
119
|
+
featureRevisionIdFromDigest,
|
|
120
|
+
featureRevisionIdSchema,
|
|
121
|
+
featureRevisionIdStringSchema,
|
|
40
122
|
findingFixSchema,
|
|
41
123
|
findingReplaceClassTokenFixSchema,
|
|
42
124
|
findingReplaceComponentFixSchema,
|
|
@@ -100,6 +182,8 @@ import {
|
|
|
100
182
|
markPresetSourcedRules,
|
|
101
183
|
matchPolicyExclude,
|
|
102
184
|
matchesGlob,
|
|
185
|
+
mintEvaluationReceiptId,
|
|
186
|
+
normalizeCanonicalFactIntegrityV1,
|
|
103
187
|
normalizeExcludePath,
|
|
104
188
|
normalizeFinding,
|
|
105
189
|
normalizeGovernanceConfig,
|
|
@@ -109,24 +193,37 @@ import {
|
|
|
109
193
|
ownedComponentIdsEqual,
|
|
110
194
|
ownedImportMatchesRoot,
|
|
111
195
|
ownedImportsEqual,
|
|
196
|
+
parseAnalysisPlanId,
|
|
197
|
+
parseDigestHex,
|
|
198
|
+
parseEvaluationReceiptId,
|
|
199
|
+
parseFeaturePlanId,
|
|
200
|
+
parseFeatureRevisionId,
|
|
112
201
|
policyExcludeMatchesPath,
|
|
113
202
|
policyExcludeSchema,
|
|
114
203
|
projectSupersededImportPathPreferences,
|
|
115
204
|
resolveComponentGovernance,
|
|
205
|
+
resolveGovernanceRecordsForIdentity,
|
|
116
206
|
ruleFamilyMembers,
|
|
117
207
|
scaleGovernanceRecordSchema,
|
|
118
208
|
suppressionDirectiveSchema,
|
|
119
209
|
validatorResultSchema,
|
|
120
210
|
violationSchema
|
|
121
|
-
} from "./chunk-
|
|
211
|
+
} from "./chunk-RPSEABY3.js";
|
|
122
212
|
import {
|
|
123
|
-
|
|
124
|
-
|
|
213
|
+
isPortableRepoPath,
|
|
214
|
+
normalizeConfigPath,
|
|
215
|
+
portableRepoPathError,
|
|
216
|
+
resolveConfiguredAppPath,
|
|
217
|
+
tokenIncludesFromConfig,
|
|
218
|
+
topologyBase
|
|
219
|
+
} from "./chunk-EIYNNS77.js";
|
|
125
220
|
import {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
221
|
+
artifactContentHash,
|
|
222
|
+
canonicalPreimage,
|
|
223
|
+
compareCanonicalStrings,
|
|
224
|
+
contractHash,
|
|
225
|
+
sha256Hex
|
|
226
|
+
} from "./chunk-PWIJMOI4.js";
|
|
130
227
|
import {
|
|
131
228
|
OWNED_PACKAGE_IDENTITY_EPOCH,
|
|
132
229
|
OWNED_PACKAGE_IDENTITY_SOURCE_SHA256,
|
|
@@ -138,53 +235,13 @@ import {
|
|
|
138
235
|
projectV1OwnedImportIdentity,
|
|
139
236
|
resolveOwnedPackageImport
|
|
140
237
|
} from "./chunk-JNBFJ34I.js";
|
|
141
|
-
import {
|
|
142
|
-
REGISTRY_ARTIFACT_SCHEMA_VERSION,
|
|
143
|
-
REGISTRY_INSTALL_RECEIPT_SCHEMA_VERSION,
|
|
144
|
-
REGISTRY_MANIFEST_SCHEMA_VERSION,
|
|
145
|
-
assertValidRegistryArtifact,
|
|
146
|
-
buildRegistryArtifact,
|
|
147
|
-
buildRegistryFile,
|
|
148
|
-
canonicalPreimage,
|
|
149
|
-
computeRegistryHash,
|
|
150
|
-
contractHash,
|
|
151
|
-
finalizeRegistryManifest,
|
|
152
|
-
hashRegistryFileContent,
|
|
153
|
-
registryArtifactDigest,
|
|
154
|
-
registryArtifactSchema,
|
|
155
|
-
registryComponentExportSchema,
|
|
156
|
-
registryComponentSchema,
|
|
157
|
-
registryDependencySchema,
|
|
158
|
-
registryDependencyTypeSchema,
|
|
159
|
-
registryEntrypointSchema,
|
|
160
|
-
registryFileContentSchema,
|
|
161
|
-
registryFileRoleSchema,
|
|
162
|
-
registryFileSchema,
|
|
163
|
-
registryFileSize,
|
|
164
|
-
registryInstallProfileSchema,
|
|
165
|
-
registryInstallReceiptComponentSchema,
|
|
166
|
-
registryInstallReceiptFileSchema,
|
|
167
|
-
registryInstallReceiptSchema,
|
|
168
|
-
registryManifestCanonicalPreimage,
|
|
169
|
-
registryManifestDraftSchema,
|
|
170
|
-
registryManifestSchema,
|
|
171
|
-
registrySourceSchema,
|
|
172
|
-
sha256Hex
|
|
173
|
-
} from "./chunk-YF65VYRY.js";
|
|
174
|
-
import {
|
|
175
|
-
isPortableRepoPath,
|
|
176
|
-
normalizeConfigPath,
|
|
177
|
-
portableRepoPathError,
|
|
178
|
-
resolveConfiguredAppPath,
|
|
179
|
-
tokenIncludesFromConfig,
|
|
180
|
-
topologyBase
|
|
181
|
-
} from "./chunk-EIYNNS77.js";
|
|
182
238
|
import {
|
|
183
239
|
SEVERITIES,
|
|
184
240
|
SEVERITY_RANK,
|
|
185
241
|
SEVERITY_WEIGHTS,
|
|
186
242
|
compareSeverity,
|
|
187
243
|
maxSeverity,
|
|
244
|
+
severityFromLevel,
|
|
188
245
|
severityLevel,
|
|
189
246
|
severitySchema,
|
|
190
247
|
sortBySeverity
|
|
@@ -200,8 +257,6 @@ var BRAND = {
|
|
|
200
257
|
fileExtension: ".contract.json",
|
|
201
258
|
/** Legacy file extension for segments (still supported for migration) */
|
|
202
259
|
legacyFileExtension: ".segment.tsx",
|
|
203
|
-
/** JSON file extension for compiled output */
|
|
204
|
-
jsonExtension: ".fragment.json",
|
|
205
260
|
/** Default output file name (e.g., "fragments.json") */
|
|
206
261
|
outFile: "fragments.json",
|
|
207
262
|
/** Config file name (e.g., "fragments.config.ts") */
|
|
@@ -238,11 +293,10 @@ var BRAND = {
|
|
|
238
293
|
mcpToolPrefix: "fragments_",
|
|
239
294
|
/** File extension for block definition files */
|
|
240
295
|
blockFileExtension: ".block.ts",
|
|
241
|
-
/** @deprecated Use blockFileExtension instead */
|
|
242
|
-
recipeFileExtension: ".recipe.ts",
|
|
243
296
|
/** Vite plugin namespace */
|
|
244
297
|
vitePluginNamespace: "fragments-core-shim"
|
|
245
298
|
};
|
|
299
|
+
var FRAGMENT_V3_SCHEMA_URL = "https://usefragments.com/schemas/fragment.v3.json";
|
|
246
300
|
var DEFAULTS = {
|
|
247
301
|
/** Default viewport dimensions */
|
|
248
302
|
viewport: {
|
|
@@ -741,6 +795,9 @@ function assertPortableRegistryPath(path, label) {
|
|
|
741
795
|
function joinRegistryPath(...parts) {
|
|
742
796
|
return normalizeRegistryRepoPath(parts.filter(Boolean).join("/"));
|
|
743
797
|
}
|
|
798
|
+
function sortStrings(values) {
|
|
799
|
+
return [...new Set(values)].sort((left, right) => left.localeCompare(right));
|
|
800
|
+
}
|
|
744
801
|
function sourceToRegistryTargetPath(targetRoot, sourcePath) {
|
|
745
802
|
const source = normalizeRegistryRepoPath(sourcePath);
|
|
746
803
|
const withoutSrc = source.startsWith("src/") ? source.slice("src/".length) : source;
|
|
@@ -749,37 +806,69 @@ function sourceToRegistryTargetPath(targetRoot, sourcePath) {
|
|
|
749
806
|
"Registry install target"
|
|
750
807
|
);
|
|
751
808
|
}
|
|
752
|
-
function
|
|
753
|
-
if (
|
|
754
|
-
|
|
755
|
-
|
|
809
|
+
function resolveRegistryComponentId(manifest, requested) {
|
|
810
|
+
if (manifest.components[requested]) return requested;
|
|
811
|
+
const lowered = requested.toLowerCase();
|
|
812
|
+
const matches = Object.keys(manifest.components).filter((name) => name.toLowerCase() === lowered);
|
|
813
|
+
if (matches.length === 1) return matches[0];
|
|
814
|
+
if (matches.length > 1) {
|
|
815
|
+
throw new Error(
|
|
816
|
+
`Ambiguous registry component ${requested}: matches ${matches.sort().join(", ")}`
|
|
756
817
|
);
|
|
757
818
|
}
|
|
758
|
-
|
|
759
|
-
|
|
819
|
+
throw new Error(`Unknown registry component ${requested}`);
|
|
820
|
+
}
|
|
821
|
+
function expandRegistryComponentClosure(manifest, names) {
|
|
822
|
+
const closure = /* @__PURE__ */ new Set();
|
|
823
|
+
const queue = [...names];
|
|
824
|
+
while (queue.length > 0) {
|
|
825
|
+
const name = queue.shift();
|
|
826
|
+
if (closure.has(name)) continue;
|
|
827
|
+
const component = manifest.components[name];
|
|
828
|
+
if (!component) throw new Error(`Unknown registry component ${name}`);
|
|
829
|
+
closure.add(name);
|
|
830
|
+
queue.push(...component.internalDependencies);
|
|
760
831
|
}
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
832
|
+
return sortStrings(closure);
|
|
833
|
+
}
|
|
834
|
+
function resolveRegistryInstallSelection(input) {
|
|
835
|
+
const { manifest } = input;
|
|
836
|
+
if (input.all || input.requestedComponents.includes("*")) {
|
|
837
|
+
const components2 = sortStrings(Object.keys(manifest.components));
|
|
838
|
+
return { requested: components2, implied: [], components: components2 };
|
|
765
839
|
}
|
|
766
|
-
|
|
840
|
+
if (input.requestedComponents.length === 0) {
|
|
841
|
+
throw new Error("Choose at least one registry component to install.");
|
|
842
|
+
}
|
|
843
|
+
const requested = sortStrings(
|
|
844
|
+
input.requestedComponents.map((name) => resolveRegistryComponentId(manifest, name))
|
|
845
|
+
);
|
|
846
|
+
const components = expandRegistryComponentClosure(manifest, requested);
|
|
847
|
+
const requestedSet = new Set(requested);
|
|
848
|
+
return {
|
|
849
|
+
requested,
|
|
850
|
+
implied: components.filter((name) => !requestedSet.has(name)),
|
|
851
|
+
components
|
|
852
|
+
};
|
|
767
853
|
}
|
|
768
|
-
function installsCompleteRegistry(
|
|
769
|
-
const allComponents = Object.keys(
|
|
854
|
+
function installsCompleteRegistry(manifest, componentNames) {
|
|
855
|
+
const allComponents = Object.keys(manifest.components);
|
|
770
856
|
return componentNames.length === allComponents.length && allComponents.every((name) => componentNames.includes(name));
|
|
771
857
|
}
|
|
858
|
+
var AUTHORING_ROLES = /* @__PURE__ */ new Set(["test", "story", "example"]);
|
|
772
859
|
function shouldInstallFile(file, includeTests) {
|
|
773
860
|
if (includeTests) return true;
|
|
774
|
-
return
|
|
861
|
+
return !AUTHORING_ROLES.has(file.role);
|
|
775
862
|
}
|
|
776
863
|
function dependencyKey(dependency) {
|
|
777
864
|
return `${dependency.type}:${dependency.name}:${dependency.versionRange}:${dependency.optional ? 1 : 0}`;
|
|
778
865
|
}
|
|
779
866
|
function collectRegistryInstallDependencies(artifact, componentNames) {
|
|
780
867
|
const dependencies = /* @__PURE__ */ new Map();
|
|
781
|
-
|
|
782
|
-
|
|
868
|
+
if (installsCompleteRegistry(artifact.manifest, componentNames)) {
|
|
869
|
+
for (const dependency of artifact.manifest.dependencies) {
|
|
870
|
+
dependencies.set(dependencyKey(dependency), dependency);
|
|
871
|
+
}
|
|
783
872
|
}
|
|
784
873
|
for (const name of componentNames) {
|
|
785
874
|
const component = artifact.manifest.components[name];
|
|
@@ -789,24 +878,44 @@ function collectRegistryInstallDependencies(artifact, componentNames) {
|
|
|
789
878
|
}
|
|
790
879
|
return [...dependencies.values()].sort((left, right) => left.name.localeCompare(right.name));
|
|
791
880
|
}
|
|
792
|
-
function
|
|
793
|
-
const
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
881
|
+
function packageFileEntries(manifest) {
|
|
882
|
+
const packageFiles = new Map(
|
|
883
|
+
manifest.packageFiles.map((file) => [file.path, file])
|
|
884
|
+
);
|
|
885
|
+
for (const entrypoint of manifest.entrypoints) {
|
|
886
|
+
if (!packageFiles.has(entrypoint.sourcePath)) packageFiles.set(entrypoint.sourcePath, null);
|
|
887
|
+
}
|
|
888
|
+
return packageFiles;
|
|
889
|
+
}
|
|
890
|
+
function resolveRegistryInstallSources(input) {
|
|
891
|
+
const { manifest } = input;
|
|
892
|
+
const selection = resolveRegistryInstallSelection(input);
|
|
893
|
+
const complete = installsCompleteRegistry(manifest, selection.components);
|
|
894
|
+
const files = /* @__PURE__ */ new Map();
|
|
895
|
+
const paths = /* @__PURE__ */ new Set();
|
|
896
|
+
const add = (file, componentId2) => {
|
|
897
|
+
if (!shouldInstallFile(file, input.includeTests)) return;
|
|
898
|
+
if (!files.has(file.path)) files.set(file.path, { file, componentId: componentId2 });
|
|
899
|
+
paths.add(file.path);
|
|
900
|
+
};
|
|
901
|
+
if (complete) {
|
|
902
|
+
for (const [path, file] of packageFileEntries(manifest)) {
|
|
903
|
+
if (file) add(file);
|
|
904
|
+
else paths.add(path);
|
|
807
905
|
}
|
|
906
|
+
} else {
|
|
907
|
+
for (const file of manifest.baseFiles) add(file);
|
|
808
908
|
}
|
|
809
|
-
|
|
909
|
+
for (const name of selection.components) {
|
|
910
|
+
const component = manifest.components[name];
|
|
911
|
+
for (const file of component.files) add(file, component.componentId);
|
|
912
|
+
}
|
|
913
|
+
return {
|
|
914
|
+
selection,
|
|
915
|
+
complete,
|
|
916
|
+
files: [...files.values()].sort((left, right) => left.file.path.localeCompare(right.file.path)),
|
|
917
|
+
paths: sortStrings(paths)
|
|
918
|
+
};
|
|
810
919
|
}
|
|
811
920
|
function rewriteInstalledPackagePath(value) {
|
|
812
921
|
if (value.startsWith("./src/")) return `./${value.slice("./src/".length)}`;
|
|
@@ -843,41 +952,14 @@ function rewriteInstalledPackageJson(content) {
|
|
|
843
952
|
return `${JSON.stringify(installed, null, 2)}
|
|
844
953
|
`;
|
|
845
954
|
}
|
|
846
|
-
function
|
|
847
|
-
const
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
);
|
|
851
|
-
for (const entrypoint of args.artifact.manifest.entrypoints) {
|
|
852
|
-
const file = packageFiles.get(entrypoint.sourcePath);
|
|
853
|
-
if (file) continue;
|
|
854
|
-
const content = args.artifact.files[entrypoint.sourcePath];
|
|
855
|
-
if (!content) throw new Error(`Artifact is missing file content for ${entrypoint.sourcePath}`);
|
|
856
|
-
packageFiles.set(entrypoint.sourcePath, {
|
|
857
|
-
path: entrypoint.sourcePath,
|
|
858
|
-
role: "barrel",
|
|
859
|
-
sha256: content.sha256,
|
|
860
|
-
size: content.size,
|
|
861
|
-
contentType: content.contentType,
|
|
862
|
-
contentRef: `sha256:${content.sha256}`
|
|
863
|
-
});
|
|
864
|
-
}
|
|
865
|
-
for (const file of packageFiles.values()) {
|
|
866
|
-
if (!shouldInstallFile(file, args.includeTests)) continue;
|
|
867
|
-
const content = args.artifact.files[file.path];
|
|
868
|
-
if (!content) throw new Error(`Artifact is missing file content for ${file.path}`);
|
|
869
|
-
const target = sourceToRegistryTargetPath(args.targetPath, file.path);
|
|
870
|
-
writes.set(target, {
|
|
871
|
-
path: target,
|
|
872
|
-
sourcePath: file.path,
|
|
873
|
-
content: file.path === "package.json" ? rewriteInstalledPackageJson(content.content) : content.content
|
|
874
|
-
});
|
|
875
|
-
}
|
|
876
|
-
return [...writes.values()].sort((left, right) => left.path.localeCompare(right.path));
|
|
955
|
+
function contentFor(artifact, path) {
|
|
956
|
+
const content = artifact.files[path];
|
|
957
|
+
if (!content) throw new Error(`Artifact is missing file content for ${path}`);
|
|
958
|
+
return content.content;
|
|
877
959
|
}
|
|
878
960
|
function generatedIndexPlan(args) {
|
|
879
961
|
const lines = args.componentNames.map((name) => {
|
|
880
|
-
const component = args.
|
|
962
|
+
const component = args.manifest.components[name];
|
|
881
963
|
const exportName = component.exports[0]?.name ?? component.name;
|
|
882
964
|
return `export { ${exportName} } from "./components/${component.componentId}";`;
|
|
883
965
|
});
|
|
@@ -903,32 +985,47 @@ function dedupePlans(plans) {
|
|
|
903
985
|
return [...byPath.values()].sort((left, right) => left.path.localeCompare(right.path));
|
|
904
986
|
}
|
|
905
987
|
function buildRegistryInstallPlan(input) {
|
|
988
|
+
const { manifest } = input.artifact;
|
|
906
989
|
const targetPath = assertPortableRegistryPath(input.targetPath, "Registry target");
|
|
907
|
-
const
|
|
908
|
-
|
|
909
|
-
input.requestedComponents,
|
|
910
|
-
input.all
|
|
911
|
-
|
|
990
|
+
const sources = resolveRegistryInstallSources({
|
|
991
|
+
manifest,
|
|
992
|
+
requestedComponents: input.requestedComponents,
|
|
993
|
+
all: input.all,
|
|
994
|
+
includeTests: input.includeTests
|
|
995
|
+
});
|
|
996
|
+
const componentNames = sources.selection.components;
|
|
912
997
|
const dependencies = collectRegistryInstallDependencies(input.artifact, componentNames);
|
|
913
|
-
const
|
|
914
|
-
const
|
|
915
|
-
|
|
916
|
-
|
|
998
|
+
const hasPackageRoot = manifest.entrypoints.some((entrypoint) => entrypoint.specifier === ".");
|
|
999
|
+
const writes = sources.files.map(({ file, componentId: componentId2 }) => {
|
|
1000
|
+
const raw = contentFor(input.artifact, file.path);
|
|
1001
|
+
return {
|
|
1002
|
+
path: sourceToRegistryTargetPath(targetPath, file.path),
|
|
1003
|
+
sourcePath: file.path,
|
|
1004
|
+
content: sources.complete && file.path === "package.json" ? rewriteInstalledPackageJson(raw) : raw,
|
|
1005
|
+
...componentId2 && { componentId: componentId2 }
|
|
1006
|
+
};
|
|
1007
|
+
});
|
|
1008
|
+
if (sources.complete) {
|
|
1009
|
+
for (const entrypoint of manifest.entrypoints) {
|
|
1010
|
+
if (writes.some((plan) => plan.sourcePath === entrypoint.sourcePath)) continue;
|
|
1011
|
+
writes.push({
|
|
1012
|
+
path: sourceToRegistryTargetPath(targetPath, entrypoint.sourcePath),
|
|
1013
|
+
sourcePath: entrypoint.sourcePath,
|
|
1014
|
+
content: contentFor(input.artifact, entrypoint.sourcePath)
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
917
1018
|
const plans = dedupePlans([
|
|
918
|
-
...
|
|
919
|
-
|
|
920
|
-
targetPath,
|
|
921
|
-
includeTests: input.includeTests
|
|
922
|
-
}) : [],
|
|
923
|
-
...collectComponentWritePlan({
|
|
924
|
-
artifact: input.artifact,
|
|
925
|
-
componentNames,
|
|
926
|
-
targetPath,
|
|
927
|
-
includeTests: input.includeTests
|
|
928
|
-
}),
|
|
929
|
-
...isCompleteInstall && hasPackageRoot ? [] : [generatedIndexPlan({ artifact: input.artifact, componentNames, targetPath })]
|
|
1019
|
+
...writes,
|
|
1020
|
+
...sources.complete && hasPackageRoot ? [] : [generatedIndexPlan({ manifest, componentNames, targetPath })]
|
|
930
1021
|
]);
|
|
931
|
-
return {
|
|
1022
|
+
return {
|
|
1023
|
+
componentNames,
|
|
1024
|
+
requestedComponents: sources.selection.requested,
|
|
1025
|
+
impliedComponents: sources.selection.implied,
|
|
1026
|
+
plans,
|
|
1027
|
+
dependencies
|
|
1028
|
+
};
|
|
932
1029
|
}
|
|
933
1030
|
function buildRegistryInstallReceipt(args) {
|
|
934
1031
|
const installedComponents = args.componentNames.map((name) => {
|
|
@@ -1249,14 +1346,14 @@ function rgbToLab(rgb) {
|
|
|
1249
1346
|
b = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92;
|
|
1250
1347
|
let x = (r * 0.4124564 + g2 * 0.3575761 + b * 0.1804375) / 0.95047;
|
|
1251
1348
|
let y = r * 0.2126729 + g2 * 0.7151522 + b * 0.072175;
|
|
1252
|
-
let
|
|
1349
|
+
let z12 = (r * 0.0193339 + g2 * 0.119192 + b * 0.9503041) / 1.08883;
|
|
1253
1350
|
x = x > 8856e-6 ? Math.pow(x, 1 / 3) : 7.787 * x + 16 / 116;
|
|
1254
1351
|
y = y > 8856e-6 ? Math.pow(y, 1 / 3) : 7.787 * y + 16 / 116;
|
|
1255
|
-
|
|
1352
|
+
z12 = z12 > 8856e-6 ? Math.pow(z12, 1 / 3) : 7.787 * z12 + 16 / 116;
|
|
1256
1353
|
return {
|
|
1257
1354
|
l: 116 * y - 16,
|
|
1258
1355
|
a: 500 * (x - y),
|
|
1259
|
-
b: 200 * (y -
|
|
1356
|
+
b: 200 * (y - z12)
|
|
1260
1357
|
};
|
|
1261
1358
|
}
|
|
1262
1359
|
|
|
@@ -1521,10 +1618,14 @@ var figmaStringMappingSchema = z4.object({
|
|
|
1521
1618
|
__type: z4.literal("figma-string"),
|
|
1522
1619
|
figmaProperty: z4.string().min(1)
|
|
1523
1620
|
});
|
|
1621
|
+
var requiredUnknownSchema = z4.custom(
|
|
1622
|
+
(value) => value !== void 0,
|
|
1623
|
+
"Expected an explicitly present value"
|
|
1624
|
+
);
|
|
1524
1625
|
var figmaBooleanMappingSchema = z4.object({
|
|
1525
1626
|
__type: z4.literal("figma-boolean"),
|
|
1526
1627
|
figmaProperty: z4.string().min(1),
|
|
1527
|
-
valueMapping: z4.object({ true:
|
|
1628
|
+
valueMapping: z4.object({ true: requiredUnknownSchema, false: requiredUnknownSchema }).optional()
|
|
1528
1629
|
});
|
|
1529
1630
|
var figmaEnumMappingSchema = z4.object({
|
|
1530
1631
|
__type: z4.literal("figma-enum"),
|
|
@@ -1629,7 +1730,7 @@ var fragmentContractSchema = z4.object({
|
|
|
1629
1730
|
a11yRules: z4.array(z4.string()).optional(),
|
|
1630
1731
|
bans: z4.array(fragmentBanSchema).optional(),
|
|
1631
1732
|
scenarioTags: z4.array(z4.string()).optional(),
|
|
1632
|
-
performanceBudget: z4.number().positive().optional(),
|
|
1733
|
+
performanceBudget: z4.number().positive().finite().optional(),
|
|
1633
1734
|
compoundChildren: z4.record(
|
|
1634
1735
|
z4.object({
|
|
1635
1736
|
required: z4.boolean().optional(),
|
|
@@ -1643,10 +1744,20 @@ var fragmentContractSchema = z4.object({
|
|
|
1643
1744
|
// `CompositionPattern[]` the composition/* rules read from policy.
|
|
1644
1745
|
composition: z4.array(compositionAuthoringEntrySchema).optional()
|
|
1645
1746
|
});
|
|
1747
|
+
var fragmentSourceValues = [
|
|
1748
|
+
"storybook",
|
|
1749
|
+
"manual",
|
|
1750
|
+
"ai",
|
|
1751
|
+
"scan",
|
|
1752
|
+
"extracted",
|
|
1753
|
+
"merged",
|
|
1754
|
+
"migrated"
|
|
1755
|
+
];
|
|
1646
1756
|
var fragmentGeneratedSchema = z4.object({
|
|
1647
|
-
source: z4.enum(
|
|
1757
|
+
source: z4.enum(fragmentSourceValues),
|
|
1648
1758
|
sourceFile: z4.string().optional(),
|
|
1649
1759
|
confidence: z4.number().min(0).max(1).optional(),
|
|
1760
|
+
verified: z4.boolean().optional(),
|
|
1650
1761
|
timestamp: z4.string().datetime().optional()
|
|
1651
1762
|
});
|
|
1652
1763
|
var aiMetadataSchema = z4.object({
|
|
@@ -1785,14 +1896,6 @@ var fragmentsConfigSchema = z4.object({
|
|
|
1785
1896
|
}).optional()
|
|
1786
1897
|
})
|
|
1787
1898
|
]).optional(),
|
|
1788
|
-
storybook: z4.object({
|
|
1789
|
-
exclude: z4.array(z4.string()).optional(),
|
|
1790
|
-
include: z4.array(z4.string()).optional(),
|
|
1791
|
-
excludeDeprecated: z4.boolean().optional(),
|
|
1792
|
-
excludeTests: z4.boolean().optional(),
|
|
1793
|
-
excludeSvgIcons: z4.boolean().optional(),
|
|
1794
|
-
excludeSubComponents: z4.boolean().optional()
|
|
1795
|
-
}).optional(),
|
|
1796
1899
|
topology: topologySchema.optional(),
|
|
1797
1900
|
govern: governanceConfigSchema.optional(),
|
|
1798
1901
|
inspect: z4.object({
|
|
@@ -1830,10 +1933,13 @@ var compositionMetadataSchema = z4.object({
|
|
|
1830
1933
|
commonPatterns: z4.array(z4.string()).optional()
|
|
1831
1934
|
});
|
|
1832
1935
|
var fragmentProvenanceSchema = z4.object({
|
|
1833
|
-
source: z4.enum(
|
|
1936
|
+
source: z4.enum(fragmentSourceValues),
|
|
1834
1937
|
sourceFile: z4.string().optional(),
|
|
1835
1938
|
confidence: z4.number().min(0).max(1).optional(),
|
|
1836
|
-
|
|
1939
|
+
verified: z4.boolean().optional(),
|
|
1940
|
+
frameworkSupport: z4.enum(["native", "manual-only"]).optional(),
|
|
1941
|
+
sourceHash: z4.string().optional(),
|
|
1942
|
+
timestamp: z4.string().datetime({ offset: true }).optional(),
|
|
1837
1943
|
autoFields: z4.array(z4.string()).optional(),
|
|
1838
1944
|
humanFields: z4.array(z4.string()).optional()
|
|
1839
1945
|
});
|
|
@@ -1860,8 +1966,119 @@ var governedFragmentDefinitionSchema = z4.object({
|
|
|
1860
1966
|
_provenance: fragmentProvenanceSchema.optional(),
|
|
1861
1967
|
govern: z4.function().optional(),
|
|
1862
1968
|
governance: z4.array(componentGovernanceRecordSchema).optional()
|
|
1969
|
+
}).superRefine((def, ctx) => {
|
|
1970
|
+
if (def.govern === void 0 && def.governance === void 0) {
|
|
1971
|
+
ctx.addIssue({
|
|
1972
|
+
code: z4.ZodIssueCode.custom,
|
|
1973
|
+
message: "Governed definitions require `govern` or `governance`",
|
|
1974
|
+
path: ["govern"]
|
|
1975
|
+
});
|
|
1976
|
+
}
|
|
1863
1977
|
});
|
|
1864
|
-
var
|
|
1978
|
+
var fragmentRenderSchema = z4.custom(
|
|
1979
|
+
(value) => value !== void 0 && typeof value !== "string",
|
|
1980
|
+
"Expected JSX/render value, not a code string"
|
|
1981
|
+
);
|
|
1982
|
+
var fragmentMetaV3Schema = z4.object({
|
|
1983
|
+
name: z4.string().min(1),
|
|
1984
|
+
purpose: z4.string().min(1),
|
|
1985
|
+
category: z4.string().min(1),
|
|
1986
|
+
status: z4.enum(["stable", "beta", "deprecated", "experimental"]).optional(),
|
|
1987
|
+
aliases: z4.array(z4.string().min(1)).optional(),
|
|
1988
|
+
tags: z4.array(z4.string()).optional(),
|
|
1989
|
+
since: z4.string().optional(),
|
|
1990
|
+
dependencies: z4.array(
|
|
1991
|
+
z4.object({
|
|
1992
|
+
name: z4.string().min(1),
|
|
1993
|
+
version: z4.string().min(1),
|
|
1994
|
+
reason: z4.string().optional()
|
|
1995
|
+
}).strict()
|
|
1996
|
+
).optional(),
|
|
1997
|
+
figma: z4.string().url().optional(),
|
|
1998
|
+
figmaProps: z4.record(figmaPropMappingSchema).optional()
|
|
1999
|
+
}).strict();
|
|
2000
|
+
var fragmentStateV3Schema = z4.object({
|
|
2001
|
+
render: fragmentRenderSchema,
|
|
2002
|
+
note: z4.string().optional(),
|
|
2003
|
+
canonical: z4.boolean().optional()
|
|
2004
|
+
}).strict();
|
|
2005
|
+
var fragmentDontExampleV3Schema = z4.object({
|
|
2006
|
+
reason: z4.string().min(1),
|
|
2007
|
+
bad: z4.string().min(1),
|
|
2008
|
+
good: fragmentRenderSchema
|
|
2009
|
+
}).strict();
|
|
2010
|
+
var fragmentGuidanceV3Schema = z4.object({
|
|
2011
|
+
when: z4.array(z4.string()),
|
|
2012
|
+
whenNot: z4.array(z4.string()),
|
|
2013
|
+
choose: z4.record(z4.string()).optional(),
|
|
2014
|
+
dont: z4.array(fragmentDontExampleV3Schema).optional(),
|
|
2015
|
+
guidelines: z4.array(z4.string()).optional(),
|
|
2016
|
+
accessibility: z4.array(z4.string()).optional()
|
|
2017
|
+
}).strict();
|
|
2018
|
+
var fragmentMatrixV3Schema = z4.object({
|
|
2019
|
+
axes: z4.record(z4.union([z4.literal("auto"), z4.array(z4.string().min(1)).readonly()])).optional(),
|
|
2020
|
+
forced: z4.array(z4.string().min(1)).optional(),
|
|
2021
|
+
worstCase: z4.record(z4.unknown()).optional()
|
|
2022
|
+
}).strict();
|
|
2023
|
+
var fragmentPreviewV3Schema = z4.object({
|
|
2024
|
+
providers: z4.array(z4.unknown()).optional(),
|
|
2025
|
+
dynamicRegions: z4.array(z4.string()).optional()
|
|
2026
|
+
}).strict();
|
|
2027
|
+
var fragmentDesignV3Schema = z4.object({
|
|
2028
|
+
figmaNode: z4.string().min(1).optional()
|
|
2029
|
+
}).strict();
|
|
2030
|
+
var propAnnotationSchema = z4.object({
|
|
2031
|
+
description: z4.string().optional(),
|
|
2032
|
+
controlType: z4.enum([
|
|
2033
|
+
"text",
|
|
2034
|
+
"number",
|
|
2035
|
+
"range",
|
|
2036
|
+
"boolean",
|
|
2037
|
+
"select",
|
|
2038
|
+
"multi-select",
|
|
2039
|
+
"radio",
|
|
2040
|
+
"inline-radio",
|
|
2041
|
+
"check",
|
|
2042
|
+
"inline-check",
|
|
2043
|
+
"object",
|
|
2044
|
+
"file",
|
|
2045
|
+
"color",
|
|
2046
|
+
"date"
|
|
2047
|
+
]).optional(),
|
|
2048
|
+
controlOptions: z4.record(z4.unknown()).optional(),
|
|
2049
|
+
visibility: z4.enum(["public", "internal", "hidden"]).optional(),
|
|
2050
|
+
constraints: z4.array(z4.string()).optional()
|
|
2051
|
+
}).strict();
|
|
2052
|
+
var fragmentAnnotationsV3Schema = z4.object({
|
|
2053
|
+
notes: z4.array(z4.string()).optional(),
|
|
2054
|
+
review: z4.array(z4.string()).optional()
|
|
2055
|
+
}).passthrough();
|
|
2056
|
+
var fragmentDefinitionV3BodyShape = {
|
|
2057
|
+
meta: fragmentMetaV3Schema,
|
|
2058
|
+
states: z4.record(fragmentStateV3Schema).refine((states) => Object.keys(states).length > 0, {
|
|
2059
|
+
message: "At least one state is required"
|
|
2060
|
+
}),
|
|
2061
|
+
guidance: fragmentGuidanceV3Schema,
|
|
2062
|
+
matrix: fragmentMatrixV3Schema.optional(),
|
|
2063
|
+
preview: fragmentPreviewV3Schema.optional(),
|
|
2064
|
+
design: fragmentDesignV3Schema.optional(),
|
|
2065
|
+
annotations: fragmentAnnotationsV3Schema.optional(),
|
|
2066
|
+
props: z4.record(propAnnotationSchema).optional(),
|
|
2067
|
+
relations: z4.array(componentRelationSchema.strict()).optional(),
|
|
2068
|
+
composition: compositionMetadataSchema.strict().optional(),
|
|
2069
|
+
contract: fragmentContractSchema.optional(),
|
|
2070
|
+
_provenance: fragmentProvenanceSchema.optional(),
|
|
2071
|
+
govern: z4.function().optional(),
|
|
2072
|
+
governance: z4.array(componentGovernanceRecordSchema).optional()
|
|
2073
|
+
};
|
|
2074
|
+
var fragmentDefinitionV3BodySchema = z4.object(fragmentDefinitionV3BodyShape).strict();
|
|
2075
|
+
var fragmentDefinitionV3Schema = z4.object({
|
|
2076
|
+
...fragmentDefinitionV3BodyShape,
|
|
2077
|
+
component: z4.unknown().refine((component) => component !== void 0, {
|
|
2078
|
+
message: "Component is required"
|
|
2079
|
+
}),
|
|
2080
|
+
governance: z4.array(componentGovernanceRecordSchema)
|
|
2081
|
+
}).strict();
|
|
1865
2082
|
|
|
1866
2083
|
// src/config.ts
|
|
1867
2084
|
var RAW_CONFIG_DECLARATION = /* @__PURE__ */ Symbol.for("@usefragments/core/raw-config-declaration");
|
|
@@ -1890,11 +2107,51 @@ ${formatZodErrors(result.error.errors)}`);
|
|
|
1890
2107
|
|
|
1891
2108
|
// src/defineFragment.ts
|
|
1892
2109
|
function isGovernedDefinition(def) {
|
|
1893
|
-
|
|
2110
|
+
if (!def || typeof def !== "object") return false;
|
|
2111
|
+
const record = def;
|
|
2112
|
+
return typeof record.govern === "function" || Array.isArray(record.governance);
|
|
1894
2113
|
}
|
|
1895
2114
|
function isV2Definition(def) {
|
|
2115
|
+
if (!def || typeof def !== "object") return false;
|
|
1896
2116
|
return !isGovernedDefinition(def) && ("guidance" in def || "examples" in def);
|
|
1897
2117
|
}
|
|
2118
|
+
function rejectInvalidGovernanceDiscriminants(definition) {
|
|
2119
|
+
if (!definition || typeof definition !== "object") return;
|
|
2120
|
+
const record = definition;
|
|
2121
|
+
const hasOwn = (key) => Object.prototype.hasOwnProperty.call(record, key);
|
|
2122
|
+
const errors = [];
|
|
2123
|
+
if (hasOwn("govern") && typeof record.govern !== "function") {
|
|
2124
|
+
errors.push({ path: ["govern"], message: "Expected a governance authoring function" });
|
|
2125
|
+
}
|
|
2126
|
+
if (hasOwn("governance") && !Array.isArray(record.governance)) {
|
|
2127
|
+
errors.push({ path: ["governance"], message: "Expected an array of governance records" });
|
|
2128
|
+
}
|
|
2129
|
+
if (errors.length > 0) {
|
|
2130
|
+
const name = record.meta && typeof record.meta === "object" && "name" in record.meta ? String(record.meta.name) : "unknown";
|
|
2131
|
+
throwInvalidFragment(name, "governed", errors);
|
|
2132
|
+
}
|
|
2133
|
+
}
|
|
2134
|
+
var InvalidFragmentDefinitionError = class _InvalidFragmentDefinitionError extends Error {
|
|
2135
|
+
code = "FUI9010";
|
|
2136
|
+
source = "@usefragments/core/defineFragment";
|
|
2137
|
+
api;
|
|
2138
|
+
issues;
|
|
2139
|
+
constructor(name, api, errors) {
|
|
2140
|
+
const issues = errors.map((error) => `${error.path.join(".") || "(root)"}: ${error.message}`).sort();
|
|
2141
|
+
super(
|
|
2142
|
+
[
|
|
2143
|
+
`${_InvalidFragmentDefinitionError.name}: Invalid fragment definition for "${name}":`,
|
|
2144
|
+
...issues.map((issue) => ` - ${issue}`)
|
|
2145
|
+
].join("\n")
|
|
2146
|
+
);
|
|
2147
|
+
this.name = _InvalidFragmentDefinitionError.name;
|
|
2148
|
+
this.api = api;
|
|
2149
|
+
this.issues = issues;
|
|
2150
|
+
}
|
|
2151
|
+
};
|
|
2152
|
+
function throwInvalidFragment(name, api, errors) {
|
|
2153
|
+
throw new InvalidFragmentDefinitionError(name, api, errors);
|
|
2154
|
+
}
|
|
1898
2155
|
function normalizeToV1(def) {
|
|
1899
2156
|
let ai;
|
|
1900
2157
|
if (def.composition) {
|
|
@@ -1908,9 +2165,10 @@ function normalizeToV1(def) {
|
|
|
1908
2165
|
let generated;
|
|
1909
2166
|
if (def._provenance) {
|
|
1910
2167
|
generated = {
|
|
1911
|
-
source: def._provenance.source
|
|
2168
|
+
source: def._provenance.source,
|
|
1912
2169
|
sourceFile: def._provenance.sourceFile,
|
|
1913
2170
|
confidence: def._provenance.confidence,
|
|
2171
|
+
verified: def._provenance.verified,
|
|
1914
2172
|
timestamp: def._provenance.timestamp
|
|
1915
2173
|
};
|
|
1916
2174
|
}
|
|
@@ -1926,18 +2184,60 @@ function normalizeToV1(def) {
|
|
|
1926
2184
|
_generated: generated
|
|
1927
2185
|
};
|
|
1928
2186
|
}
|
|
1929
|
-
function
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
2187
|
+
function defineFragmentV3(component, definition) {
|
|
2188
|
+
const result = fragmentDefinitionV3BodySchema.safeParse(definition);
|
|
2189
|
+
if (!result.success) {
|
|
2190
|
+
throwInvalidFragment(
|
|
2191
|
+
definition?.meta?.name || "unknown",
|
|
2192
|
+
"v3",
|
|
2193
|
+
result.error.errors.map((e) => ({ path: e.path, message: e.message }))
|
|
2194
|
+
);
|
|
2195
|
+
}
|
|
2196
|
+
const governance = typeof definition.govern === "function" || Array.isArray(definition.governance) ? resolveComponentGovernance({
|
|
2197
|
+
component,
|
|
2198
|
+
meta: {
|
|
2199
|
+
name: definition.meta.name,
|
|
2200
|
+
description: definition.meta.purpose,
|
|
2201
|
+
category: definition.meta.category,
|
|
2202
|
+
status: definition.meta.status,
|
|
2203
|
+
tags: definition.meta.tags,
|
|
2204
|
+
since: definition.meta.since,
|
|
2205
|
+
dependencies: definition.meta.dependencies,
|
|
2206
|
+
figma: definition.meta.figma,
|
|
2207
|
+
figmaProps: definition.meta.figmaProps
|
|
2208
|
+
},
|
|
2209
|
+
guidance: {
|
|
2210
|
+
when: definition.guidance.when,
|
|
2211
|
+
whenNot: definition.guidance.whenNot,
|
|
2212
|
+
guidelines: definition.guidance.guidelines,
|
|
2213
|
+
accessibility: definition.guidance.accessibility
|
|
2214
|
+
},
|
|
2215
|
+
govern: definition.govern,
|
|
2216
|
+
governance: definition.governance
|
|
2217
|
+
}) : [];
|
|
2218
|
+
return {
|
|
2219
|
+
...definition,
|
|
2220
|
+
component,
|
|
2221
|
+
governance
|
|
2222
|
+
};
|
|
2223
|
+
}
|
|
2224
|
+
function defineFragmentOneArg(definition) {
|
|
2225
|
+
if (!definition || typeof definition !== "object") {
|
|
2226
|
+
throwInvalidFragment("unknown", "unknown", [
|
|
2227
|
+
{ path: [], message: "Expected a fragment definition object" }
|
|
2228
|
+
]);
|
|
2229
|
+
}
|
|
2230
|
+
rejectInvalidGovernanceDiscriminants(definition);
|
|
2231
|
+
const governed = isGovernedDefinition(definition);
|
|
2232
|
+
const v2 = isV2Definition(definition);
|
|
2233
|
+
const schema = governed ? governedFragmentDefinitionSchema : v2 ? fragmentDefinitionV2Schema : fragmentDefinitionSchema;
|
|
2234
|
+
const result = schema.safeParse(definition);
|
|
2235
|
+
if (!result.success) {
|
|
2236
|
+
throwInvalidFragment(
|
|
2237
|
+
definition?.meta?.name || "unknown",
|
|
2238
|
+
governed ? "governed" : v2 ? "v2" : "v1",
|
|
2239
|
+
result.error.errors.map((e) => ({ path: e.path, message: e.message }))
|
|
2240
|
+
);
|
|
1941
2241
|
}
|
|
1942
2242
|
if (isGovernedDefinition(definition)) {
|
|
1943
2243
|
const governance = resolveComponentGovernance(definition);
|
|
@@ -1948,6 +2248,17 @@ ${errors}`);
|
|
|
1948
2248
|
}
|
|
1949
2249
|
return definition;
|
|
1950
2250
|
}
|
|
2251
|
+
function defineFragment(componentOrDefinition, maybeDefinition) {
|
|
2252
|
+
if (arguments.length >= 2) {
|
|
2253
|
+
return defineFragmentV3(
|
|
2254
|
+
componentOrDefinition,
|
|
2255
|
+
maybeDefinition
|
|
2256
|
+
);
|
|
2257
|
+
}
|
|
2258
|
+
return defineFragmentOneArg(
|
|
2259
|
+
componentOrDefinition
|
|
2260
|
+
);
|
|
2261
|
+
}
|
|
1951
2262
|
function compileFragment(definition, filePath) {
|
|
1952
2263
|
const v1 = isGovernedDefinition(definition) ? {
|
|
1953
2264
|
component: definition.component,
|
|
@@ -1957,10 +2268,17 @@ function compileFragment(definition, filePath) {
|
|
|
1957
2268
|
relations: definition.relations,
|
|
1958
2269
|
variants: definition.examples ?? [],
|
|
1959
2270
|
contract: definition.contract,
|
|
2271
|
+
ai: definition.composition ? {
|
|
2272
|
+
compositionPattern: definition.composition.pattern,
|
|
2273
|
+
subComponents: definition.composition.subComponents,
|
|
2274
|
+
requiredChildren: definition.composition.requiredChildren,
|
|
2275
|
+
commonPatterns: definition.composition.commonPatterns
|
|
2276
|
+
} : void 0,
|
|
1960
2277
|
_generated: definition._provenance ? {
|
|
1961
|
-
source: definition._provenance.source
|
|
2278
|
+
source: definition._provenance.source,
|
|
1962
2279
|
sourceFile: definition._provenance.sourceFile,
|
|
1963
2280
|
confidence: definition._provenance.confidence,
|
|
2281
|
+
verified: definition._provenance.verified,
|
|
1964
2282
|
timestamp: definition._provenance.timestamp
|
|
1965
2283
|
} : void 0
|
|
1966
2284
|
} : isV2Definition(definition) ? normalizeToV1(definition) : definition;
|
|
@@ -1986,17 +2304,14 @@ function compileFragment(definition, filePath) {
|
|
|
1986
2304
|
};
|
|
1987
2305
|
}
|
|
1988
2306
|
function defineBlock(definition) {
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
throw new Error(`Invalid block definition for "${definition.name || "unknown"}":
|
|
2307
|
+
const result = blockDefinitionSchema.safeParse(definition);
|
|
2308
|
+
if (!result.success) {
|
|
2309
|
+
const errors = result.error.errors.map((e) => `${e.path.join(".") || "(root)"}: ${e.message}`).sort().map((issue) => ` - ${issue}`).join("\n");
|
|
2310
|
+
throw new Error(`Invalid block definition for "${definition.name || "unknown"}":
|
|
1994
2311
|
${errors}`);
|
|
1995
|
-
}
|
|
1996
2312
|
}
|
|
1997
2313
|
return definition;
|
|
1998
2314
|
}
|
|
1999
|
-
var defineRecipe = defineBlock;
|
|
2000
2315
|
function compileBlock(definition, filePath) {
|
|
2001
2316
|
return {
|
|
2002
2317
|
filePath,
|
|
@@ -2008,129 +2323,6 @@ function compileBlock(definition, filePath) {
|
|
|
2008
2323
|
tags: definition.tags
|
|
2009
2324
|
};
|
|
2010
2325
|
}
|
|
2011
|
-
var compileRecipe = compileBlock;
|
|
2012
|
-
|
|
2013
|
-
// src/storyFilters.ts
|
|
2014
|
-
var EXCLUDED_TAGS = /* @__PURE__ */ new Set(["hidden", "internal", "no-fragment"]);
|
|
2015
|
-
var SVG_ICON_RE = /^Svg[A-Z]/;
|
|
2016
|
-
var TEST_TITLE_RE = /\/tests?$/i;
|
|
2017
|
-
var TEST_FILE_RE = /\.test\.stories\./;
|
|
2018
|
-
var DEPRECATED_TITLE_RE = /\bDeprecated\b/i;
|
|
2019
|
-
function checkStoryExclusion(opts) {
|
|
2020
|
-
const { config } = opts;
|
|
2021
|
-
if (isForceIncluded(opts.componentName, config)) {
|
|
2022
|
-
return { excluded: false };
|
|
2023
|
-
}
|
|
2024
|
-
if (isConfigExcluded(opts.componentName, config)) {
|
|
2025
|
-
return {
|
|
2026
|
-
excluded: true,
|
|
2027
|
-
reason: "config-excluded",
|
|
2028
|
-
detail: `'${opts.componentName}' matches storybook.exclude pattern`
|
|
2029
|
-
};
|
|
2030
|
-
}
|
|
2031
|
-
if (config.excludeDeprecated !== false && opts.storybookTitle && DEPRECATED_TITLE_RE.test(opts.storybookTitle)) {
|
|
2032
|
-
return {
|
|
2033
|
-
excluded: true,
|
|
2034
|
-
reason: "deprecated",
|
|
2035
|
-
detail: `Title "${opts.storybookTitle}" contains "Deprecated"`
|
|
2036
|
-
};
|
|
2037
|
-
}
|
|
2038
|
-
if (config.excludeTests !== false) {
|
|
2039
|
-
if (opts.storybookTitle && TEST_TITLE_RE.test(opts.storybookTitle)) {
|
|
2040
|
-
return {
|
|
2041
|
-
excluded: true,
|
|
2042
|
-
reason: "test-story",
|
|
2043
|
-
detail: `Title "${opts.storybookTitle}" ends with /test(s)`
|
|
2044
|
-
};
|
|
2045
|
-
}
|
|
2046
|
-
if (TEST_FILE_RE.test(opts.filePath)) {
|
|
2047
|
-
return {
|
|
2048
|
-
excluded: true,
|
|
2049
|
-
reason: "test-story",
|
|
2050
|
-
detail: `File path matches *.test.stories.*`
|
|
2051
|
-
};
|
|
2052
|
-
}
|
|
2053
|
-
}
|
|
2054
|
-
if (config.excludeSvgIcons !== false) {
|
|
2055
|
-
const names = [opts.componentName, opts.componentDisplayName, opts.componentFunctionName].filter(Boolean);
|
|
2056
|
-
for (const name of names) {
|
|
2057
|
-
if (SVG_ICON_RE.test(name)) {
|
|
2058
|
-
return {
|
|
2059
|
-
excluded: true,
|
|
2060
|
-
reason: "svg-icon",
|
|
2061
|
-
detail: `Component name "${name}" matches Svg[A-Z] pattern`
|
|
2062
|
-
};
|
|
2063
|
-
}
|
|
2064
|
-
}
|
|
2065
|
-
}
|
|
2066
|
-
if (opts.tags?.length) {
|
|
2067
|
-
const hit = opts.tags.find((t) => EXCLUDED_TAGS.has(t));
|
|
2068
|
-
if (hit) {
|
|
2069
|
-
return {
|
|
2070
|
-
excluded: true,
|
|
2071
|
-
reason: "tag-excluded",
|
|
2072
|
-
detail: `Tag "${hit}" is in the exclusion set`
|
|
2073
|
-
};
|
|
2074
|
-
}
|
|
2075
|
-
}
|
|
2076
|
-
if (opts.variantCount === 0) {
|
|
2077
|
-
return {
|
|
2078
|
-
excluded: true,
|
|
2079
|
-
reason: "empty-variants",
|
|
2080
|
-
detail: "Zero renderable story exports"
|
|
2081
|
-
};
|
|
2082
|
-
}
|
|
2083
|
-
return { excluded: false };
|
|
2084
|
-
}
|
|
2085
|
-
function detectSubComponentPaths(storyFiles) {
|
|
2086
|
-
const byDir = /* @__PURE__ */ new Map();
|
|
2087
|
-
for (const file of storyFiles) {
|
|
2088
|
-
const parts = file.relativePath.split("/");
|
|
2089
|
-
if (parts.length < 2) continue;
|
|
2090
|
-
const fileName = parts[parts.length - 1];
|
|
2091
|
-
const baseMatch = fileName.match(/^([^.]+)\.stories\./);
|
|
2092
|
-
if (!baseMatch) continue;
|
|
2093
|
-
const dir = parts.slice(0, -1).join("/");
|
|
2094
|
-
const baseName = baseMatch[1];
|
|
2095
|
-
if (!byDir.has(dir)) byDir.set(dir, []);
|
|
2096
|
-
byDir.get(dir).push({ relativePath: file.relativePath, baseName });
|
|
2097
|
-
}
|
|
2098
|
-
const subComponentMap = /* @__PURE__ */ new Map();
|
|
2099
|
-
for (const [dir, files] of byDir) {
|
|
2100
|
-
if (files.length <= 1) continue;
|
|
2101
|
-
const dirName = dir.split("/").pop();
|
|
2102
|
-
const primary = files.find((f) => f.baseName === dirName);
|
|
2103
|
-
if (!primary) continue;
|
|
2104
|
-
for (const file of files) {
|
|
2105
|
-
if (file.relativePath === primary.relativePath) continue;
|
|
2106
|
-
subComponentMap.set(file.relativePath, primary.baseName);
|
|
2107
|
-
}
|
|
2108
|
-
}
|
|
2109
|
-
return subComponentMap;
|
|
2110
|
-
}
|
|
2111
|
-
function isForceIncluded(name, config) {
|
|
2112
|
-
if (!config.include?.length) return false;
|
|
2113
|
-
return config.include.some((pattern) => matchesPattern(name, pattern));
|
|
2114
|
-
}
|
|
2115
|
-
function isConfigExcluded(name, config) {
|
|
2116
|
-
if (!config.exclude?.length) return false;
|
|
2117
|
-
return config.exclude.some((pattern) => matchesPattern(name, pattern));
|
|
2118
|
-
}
|
|
2119
|
-
function matchesPattern(name, pattern) {
|
|
2120
|
-
if (!pattern.includes("*")) {
|
|
2121
|
-
return name === pattern;
|
|
2122
|
-
}
|
|
2123
|
-
const parts = pattern.split("*");
|
|
2124
|
-
if (parts.length === 2) {
|
|
2125
|
-
const [prefix, suffix] = parts;
|
|
2126
|
-
if (prefix && suffix) return name.startsWith(prefix) && name.endsWith(suffix);
|
|
2127
|
-
if (prefix) return name.startsWith(prefix);
|
|
2128
|
-
if (suffix) return name.endsWith(suffix);
|
|
2129
|
-
return true;
|
|
2130
|
-
}
|
|
2131
|
-
const escaped = parts.map((p) => p.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join(".*");
|
|
2132
|
-
return new RegExp(`^${escaped}$`).test(name);
|
|
2133
|
-
}
|
|
2134
2326
|
|
|
2135
2327
|
// src/figma.ts
|
|
2136
2328
|
function string(figmaProperty) {
|
|
@@ -3694,24 +3886,37 @@ var contractExampleSchema = z6.object({
|
|
|
3694
3886
|
});
|
|
3695
3887
|
var contractRelationSchema = z6.object({
|
|
3696
3888
|
component: z6.string(),
|
|
3697
|
-
relationship: z6.enum([
|
|
3889
|
+
relationship: z6.enum([
|
|
3890
|
+
"alternative",
|
|
3891
|
+
"parent",
|
|
3892
|
+
"child",
|
|
3893
|
+
"sibling",
|
|
3894
|
+
"composition",
|
|
3895
|
+
"complementary",
|
|
3896
|
+
"used-by"
|
|
3897
|
+
]),
|
|
3698
3898
|
note: z6.string()
|
|
3699
3899
|
});
|
|
3700
3900
|
var contractContractSchema = z6.object({
|
|
3701
3901
|
propsSummary: z6.array(z6.string()).optional(),
|
|
3702
3902
|
scenarioTags: z6.array(z6.string()).optional(),
|
|
3703
3903
|
a11yRules: z6.array(z6.string()).optional(),
|
|
3704
|
-
bans: z6.array(
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3904
|
+
bans: z6.array(
|
|
3905
|
+
z6.object({
|
|
3906
|
+
pattern: z6.string(),
|
|
3907
|
+
message: z6.string()
|
|
3908
|
+
})
|
|
3909
|
+
).optional(),
|
|
3910
|
+
compoundChildren: z6.record(
|
|
3911
|
+
z6.string(),
|
|
3912
|
+
z6.object({
|
|
3913
|
+
required: z6.boolean().optional(),
|
|
3914
|
+
accepts: z6.array(z6.string()).optional(),
|
|
3915
|
+
description: z6.string().optional()
|
|
3916
|
+
})
|
|
3917
|
+
).optional(),
|
|
3713
3918
|
canonicalUsage: z6.array(z6.string()).optional(),
|
|
3714
|
-
performanceBudget: z6.number().optional()
|
|
3919
|
+
performanceBudget: z6.number().positive().finite().optional()
|
|
3715
3920
|
});
|
|
3716
3921
|
var contractAiSchema = z6.object({
|
|
3717
3922
|
compositionPattern: z6.enum(["compound", "simple", "controlled", "wrapper"]).optional(),
|
|
@@ -3735,11 +3940,14 @@ var contractProvenanceSchema = z6.object({
|
|
|
3735
3940
|
});
|
|
3736
3941
|
var contractFigmaSchema = z6.object({
|
|
3737
3942
|
nodeUrl: z6.string().optional(),
|
|
3738
|
-
propMappings: z6.record(
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3943
|
+
propMappings: z6.record(
|
|
3944
|
+
z6.string(),
|
|
3945
|
+
z6.object({
|
|
3946
|
+
type: z6.enum(["string", "boolean", "enum", "instance", "children", "textContent"]),
|
|
3947
|
+
figmaProperty: z6.string(),
|
|
3948
|
+
values: z6.record(z6.string(), z6.string()).optional()
|
|
3949
|
+
})
|
|
3950
|
+
).optional()
|
|
3743
3951
|
});
|
|
3744
3952
|
var componentContractSchema = z6.object({
|
|
3745
3953
|
$schema: z6.string(),
|
|
@@ -3749,11 +3957,13 @@ var componentContractSchema = z6.object({
|
|
|
3749
3957
|
tags: z6.array(z6.string()).optional(),
|
|
3750
3958
|
status: z6.enum(["stable", "beta", "deprecated", "experimental"]).optional(),
|
|
3751
3959
|
framework: z6.enum(["react", "vue", "svelte", "web-components", "angular"]).optional(),
|
|
3752
|
-
dependencies: z6.array(
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3960
|
+
dependencies: z6.array(
|
|
3961
|
+
z6.object({
|
|
3962
|
+
name: z6.string(),
|
|
3963
|
+
version: z6.string(),
|
|
3964
|
+
reason: z6.string().optional()
|
|
3965
|
+
})
|
|
3966
|
+
).optional(),
|
|
3757
3967
|
sourcePath: z6.string(),
|
|
3758
3968
|
exportName: z6.string(),
|
|
3759
3969
|
propsSummary: z6.array(z6.string()),
|
|
@@ -3804,6 +4014,8 @@ function parseComponentContract(content, filePath) {
|
|
|
3804
4014
|
} : {
|
|
3805
4015
|
propsSummary: validated.propsSummary
|
|
3806
4016
|
},
|
|
4017
|
+
preview: validated.preview,
|
|
4018
|
+
tokens: validated.tokens,
|
|
3807
4019
|
framework: validated.framework,
|
|
3808
4020
|
ai: validated.ai,
|
|
3809
4021
|
propsSummary: validated.propsSummary,
|
|
@@ -4015,6 +4227,7 @@ function parseFigmaValue(cssValue, category) {
|
|
|
4015
4227
|
// src/composition.ts
|
|
4016
4228
|
var CATEGORY_AFFINITIES = {
|
|
4017
4229
|
forms: ["feedback"],
|
|
4230
|
+
inputs: ["feedback"],
|
|
4018
4231
|
actions: ["feedback"]
|
|
4019
4232
|
};
|
|
4020
4233
|
function analyzeComposition(fragments, componentNames, _context, options) {
|
|
@@ -4120,9 +4333,7 @@ function analyzeComposition(fragments, componentNames, _context, options) {
|
|
|
4120
4333
|
});
|
|
4121
4334
|
}
|
|
4122
4335
|
}
|
|
4123
|
-
const selectedCategories = new Set(
|
|
4124
|
-
components.map((name) => fragments[name].meta.category)
|
|
4125
|
-
);
|
|
4336
|
+
const selectedCategories = new Set(components.map((name) => fragments[name].meta.category));
|
|
4126
4337
|
for (const [category, affinities] of Object.entries(CATEGORY_AFFINITIES)) {
|
|
4127
4338
|
if (!selectedCategories.has(category)) continue;
|
|
4128
4339
|
for (const neededCategory of affinities) {
|
|
@@ -4138,9 +4349,7 @@ function analyzeComposition(fragments, componentNames, _context, options) {
|
|
|
4138
4349
|
component: candidate,
|
|
4139
4350
|
reason: `Compositions using "${category}" components often benefit from a "${neededCategory}" component`,
|
|
4140
4351
|
relationship: "category_gap",
|
|
4141
|
-
sourceComponent: components.find(
|
|
4142
|
-
(n) => fragments[n].meta.category === category
|
|
4143
|
-
)
|
|
4352
|
+
sourceComponent: components.find((n) => fragments[n].meta.category === category)
|
|
4144
4353
|
});
|
|
4145
4354
|
suggestedSet.add(candidate);
|
|
4146
4355
|
}
|
|
@@ -4263,7 +4472,7 @@ function makeFinding(input) {
|
|
|
4263
4472
|
canonicalJson({ ruleId: input.ruleId, ...input.fingerprintIdentity })
|
|
4264
4473
|
);
|
|
4265
4474
|
const previousFingerprint = input.previousFingerprintIdentity ? hash64Hex(canonicalJson({ ruleId: input.ruleId, ...input.previousFingerprintIdentity })) : void 0;
|
|
4266
|
-
const code = byRuleId.get(input.ruleId);
|
|
4475
|
+
const code = input.code ? byCode.get(input.code) : byRuleId.get(input.ruleId);
|
|
4267
4476
|
return normalizeFinding({
|
|
4268
4477
|
ruleId: input.ruleId,
|
|
4269
4478
|
ruleVersion: input.ruleVersion,
|
|
@@ -8374,6 +8583,14 @@ function indexTokensByCssVariable(tokens) {
|
|
|
8374
8583
|
// src/rules/tokens-css-vars-must-be-defined.ts
|
|
8375
8584
|
var RULE_ID22 = "tokens/css-vars-must-be-defined";
|
|
8376
8585
|
var RULE_VERSION23 = "1";
|
|
8586
|
+
var EMPTY_VOCABULARY_CODE = "FUI2018";
|
|
8587
|
+
var EMPTY_VOCABULARY_MESSAGE = "token sources resolved to 0 tokens \u2014 rule inert";
|
|
8588
|
+
var EMPTY_VOCABULARY_CONFIG_FALLBACK = "your fragments config";
|
|
8589
|
+
function emptyVocabularyConfigFile(configPath2) {
|
|
8590
|
+
if (!configPath2) return EMPTY_VOCABULARY_CONFIG_FALLBACK;
|
|
8591
|
+
const base = configPath2.replaceAll("\\", "/").replace(/\/+$/u, "").split("/").pop();
|
|
8592
|
+
return base && base.length > 0 ? base : EMPTY_VOCABULARY_CONFIG_FALLBACK;
|
|
8593
|
+
}
|
|
8377
8594
|
var CSS_VAR_REFERENCE = /var\(\s*(--[A-Za-z0-9_-]+)/gi;
|
|
8378
8595
|
function contractVocabularyContext(ix) {
|
|
8379
8596
|
if (!ix.policy.cssVarsMustBeDefined()) return void 0;
|
|
@@ -8395,7 +8612,7 @@ function ruleTokensCssVarsMustBeDefined(ix) {
|
|
|
8395
8612
|
const policy = ix.policy.cssVarsMustBeDefined();
|
|
8396
8613
|
if (!policy) return [];
|
|
8397
8614
|
const context = contractVocabularyContext(ix);
|
|
8398
|
-
if (!context) return [];
|
|
8615
|
+
if (!context) return [emptyVocabularyFinding(ix, policy)];
|
|
8399
8616
|
const { vocabulary } = context;
|
|
8400
8617
|
const findings = [];
|
|
8401
8618
|
for (const decl of ix.byKind("style_declaration")) {
|
|
@@ -8436,6 +8653,27 @@ function ruleTokensCssVarsMustBeDefined(ix) {
|
|
|
8436
8653
|
}
|
|
8437
8654
|
return findings;
|
|
8438
8655
|
}
|
|
8656
|
+
function emptyVocabularyFinding(ix, policy) {
|
|
8657
|
+
return makeFinding({
|
|
8658
|
+
ruleId: RULE_ID22,
|
|
8659
|
+
ruleVersion: RULE_VERSION23,
|
|
8660
|
+
severity: "error",
|
|
8661
|
+
code: EMPTY_VOCABULARY_CODE,
|
|
8662
|
+
message: EMPTY_VOCABULARY_MESSAGE,
|
|
8663
|
+
location: {
|
|
8664
|
+
file: policy.configPath ?? EMPTY_VOCABULARY_CONFIG_FALLBACK,
|
|
8665
|
+
line: 0,
|
|
8666
|
+
column: 0
|
|
8667
|
+
},
|
|
8668
|
+
evidence: ix.evidence([policy.id]),
|
|
8669
|
+
fingerprintIdentity: { reason: "empty-vocabulary" },
|
|
8670
|
+
attributes: {
|
|
8671
|
+
source: "config",
|
|
8672
|
+
inert: true,
|
|
8673
|
+
tokenCount: 0
|
|
8674
|
+
}
|
|
8675
|
+
});
|
|
8676
|
+
}
|
|
8439
8677
|
function sharesContractPrefix(name, prefixes) {
|
|
8440
8678
|
for (const prefix of prefixes) {
|
|
8441
8679
|
if (name.startsWith(prefix)) return true;
|
|
@@ -8526,6 +8764,30 @@ function ruleTokensUpstreamDrift(ix) {
|
|
|
8526
8764
|
return findings;
|
|
8527
8765
|
}
|
|
8528
8766
|
|
|
8767
|
+
// src/rules/rule-config.ts
|
|
8768
|
+
function readRuleConfig(ix) {
|
|
8769
|
+
const disabled = /* @__PURE__ */ new Set();
|
|
8770
|
+
const severities = /* @__PURE__ */ new Map();
|
|
8771
|
+
for (const fact of ix.byKind("governance_rule_config")) {
|
|
8772
|
+
if (!fact.enabled) {
|
|
8773
|
+
disabled.add(fact.ruleId);
|
|
8774
|
+
continue;
|
|
8775
|
+
}
|
|
8776
|
+
if (fact.severity) severities.set(fact.ruleId, fact.severity);
|
|
8777
|
+
}
|
|
8778
|
+
return { disabled, severities };
|
|
8779
|
+
}
|
|
8780
|
+
function capConfiguredSeverity(finding, configured) {
|
|
8781
|
+
if (finding.attributes?.advisory === true && severityLevel(configured) === "error") {
|
|
8782
|
+
return severityLevel(finding.severity) === "error" ? severityFromLevel("warn") : finding.severity;
|
|
8783
|
+
}
|
|
8784
|
+
return configured;
|
|
8785
|
+
}
|
|
8786
|
+
function configuredFindingSeverity(finding, config) {
|
|
8787
|
+
const configured = config.severities.get(finding.ruleId);
|
|
8788
|
+
return configured ? capConfiguredSeverity(finding, severityFromLevel(configured)) : finding.severity;
|
|
8789
|
+
}
|
|
8790
|
+
|
|
8529
8791
|
// src/rules/emit-gate.ts
|
|
8530
8792
|
var BLOCKING_RULE_ALLOWLIST = /* @__PURE__ */ new Set([
|
|
8531
8793
|
"styles/no-raw-color",
|
|
@@ -8778,8 +9040,12 @@ var RULES = [
|
|
|
8778
9040
|
}
|
|
8779
9041
|
];
|
|
8780
9042
|
function runRules(ix) {
|
|
9043
|
+
const { disabled } = readRuleConfig(ix);
|
|
8781
9044
|
const findings = [];
|
|
8782
|
-
for (const rule of RULES)
|
|
9045
|
+
for (const rule of RULES) {
|
|
9046
|
+
if (disabled.has(rule.id)) continue;
|
|
9047
|
+
findings.push(...rule.run(ix));
|
|
9048
|
+
}
|
|
8783
9049
|
return sortFindings(findings);
|
|
8784
9050
|
}
|
|
8785
9051
|
function sortFindings(findings) {
|
|
@@ -8869,7 +9135,7 @@ var PASSTHROUGH_KEYS = [
|
|
|
8869
9135
|
},
|
|
8870
9136
|
{
|
|
8871
9137
|
path: ["registry"],
|
|
8872
|
-
keys: ["requireStory", "publicOnly", "categoryDepth", "includeProps"
|
|
9138
|
+
keys: ["requireStory", "publicOnly", "categoryDepth", "includeProps"]
|
|
8873
9139
|
},
|
|
8874
9140
|
{
|
|
8875
9141
|
path: ["govern", "tailwind"],
|
|
@@ -9123,11 +9389,11 @@ function collectPassthroughRecordValues(authored, path, allowed, diagnostics) {
|
|
|
9123
9389
|
}
|
|
9124
9390
|
}
|
|
9125
9391
|
function stableConfigDiagnostics(diagnostics) {
|
|
9126
|
-
const
|
|
9392
|
+
const unique3 = /* @__PURE__ */ new Map();
|
|
9127
9393
|
for (const diagnostic of diagnostics) {
|
|
9128
|
-
|
|
9394
|
+
unique3.set(`${diagnostic.code}\0${diagnostic.path}`, diagnostic);
|
|
9129
9395
|
}
|
|
9130
|
-
return [...
|
|
9396
|
+
return [...unique3.values()].sort(
|
|
9131
9397
|
(left, right) => left.path.localeCompare(right.path) || left.code.localeCompare(right.code) || left.message.localeCompare(right.message)
|
|
9132
9398
|
);
|
|
9133
9399
|
}
|
|
@@ -9353,10 +9619,11 @@ function evaluateGovernanceIntegrity(input) {
|
|
|
9353
9619
|
const activeRuleCount = [...configs.entries()].filter(
|
|
9354
9620
|
([ruleId, config]) => CONSUMED_RULE_IDS.has(ruleId) && config.enabled
|
|
9355
9621
|
).length;
|
|
9622
|
+
const tokensVocabularyInert = !tokensArmed && tokensFamily.reason === "no token vocabulary" ? 1 : 0;
|
|
9356
9623
|
const roster = {
|
|
9357
9624
|
configured: configuredRuleCount + configDiagnostics.length,
|
|
9358
|
-
active: activeRuleCount,
|
|
9359
|
-
inert: configDiagnostics.length
|
|
9625
|
+
active: Math.max(0, activeRuleCount - tokensVocabularyInert),
|
|
9626
|
+
inert: configDiagnostics.length + tokensVocabularyInert
|
|
9360
9627
|
};
|
|
9361
9628
|
return {
|
|
9362
9629
|
status,
|
|
@@ -9454,7 +9721,30 @@ function sortRecords(values) {
|
|
|
9454
9721
|
}
|
|
9455
9722
|
|
|
9456
9723
|
// src/contract/preimage.ts
|
|
9724
|
+
var CONTRACT_ENFORCEMENT_FIELDS = [
|
|
9725
|
+
"a11yRules",
|
|
9726
|
+
"bans",
|
|
9727
|
+
"performanceBudget",
|
|
9728
|
+
"compoundChildren",
|
|
9729
|
+
"composition"
|
|
9730
|
+
];
|
|
9731
|
+
var CONTRACT_DISPLAY_ONLY_FIELDS = [
|
|
9732
|
+
"propsSummary",
|
|
9733
|
+
"canonicalUsage",
|
|
9734
|
+
"scenarioTags",
|
|
9735
|
+
"states",
|
|
9736
|
+
"variants"
|
|
9737
|
+
];
|
|
9457
9738
|
var CONTRACT_DOMAINS = ["components", "tokens", "canonicalMap", "policy"];
|
|
9739
|
+
var ContractCatalogValidationError = class extends TypeError {
|
|
9740
|
+
issues;
|
|
9741
|
+
constructor(issues) {
|
|
9742
|
+
const sortedIssues = [...issues].sort();
|
|
9743
|
+
super(["Invalid contract catalog:", ...sortedIssues.map((issue) => ` - ${issue}`)].join("\n"));
|
|
9744
|
+
this.name = "ContractCatalogValidationError";
|
|
9745
|
+
this.issues = sortedIssues;
|
|
9746
|
+
}
|
|
9747
|
+
};
|
|
9458
9748
|
var CONTRACT_PREIMAGE_SCHEMA = "fcid-preimage:v1";
|
|
9459
9749
|
var CONTRACT_PREIMAGE_CAPABILITY_HEADER = "X-Fragments-Contract-Preimage";
|
|
9460
9750
|
var SHA256_HEX_PATTERN = /^[0-9a-f]{64}$/u;
|
|
@@ -9482,13 +9772,225 @@ function verifiedContractPreimageFromPin(pin) {
|
|
|
9482
9772
|
function sortCanonical(items) {
|
|
9483
9773
|
return items.map((item) => ({ item, key: canonicalPreimage(item) })).sort((a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0).map(({ item }) => item);
|
|
9484
9774
|
}
|
|
9775
|
+
function isPlainRecord(value) {
|
|
9776
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
9777
|
+
const prototype = Object.getPrototypeOf(value);
|
|
9778
|
+
return prototype === Object.prototype || prototype === null;
|
|
9779
|
+
}
|
|
9780
|
+
function requireNonEmptyString(value, path, issues) {
|
|
9781
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
9782
|
+
issues.push(`${path}: expected a non-empty string`);
|
|
9783
|
+
}
|
|
9784
|
+
}
|
|
9785
|
+
function validateStringArray(value, path, issues) {
|
|
9786
|
+
if (!Array.isArray(value)) {
|
|
9787
|
+
issues.push(`${path}: expected an array`);
|
|
9788
|
+
return;
|
|
9789
|
+
}
|
|
9790
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9791
|
+
for (const [index, entry] of value.entries()) {
|
|
9792
|
+
requireNonEmptyString(entry, `${path}[${index}]`, issues);
|
|
9793
|
+
if (typeof entry === "string" && entry.length > 0) {
|
|
9794
|
+
if (seen.has(entry)) issues.push(`${path}: duplicate value "${entry}"`);
|
|
9795
|
+
seen.add(entry);
|
|
9796
|
+
}
|
|
9797
|
+
}
|
|
9798
|
+
}
|
|
9799
|
+
function validateContractCatalog(catalog) {
|
|
9800
|
+
const issues = [];
|
|
9801
|
+
if (!isPlainRecord(catalog)) {
|
|
9802
|
+
throw new ContractCatalogValidationError(["(root): expected a plain object"]);
|
|
9803
|
+
}
|
|
9804
|
+
const componentIdentities = /* @__PURE__ */ new Set();
|
|
9805
|
+
if (catalog.components !== void 0) {
|
|
9806
|
+
if (!Array.isArray(catalog.components)) {
|
|
9807
|
+
issues.push("components: expected an array");
|
|
9808
|
+
} else {
|
|
9809
|
+
for (const [index, value] of catalog.components.entries()) {
|
|
9810
|
+
const path = `components[${index}]`;
|
|
9811
|
+
if (!isPlainRecord(value)) {
|
|
9812
|
+
issues.push(`${path}: expected a plain object`);
|
|
9813
|
+
continue;
|
|
9814
|
+
}
|
|
9815
|
+
requireNonEmptyString(value.name, `${path}.name`, issues);
|
|
9816
|
+
if (value.parentName !== void 0) {
|
|
9817
|
+
requireNonEmptyString(value.parentName, `${path}.parentName`, issues);
|
|
9818
|
+
}
|
|
9819
|
+
if (typeof value.name === "string" && value.name.length > 0) {
|
|
9820
|
+
const identity = `${typeof value.parentName === "string" ? value.parentName : ""}#${value.name}`;
|
|
9821
|
+
if (componentIdentities.has(identity)) {
|
|
9822
|
+
issues.push(`components: duplicate identity "${identity}"`);
|
|
9823
|
+
}
|
|
9824
|
+
componentIdentities.add(identity);
|
|
9825
|
+
}
|
|
9826
|
+
if (value.props !== void 0) validateStringArray(value.props, `${path}.props`, issues);
|
|
9827
|
+
if (value.compoundChildren !== void 0) {
|
|
9828
|
+
validateStringArray(value.compoundChildren, `${path}.compoundChildren`, issues);
|
|
9829
|
+
}
|
|
9830
|
+
if (value.contract !== void 0 && !isPlainRecord(value.contract)) {
|
|
9831
|
+
issues.push(`${path}.contract: expected a plain object`);
|
|
9832
|
+
}
|
|
9833
|
+
if (value.governance !== void 0 && !Array.isArray(value.governance)) {
|
|
9834
|
+
issues.push(`${path}.governance: expected an array`);
|
|
9835
|
+
}
|
|
9836
|
+
}
|
|
9837
|
+
}
|
|
9838
|
+
}
|
|
9839
|
+
const tokenNames = /* @__PURE__ */ new Set();
|
|
9840
|
+
if (catalog.tokens !== void 0) {
|
|
9841
|
+
if (!Array.isArray(catalog.tokens)) {
|
|
9842
|
+
issues.push("tokens: expected an array");
|
|
9843
|
+
} else {
|
|
9844
|
+
for (const [index, value] of catalog.tokens.entries()) {
|
|
9845
|
+
const path = `tokens[${index}]`;
|
|
9846
|
+
if (!isPlainRecord(value)) {
|
|
9847
|
+
issues.push(`${path}: expected a plain object`);
|
|
9848
|
+
continue;
|
|
9849
|
+
}
|
|
9850
|
+
requireNonEmptyString(value.name, `${path}.name`, issues);
|
|
9851
|
+
if (typeof value.name === "string" && value.name.length > 0) {
|
|
9852
|
+
if (tokenNames.has(value.name)) issues.push(`tokens: duplicate identity "${value.name}"`);
|
|
9853
|
+
tokenNames.add(value.name);
|
|
9854
|
+
}
|
|
9855
|
+
if (typeof value.value !== "string" && typeof value.value !== "number" || typeof value.value === "number" && !Number.isFinite(value.value)) {
|
|
9856
|
+
issues.push(`${path}.value: expected a finite number or string`);
|
|
9857
|
+
}
|
|
9858
|
+
if (value.type !== void 0) requireNonEmptyString(value.type, `${path}.type`, issues);
|
|
9859
|
+
}
|
|
9860
|
+
}
|
|
9861
|
+
}
|
|
9862
|
+
const confirmedMappings = /* @__PURE__ */ new Set();
|
|
9863
|
+
if (catalog.canonicalMappings !== void 0) {
|
|
9864
|
+
if (!Array.isArray(catalog.canonicalMappings)) {
|
|
9865
|
+
issues.push("canonicalMappings: expected an array");
|
|
9866
|
+
} else {
|
|
9867
|
+
for (const [index, value] of catalog.canonicalMappings.entries()) {
|
|
9868
|
+
const path = `canonicalMappings[${index}]`;
|
|
9869
|
+
if (!isPlainRecord(value)) {
|
|
9870
|
+
issues.push(`${path}: expected a plain object`);
|
|
9871
|
+
continue;
|
|
9872
|
+
}
|
|
9873
|
+
requireNonEmptyString(value.component, `${path}.component`, issues);
|
|
9874
|
+
requireNonEmptyString(value.canonical, `${path}.canonical`, issues);
|
|
9875
|
+
if (!["confirmed", "proposed", "unknown"].includes(value.status)) {
|
|
9876
|
+
issues.push(`${path}.status: expected confirmed, proposed, or unknown`);
|
|
9877
|
+
}
|
|
9878
|
+
if (value.status === "confirmed" && typeof value.component === "string") {
|
|
9879
|
+
if (confirmedMappings.has(value.component)) {
|
|
9880
|
+
issues.push(`canonicalMappings: duplicate confirmed identity "${value.component}"`);
|
|
9881
|
+
}
|
|
9882
|
+
confirmedMappings.add(value.component);
|
|
9883
|
+
}
|
|
9884
|
+
if (value.importPath !== void 0) {
|
|
9885
|
+
requireNonEmptyString(value.importPath, `${path}.importPath`, issues);
|
|
9886
|
+
}
|
|
9887
|
+
if (value.propMapping !== void 0 && !Array.isArray(value.propMapping)) {
|
|
9888
|
+
issues.push(`${path}.propMapping: expected an array`);
|
|
9889
|
+
}
|
|
9890
|
+
if (value.resolves !== void 0 && !Array.isArray(value.resolves)) {
|
|
9891
|
+
issues.push(`${path}.resolves: expected an array`);
|
|
9892
|
+
}
|
|
9893
|
+
if (value.bridge !== void 0 && !isPlainRecord(value.bridge)) {
|
|
9894
|
+
issues.push(`${path}.bridge: expected a plain object`);
|
|
9895
|
+
}
|
|
9896
|
+
}
|
|
9897
|
+
}
|
|
9898
|
+
}
|
|
9899
|
+
if (catalog.policy !== void 0 && catalog.policy !== null) {
|
|
9900
|
+
if (!isPlainRecord(catalog.policy)) {
|
|
9901
|
+
issues.push("policy: expected a plain object or null");
|
|
9902
|
+
} else {
|
|
9903
|
+
if (catalog.policy.rules !== void 0 && !isPlainRecord(catalog.policy.rules)) {
|
|
9904
|
+
issues.push("policy.rules: expected a plain object");
|
|
9905
|
+
}
|
|
9906
|
+
if (catalog.policy.codes !== void 0 && !isPlainRecord(catalog.policy.codes)) {
|
|
9907
|
+
issues.push("policy.codes: expected a plain object");
|
|
9908
|
+
}
|
|
9909
|
+
if (catalog.policy.compositionPatterns !== void 0 && !Array.isArray(catalog.policy.compositionPatterns)) {
|
|
9910
|
+
issues.push("policy.compositionPatterns: expected an array");
|
|
9911
|
+
}
|
|
9912
|
+
if (catalog.policy.waivers !== void 0) {
|
|
9913
|
+
if (!Array.isArray(catalog.policy.waivers)) {
|
|
9914
|
+
issues.push("policy.waivers: expected an array");
|
|
9915
|
+
} else {
|
|
9916
|
+
const waiverIds = /* @__PURE__ */ new Set();
|
|
9917
|
+
for (const [index, value] of catalog.policy.waivers.entries()) {
|
|
9918
|
+
const path = `policy.waivers[${index}]`;
|
|
9919
|
+
if (!isPlainRecord(value)) {
|
|
9920
|
+
issues.push(`${path}: expected a plain object`);
|
|
9921
|
+
continue;
|
|
9922
|
+
}
|
|
9923
|
+
requireNonEmptyString(value.id, `${path}.id`, issues);
|
|
9924
|
+
requireNonEmptyString(value.target, `${path}.target`, issues);
|
|
9925
|
+
requireNonEmptyString(value.reason, `${path}.reason`, issues);
|
|
9926
|
+
if (value.expiresOn !== void 0) {
|
|
9927
|
+
requireNonEmptyString(value.expiresOn, `${path}.expiresOn`, issues);
|
|
9928
|
+
}
|
|
9929
|
+
if (typeof value.id === "string" && value.id.length > 0) {
|
|
9930
|
+
if (waiverIds.has(value.id)) {
|
|
9931
|
+
issues.push(`policy.waivers: duplicate identity "${value.id}"`);
|
|
9932
|
+
}
|
|
9933
|
+
waiverIds.add(value.id);
|
|
9934
|
+
}
|
|
9935
|
+
}
|
|
9936
|
+
}
|
|
9937
|
+
}
|
|
9938
|
+
}
|
|
9939
|
+
}
|
|
9940
|
+
if (issues.length > 0) throw new ContractCatalogValidationError(issues);
|
|
9941
|
+
}
|
|
9942
|
+
function projectEnforcementContract(contract) {
|
|
9943
|
+
if (!contract || typeof contract !== "object" || Array.isArray(contract)) {
|
|
9944
|
+
return void 0;
|
|
9945
|
+
}
|
|
9946
|
+
const source = contract;
|
|
9947
|
+
const projected = {};
|
|
9948
|
+
if (Array.isArray(source.a11yRules)) {
|
|
9949
|
+
projected.a11yRules = sortCanonical([...source.a11yRules]);
|
|
9950
|
+
}
|
|
9951
|
+
if (Array.isArray(source.bans)) {
|
|
9952
|
+
projected.bans = sortCanonical([...source.bans]);
|
|
9953
|
+
}
|
|
9954
|
+
if (typeof source.performanceBudget === "number") {
|
|
9955
|
+
projected.performanceBudget = source.performanceBudget;
|
|
9956
|
+
}
|
|
9957
|
+
if (Array.isArray(source.composition)) {
|
|
9958
|
+
projected.composition = sortCanonical([...source.composition]);
|
|
9959
|
+
}
|
|
9960
|
+
const compoundChildren = projectContractCompoundChildren(source.compoundChildren);
|
|
9961
|
+
if (compoundChildren !== void 0) {
|
|
9962
|
+
projected.compoundChildren = compoundChildren;
|
|
9963
|
+
}
|
|
9964
|
+
return Object.keys(projected).length > 0 ? projected : void 0;
|
|
9965
|
+
}
|
|
9966
|
+
function projectContractCompoundChildren(value) {
|
|
9967
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
9968
|
+
const entries = Object.entries(value).map(([name, raw]) => {
|
|
9969
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
9970
|
+
return [name, {}];
|
|
9971
|
+
}
|
|
9972
|
+
const child = raw;
|
|
9973
|
+
const projected = {};
|
|
9974
|
+
if (typeof child.required === "boolean") projected.required = child.required;
|
|
9975
|
+
if (Array.isArray(child.accepts)) {
|
|
9976
|
+
projected.accepts = [...child.accepts].filter((entry) => typeof entry === "string").sort();
|
|
9977
|
+
}
|
|
9978
|
+
return [name, projected];
|
|
9979
|
+
}).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
|
|
9980
|
+
return Object.fromEntries(entries);
|
|
9981
|
+
}
|
|
9982
|
+
function projectGovernanceRecords(records) {
|
|
9983
|
+
if (!records || records.length === 0) return void 0;
|
|
9984
|
+
return sortCanonical([...records]);
|
|
9985
|
+
}
|
|
9485
9986
|
function projectComponents(components) {
|
|
9486
9987
|
return sortCanonical(
|
|
9487
9988
|
(components ?? []).map((component) => ({
|
|
9488
9989
|
name: component.name,
|
|
9489
9990
|
parentName: component.parentName,
|
|
9490
9991
|
props: component.props ? [...component.props].sort() : void 0,
|
|
9491
|
-
contract: component.contract,
|
|
9992
|
+
contract: projectEnforcementContract(component.contract),
|
|
9993
|
+
governance: projectGovernanceRecords(component.governance),
|
|
9492
9994
|
compoundChildren: component.compoundChildren ? [...component.compoundChildren].sort() : void 0
|
|
9493
9995
|
}))
|
|
9494
9996
|
);
|
|
@@ -9570,6 +10072,7 @@ function projectPolicy(policy) {
|
|
|
9570
10072
|
};
|
|
9571
10073
|
}
|
|
9572
10074
|
function projectContractPreimage(catalog) {
|
|
10075
|
+
validateContractCatalog(catalog);
|
|
9573
10076
|
return {
|
|
9574
10077
|
schema: CONTRACT_PREIMAGE_SCHEMA,
|
|
9575
10078
|
domains: {
|
|
@@ -9609,16 +10112,31 @@ function contractComponentsFromFragments(fragments) {
|
|
|
9609
10112
|
const parentName = fragment?.meta?.parentComponentName;
|
|
9610
10113
|
const rawChildren = fragment?.structure?.compoundChildren;
|
|
9611
10114
|
const compoundChildren = Array.isArray(rawChildren) ? rawChildren.map((child) => child?.name).filter((childName) => typeof childName === "string") : void 0;
|
|
10115
|
+
const governance = resolveGovernanceRecordsForIdentity({
|
|
10116
|
+
governance: Array.isArray(fragment?.governance) ? fragment.governance : void 0,
|
|
10117
|
+
govern: typeof fragment?.govern === "function" ? fragment.govern : void 0
|
|
10118
|
+
});
|
|
9612
10119
|
components.push({
|
|
9613
10120
|
name,
|
|
9614
10121
|
parentName: typeof parentName === "string" ? parentName : void 0,
|
|
9615
10122
|
props: Object.keys(fragment?.props ?? {}),
|
|
9616
10123
|
contract: fragment?.contract,
|
|
10124
|
+
governance,
|
|
9617
10125
|
compoundChildren
|
|
9618
10126
|
});
|
|
9619
10127
|
}
|
|
9620
10128
|
return components;
|
|
9621
10129
|
}
|
|
10130
|
+
function deriveArtifactId(content) {
|
|
10131
|
+
return artifactContentHash({
|
|
10132
|
+
schema: "artifact-content:v1",
|
|
10133
|
+
modules: content.modules,
|
|
10134
|
+
states: content.states,
|
|
10135
|
+
guidance: content.guidance,
|
|
10136
|
+
render: content.render,
|
|
10137
|
+
runtime: content.runtime
|
|
10138
|
+
});
|
|
10139
|
+
}
|
|
9622
10140
|
|
|
9623
10141
|
// src/contract/stamp.ts
|
|
9624
10142
|
var AGENT_CONTEXT_RELATIVE_PATH = ".fragments/agent-context.md";
|
|
@@ -9650,7 +10168,7 @@ function parseContractStamp(text) {
|
|
|
9650
10168
|
const fcidLine = STAMP_FCID_LINE.exec(text);
|
|
9651
10169
|
if (!header || !fcidLine) return null;
|
|
9652
10170
|
const contractVersion = Number(header[1]);
|
|
9653
|
-
if (!Number.isSafeInteger(contractVersion)) return null;
|
|
10171
|
+
if (!Number.isSafeInteger(contractVersion) || contractVersion < 1) return null;
|
|
9654
10172
|
const fcid = fcidLine[1];
|
|
9655
10173
|
if (!fcid.startsWith(header[2])) return null;
|
|
9656
10174
|
const domainsLine = STAMP_DOMAINS_LINE.exec(text);
|
|
@@ -9936,24 +10454,2078 @@ function strongOverlap(overlap) {
|
|
|
9936
10454
|
function withTarget(state, confidence, canonicalTarget) {
|
|
9937
10455
|
return canonicalTarget ? { state, confidence, canonicalTarget } : { state, confidence };
|
|
9938
10456
|
}
|
|
10457
|
+
|
|
10458
|
+
// src/repository-binding.ts
|
|
10459
|
+
import { z as z8 } from "zod";
|
|
10460
|
+
var REPOSITORY_BINDING_ID_MAX_BYTES_V1 = 256;
|
|
10461
|
+
var PROVIDER_ID_MAX_BYTES_V1 = 64;
|
|
10462
|
+
var utf8Length = (value) => new TextEncoder().encode(value).byteLength;
|
|
10463
|
+
var boundedString = (label, maxBytes) => z8.string().min(1, `${label} is required`).refine((value) => utf8Length(value) <= maxBytes, `${label} exceeds ${maxBytes} UTF-8 bytes`);
|
|
10464
|
+
var providerSchema = boundedString("provider", PROVIDER_ID_MAX_BYTES_V1).transform((value) => value.trim().toLowerCase()).refine(
|
|
10465
|
+
(value) => /^[a-z][a-z0-9_-]*$/u.test(value),
|
|
10466
|
+
"provider must be a bounded lowercase identifier"
|
|
10467
|
+
);
|
|
10468
|
+
function normalizeProviderInstanceId(value) {
|
|
10469
|
+
const trimmed = value.trim();
|
|
10470
|
+
if (trimmed.length === 0) throw new TypeError("providerInstanceId is required");
|
|
10471
|
+
if (trimmed.includes("://")) {
|
|
10472
|
+
const url = new URL(trimmed);
|
|
10473
|
+
if (url.protocol !== "https:" && url.protocol !== "http:") {
|
|
10474
|
+
throw new TypeError("providerInstanceId URL must use http or https");
|
|
10475
|
+
}
|
|
10476
|
+
if (url.username || url.password || url.search || url.hash || url.pathname !== "" && url.pathname !== "/") {
|
|
10477
|
+
throw new TypeError("providerInstanceId must identify an origin, not a path or credential");
|
|
10478
|
+
}
|
|
10479
|
+
return url.host.toLowerCase().replace(/\.$/u, "");
|
|
10480
|
+
}
|
|
10481
|
+
const normalized = trimmed.toLowerCase().replace(/\.$/u, "");
|
|
10482
|
+
if (!/^[a-z0-9](?:[a-z0-9._:-]*[a-z0-9])?$/u.test(normalized)) {
|
|
10483
|
+
throw new TypeError("providerInstanceId must be a normalized origin or tenant key");
|
|
10484
|
+
}
|
|
10485
|
+
return normalized;
|
|
10486
|
+
}
|
|
10487
|
+
var providerInstanceSchema = boundedString(
|
|
10488
|
+
"providerInstanceId",
|
|
10489
|
+
REPOSITORY_BINDING_ID_MAX_BYTES_V1
|
|
10490
|
+
).transform((value, context) => {
|
|
10491
|
+
try {
|
|
10492
|
+
return normalizeProviderInstanceId(value);
|
|
10493
|
+
} catch (error) {
|
|
10494
|
+
context.addIssue({
|
|
10495
|
+
code: z8.ZodIssueCode.custom,
|
|
10496
|
+
message: error instanceof Error ? error.message : String(error)
|
|
10497
|
+
});
|
|
10498
|
+
return z8.NEVER;
|
|
10499
|
+
}
|
|
10500
|
+
});
|
|
10501
|
+
var repositoryBindingKeyV1Schema = z8.object({
|
|
10502
|
+
provider: providerSchema,
|
|
10503
|
+
providerInstanceId: providerInstanceSchema,
|
|
10504
|
+
repositoryExternalId: boundedString("repositoryExternalId", REPOSITORY_BINDING_ID_MAX_BYTES_V1),
|
|
10505
|
+
bindingId: boundedString("bindingId", REPOSITORY_BINDING_ID_MAX_BYTES_V1)
|
|
10506
|
+
}).strict();
|
|
10507
|
+
function normalizeRepositoryBindingKeyV1(value) {
|
|
10508
|
+
return repositoryBindingKeyV1Schema.parse(value);
|
|
10509
|
+
}
|
|
10510
|
+
function repositoryBindingDigestV1(value) {
|
|
10511
|
+
const binding = normalizeRepositoryBindingKeyV1(value);
|
|
10512
|
+
return digestHexSchema.parse(
|
|
10513
|
+
sha256Hex(
|
|
10514
|
+
canonicalPreimage({
|
|
10515
|
+
schema: "repository-binding.v1",
|
|
10516
|
+
provider: binding.provider,
|
|
10517
|
+
providerInstanceId: binding.providerInstanceId,
|
|
10518
|
+
repositoryExternalId: binding.repositoryExternalId,
|
|
10519
|
+
bindingId: binding.bindingId
|
|
10520
|
+
})
|
|
10521
|
+
)
|
|
10522
|
+
);
|
|
10523
|
+
}
|
|
10524
|
+
|
|
10525
|
+
// src/analysis-plan/types.ts
|
|
10526
|
+
import { z as z9 } from "zod";
|
|
10527
|
+
var ANALYSIS_PLAN_MAX_REGIONS_V1 = 1e3;
|
|
10528
|
+
var ANALYSIS_PLAN_MAX_CAPABILITIES_V1 = 256;
|
|
10529
|
+
var ANALYSIS_PLAN_MAX_DIALECTS_PER_REGION_V1 = 64;
|
|
10530
|
+
var ANALYSIS_LIMIT_CEILINGS_V1 = {
|
|
10531
|
+
maxSourceFiles: 1e5,
|
|
10532
|
+
maxSourceBytes: 1073741824,
|
|
10533
|
+
maxFileBytes: 10485760,
|
|
10534
|
+
maxFacts: 1e6,
|
|
10535
|
+
maxRegions: ANALYSIS_PLAN_MAX_REGIONS_V1,
|
|
10536
|
+
maxDiagnostics: 1e5,
|
|
10537
|
+
maxDurationMs: 9e5
|
|
10538
|
+
};
|
|
10539
|
+
var bounded = (max) => z9.string().min(1).max(max);
|
|
10540
|
+
var positiveBoundedInteger = (max) => z9.number().int().positive().max(max);
|
|
10541
|
+
var uniqueStrings = (values) => new Set(values).size === values.length;
|
|
10542
|
+
var coverageStateV1Schema = z9.enum([
|
|
10543
|
+
"analyzed",
|
|
10544
|
+
"unsupported",
|
|
10545
|
+
"excluded_by_contract",
|
|
10546
|
+
"skipped_limit",
|
|
10547
|
+
"failed"
|
|
10548
|
+
]);
|
|
10549
|
+
var analysisLimitsV1Schema = z9.object({
|
|
10550
|
+
maxSourceFiles: positiveBoundedInteger(ANALYSIS_LIMIT_CEILINGS_V1.maxSourceFiles),
|
|
10551
|
+
maxSourceBytes: positiveBoundedInteger(ANALYSIS_LIMIT_CEILINGS_V1.maxSourceBytes),
|
|
10552
|
+
maxFileBytes: positiveBoundedInteger(ANALYSIS_LIMIT_CEILINGS_V1.maxFileBytes),
|
|
10553
|
+
maxFacts: positiveBoundedInteger(ANALYSIS_LIMIT_CEILINGS_V1.maxFacts),
|
|
10554
|
+
maxRegions: positiveBoundedInteger(ANALYSIS_LIMIT_CEILINGS_V1.maxRegions),
|
|
10555
|
+
maxDiagnostics: positiveBoundedInteger(ANALYSIS_LIMIT_CEILINGS_V1.maxDiagnostics),
|
|
10556
|
+
maxDurationMs: positiveBoundedInteger(ANALYSIS_LIMIT_CEILINGS_V1.maxDurationMs)
|
|
10557
|
+
}).strict();
|
|
10558
|
+
var analysisRegionV1Schema = z9.object({
|
|
10559
|
+
regionId: bounded(256),
|
|
10560
|
+
pathPattern: bounded(4096),
|
|
10561
|
+
kind: z9.enum(["component_source", "style_source", "token_source", "config"]),
|
|
10562
|
+
language: bounded(64),
|
|
10563
|
+
required: z9.boolean(),
|
|
10564
|
+
requiredDialects: z9.array(bounded(128)).max(ANALYSIS_PLAN_MAX_DIALECTS_PER_REGION_V1).refine(uniqueStrings, "requiredDialects must be unique"),
|
|
10565
|
+
analyzer: z9.object({
|
|
10566
|
+
id: bounded(256),
|
|
10567
|
+
interfaceVersion: bounded(128),
|
|
10568
|
+
implementationVersion: bounded(128)
|
|
10569
|
+
}).strict()
|
|
10570
|
+
}).strict();
|
|
10571
|
+
var coverageRegionV1Schema = z9.object({
|
|
10572
|
+
regionId: bounded(256),
|
|
10573
|
+
state: coverageStateV1Schema,
|
|
10574
|
+
fileCount: z9.number().int().nonnegative().max(ANALYSIS_LIMIT_CEILINGS_V1.maxSourceFiles),
|
|
10575
|
+
byteCount: z9.number().int().nonnegative().max(ANALYSIS_LIMIT_CEILINGS_V1.maxSourceBytes),
|
|
10576
|
+
diagnosticIds: z9.array(bounded(256)).max(ANALYSIS_LIMIT_CEILINGS_V1.maxDiagnostics).refine(uniqueStrings, "diagnosticIds must be unique")
|
|
10577
|
+
}).strict();
|
|
10578
|
+
var coverageCountsV1Schema = z9.object({
|
|
10579
|
+
analyzed: z9.number().int().nonnegative(),
|
|
10580
|
+
unsupported: z9.number().int().nonnegative(),
|
|
10581
|
+
excluded_by_contract: z9.number().int().nonnegative(),
|
|
10582
|
+
skipped_limit: z9.number().int().nonnegative(),
|
|
10583
|
+
failed: z9.number().int().nonnegative()
|
|
10584
|
+
}).strict();
|
|
10585
|
+
var coverageSummaryV1Schema = z9.object({
|
|
10586
|
+
plannedRegions: z9.number().int().nonnegative(),
|
|
10587
|
+
observedRegions: z9.number().int().nonnegative(),
|
|
10588
|
+
requiredRegions: z9.number().int().nonnegative(),
|
|
10589
|
+
requiredByState: coverageCountsV1Schema,
|
|
10590
|
+
optionalByState: coverageCountsV1Schema,
|
|
10591
|
+
eligibleFiles: z9.number().int().nonnegative(),
|
|
10592
|
+
analyzedFiles: z9.number().int().nonnegative(),
|
|
10593
|
+
analyzedBytes: z9.number().int().nonnegative()
|
|
10594
|
+
}).strict();
|
|
10595
|
+
var analysisPlanBaseShape = {
|
|
10596
|
+
binding: repositoryBindingKeyV1Schema,
|
|
10597
|
+
source: z9.object({
|
|
10598
|
+
commitId: bounded(256),
|
|
10599
|
+
treeId: bounded(256).optional(),
|
|
10600
|
+
defaultBranch: bounded(256),
|
|
10601
|
+
acquiredBy: z9.enum(["github_app", "local_worktree", "ci_attested"])
|
|
10602
|
+
}).strict(),
|
|
10603
|
+
contract: z9.object({
|
|
10604
|
+
fcid: digestHexStringSchema,
|
|
10605
|
+
artifactDigest: digestHexStringSchema
|
|
10606
|
+
}).strict(),
|
|
10607
|
+
config: z9.object({
|
|
10608
|
+
path: bounded(4096).refine(
|
|
10609
|
+
(value) => !value.startsWith("/") && !value.includes("\\") && !value.split("/").includes(".."),
|
|
10610
|
+
"config path must be a portable repository-relative path"
|
|
10611
|
+
),
|
|
10612
|
+
digest: digestHexStringSchema
|
|
10613
|
+
}).strict(),
|
|
10614
|
+
profile: z9.object({
|
|
10615
|
+
id: z9.literal("react-web-v1"),
|
|
10616
|
+
version: bounded(128),
|
|
10617
|
+
capabilities: z9.array(bounded(128)).max(ANALYSIS_PLAN_MAX_CAPABILITIES_V1).refine(uniqueStrings, "capabilities must be unique")
|
|
10618
|
+
}).strict(),
|
|
10619
|
+
regions: z9.array(analysisRegionV1Schema).max(ANALYSIS_PLAN_MAX_REGIONS_V1).refine(
|
|
10620
|
+
(regions) => new Set(regions.map((region) => region.regionId)).size === regions.length,
|
|
10621
|
+
"regionId values must be unique"
|
|
10622
|
+
),
|
|
10623
|
+
limits: analysisLimitsV1Schema,
|
|
10624
|
+
evaluatorVersion: bounded(128),
|
|
10625
|
+
createdAt: z9.string().datetime({ offset: true })
|
|
10626
|
+
};
|
|
10627
|
+
function validatePlanLimits(plan, context) {
|
|
10628
|
+
if (plan.regions.length > plan.limits.maxRegions) {
|
|
10629
|
+
context.addIssue({
|
|
10630
|
+
code: z9.ZodIssueCode.custom,
|
|
10631
|
+
path: ["regions"],
|
|
10632
|
+
message: "Planned regions exceed the plan's maxRegions limit"
|
|
10633
|
+
});
|
|
10634
|
+
}
|
|
10635
|
+
if (plan.limits.maxFileBytes > plan.limits.maxSourceBytes) {
|
|
10636
|
+
context.addIssue({
|
|
10637
|
+
code: z9.ZodIssueCode.custom,
|
|
10638
|
+
path: ["limits", "maxFileBytes"],
|
|
10639
|
+
message: "maxFileBytes cannot exceed maxSourceBytes"
|
|
10640
|
+
});
|
|
10641
|
+
}
|
|
10642
|
+
}
|
|
10643
|
+
var analysisPlanInputV1Schema = z9.object(analysisPlanBaseShape).strict().superRefine(validatePlanLimits);
|
|
10644
|
+
var analysisPlanV1Schema = z9.object({
|
|
10645
|
+
schemaVersion: z9.literal(1),
|
|
10646
|
+
analysisPlanId: analysisPlanIdStringSchema,
|
|
10647
|
+
...analysisPlanBaseShape,
|
|
10648
|
+
obligationsDigest: digestHexStringSchema,
|
|
10649
|
+
digest: digestHexStringSchema
|
|
10650
|
+
}).strict().superRefine(validatePlanLimits);
|
|
10651
|
+
|
|
10652
|
+
// src/analysis-plan/digest.ts
|
|
10653
|
+
var sortedUnique = (values) => [...new Set(values)].sort();
|
|
10654
|
+
function semanticInput(input) {
|
|
10655
|
+
return {
|
|
10656
|
+
binding: input.binding,
|
|
10657
|
+
source: input.source,
|
|
10658
|
+
contract: input.contract,
|
|
10659
|
+
config: input.config,
|
|
10660
|
+
profile: input.profile,
|
|
10661
|
+
regions: input.regions,
|
|
10662
|
+
limits: input.limits,
|
|
10663
|
+
evaluatorVersion: input.evaluatorVersion,
|
|
10664
|
+
createdAt: input.createdAt
|
|
10665
|
+
};
|
|
10666
|
+
}
|
|
10667
|
+
function normalizeRegion(region) {
|
|
10668
|
+
return {
|
|
10669
|
+
...region,
|
|
10670
|
+
requiredDialects: sortedUnique(region.requiredDialects),
|
|
10671
|
+
analyzer: { ...region.analyzer }
|
|
10672
|
+
};
|
|
10673
|
+
}
|
|
10674
|
+
function normalizeAnalysisPlanInputV1(input) {
|
|
10675
|
+
const semantic = semanticInput(input);
|
|
10676
|
+
const normalized = {
|
|
10677
|
+
...semantic,
|
|
10678
|
+
binding: normalizeRepositoryBindingKeyV1(semantic.binding),
|
|
10679
|
+
source: { ...semantic.source },
|
|
10680
|
+
contract: { ...semantic.contract },
|
|
10681
|
+
config: { ...semantic.config },
|
|
10682
|
+
profile: {
|
|
10683
|
+
...semantic.profile,
|
|
10684
|
+
capabilities: sortedUnique(semantic.profile.capabilities)
|
|
10685
|
+
},
|
|
10686
|
+
regions: semantic.regions.map(normalizeRegion).sort((left, right) => compareCanonicalStrings(left.regionId, right.regionId)),
|
|
10687
|
+
limits: { ...semantic.limits }
|
|
10688
|
+
};
|
|
10689
|
+
return analysisPlanInputV1Schema.parse(normalized);
|
|
10690
|
+
}
|
|
10691
|
+
function obligationsProjection(normalized) {
|
|
10692
|
+
return {
|
|
10693
|
+
schema: "analysis-obligations.v1",
|
|
10694
|
+
bindingDigest: repositoryBindingDigestV1(normalized.binding),
|
|
10695
|
+
contract: normalized.contract,
|
|
10696
|
+
config: normalized.config,
|
|
10697
|
+
profile: normalized.profile,
|
|
10698
|
+
regions: normalized.regions,
|
|
10699
|
+
limits: normalized.limits,
|
|
10700
|
+
evaluatorVersion: normalized.evaluatorVersion
|
|
10701
|
+
};
|
|
10702
|
+
}
|
|
10703
|
+
function exactPlanProjection(normalized) {
|
|
10704
|
+
return {
|
|
10705
|
+
schema: "analysis-plan.v1",
|
|
10706
|
+
bindingDigest: repositoryBindingDigestV1(normalized.binding),
|
|
10707
|
+
source: {
|
|
10708
|
+
commitId: normalized.source.commitId,
|
|
10709
|
+
treeId: normalized.source.treeId,
|
|
10710
|
+
acquiredBy: normalized.source.acquiredBy
|
|
10711
|
+
},
|
|
10712
|
+
contract: normalized.contract,
|
|
10713
|
+
config: normalized.config,
|
|
10714
|
+
profile: normalized.profile,
|
|
10715
|
+
regions: normalized.regions,
|
|
10716
|
+
limits: normalized.limits,
|
|
10717
|
+
evaluatorVersion: normalized.evaluatorVersion
|
|
10718
|
+
};
|
|
10719
|
+
}
|
|
10720
|
+
function analysisObligationsDigestV1(input) {
|
|
10721
|
+
const normalized = normalizeAnalysisPlanInputV1(input);
|
|
10722
|
+
return digestHexSchema.parse(sha256Hex(canonicalPreimage(obligationsProjection(normalized))));
|
|
10723
|
+
}
|
|
10724
|
+
function analysisPlanDigestV1(input) {
|
|
10725
|
+
const normalized = normalizeAnalysisPlanInputV1(input);
|
|
10726
|
+
return digestHexSchema.parse(sha256Hex(canonicalPreimage(exactPlanProjection(normalized))));
|
|
10727
|
+
}
|
|
10728
|
+
function buildAnalysisPlanV1(input) {
|
|
10729
|
+
const normalized = normalizeAnalysisPlanInputV1(input);
|
|
10730
|
+
const digest = digestHexSchema.parse(
|
|
10731
|
+
sha256Hex(canonicalPreimage(exactPlanProjection(normalized)))
|
|
10732
|
+
);
|
|
10733
|
+
return analysisPlanV1Schema.parse({
|
|
10734
|
+
schemaVersion: 1,
|
|
10735
|
+
analysisPlanId: analysisPlanIdFromDigest(digest),
|
|
10736
|
+
...normalized,
|
|
10737
|
+
obligationsDigest: digestHexSchema.parse(
|
|
10738
|
+
sha256Hex(canonicalPreimage(obligationsProjection(normalized)))
|
|
10739
|
+
),
|
|
10740
|
+
digest
|
|
10741
|
+
});
|
|
10742
|
+
}
|
|
10743
|
+
function parseAnalysisPlanV1(value) {
|
|
10744
|
+
const parsed = analysisPlanV1Schema.parse(value);
|
|
10745
|
+
const rebuilt = buildAnalysisPlanV1({
|
|
10746
|
+
binding: parsed.binding,
|
|
10747
|
+
source: parsed.source,
|
|
10748
|
+
contract: parsed.contract,
|
|
10749
|
+
config: parsed.config,
|
|
10750
|
+
profile: parsed.profile,
|
|
10751
|
+
regions: parsed.regions,
|
|
10752
|
+
limits: parsed.limits,
|
|
10753
|
+
evaluatorVersion: parsed.evaluatorVersion,
|
|
10754
|
+
createdAt: parsed.createdAt
|
|
10755
|
+
});
|
|
10756
|
+
if (parsed.analysisPlanId !== rebuilt.analysisPlanId || parsed.digest !== rebuilt.digest || parsed.obligationsDigest !== rebuilt.obligationsDigest) {
|
|
10757
|
+
throw new TypeError("AnalysisPlanV1 derived identity does not match its semantic projection");
|
|
10758
|
+
}
|
|
10759
|
+
return rebuilt;
|
|
10760
|
+
}
|
|
10761
|
+
|
|
10762
|
+
// src/analysis-plan/coverage.ts
|
|
10763
|
+
var COVERAGE_STATES = [
|
|
10764
|
+
"analyzed",
|
|
10765
|
+
"unsupported",
|
|
10766
|
+
"excluded_by_contract",
|
|
10767
|
+
"skipped_limit",
|
|
10768
|
+
"failed"
|
|
10769
|
+
];
|
|
10770
|
+
function emptyCounts() {
|
|
10771
|
+
return {
|
|
10772
|
+
analyzed: 0,
|
|
10773
|
+
unsupported: 0,
|
|
10774
|
+
excluded_by_contract: 0,
|
|
10775
|
+
skipped_limit: 0,
|
|
10776
|
+
failed: 0
|
|
10777
|
+
};
|
|
10778
|
+
}
|
|
10779
|
+
var CoverageValidationErrorV1 = class extends TypeError {
|
|
10780
|
+
constructor(message, duplicateRegionIds = [], unknownRegionIds = [], missingRequiredRegionIds = [], missingOptionalRegionIds = []) {
|
|
10781
|
+
super(message);
|
|
10782
|
+
this.duplicateRegionIds = duplicateRegionIds;
|
|
10783
|
+
this.unknownRegionIds = unknownRegionIds;
|
|
10784
|
+
this.missingRequiredRegionIds = missingRequiredRegionIds;
|
|
10785
|
+
this.missingOptionalRegionIds = missingOptionalRegionIds;
|
|
10786
|
+
this.name = "CoverageValidationErrorV1";
|
|
10787
|
+
}
|
|
10788
|
+
duplicateRegionIds;
|
|
10789
|
+
unknownRegionIds;
|
|
10790
|
+
missingRequiredRegionIds;
|
|
10791
|
+
missingOptionalRegionIds;
|
|
10792
|
+
};
|
|
10793
|
+
function normalizeCoverage(coverage) {
|
|
10794
|
+
return coverage.map(
|
|
10795
|
+
(observation) => coverageRegionV1Schema.parse({
|
|
10796
|
+
...observation,
|
|
10797
|
+
diagnosticIds: [...observation.diagnosticIds].sort()
|
|
10798
|
+
})
|
|
10799
|
+
).sort((left, right) => compareCanonicalStrings(left.regionId, right.regionId));
|
|
10800
|
+
}
|
|
10801
|
+
function deriveCoverageSummaryFromNormalizedV1(plan, coverage) {
|
|
10802
|
+
const planned = new Map(plan.regions.map((region) => [region.regionId, region]));
|
|
10803
|
+
const seen = /* @__PURE__ */ new Set();
|
|
10804
|
+
const duplicateRegionIds = /* @__PURE__ */ new Set();
|
|
10805
|
+
const unknownRegionIds = /* @__PURE__ */ new Set();
|
|
10806
|
+
for (const observation of coverage) {
|
|
10807
|
+
if (seen.has(observation.regionId)) duplicateRegionIds.add(observation.regionId);
|
|
10808
|
+
seen.add(observation.regionId);
|
|
10809
|
+
if (!planned.has(observation.regionId)) unknownRegionIds.add(observation.regionId);
|
|
10810
|
+
}
|
|
10811
|
+
const missingRequiredRegionIds = plan.regions.filter((region) => region.required && !seen.has(region.regionId)).map((region) => region.regionId);
|
|
10812
|
+
const missingOptionalRegionIds = plan.regions.filter((region) => !region.required && !seen.has(region.regionId)).map((region) => region.regionId);
|
|
10813
|
+
if (duplicateRegionIds.size > 0 || unknownRegionIds.size > 0 || missingRequiredRegionIds.length > 0 || missingOptionalRegionIds.length > 0) {
|
|
10814
|
+
throw new CoverageValidationErrorV1(
|
|
10815
|
+
"Coverage observations must join exactly once to every planned region",
|
|
10816
|
+
[...duplicateRegionIds].sort(),
|
|
10817
|
+
[...unknownRegionIds].sort(),
|
|
10818
|
+
missingRequiredRegionIds.sort(),
|
|
10819
|
+
missingOptionalRegionIds.sort()
|
|
10820
|
+
);
|
|
10821
|
+
}
|
|
10822
|
+
const requiredByState = emptyCounts();
|
|
10823
|
+
const optionalByState = emptyCounts();
|
|
10824
|
+
let eligibleFiles = 0;
|
|
10825
|
+
let analyzedFiles = 0;
|
|
10826
|
+
let analyzedBytes = 0;
|
|
10827
|
+
let observedBytes = 0;
|
|
10828
|
+
let diagnosticCount = 0;
|
|
10829
|
+
for (const observation of coverage) {
|
|
10830
|
+
const region = planned.get(observation.regionId);
|
|
10831
|
+
(region.required ? requiredByState : optionalByState)[observation.state] += 1;
|
|
10832
|
+
if (observation.state !== "excluded_by_contract") eligibleFiles += observation.fileCount;
|
|
10833
|
+
if (observation.state === "analyzed") {
|
|
10834
|
+
analyzedFiles += observation.fileCount;
|
|
10835
|
+
analyzedBytes += observation.byteCount;
|
|
10836
|
+
}
|
|
10837
|
+
observedBytes += observation.byteCount;
|
|
10838
|
+
diagnosticCount += observation.diagnosticIds.length;
|
|
10839
|
+
}
|
|
10840
|
+
if (!Number.isSafeInteger(eligibleFiles) || !Number.isSafeInteger(analyzedFiles) || !Number.isSafeInteger(analyzedBytes) || !Number.isSafeInteger(observedBytes) || !Number.isSafeInteger(diagnosticCount)) {
|
|
10841
|
+
throw new RangeError("Coverage totals exceeded the safe integer range");
|
|
10842
|
+
}
|
|
10843
|
+
if (eligibleFiles > plan.limits.maxSourceFiles) {
|
|
10844
|
+
throw new CoverageValidationErrorV1("Coverage file total exceeds the analysis-plan limit");
|
|
10845
|
+
}
|
|
10846
|
+
if (observedBytes > plan.limits.maxSourceBytes) {
|
|
10847
|
+
throw new CoverageValidationErrorV1("Coverage byte total exceeds the analysis-plan limit");
|
|
10848
|
+
}
|
|
10849
|
+
if (diagnosticCount > plan.limits.maxDiagnostics) {
|
|
10850
|
+
throw new CoverageValidationErrorV1(
|
|
10851
|
+
"Coverage diagnostic total exceeds the analysis-plan limit"
|
|
10852
|
+
);
|
|
10853
|
+
}
|
|
10854
|
+
for (const state of COVERAGE_STATES) {
|
|
10855
|
+
if (!Number.isSafeInteger(requiredByState[state]) || !Number.isSafeInteger(optionalByState[state])) {
|
|
10856
|
+
throw new RangeError("Coverage count exceeded the safe integer range");
|
|
10857
|
+
}
|
|
10858
|
+
}
|
|
10859
|
+
return coverageSummaryV1Schema.parse({
|
|
10860
|
+
plannedRegions: plan.regions.length,
|
|
10861
|
+
observedRegions: coverage.length,
|
|
10862
|
+
requiredRegions: plan.regions.filter((region) => region.required).length,
|
|
10863
|
+
requiredByState,
|
|
10864
|
+
optionalByState,
|
|
10865
|
+
eligibleFiles,
|
|
10866
|
+
analyzedFiles,
|
|
10867
|
+
analyzedBytes
|
|
10868
|
+
});
|
|
10869
|
+
}
|
|
10870
|
+
function deriveCoverageSummaryV1(rawPlan, rawCoverage) {
|
|
10871
|
+
return deriveCoverageSummaryFromNormalizedV1(
|
|
10872
|
+
parseAnalysisPlanV1(rawPlan),
|
|
10873
|
+
normalizeCoverage(rawCoverage)
|
|
10874
|
+
);
|
|
10875
|
+
}
|
|
10876
|
+
function coverageArtifactDigestV1(rawPlan, rawCoverage) {
|
|
10877
|
+
const plan = parseAnalysisPlanV1(rawPlan);
|
|
10878
|
+
const coverage = normalizeCoverage(rawCoverage);
|
|
10879
|
+
const summary = deriveCoverageSummaryFromNormalizedV1(plan, coverage);
|
|
10880
|
+
return digestHexSchema.parse(
|
|
10881
|
+
sha256Hex(
|
|
10882
|
+
canonicalPreimage({
|
|
10883
|
+
schema: "analysis-coverage.v1",
|
|
10884
|
+
analysisPlanDigest: plan.digest,
|
|
10885
|
+
coverage,
|
|
10886
|
+
summary
|
|
10887
|
+
})
|
|
10888
|
+
)
|
|
10889
|
+
);
|
|
10890
|
+
}
|
|
10891
|
+
|
|
10892
|
+
// src/feature-plan/types.ts
|
|
10893
|
+
import { z as z10 } from "zod";
|
|
10894
|
+
var FEATURE_PLAN_MAX_EVIDENCE_REFS_V1 = 200;
|
|
10895
|
+
var FEATURE_PLAN_MAX_USES_PER_KIND_V1 = 100;
|
|
10896
|
+
var FEATURE_PLAN_MAX_GAPS_V1 = 50;
|
|
10897
|
+
var FEATURE_PLAN_MAX_DECISIONS_V1 = 50;
|
|
10898
|
+
var FEATURE_PLAN_MAX_SCENARIOS_V1 = 50;
|
|
10899
|
+
var FEATURE_PLAN_MAX_ACCEPTANCE_ITEMS_V1 = 100;
|
|
10900
|
+
var FEATURE_PLAN_MAX_TEXT_BYTES_V1 = 32 * 1024;
|
|
10901
|
+
var AGENT_FEATURE_CONTEXT_MAX_BYTES_V1 = 64 * 1024;
|
|
10902
|
+
var utf8Length2 = (value) => new TextEncoder().encode(value).byteLength;
|
|
10903
|
+
var boundedString2 = (maxBytes = FEATURE_PLAN_MAX_TEXT_BYTES_V1) => z10.string().min(1).refine((value) => utf8Length2(value) <= maxBytes, `Value exceeds ${maxBytes} UTF-8 bytes`);
|
|
10904
|
+
var shortString = () => boundedString2(4096);
|
|
10905
|
+
var unique = (values) => new Set(values).size === values.length;
|
|
10906
|
+
var uniqueIdArray = (max = FEATURE_PLAN_MAX_EVIDENCE_REFS_V1) => z10.array(shortString()).max(max).refine(unique, "ID references must be unique");
|
|
10907
|
+
var evidenceRefV1Schema = z10.object({
|
|
10908
|
+
evidenceId: shortString(),
|
|
10909
|
+
kind: z10.enum(["user_intent", "image", "source", "contract", "pattern", "model"]),
|
|
10910
|
+
authority: z10.enum(["user_asserted", "source_observed", "contract_approved", "model_inferred"]),
|
|
10911
|
+
ref: boundedString2(),
|
|
10912
|
+
digest: digestHexStringSchema
|
|
10913
|
+
}).strict();
|
|
10914
|
+
var placementDecisionV1Schema = z10.object({
|
|
10915
|
+
targetKind: z10.enum(["page", "section"]),
|
|
10916
|
+
targetRef: shortString(),
|
|
10917
|
+
routeRef: shortString().optional(),
|
|
10918
|
+
parentSlotRef: shortString(),
|
|
10919
|
+
evidenceRefIds: uniqueIdArray()
|
|
10920
|
+
}).strict();
|
|
10921
|
+
var propValueSchema = z10.union([boundedString2(), z10.number().finite(), z10.boolean(), z10.null()]);
|
|
10922
|
+
var componentUseDecisionV1Schema = z10.object({
|
|
10923
|
+
useId: shortString(),
|
|
10924
|
+
componentId: shortString(),
|
|
10925
|
+
importPath: shortString(),
|
|
10926
|
+
purpose: boundedString2(),
|
|
10927
|
+
props: z10.record(shortString(), propValueSchema).refine((props) => Object.keys(props).length <= 100, "Component props exceed V1 limit"),
|
|
10928
|
+
evidenceRefIds: uniqueIdArray()
|
|
10929
|
+
}).strict();
|
|
10930
|
+
var tokenUseDecisionV1Schema = z10.object({
|
|
10931
|
+
useId: shortString(),
|
|
10932
|
+
tokenId: shortString(),
|
|
10933
|
+
role: shortString(),
|
|
10934
|
+
evidenceRefIds: uniqueIdArray()
|
|
10935
|
+
}).strict();
|
|
10936
|
+
var patternStatusV1Schema = z10.enum([
|
|
10937
|
+
"observed",
|
|
10938
|
+
"candidate",
|
|
10939
|
+
"approved_guidance",
|
|
10940
|
+
"contract_canonical",
|
|
10941
|
+
"deprecated"
|
|
10942
|
+
]);
|
|
10943
|
+
var patternUseDecisionV1Schema = z10.object({
|
|
10944
|
+
useId: shortString(),
|
|
10945
|
+
patternId: shortString(),
|
|
10946
|
+
patternRevisionDigest: digestHexStringSchema,
|
|
10947
|
+
status: patternStatusV1Schema,
|
|
10948
|
+
disposition: z10.enum(["reuse", "reference", "reject"]),
|
|
10949
|
+
evidenceRefIds: uniqueIdArray()
|
|
10950
|
+
}).strict().superRefine((pattern, context) => {
|
|
10951
|
+
if (pattern.disposition === "reuse" && pattern.status !== "approved_guidance" && pattern.status !== "contract_canonical") {
|
|
10952
|
+
context.addIssue({
|
|
10953
|
+
code: z10.ZodIssueCode.custom,
|
|
10954
|
+
path: ["disposition"],
|
|
10955
|
+
message: "Only approved-guidance or contract-canonical patterns may be reused"
|
|
10956
|
+
});
|
|
10957
|
+
}
|
|
10958
|
+
});
|
|
10959
|
+
var layoutConcernV1Schema = z10.enum([
|
|
10960
|
+
"outer_inline_spacing",
|
|
10961
|
+
"outer_block_spacing",
|
|
10962
|
+
"inner_padding",
|
|
10963
|
+
"child_gap",
|
|
10964
|
+
"max_inline_size",
|
|
10965
|
+
"scroll_x",
|
|
10966
|
+
"scroll_y",
|
|
10967
|
+
"sticky_offset",
|
|
10968
|
+
"breakpoint_switching"
|
|
10969
|
+
]);
|
|
10970
|
+
var layoutConcernOwnerV1Schema = z10.object({
|
|
10971
|
+
concern: layoutConcernV1Schema,
|
|
10972
|
+
ownerLayer: z10.enum([
|
|
10973
|
+
"application_shell",
|
|
10974
|
+
"route_shell",
|
|
10975
|
+
"page",
|
|
10976
|
+
"section",
|
|
10977
|
+
"pattern",
|
|
10978
|
+
"primitive"
|
|
10979
|
+
]),
|
|
10980
|
+
ownerRef: shortString(),
|
|
10981
|
+
childAction: z10.enum(["consume", "own", "override"]),
|
|
10982
|
+
tokenRef: shortString().optional(),
|
|
10983
|
+
breakpointRef: shortString().optional(),
|
|
10984
|
+
evidenceRefIds: uniqueIdArray(),
|
|
10985
|
+
overrideDecisionId: shortString().optional()
|
|
10986
|
+
}).strict().superRefine((row, context) => {
|
|
10987
|
+
if (row.childAction === "override" && !row.overrideDecisionId) {
|
|
10988
|
+
context.addIssue({
|
|
10989
|
+
code: z10.ZodIssueCode.custom,
|
|
10990
|
+
path: ["overrideDecisionId"],
|
|
10991
|
+
message: "A layout override must reference an approved decision"
|
|
10992
|
+
});
|
|
10993
|
+
}
|
|
10994
|
+
if (row.childAction !== "override" && row.overrideDecisionId) {
|
|
10995
|
+
context.addIssue({
|
|
10996
|
+
code: z10.ZodIssueCode.custom,
|
|
10997
|
+
path: ["overrideDecisionId"],
|
|
10998
|
+
message: "Only an override may reference an override decision"
|
|
10999
|
+
});
|
|
11000
|
+
}
|
|
11001
|
+
});
|
|
11002
|
+
var layoutOwnershipV1Schema = z10.object({
|
|
11003
|
+
concerns: z10.array(layoutConcernOwnerV1Schema).max(32).refine(
|
|
11004
|
+
(rows) => new Set(rows.map((row) => row.concern)).size === rows.length,
|
|
11005
|
+
"Each layout concern must have exactly one owner"
|
|
11006
|
+
)
|
|
11007
|
+
}).strict();
|
|
11008
|
+
var responsiveDecisionV1Schema = z10.object({
|
|
11009
|
+
decisionId: shortString(),
|
|
11010
|
+
source: z10.enum(["contract", "observed", "desktop_only"]),
|
|
11011
|
+
breakpointRef: shortString().optional(),
|
|
11012
|
+
behavior: boundedString2(),
|
|
11013
|
+
evidenceRefIds: uniqueIdArray()
|
|
11014
|
+
}).strict().superRefine((decision, context) => {
|
|
11015
|
+
if (decision.source !== "desktop_only" && !decision.breakpointRef) {
|
|
11016
|
+
context.addIssue({
|
|
11017
|
+
code: z10.ZodIssueCode.custom,
|
|
11018
|
+
path: ["breakpointRef"],
|
|
11019
|
+
message: "Responsive contract/observed decisions must pin a breakpoint"
|
|
11020
|
+
});
|
|
11021
|
+
}
|
|
11022
|
+
});
|
|
11023
|
+
var scenarioRequirementV1Schema = z10.object({
|
|
11024
|
+
scenarioId: shortString(),
|
|
11025
|
+
viewportRef: shortString().optional(),
|
|
11026
|
+
themeRef: shortString().optional(),
|
|
11027
|
+
actorRole: shortString().optional(),
|
|
11028
|
+
dataState: z10.enum(["default", "loading", "empty", "partial", "error"]),
|
|
11029
|
+
interactionState: z10.enum(["pristine", "dirty", "validating", "saving", "saved", "disabled"]).optional(),
|
|
11030
|
+
acceptanceIds: uniqueIdArray(FEATURE_PLAN_MAX_ACCEPTANCE_ITEMS_V1)
|
|
11031
|
+
}).strict();
|
|
11032
|
+
var gapDispositionV1Schema = z10.enum([
|
|
11033
|
+
"canonical_reuse",
|
|
11034
|
+
"approved_pattern",
|
|
11035
|
+
"local_composition",
|
|
11036
|
+
"intentional_one_off",
|
|
11037
|
+
"proposed_contract_addition",
|
|
11038
|
+
"unresolved"
|
|
11039
|
+
]);
|
|
11040
|
+
var capabilityGapV1Schema = z10.object({
|
|
11041
|
+
gapId: shortString(),
|
|
11042
|
+
capability: boundedString2(),
|
|
11043
|
+
required: z10.boolean(),
|
|
11044
|
+
disposition: gapDispositionV1Schema,
|
|
11045
|
+
reason: boundedString2(),
|
|
11046
|
+
evidenceRefIds: uniqueIdArray(),
|
|
11047
|
+
proposedContractCandidateId: shortString().optional()
|
|
11048
|
+
}).strict().superRefine((gap, context) => {
|
|
11049
|
+
if (gap.disposition === "proposed_contract_addition" && !gap.proposedContractCandidateId) {
|
|
11050
|
+
context.addIssue({
|
|
11051
|
+
code: z10.ZodIssueCode.custom,
|
|
11052
|
+
path: ["proposedContractCandidateId"],
|
|
11053
|
+
message: "A proposed contract addition must pin its candidate"
|
|
11054
|
+
});
|
|
11055
|
+
}
|
|
11056
|
+
if (gap.disposition !== "proposed_contract_addition" && gap.proposedContractCandidateId) {
|
|
11057
|
+
context.addIssue({
|
|
11058
|
+
code: z10.ZodIssueCode.custom,
|
|
11059
|
+
path: ["proposedContractCandidateId"],
|
|
11060
|
+
message: "Only a proposed contract addition may carry a candidate ID"
|
|
11061
|
+
});
|
|
11062
|
+
}
|
|
11063
|
+
});
|
|
11064
|
+
var featureAcceptanceItemV1Schema = z10.object({
|
|
11065
|
+
acceptanceId: shortString(),
|
|
11066
|
+
statement: boundedString2(),
|
|
11067
|
+
proof: z10.enum(["unit", "integration", "browser", "governance", "manual"]),
|
|
11068
|
+
required: z10.boolean(),
|
|
11069
|
+
evidenceRefIds: uniqueIdArray()
|
|
11070
|
+
}).strict();
|
|
11071
|
+
var decisionOptionV1Schema = z10.object({ optionId: shortString(), label: boundedString2(), consequence: boundedString2() }).strict();
|
|
11072
|
+
var decisionRequestV1Schema = z10.object({
|
|
11073
|
+
decisionId: shortString(),
|
|
11074
|
+
kind: z10.enum(["placement", "reuse", "gap", "layout_override", "responsive", "scope"]),
|
|
11075
|
+
question: boundedString2(),
|
|
11076
|
+
options: z10.array(decisionOptionV1Schema).min(2).max(20).refine(
|
|
11077
|
+
(options) => new Set(options.map((option) => option.optionId)).size === options.length,
|
|
11078
|
+
"Decision option IDs must be unique"
|
|
11079
|
+
),
|
|
11080
|
+
recommendedOptionId: shortString().optional(),
|
|
11081
|
+
required: z10.boolean(),
|
|
11082
|
+
evidenceRefIds: uniqueIdArray()
|
|
11083
|
+
}).strict().superRefine((decision, context) => {
|
|
11084
|
+
if (decision.recommendedOptionId && !decision.options.some((option) => option.optionId === decision.recommendedOptionId)) {
|
|
11085
|
+
context.addIssue({
|
|
11086
|
+
code: z10.ZodIssueCode.custom,
|
|
11087
|
+
path: ["recommendedOptionId"],
|
|
11088
|
+
message: "Recommended option must resolve inside the decision"
|
|
11089
|
+
});
|
|
11090
|
+
}
|
|
11091
|
+
});
|
|
11092
|
+
var decisionResolutionV1Schema = z10.object({ decisionId: shortString(), selectedOptionId: shortString() }).strict();
|
|
11093
|
+
var featurePinsV1Schema = z10.object({
|
|
11094
|
+
bindingId: shortString(),
|
|
11095
|
+
grounding: z10.object({
|
|
11096
|
+
sourceCommitId: shortString(),
|
|
11097
|
+
analysisPlanDigest: digestHexStringSchema,
|
|
11098
|
+
contextSliceDigest: digestHexStringSchema
|
|
11099
|
+
}).strict(),
|
|
11100
|
+
authority: z10.object({
|
|
11101
|
+
fcid: digestHexStringSchema,
|
|
11102
|
+
contractArtifactDigest: digestHexStringSchema,
|
|
11103
|
+
analysisObligationsDigest: digestHexStringSchema
|
|
11104
|
+
}).strict(),
|
|
11105
|
+
evidenceDigest: digestHexStringSchema
|
|
11106
|
+
}).strict();
|
|
11107
|
+
var commonRevisionShape = {
|
|
11108
|
+
pins: featurePinsV1Schema,
|
|
11109
|
+
placement: placementDecisionV1Schema,
|
|
11110
|
+
componentUses: z10.array(componentUseDecisionV1Schema).max(FEATURE_PLAN_MAX_USES_PER_KIND_V1),
|
|
11111
|
+
tokenUses: z10.array(tokenUseDecisionV1Schema).max(FEATURE_PLAN_MAX_USES_PER_KIND_V1),
|
|
11112
|
+
patternUses: z10.array(patternUseDecisionV1Schema).max(FEATURE_PLAN_MAX_USES_PER_KIND_V1),
|
|
11113
|
+
layout: layoutOwnershipV1Schema,
|
|
11114
|
+
responsive: z10.array(responsiveDecisionV1Schema).max(FEATURE_PLAN_MAX_DECISIONS_V1),
|
|
11115
|
+
scenarios: z10.array(scenarioRequirementV1Schema).max(FEATURE_PLAN_MAX_SCENARIOS_V1),
|
|
11116
|
+
gaps: z10.array(capabilityGapV1Schema).max(FEATURE_PLAN_MAX_GAPS_V1),
|
|
11117
|
+
acceptance: z10.array(featureAcceptanceItemV1Schema).max(FEATURE_PLAN_MAX_ACCEPTANCE_ITEMS_V1),
|
|
11118
|
+
evidenceRefs: z10.array(evidenceRefV1Schema).max(FEATURE_PLAN_MAX_EVIDENCE_REFS_V1)
|
|
11119
|
+
};
|
|
11120
|
+
function addUniqueIdIssue(rows, key, path, context) {
|
|
11121
|
+
const values = rows.map((row) => row[key]).filter((value) => typeof value === "string");
|
|
11122
|
+
if (new Set(values).size !== values.length) {
|
|
11123
|
+
context.addIssue({
|
|
11124
|
+
code: z10.ZodIssueCode.custom,
|
|
11125
|
+
path: [path],
|
|
11126
|
+
message: `${path} IDs must be unique`
|
|
11127
|
+
});
|
|
11128
|
+
}
|
|
11129
|
+
}
|
|
11130
|
+
function validateCommonGraph(graph, context, decisionIds) {
|
|
11131
|
+
addUniqueIdIssue(graph.evidenceRefs, "evidenceId", "evidenceRefs", context);
|
|
11132
|
+
addUniqueIdIssue(graph.componentUses, "useId", "componentUses", context);
|
|
11133
|
+
addUniqueIdIssue(graph.tokenUses, "useId", "tokenUses", context);
|
|
11134
|
+
addUniqueIdIssue(graph.patternUses, "useId", "patternUses", context);
|
|
11135
|
+
addUniqueIdIssue(graph.responsive, "decisionId", "responsive", context);
|
|
11136
|
+
addUniqueIdIssue(graph.scenarios, "scenarioId", "scenarios", context);
|
|
11137
|
+
addUniqueIdIssue(graph.gaps, "gapId", "gaps", context);
|
|
11138
|
+
addUniqueIdIssue(graph.acceptance, "acceptanceId", "acceptance", context);
|
|
11139
|
+
const evidenceIds = new Set(graph.evidenceRefs.map((evidence) => evidence.evidenceId));
|
|
11140
|
+
const acceptanceIds = new Set(graph.acceptance.map((acceptance) => acceptance.acceptanceId));
|
|
11141
|
+
const evidenceReferences = [
|
|
11142
|
+
[graph.placement.evidenceRefIds, "placement.evidenceRefIds"],
|
|
11143
|
+
...graph.componentUses.map(
|
|
11144
|
+
(row, index) => [row.evidenceRefIds, `componentUses.${index}.evidenceRefIds`]
|
|
11145
|
+
),
|
|
11146
|
+
...graph.tokenUses.map(
|
|
11147
|
+
(row, index) => [row.evidenceRefIds, `tokenUses.${index}.evidenceRefIds`]
|
|
11148
|
+
),
|
|
11149
|
+
...graph.patternUses.map(
|
|
11150
|
+
(row, index) => [row.evidenceRefIds, `patternUses.${index}.evidenceRefIds`]
|
|
11151
|
+
),
|
|
11152
|
+
...graph.layout.concerns.map(
|
|
11153
|
+
(row, index) => [row.evidenceRefIds, `layout.concerns.${index}.evidenceRefIds`]
|
|
11154
|
+
),
|
|
11155
|
+
...graph.responsive.map(
|
|
11156
|
+
(row, index) => [row.evidenceRefIds, `responsive.${index}.evidenceRefIds`]
|
|
11157
|
+
),
|
|
11158
|
+
...graph.gaps.map(
|
|
11159
|
+
(row, index) => [row.evidenceRefIds, `gaps.${index}.evidenceRefIds`]
|
|
11160
|
+
),
|
|
11161
|
+
...graph.acceptance.map(
|
|
11162
|
+
(row, index) => [row.evidenceRefIds, `acceptance.${index}.evidenceRefIds`]
|
|
11163
|
+
)
|
|
11164
|
+
];
|
|
11165
|
+
for (const [references, path] of evidenceReferences) {
|
|
11166
|
+
for (const reference of references) {
|
|
11167
|
+
if (!evidenceIds.has(reference)) {
|
|
11168
|
+
context.addIssue({
|
|
11169
|
+
code: z10.ZodIssueCode.custom,
|
|
11170
|
+
path: path.split("."),
|
|
11171
|
+
message: `Unknown evidence reference: ${reference}`
|
|
11172
|
+
});
|
|
11173
|
+
}
|
|
11174
|
+
}
|
|
11175
|
+
}
|
|
11176
|
+
for (const [index, scenario] of graph.scenarios.entries()) {
|
|
11177
|
+
for (const acceptanceId of scenario.acceptanceIds) {
|
|
11178
|
+
if (!acceptanceIds.has(acceptanceId)) {
|
|
11179
|
+
context.addIssue({
|
|
11180
|
+
code: z10.ZodIssueCode.custom,
|
|
11181
|
+
path: ["scenarios", index, "acceptanceIds"],
|
|
11182
|
+
message: `Unknown acceptance reference: ${acceptanceId}`
|
|
11183
|
+
});
|
|
11184
|
+
}
|
|
11185
|
+
}
|
|
11186
|
+
}
|
|
11187
|
+
for (const [index, row] of graph.layout.concerns.entries()) {
|
|
11188
|
+
if (row.overrideDecisionId && !decisionIds.has(row.overrideDecisionId)) {
|
|
11189
|
+
context.addIssue({
|
|
11190
|
+
code: z10.ZodIssueCode.custom,
|
|
11191
|
+
path: ["layout", "concerns", index, "overrideDecisionId"],
|
|
11192
|
+
message: `Unknown decision reference: ${row.overrideDecisionId}`
|
|
11193
|
+
});
|
|
11194
|
+
}
|
|
11195
|
+
}
|
|
11196
|
+
}
|
|
11197
|
+
var proposalInputShape = {
|
|
11198
|
+
schemaVersion: z10.literal(1),
|
|
11199
|
+
kind: z10.literal("proposal"),
|
|
11200
|
+
planId: featurePlanIdStringSchema,
|
|
11201
|
+
parentRevisionDigest: digestHexStringSchema.optional(),
|
|
11202
|
+
...commonRevisionShape,
|
|
11203
|
+
questions: z10.array(decisionRequestV1Schema).max(FEATURE_PLAN_MAX_DECISIONS_V1)
|
|
11204
|
+
};
|
|
11205
|
+
function validateProposal(proposal, context) {
|
|
11206
|
+
addUniqueIdIssue(proposal.questions, "decisionId", "questions", context);
|
|
11207
|
+
const decisionIds = new Set(proposal.questions.map((question) => question.decisionId));
|
|
11208
|
+
validateCommonGraph(proposal, context, decisionIds);
|
|
11209
|
+
const evidenceIds = new Set(proposal.evidenceRefs.map((evidence) => evidence.evidenceId));
|
|
11210
|
+
for (const [index, question] of proposal.questions.entries()) {
|
|
11211
|
+
for (const reference of question.evidenceRefIds) {
|
|
11212
|
+
if (!evidenceIds.has(reference)) {
|
|
11213
|
+
context.addIssue({
|
|
11214
|
+
code: z10.ZodIssueCode.custom,
|
|
11215
|
+
path: ["questions", index, "evidenceRefIds"],
|
|
11216
|
+
message: `Unknown evidence reference: ${reference}`
|
|
11217
|
+
});
|
|
11218
|
+
}
|
|
11219
|
+
}
|
|
11220
|
+
}
|
|
11221
|
+
}
|
|
11222
|
+
var featureProposalInputV1Schema = z10.object(proposalInputShape).strict().superRefine(validateProposal);
|
|
11223
|
+
var featureProposalV1Schema = z10.object({
|
|
11224
|
+
...proposalInputShape,
|
|
11225
|
+
revisionId: featureRevisionIdStringSchema,
|
|
11226
|
+
revisionDigest: digestHexStringSchema
|
|
11227
|
+
}).strict().superRefine(validateProposal);
|
|
11228
|
+
var manifestInputShape = {
|
|
11229
|
+
schemaVersion: z10.literal(1),
|
|
11230
|
+
kind: z10.literal("approved_manifest"),
|
|
11231
|
+
planId: featurePlanIdStringSchema,
|
|
11232
|
+
parentRevisionDigest: digestHexStringSchema,
|
|
11233
|
+
proposalRevisionDigest: digestHexStringSchema,
|
|
11234
|
+
...commonRevisionShape,
|
|
11235
|
+
validatedGrounding: z10.object({
|
|
11236
|
+
sourceCommitId: shortString(),
|
|
11237
|
+
analysisPlanDigest: digestHexStringSchema,
|
|
11238
|
+
contextSliceDigest: digestHexStringSchema
|
|
11239
|
+
}).strict(),
|
|
11240
|
+
decisions: z10.array(decisionResolutionV1Schema).max(FEATURE_PLAN_MAX_DECISIONS_V1),
|
|
11241
|
+
approval: z10.object({
|
|
11242
|
+
approverUserId: shortString(),
|
|
11243
|
+
decisionDigest: digestHexStringSchema,
|
|
11244
|
+
approvedAt: z10.string().datetime({ offset: true }),
|
|
11245
|
+
expiresAt: z10.string().datetime({ offset: true }).optional()
|
|
11246
|
+
}).strict()
|
|
11247
|
+
};
|
|
11248
|
+
var portableRepositoryPathSchema = shortString().refine(
|
|
11249
|
+
(value) => !value.startsWith("/") && !value.includes("\\") && !value.split("/").includes(".."),
|
|
11250
|
+
"Expected a portable repository-relative path"
|
|
11251
|
+
);
|
|
11252
|
+
function validateManifest(manifest, context) {
|
|
11253
|
+
addUniqueIdIssue(manifest.decisions, "decisionId", "decisions", context);
|
|
11254
|
+
validateCommonGraph(manifest, context, new Set(manifest.decisions.map((row) => row.decisionId)));
|
|
11255
|
+
if (manifest.validatedGrounding.contextSliceDigest !== manifest.pins.grounding.contextSliceDigest) {
|
|
11256
|
+
context.addIssue({
|
|
11257
|
+
code: z10.ZodIssueCode.custom,
|
|
11258
|
+
path: ["validatedGrounding", "contextSliceDigest"],
|
|
11259
|
+
message: "Validated material context must match the pinned proposal context"
|
|
11260
|
+
});
|
|
11261
|
+
}
|
|
11262
|
+
for (const [index, gap] of manifest.gaps.entries()) {
|
|
11263
|
+
if (gap.required && (gap.disposition === "unresolved" || gap.disposition === "proposed_contract_addition")) {
|
|
11264
|
+
context.addIssue({
|
|
11265
|
+
code: z10.ZodIssueCode.custom,
|
|
11266
|
+
path: ["gaps", index, "disposition"],
|
|
11267
|
+
message: "A required unresolved or proposed-contract gap blocks approval until it is resolved"
|
|
11268
|
+
});
|
|
11269
|
+
}
|
|
11270
|
+
}
|
|
11271
|
+
}
|
|
11272
|
+
var approvedFeatureManifestInputV1Schema = z10.object(manifestInputShape).strict().superRefine(validateManifest);
|
|
11273
|
+
var approvedFeatureManifestV1Schema = z10.object({
|
|
11274
|
+
...manifestInputShape,
|
|
11275
|
+
revisionId: featureRevisionIdStringSchema,
|
|
11276
|
+
revisionDigest: digestHexStringSchema
|
|
11277
|
+
}).strict().superRefine(validateManifest);
|
|
11278
|
+
var agentFeatureContextV1Schema = z10.object({
|
|
11279
|
+
schemaVersion: z10.literal(1),
|
|
11280
|
+
planId: featurePlanIdStringSchema,
|
|
11281
|
+
manifestDigest: digestHexStringSchema,
|
|
11282
|
+
pins: featurePinsV1Schema,
|
|
11283
|
+
validatedGrounding: manifestInputShape.validatedGrounding,
|
|
11284
|
+
target: placementDecisionV1Schema,
|
|
11285
|
+
componentUses: commonRevisionShape.componentUses,
|
|
11286
|
+
tokenUses: commonRevisionShape.tokenUses,
|
|
11287
|
+
patternUses: commonRevisionShape.patternUses,
|
|
11288
|
+
layout: layoutOwnershipV1Schema,
|
|
11289
|
+
responsive: commonRevisionShape.responsive,
|
|
11290
|
+
scenarios: commonRevisionShape.scenarios,
|
|
11291
|
+
acceptedGaps: commonRevisionShape.gaps,
|
|
11292
|
+
acceptance: commonRevisionShape.acceptance,
|
|
11293
|
+
decisions: manifestInputShape.decisions,
|
|
11294
|
+
relevantFiles: z10.array(portableRepositoryPathSchema).max(500).refine(unique, "relevantFiles must be unique"),
|
|
11295
|
+
commands: z10.array(boundedString2()).max(100)
|
|
11296
|
+
}).strict().superRefine((contextValue, context) => {
|
|
11297
|
+
const graph = {
|
|
11298
|
+
pins: contextValue.pins,
|
|
11299
|
+
placement: contextValue.target,
|
|
11300
|
+
componentUses: contextValue.componentUses,
|
|
11301
|
+
tokenUses: contextValue.tokenUses,
|
|
11302
|
+
patternUses: contextValue.patternUses,
|
|
11303
|
+
layout: contextValue.layout,
|
|
11304
|
+
responsive: contextValue.responsive,
|
|
11305
|
+
scenarios: contextValue.scenarios,
|
|
11306
|
+
gaps: contextValue.acceptedGaps,
|
|
11307
|
+
acceptance: contextValue.acceptance,
|
|
11308
|
+
evidenceRefs: []
|
|
11309
|
+
};
|
|
11310
|
+
addUniqueIdIssue(contextValue.decisions, "decisionId", "decisions", context);
|
|
11311
|
+
addUniqueIdIssue(graph.componentUses, "useId", "componentUses", context);
|
|
11312
|
+
addUniqueIdIssue(graph.tokenUses, "useId", "tokenUses", context);
|
|
11313
|
+
addUniqueIdIssue(graph.patternUses, "useId", "patternUses", context);
|
|
11314
|
+
addUniqueIdIssue(graph.scenarios, "scenarioId", "scenarios", context);
|
|
11315
|
+
addUniqueIdIssue(graph.acceptance, "acceptanceId", "acceptance", context);
|
|
11316
|
+
const decisions = new Set(contextValue.decisions.map((row) => row.decisionId));
|
|
11317
|
+
for (const [index, row] of contextValue.layout.concerns.entries()) {
|
|
11318
|
+
if (row.overrideDecisionId && !decisions.has(row.overrideDecisionId)) {
|
|
11319
|
+
context.addIssue({
|
|
11320
|
+
code: z10.ZodIssueCode.custom,
|
|
11321
|
+
path: ["layout", "concerns", index, "overrideDecisionId"],
|
|
11322
|
+
message: `Unknown decision reference: ${row.overrideDecisionId}`
|
|
11323
|
+
});
|
|
11324
|
+
}
|
|
11325
|
+
}
|
|
11326
|
+
for (const [index, gap] of contextValue.acceptedGaps.entries()) {
|
|
11327
|
+
if (gap.required && (gap.disposition === "unresolved" || gap.disposition === "proposed_contract_addition")) {
|
|
11328
|
+
context.addIssue({
|
|
11329
|
+
code: z10.ZodIssueCode.custom,
|
|
11330
|
+
path: ["acceptedGaps", index],
|
|
11331
|
+
message: "Agent context cannot contain a required unresolved or proposed-contract gap"
|
|
11332
|
+
});
|
|
11333
|
+
}
|
|
11334
|
+
}
|
|
11335
|
+
});
|
|
11336
|
+
|
|
11337
|
+
// src/feature-plan/digest.ts
|
|
11338
|
+
var sortedUnique2 = (values) => [...new Set(values)].sort();
|
|
11339
|
+
function normalizeEvidenceRefs(row) {
|
|
11340
|
+
return { ...row, evidenceRefIds: sortedUnique2(row.evidenceRefIds) };
|
|
11341
|
+
}
|
|
11342
|
+
function normalizeCommon(value) {
|
|
11343
|
+
return {
|
|
11344
|
+
...value,
|
|
11345
|
+
placement: normalizeEvidenceRefs(value.placement),
|
|
11346
|
+
componentUses: value.componentUses.map(normalizeEvidenceRefs).sort((left, right) => compareCanonicalStrings(left.useId, right.useId)),
|
|
11347
|
+
tokenUses: value.tokenUses.map(normalizeEvidenceRefs).sort((left, right) => compareCanonicalStrings(left.useId, right.useId)),
|
|
11348
|
+
patternUses: value.patternUses.map(normalizeEvidenceRefs).sort((left, right) => compareCanonicalStrings(left.useId, right.useId)),
|
|
11349
|
+
layout: {
|
|
11350
|
+
concerns: value.layout.concerns.map(normalizeEvidenceRefs).sort((left, right) => compareCanonicalStrings(left.concern, right.concern))
|
|
11351
|
+
},
|
|
11352
|
+
responsive: value.responsive.map(normalizeEvidenceRefs).sort((left, right) => compareCanonicalStrings(left.decisionId, right.decisionId)),
|
|
11353
|
+
scenarios: value.scenarios.map((scenario) => ({ ...scenario, acceptanceIds: sortedUnique2(scenario.acceptanceIds) })).sort((left, right) => compareCanonicalStrings(left.scenarioId, right.scenarioId)),
|
|
11354
|
+
gaps: value.gaps.map(normalizeEvidenceRefs).sort((left, right) => compareCanonicalStrings(left.gapId, right.gapId)),
|
|
11355
|
+
acceptance: value.acceptance.map(normalizeEvidenceRefs).sort((left, right) => compareCanonicalStrings(left.acceptanceId, right.acceptanceId)),
|
|
11356
|
+
evidenceRefs: [...value.evidenceRefs].sort(
|
|
11357
|
+
(left, right) => compareCanonicalStrings(left.evidenceId, right.evidenceId)
|
|
11358
|
+
)
|
|
11359
|
+
};
|
|
11360
|
+
}
|
|
11361
|
+
function normalizeFeatureProposalInputV1(value) {
|
|
11362
|
+
const parsed = featureProposalInputV1Schema.parse(value);
|
|
11363
|
+
return normalizeCommon({
|
|
11364
|
+
...parsed,
|
|
11365
|
+
questions: parsed.questions.map((question) => ({ ...normalizeEvidenceRefs(question), options: [...question.options] })).sort((left, right) => compareCanonicalStrings(left.decisionId, right.decisionId))
|
|
11366
|
+
});
|
|
11367
|
+
}
|
|
11368
|
+
function proposalProjection(proposal) {
|
|
11369
|
+
return {
|
|
11370
|
+
schema: "feature-revision.v1",
|
|
11371
|
+
kind: proposal.kind,
|
|
11372
|
+
planId: proposal.planId,
|
|
11373
|
+
parentRevisionDigest: proposal.parentRevisionDigest,
|
|
11374
|
+
pins: proposal.pins,
|
|
11375
|
+
placement: proposal.placement,
|
|
11376
|
+
componentUses: proposal.componentUses,
|
|
11377
|
+
tokenUses: proposal.tokenUses,
|
|
11378
|
+
patternUses: proposal.patternUses,
|
|
11379
|
+
layout: proposal.layout,
|
|
11380
|
+
responsive: proposal.responsive,
|
|
11381
|
+
scenarios: proposal.scenarios,
|
|
11382
|
+
gaps: proposal.gaps,
|
|
11383
|
+
acceptance: proposal.acceptance,
|
|
11384
|
+
questions: proposal.questions,
|
|
11385
|
+
evidenceRefs: proposal.evidenceRefs
|
|
11386
|
+
};
|
|
11387
|
+
}
|
|
11388
|
+
function featureProposalRevisionDigestV1(value) {
|
|
11389
|
+
const proposal = normalizeFeatureProposalInputV1(value);
|
|
11390
|
+
return sha256Hex(canonicalPreimage(proposalProjection(proposal)));
|
|
11391
|
+
}
|
|
11392
|
+
function buildFeatureProposalV1(value) {
|
|
11393
|
+
const proposal = normalizeFeatureProposalInputV1(value);
|
|
11394
|
+
const revisionDigest = sha256Hex(canonicalPreimage(proposalProjection(proposal)));
|
|
11395
|
+
return featureProposalV1Schema.parse({
|
|
11396
|
+
...proposal,
|
|
11397
|
+
revisionId: featureRevisionIdFromDigest(revisionDigest),
|
|
11398
|
+
revisionDigest
|
|
11399
|
+
});
|
|
11400
|
+
}
|
|
11401
|
+
function parseFeatureProposalV1(value) {
|
|
11402
|
+
const parsed = featureProposalV1Schema.parse(value);
|
|
11403
|
+
const { revisionId, revisionDigest, ...input } = parsed;
|
|
11404
|
+
const rebuilt = buildFeatureProposalV1(input);
|
|
11405
|
+
if (revisionId !== rebuilt.revisionId || revisionDigest !== rebuilt.revisionDigest) {
|
|
11406
|
+
throw new TypeError("Feature proposal derived identity does not match its semantic projection");
|
|
11407
|
+
}
|
|
11408
|
+
return rebuilt;
|
|
11409
|
+
}
|
|
11410
|
+
function normalizeApprovedFeatureManifestInputV1(value) {
|
|
11411
|
+
const parsed = approvedFeatureManifestInputV1Schema.parse(value);
|
|
11412
|
+
return normalizeCommon({
|
|
11413
|
+
...parsed,
|
|
11414
|
+
decisions: [...parsed.decisions].sort(
|
|
11415
|
+
(left, right) => compareCanonicalStrings(left.decisionId, right.decisionId)
|
|
11416
|
+
),
|
|
11417
|
+
approval: { ...parsed.approval },
|
|
11418
|
+
validatedGrounding: { ...parsed.validatedGrounding }
|
|
11419
|
+
});
|
|
11420
|
+
}
|
|
11421
|
+
function manifestProjection(manifest) {
|
|
11422
|
+
return {
|
|
11423
|
+
schema: "feature-revision.v1",
|
|
11424
|
+
kind: manifest.kind,
|
|
11425
|
+
planId: manifest.planId,
|
|
11426
|
+
parentRevisionDigest: manifest.parentRevisionDigest,
|
|
11427
|
+
proposalRevisionDigest: manifest.proposalRevisionDigest,
|
|
11428
|
+
pins: manifest.pins,
|
|
11429
|
+
validatedGrounding: manifest.validatedGrounding,
|
|
11430
|
+
placement: manifest.placement,
|
|
11431
|
+
componentUses: manifest.componentUses,
|
|
11432
|
+
tokenUses: manifest.tokenUses,
|
|
11433
|
+
patternUses: manifest.patternUses,
|
|
11434
|
+
layout: manifest.layout,
|
|
11435
|
+
responsive: manifest.responsive,
|
|
11436
|
+
scenarios: manifest.scenarios,
|
|
11437
|
+
gaps: manifest.gaps,
|
|
11438
|
+
acceptance: manifest.acceptance,
|
|
11439
|
+
evidenceRefs: manifest.evidenceRefs,
|
|
11440
|
+
decisions: manifest.decisions,
|
|
11441
|
+
approval: {
|
|
11442
|
+
approverUserId: manifest.approval.approverUserId,
|
|
11443
|
+
decisionDigest: manifest.approval.decisionDigest,
|
|
11444
|
+
expiresAt: manifest.approval.expiresAt
|
|
11445
|
+
}
|
|
11446
|
+
};
|
|
11447
|
+
}
|
|
11448
|
+
function approvedFeatureManifestRevisionDigestV1(value) {
|
|
11449
|
+
const manifest = normalizeApprovedFeatureManifestInputV1(value);
|
|
11450
|
+
return sha256Hex(canonicalPreimage(manifestProjection(manifest)));
|
|
11451
|
+
}
|
|
11452
|
+
function buildApprovedFeatureManifestV1(value) {
|
|
11453
|
+
const manifest = normalizeApprovedFeatureManifestInputV1(value);
|
|
11454
|
+
const revisionDigest = sha256Hex(canonicalPreimage(manifestProjection(manifest)));
|
|
11455
|
+
return approvedFeatureManifestV1Schema.parse({
|
|
11456
|
+
...manifest,
|
|
11457
|
+
revisionId: featureRevisionIdFromDigest(revisionDigest),
|
|
11458
|
+
revisionDigest
|
|
11459
|
+
});
|
|
11460
|
+
}
|
|
11461
|
+
function parseApprovedFeatureManifestV1(value) {
|
|
11462
|
+
const parsed = approvedFeatureManifestV1Schema.parse(value);
|
|
11463
|
+
const { revisionId, revisionDigest, ...input } = parsed;
|
|
11464
|
+
const rebuilt = buildApprovedFeatureManifestV1(input);
|
|
11465
|
+
if (revisionId !== rebuilt.revisionId || revisionDigest !== rebuilt.revisionDigest) {
|
|
11466
|
+
throw new TypeError(
|
|
11467
|
+
"Approved manifest derived identity does not match its semantic projection"
|
|
11468
|
+
);
|
|
11469
|
+
}
|
|
11470
|
+
return rebuilt;
|
|
11471
|
+
}
|
|
11472
|
+
var agentFeatureContextV1Schema2 = agentFeatureContextV1Schema.superRefine(
|
|
11473
|
+
(value, context) => {
|
|
11474
|
+
const bytes = new TextEncoder().encode(canonicalPreimage(value)).byteLength;
|
|
11475
|
+
if (bytes > AGENT_FEATURE_CONTEXT_MAX_BYTES_V1) {
|
|
11476
|
+
context.addIssue({
|
|
11477
|
+
code: "custom",
|
|
11478
|
+
message: `Agent feature context exceeds ${AGENT_FEATURE_CONTEXT_MAX_BYTES_V1} UTF-8 bytes`
|
|
11479
|
+
});
|
|
11480
|
+
}
|
|
11481
|
+
}
|
|
11482
|
+
);
|
|
11483
|
+
function parseAgentFeatureContextV1(value) {
|
|
11484
|
+
return agentFeatureContextV1Schema2.parse(value);
|
|
11485
|
+
}
|
|
11486
|
+
|
|
11487
|
+
// src/evaluation/types.ts
|
|
11488
|
+
var EVALUATOR_VERSION = "evaluation-kernel:v1";
|
|
11489
|
+
var EVALUATOR_VERSION_V2 = "evaluation-kernel:v2";
|
|
11490
|
+
|
|
11491
|
+
// src/evaluation/receipt.ts
|
|
11492
|
+
import { z as z11 } from "zod";
|
|
11493
|
+
var EVALUATION_MAX_WAIVERS_V2 = 1e3;
|
|
11494
|
+
var EVALUATION_MAX_WAIVER_MATCHES_V2 = 1e4;
|
|
11495
|
+
var EVALUATION_MAX_FINDINGS_V2 = 1e4;
|
|
11496
|
+
var EVALUATION_MAX_REASON_CODES_V2 = 64;
|
|
11497
|
+
var EVALUATION_MAX_MAP_ENTRIES_V2 = 1e5;
|
|
11498
|
+
var EVALUATION_MAX_POLICY_RULES_V2 = 1e4;
|
|
11499
|
+
var EVALUATION_RECEIPT_STRING_MAX_BYTES_V1 = 4096;
|
|
11500
|
+
var utf8Length3 = (value) => new TextEncoder().encode(value).byteLength;
|
|
11501
|
+
var boundedString3 = (maxBytes = EVALUATION_RECEIPT_STRING_MAX_BYTES_V1) => z11.string().min(1).refine((value) => utf8Length3(value) <= maxBytes, `Value exceeds ${maxBytes} UTF-8 bytes`);
|
|
11502
|
+
var unique2 = (values) => new Set(values).size === values.length;
|
|
11503
|
+
var contractPreimageV1Schema = z11.object({
|
|
11504
|
+
schema: z11.literal(CONTRACT_PREIMAGE_SCHEMA),
|
|
11505
|
+
domains: z11.object({
|
|
11506
|
+
components: digestHexStringSchema,
|
|
11507
|
+
tokens: digestHexStringSchema,
|
|
11508
|
+
canonicalMap: digestHexStringSchema,
|
|
11509
|
+
policy: digestHexStringSchema
|
|
11510
|
+
}).strict()
|
|
11511
|
+
}).strict();
|
|
11512
|
+
var effectiveRulePolicySchema = z11.object({ trust: z11.enum(["canonical", "evidence", "none"]).optional() }).strict();
|
|
11513
|
+
var effectivePolicySchema = z11.object({
|
|
11514
|
+
failOnWarnings: z11.boolean(),
|
|
11515
|
+
failOnInert: z11.boolean().optional(),
|
|
11516
|
+
rules: z11.record(boundedString3(), effectiveRulePolicySchema).refine(
|
|
11517
|
+
(rules) => Object.keys(rules).length <= EVALUATION_MAX_POLICY_RULES_V2,
|
|
11518
|
+
"Policy rule map exceeds the V2 limit"
|
|
11519
|
+
).optional()
|
|
11520
|
+
}).strict();
|
|
11521
|
+
var evaluationTrustSchema = z11.object({
|
|
11522
|
+
source: z11.enum(["verified", "unverified", "unknown"]),
|
|
11523
|
+
sources: z11.record(boundedString3(), z11.enum(["verified", "unverified", "unknown"])).refine(
|
|
11524
|
+
(sources) => Object.keys(sources).length <= EVALUATION_MAX_MAP_ENTRIES_V2,
|
|
11525
|
+
"Source trust map exceeds the V2 limit"
|
|
11526
|
+
).optional(),
|
|
11527
|
+
mappings: z11.record(boundedString3(), z11.enum(["confirmed", "unconfirmed", "unknown"])).refine(
|
|
11528
|
+
(mappings) => Object.keys(mappings).length <= EVALUATION_MAX_MAP_ENTRIES_V2,
|
|
11529
|
+
"Mapping trust map exceeds the V2 limit"
|
|
11530
|
+
)
|
|
11531
|
+
}).strict();
|
|
11532
|
+
var waiverScopeSchema = z11.discriminatedUnion("kind", [
|
|
11533
|
+
z11.object({ kind: z11.literal("finding"), fingerprint: boundedString3() }).strict(),
|
|
11534
|
+
z11.object({ kind: z11.literal("rule"), ruleId: boundedString3() }).strict(),
|
|
11535
|
+
z11.object({ kind: z11.literal("path"), pathPattern: boundedString3() }).strict(),
|
|
11536
|
+
z11.object({ kind: z11.literal("rule_path"), ruleId: boundedString3(), pathPattern: boundedString3() }).strict()
|
|
11537
|
+
]);
|
|
11538
|
+
var effectiveEvaluationWaiverV2Schema = z11.object({
|
|
11539
|
+
waiverId: boundedString3(),
|
|
11540
|
+
scope: waiverScopeSchema,
|
|
11541
|
+
matchedFindingFingerprints: z11.array(boundedString3()).min(1).max(EVALUATION_MAX_WAIVER_MATCHES_V2).refine(unique2, "matched finding fingerprints must be unique"),
|
|
11542
|
+
reason: boundedString3(),
|
|
11543
|
+
expiresAt: z11.number().finite().optional()
|
|
11544
|
+
}).strict();
|
|
11545
|
+
var evaluationIntegrityInputV2Schema = z11.object({
|
|
11546
|
+
governance: z11.enum(["healthy", "inert"]),
|
|
11547
|
+
inertConfigDiagnosticCount: z11.number().int().nonnegative(),
|
|
11548
|
+
profile: z11.discriminatedUnion("state", [
|
|
11549
|
+
z11.object({
|
|
11550
|
+
state: z11.literal("known"),
|
|
11551
|
+
profileId: boundedString3(),
|
|
11552
|
+
profileVersion: boundedString3()
|
|
11553
|
+
}).strict(),
|
|
11554
|
+
z11.object({
|
|
11555
|
+
state: z11.literal("unknown"),
|
|
11556
|
+
profileId: boundedString3(),
|
|
11557
|
+
profileVersion: boundedString3().optional()
|
|
11558
|
+
}).strict()
|
|
11559
|
+
]),
|
|
11560
|
+
facts: canonicalFactIntegrityV1Schema
|
|
11561
|
+
}).strict();
|
|
11562
|
+
var baselineSchema = z11.object({
|
|
11563
|
+
identity: z11.object({
|
|
11564
|
+
bindingDigest: digestHexStringSchema,
|
|
11565
|
+
repositoryExternalId: boundedString3(),
|
|
11566
|
+
fcid: digestHexStringSchema,
|
|
11567
|
+
sourceCommitId: boundedString3(),
|
|
11568
|
+
generationId: boundedString3()
|
|
11569
|
+
}).strict(),
|
|
11570
|
+
findingStates: z11.record(boundedString3(), z11.enum(["introduced", "existing", "unknown"])).refine(
|
|
11571
|
+
(states) => Object.keys(states).length <= EVALUATION_MAX_MAP_ENTRIES_V2,
|
|
11572
|
+
"Baseline finding-state map exceeds the V2 limit"
|
|
11573
|
+
)
|
|
11574
|
+
}).strict();
|
|
11575
|
+
var evaluationInputV2RawSchema = z11.object({
|
|
11576
|
+
schemaVersion: z11.literal(2),
|
|
11577
|
+
binding: repositoryBindingKeyV1Schema,
|
|
11578
|
+
analysisPlan: analysisPlanV1Schema,
|
|
11579
|
+
contract: z11.object({
|
|
11580
|
+
fcid: digestHexStringSchema,
|
|
11581
|
+
preimage: contractPreimageV1Schema,
|
|
11582
|
+
active: z11.boolean()
|
|
11583
|
+
}).strict(),
|
|
11584
|
+
factSchemaVersion: boundedString3(256),
|
|
11585
|
+
facts: z11.instanceof(FactIndex),
|
|
11586
|
+
factsDigest: digestHexStringSchema,
|
|
11587
|
+
coverage: z11.array(coverageRegionV1Schema).max(1e3),
|
|
11588
|
+
policy: effectivePolicySchema,
|
|
11589
|
+
baseline: baselineSchema.optional(),
|
|
11590
|
+
adoption: z11.union([z11.literal("unavailable"), z11.object({ regressed: z11.boolean() }).strict()]).optional(),
|
|
11591
|
+
trust: evaluationTrustSchema.optional(),
|
|
11592
|
+
waivers: z11.array(effectiveEvaluationWaiverV2Schema).max(EVALUATION_MAX_WAIVERS_V2).refine(
|
|
11593
|
+
(waivers) => new Set(waivers.map((waiver) => waiver.waiverId)).size === waivers.length,
|
|
11594
|
+
"waiver IDs must be unique"
|
|
11595
|
+
),
|
|
11596
|
+
integrity: evaluationIntegrityInputV2Schema,
|
|
11597
|
+
evaluatedAt: z11.number().finite(),
|
|
11598
|
+
evaluatorVersion: boundedString3(256)
|
|
11599
|
+
}).strict().superRefine((input, context) => {
|
|
11600
|
+
let plan;
|
|
11601
|
+
try {
|
|
11602
|
+
plan = parseAnalysisPlanV1(input.analysisPlan);
|
|
11603
|
+
} catch (error) {
|
|
11604
|
+
context.addIssue({
|
|
11605
|
+
code: z11.ZodIssueCode.custom,
|
|
11606
|
+
path: ["analysisPlan"],
|
|
11607
|
+
message: error instanceof Error ? error.message : "Invalid analysis plan identity"
|
|
11608
|
+
});
|
|
11609
|
+
return;
|
|
11610
|
+
}
|
|
11611
|
+
if (repositoryBindingDigestV1(plan.binding) !== repositoryBindingDigestV1(input.binding)) {
|
|
11612
|
+
context.addIssue({
|
|
11613
|
+
code: z11.ZodIssueCode.custom,
|
|
11614
|
+
path: ["binding"],
|
|
11615
|
+
message: "Evaluation binding does not match the analysis plan binding"
|
|
11616
|
+
});
|
|
11617
|
+
}
|
|
11618
|
+
if (plan.contract.fcid !== input.contract.fcid) {
|
|
11619
|
+
context.addIssue({
|
|
11620
|
+
code: z11.ZodIssueCode.custom,
|
|
11621
|
+
path: ["contract", "fcid"],
|
|
11622
|
+
message: "Evaluation FCID does not match the analysis plan"
|
|
11623
|
+
});
|
|
11624
|
+
}
|
|
11625
|
+
if (contractHash(input.contract.preimage) !== input.contract.fcid) {
|
|
11626
|
+
context.addIssue({
|
|
11627
|
+
code: z11.ZodIssueCode.custom,
|
|
11628
|
+
path: ["contract", "preimage"],
|
|
11629
|
+
message: "Contract preimage does not reproduce the pinned FCID"
|
|
11630
|
+
});
|
|
11631
|
+
}
|
|
11632
|
+
if (plan.evaluatorVersion !== input.evaluatorVersion) {
|
|
11633
|
+
context.addIssue({
|
|
11634
|
+
code: z11.ZodIssueCode.custom,
|
|
11635
|
+
path: ["evaluatorVersion"],
|
|
11636
|
+
message: "Evaluator version does not match the analysis plan"
|
|
11637
|
+
});
|
|
11638
|
+
}
|
|
11639
|
+
if (input.integrity.profile.state === "known" && (input.integrity.profile.profileId !== plan.profile.id || input.integrity.profile.profileVersion !== plan.profile.version)) {
|
|
11640
|
+
context.addIssue({
|
|
11641
|
+
code: z11.ZodIssueCode.custom,
|
|
11642
|
+
path: ["integrity", "profile"],
|
|
11643
|
+
message: "Known profile identity does not match the analysis plan"
|
|
11644
|
+
});
|
|
11645
|
+
}
|
|
11646
|
+
if (input.baseline) {
|
|
11647
|
+
const expectedBindingDigest = repositoryBindingDigestV1(input.binding);
|
|
11648
|
+
if (input.baseline.identity.bindingDigest !== expectedBindingDigest || input.baseline.identity.repositoryExternalId !== input.binding.repositoryExternalId || input.baseline.identity.fcid !== input.contract.fcid) {
|
|
11649
|
+
context.addIssue({
|
|
11650
|
+
code: z11.ZodIssueCode.custom,
|
|
11651
|
+
path: ["baseline", "identity"],
|
|
11652
|
+
message: "Baseline identity does not match the evaluation binding and FCID"
|
|
11653
|
+
});
|
|
11654
|
+
}
|
|
11655
|
+
}
|
|
11656
|
+
if (input.facts.size() > plan.limits.maxFacts) {
|
|
11657
|
+
context.addIssue({
|
|
11658
|
+
code: z11.ZodIssueCode.custom,
|
|
11659
|
+
path: ["facts"],
|
|
11660
|
+
message: "Fact count exceeds the analysis-plan limit"
|
|
11661
|
+
});
|
|
11662
|
+
}
|
|
11663
|
+
try {
|
|
11664
|
+
deriveCoverageSummaryV1(plan, input.coverage);
|
|
11665
|
+
} catch (error) {
|
|
11666
|
+
context.addIssue({
|
|
11667
|
+
code: z11.ZodIssueCode.custom,
|
|
11668
|
+
path: ["coverage"],
|
|
11669
|
+
message: error instanceof Error ? error.message : "Coverage does not match the plan"
|
|
11670
|
+
});
|
|
11671
|
+
}
|
|
11672
|
+
});
|
|
11673
|
+
var evaluationInputV2Schema = evaluationInputV2RawSchema.transform(
|
|
11674
|
+
(input) => ({
|
|
11675
|
+
...input,
|
|
11676
|
+
binding: normalizeRepositoryBindingKeyV1(input.binding),
|
|
11677
|
+
analysisPlan: parseAnalysisPlanV1(input.analysisPlan)
|
|
11678
|
+
})
|
|
11679
|
+
);
|
|
11680
|
+
var evaluationReasonV2Schema = z11.enum([
|
|
11681
|
+
"zeroFileScan",
|
|
11682
|
+
"governanceInert",
|
|
11683
|
+
"contractUnpinned",
|
|
11684
|
+
"contractStale",
|
|
11685
|
+
"contractIdentityMismatch",
|
|
11686
|
+
"inertConfigPresent",
|
|
11687
|
+
"unknownPresetPresent",
|
|
11688
|
+
"blockedFindings",
|
|
11689
|
+
"adoptionRegression",
|
|
11690
|
+
"expiredSuppression",
|
|
11691
|
+
"pendingCloudTrust",
|
|
11692
|
+
"adoptionBaselineUnavailable",
|
|
11693
|
+
"analysisPlanIdentityMismatch",
|
|
11694
|
+
"requiredCoverageMissing",
|
|
11695
|
+
"requiredCoverageIncomplete",
|
|
11696
|
+
"factConflict",
|
|
11697
|
+
"unknownAnalysisProfile"
|
|
11698
|
+
]);
|
|
11699
|
+
var evaluationResultV2Schema = z11.object({
|
|
11700
|
+
schemaVersion: z11.literal(2),
|
|
11701
|
+
verdict: z11.enum(["pass", "block", "indeterminate"]),
|
|
11702
|
+
reasons: z11.array(evaluationReasonV2Schema).max(EVALUATION_MAX_REASON_CODES_V2).refine(unique2, "Evaluation reason codes must be unique"),
|
|
11703
|
+
findings: z11.array(
|
|
11704
|
+
z11.object({
|
|
11705
|
+
fingerprint: boundedString3(),
|
|
11706
|
+
ruleId: boundedString3(),
|
|
11707
|
+
severity: z11.enum(["error", "warn", "info"]),
|
|
11708
|
+
state: z11.enum(["blocked", "advisory", "pending_cloud_trust"]),
|
|
11709
|
+
stateReasons: z11.array(boundedString3()).max(256)
|
|
11710
|
+
}).strict()
|
|
11711
|
+
).max(EVALUATION_MAX_FINDINGS_V2),
|
|
11712
|
+
counts: z11.object({
|
|
11713
|
+
blocked: z11.number().int().nonnegative().max(EVALUATION_MAX_FINDINGS_V2),
|
|
11714
|
+
advisory: z11.number().int().nonnegative().max(EVALUATION_MAX_FINDINGS_V2),
|
|
11715
|
+
pendingCloudTrust: z11.number().int().nonnegative().max(EVALUATION_MAX_FINDINGS_V2)
|
|
11716
|
+
}).strict(),
|
|
11717
|
+
derived: z11.object({ warnPresent: z11.boolean(), gatingFindingsPresent: z11.boolean() }).strict(),
|
|
11718
|
+
coverageSummary: coverageSummaryV1Schema,
|
|
11719
|
+
integrity: z11.object({
|
|
11720
|
+
fcidVerified: z11.boolean(),
|
|
11721
|
+
analysisPlanVerified: z11.boolean(),
|
|
11722
|
+
factIntegrity: z11.enum(["healthy", "conflict"]),
|
|
11723
|
+
requiredCoverage: z11.enum(["complete", "incomplete", "no_required_regions"]),
|
|
11724
|
+
governance: z11.enum(["healthy", "inert"]),
|
|
11725
|
+
profile: z11.enum(["known", "unknown"])
|
|
11726
|
+
}).strict(),
|
|
11727
|
+
inputDigest: digestHexStringSchema,
|
|
11728
|
+
resultDigest: digestHexStringSchema
|
|
11729
|
+
}).strict().superRefine((result, context) => {
|
|
11730
|
+
const expectedCounts = { blocked: 0, advisory: 0, pendingCloudTrust: 0 };
|
|
11731
|
+
let emittedWarnPresent = false;
|
|
11732
|
+
for (const [index, finding] of result.findings.entries()) {
|
|
11733
|
+
if (finding.state === "blocked") expectedCounts.blocked += 1;
|
|
11734
|
+
else if (finding.state === "pending_cloud_trust") expectedCounts.pendingCloudTrust += 1;
|
|
11735
|
+
else expectedCounts.advisory += 1;
|
|
11736
|
+
if (finding.severity === "warn") emittedWarnPresent = true;
|
|
11737
|
+
if (new Set(finding.stateReasons).size !== finding.stateReasons.length) {
|
|
11738
|
+
context.addIssue({
|
|
11739
|
+
code: z11.ZodIssueCode.custom,
|
|
11740
|
+
path: ["findings", index, "stateReasons"],
|
|
11741
|
+
message: "Finding state reasons must be unique"
|
|
11742
|
+
});
|
|
11743
|
+
}
|
|
11744
|
+
}
|
|
11745
|
+
if (new Set(result.findings.map((finding) => finding.fingerprint)).size !== result.findings.length) {
|
|
11746
|
+
context.addIssue({
|
|
11747
|
+
code: z11.ZodIssueCode.custom,
|
|
11748
|
+
path: ["findings"],
|
|
11749
|
+
message: "Evaluation finding fingerprints must be unique"
|
|
11750
|
+
});
|
|
11751
|
+
}
|
|
11752
|
+
for (const key of ["blocked", "advisory", "pendingCloudTrust"]) {
|
|
11753
|
+
if (result.counts[key] !== expectedCounts[key]) {
|
|
11754
|
+
context.addIssue({
|
|
11755
|
+
code: z11.ZodIssueCode.custom,
|
|
11756
|
+
path: ["counts", key],
|
|
11757
|
+
message: `Evaluation ${key} count must match findings`
|
|
11758
|
+
});
|
|
11759
|
+
}
|
|
11760
|
+
}
|
|
11761
|
+
if (emittedWarnPresent && !result.derived.warnPresent) {
|
|
11762
|
+
context.addIssue({
|
|
11763
|
+
code: z11.ZodIssueCode.custom,
|
|
11764
|
+
path: ["derived", "warnPresent"],
|
|
11765
|
+
message: "An emitted warning finding requires warnPresent"
|
|
11766
|
+
});
|
|
11767
|
+
}
|
|
11768
|
+
if (result.derived.gatingFindingsPresent !== expectedCounts.blocked > 0) {
|
|
11769
|
+
context.addIssue({
|
|
11770
|
+
code: z11.ZodIssueCode.custom,
|
|
11771
|
+
path: ["derived", "gatingFindingsPresent"],
|
|
11772
|
+
message: "gatingFindingsPresent must match blocked findings"
|
|
11773
|
+
});
|
|
11774
|
+
}
|
|
11775
|
+
const coverageStates = [
|
|
11776
|
+
"analyzed",
|
|
11777
|
+
"unsupported",
|
|
11778
|
+
"excluded_by_contract",
|
|
11779
|
+
"skipped_limit",
|
|
11780
|
+
"failed"
|
|
11781
|
+
];
|
|
11782
|
+
const requiredCount = coverageStates.reduce(
|
|
11783
|
+
(total, state) => total + result.coverageSummary.requiredByState[state],
|
|
11784
|
+
0
|
|
11785
|
+
);
|
|
11786
|
+
const optionalCount = coverageStates.reduce(
|
|
11787
|
+
(total, state) => total + result.coverageSummary.optionalByState[state],
|
|
11788
|
+
0
|
|
11789
|
+
);
|
|
11790
|
+
if (requiredCount !== result.coverageSummary.requiredRegions || requiredCount + optionalCount !== result.coverageSummary.observedRegions || result.coverageSummary.observedRegions !== result.coverageSummary.plannedRegions) {
|
|
11791
|
+
context.addIssue({
|
|
11792
|
+
code: z11.ZodIssueCode.custom,
|
|
11793
|
+
path: ["coverageSummary"],
|
|
11794
|
+
message: "Coverage summary counts must reconcile with planned and observed regions"
|
|
11795
|
+
});
|
|
11796
|
+
}
|
|
11797
|
+
if (result.coverageSummary.analyzedFiles > result.coverageSummary.eligibleFiles) {
|
|
11798
|
+
context.addIssue({
|
|
11799
|
+
code: z11.ZodIssueCode.custom,
|
|
11800
|
+
path: ["coverageSummary", "analyzedFiles"],
|
|
11801
|
+
message: "Analyzed files cannot exceed eligible files"
|
|
11802
|
+
});
|
|
11803
|
+
}
|
|
11804
|
+
const expectedRequiredCoverage = result.coverageSummary.requiredRegions === 0 ? "no_required_regions" : result.coverageSummary.requiredByState.analyzed === result.coverageSummary.requiredRegions ? "complete" : "incomplete";
|
|
11805
|
+
if (result.integrity.requiredCoverage !== expectedRequiredCoverage) {
|
|
11806
|
+
context.addIssue({
|
|
11807
|
+
code: z11.ZodIssueCode.custom,
|
|
11808
|
+
path: ["integrity", "requiredCoverage"],
|
|
11809
|
+
message: "Required coverage integrity must match the derived coverage summary"
|
|
11810
|
+
});
|
|
11811
|
+
}
|
|
11812
|
+
const reasons = new Set(result.reasons);
|
|
11813
|
+
const requireReason = (reason, required, path) => {
|
|
11814
|
+
if (reasons.has(reason) !== required) {
|
|
11815
|
+
context.addIssue({
|
|
11816
|
+
code: z11.ZodIssueCode.custom,
|
|
11817
|
+
path,
|
|
11818
|
+
message: `${reason} must match the evaluation result`
|
|
11819
|
+
});
|
|
11820
|
+
}
|
|
11821
|
+
};
|
|
11822
|
+
requireReason("blockedFindings", expectedCounts.blocked > 0, ["reasons"]);
|
|
11823
|
+
requireReason("pendingCloudTrust", expectedCounts.pendingCloudTrust > 0, ["reasons"]);
|
|
11824
|
+
requireReason("contractIdentityMismatch", !result.integrity.fcidVerified, ["reasons"]);
|
|
11825
|
+
requireReason("analysisPlanIdentityMismatch", !result.integrity.analysisPlanVerified, [
|
|
11826
|
+
"reasons"
|
|
11827
|
+
]);
|
|
11828
|
+
requireReason("factConflict", result.integrity.factIntegrity === "conflict", ["reasons"]);
|
|
11829
|
+
requireReason("governanceInert", result.integrity.governance === "inert", ["reasons"]);
|
|
11830
|
+
requireReason("unknownAnalysisProfile", result.integrity.profile === "unknown", ["reasons"]);
|
|
11831
|
+
requireReason(
|
|
11832
|
+
"requiredCoverageIncomplete",
|
|
11833
|
+
result.integrity.requiredCoverage === "incomplete",
|
|
11834
|
+
["reasons"]
|
|
11835
|
+
);
|
|
11836
|
+
requireReason(
|
|
11837
|
+
"requiredCoverageMissing",
|
|
11838
|
+
result.integrity.requiredCoverage === "no_required_regions",
|
|
11839
|
+
["reasons"]
|
|
11840
|
+
);
|
|
11841
|
+
const integrityHealthy = result.integrity.fcidVerified && result.integrity.analysisPlanVerified && result.integrity.factIntegrity === "healthy" && result.integrity.requiredCoverage === "complete" && result.integrity.governance === "healthy" && result.integrity.profile === "known";
|
|
11842
|
+
const blockingReasons = /* @__PURE__ */ new Set([
|
|
11843
|
+
"blockedFindings",
|
|
11844
|
+
"adoptionRegression",
|
|
11845
|
+
"expiredSuppression"
|
|
11846
|
+
]);
|
|
11847
|
+
const integrityReasons = /* @__PURE__ */ new Set([
|
|
11848
|
+
"zeroFileScan",
|
|
11849
|
+
"governanceInert",
|
|
11850
|
+
"contractUnpinned",
|
|
11851
|
+
"contractStale",
|
|
11852
|
+
"contractIdentityMismatch",
|
|
11853
|
+
"inertConfigPresent",
|
|
11854
|
+
"unknownPresetPresent",
|
|
11855
|
+
"analysisPlanIdentityMismatch",
|
|
11856
|
+
"requiredCoverageMissing",
|
|
11857
|
+
"requiredCoverageIncomplete",
|
|
11858
|
+
"factConflict",
|
|
11859
|
+
"unknownAnalysisProfile"
|
|
11860
|
+
]);
|
|
11861
|
+
const expectedVerdict = !integrityHealthy || result.reasons.some((reason) => integrityReasons.has(reason)) ? "indeterminate" : result.reasons.some((reason) => blockingReasons.has(reason)) ? "block" : result.reasons.length > 0 ? "indeterminate" : "pass";
|
|
11862
|
+
if (result.verdict !== expectedVerdict) {
|
|
11863
|
+
context.addIssue({
|
|
11864
|
+
code: z11.ZodIssueCode.custom,
|
|
11865
|
+
path: ["verdict"],
|
|
11866
|
+
message: `Evaluation verdict must be ${expectedVerdict} for its reasons and integrity`
|
|
11867
|
+
});
|
|
11868
|
+
}
|
|
11869
|
+
});
|
|
11870
|
+
var providerProofSemanticV1Schema = z11.object({
|
|
11871
|
+
schemaVersion: z11.literal(1),
|
|
11872
|
+
adapterId: boundedString3(),
|
|
11873
|
+
adapterVersion: boundedString3(),
|
|
11874
|
+
providerInstanceId: boundedString3(),
|
|
11875
|
+
bindingDigest: digestHexStringSchema,
|
|
11876
|
+
repositoryExternalId: boundedString3(),
|
|
11877
|
+
sourceCommitId: boundedString3(),
|
|
11878
|
+
eventExternalId: boundedString3(),
|
|
11879
|
+
changeExternalId: boundedString3().optional(),
|
|
11880
|
+
publisherExternalId: boundedString3()
|
|
11881
|
+
}).strict();
|
|
11882
|
+
function providerProofDigestV1(value) {
|
|
11883
|
+
const proof = providerProofSemanticV1Schema.parse(value);
|
|
11884
|
+
return sha256Hex(canonicalPreimage({ schema: "provider-proof.v1", ...proof }));
|
|
11885
|
+
}
|
|
11886
|
+
var providerProofV1Schema = z11.object({
|
|
11887
|
+
schemaVersion: z11.literal(1),
|
|
11888
|
+
adapterId: boundedString3(),
|
|
11889
|
+
adapterVersion: boundedString3(),
|
|
11890
|
+
providerInstanceId: boundedString3(),
|
|
11891
|
+
bindingDigest: digestHexStringSchema,
|
|
11892
|
+
repositoryExternalId: boundedString3(),
|
|
11893
|
+
sourceCommitId: boundedString3(),
|
|
11894
|
+
eventExternalId: boundedString3(),
|
|
11895
|
+
changeExternalId: boundedString3().optional(),
|
|
11896
|
+
publisherExternalId: boundedString3(),
|
|
11897
|
+
proofDigest: digestHexStringSchema
|
|
11898
|
+
}).strict().superRefine((proof, context) => {
|
|
11899
|
+
const { proofDigest, ...semantic } = proof;
|
|
11900
|
+
if (providerProofDigestV1(semantic) !== proofDigest) {
|
|
11901
|
+
context.addIssue({
|
|
11902
|
+
code: z11.ZodIssueCode.custom,
|
|
11903
|
+
path: ["proofDigest"],
|
|
11904
|
+
message: "Provider proof digest mismatch"
|
|
11905
|
+
});
|
|
11906
|
+
}
|
|
11907
|
+
});
|
|
11908
|
+
var receiptSemanticShape = {
|
|
11909
|
+
schemaVersion: z11.literal(1),
|
|
11910
|
+
trust: z11.enum(["source_verified", "ci_attested", "local", "unknown"]),
|
|
11911
|
+
authority: z11.enum(["advisory", "enforcement_eligible"]),
|
|
11912
|
+
binding: repositoryBindingKeyV1Schema,
|
|
11913
|
+
sourceCommitId: boundedString3(),
|
|
11914
|
+
fcid: digestHexStringSchema,
|
|
11915
|
+
analysisPlanDigest: digestHexStringSchema,
|
|
11916
|
+
factsDigest: digestHexStringSchema,
|
|
11917
|
+
inputDigest: digestHexStringSchema,
|
|
11918
|
+
resultDigest: digestHexStringSchema,
|
|
11919
|
+
evaluatorVersion: boundedString3(),
|
|
11920
|
+
providerProof: providerProofV1Schema.optional()
|
|
11921
|
+
};
|
|
11922
|
+
function validateReceiptSemantics(receipt, context) {
|
|
11923
|
+
if (receipt.authority === "enforcement_eligible") {
|
|
11924
|
+
if (receipt.trust !== "source_verified") {
|
|
11925
|
+
context.addIssue({
|
|
11926
|
+
code: z11.ZodIssueCode.custom,
|
|
11927
|
+
path: ["authority"],
|
|
11928
|
+
message: "Only source-verified evidence can enforce"
|
|
11929
|
+
});
|
|
11930
|
+
}
|
|
11931
|
+
if (!receipt.providerProof) {
|
|
11932
|
+
context.addIssue({
|
|
11933
|
+
code: z11.ZodIssueCode.custom,
|
|
11934
|
+
path: ["providerProof"],
|
|
11935
|
+
message: "Source-verified enforcement requires provider proof"
|
|
11936
|
+
});
|
|
11937
|
+
}
|
|
11938
|
+
}
|
|
11939
|
+
if (receipt.trust === "source_verified" && !receipt.providerProof) {
|
|
11940
|
+
context.addIssue({
|
|
11941
|
+
code: z11.ZodIssueCode.custom,
|
|
11942
|
+
path: ["providerProof"],
|
|
11943
|
+
message: "Source-verified trust requires provider proof"
|
|
11944
|
+
});
|
|
11945
|
+
}
|
|
11946
|
+
if (receipt.trust !== "source_verified" && receipt.providerProof) {
|
|
11947
|
+
context.addIssue({
|
|
11948
|
+
code: z11.ZodIssueCode.custom,
|
|
11949
|
+
path: ["providerProof"],
|
|
11950
|
+
message: "Provider proof is reserved for source-verified trust"
|
|
11951
|
+
});
|
|
11952
|
+
}
|
|
11953
|
+
if (!receipt.providerProof) return;
|
|
11954
|
+
const proof = receipt.providerProof;
|
|
11955
|
+
const binding = normalizeRepositoryBindingKeyV1(receipt.binding);
|
|
11956
|
+
if (proof.bindingDigest !== repositoryBindingDigestV1(binding)) {
|
|
11957
|
+
context.addIssue({
|
|
11958
|
+
code: z11.ZodIssueCode.custom,
|
|
11959
|
+
path: ["providerProof", "bindingDigest"],
|
|
11960
|
+
message: "Provider proof binding mismatch"
|
|
11961
|
+
});
|
|
11962
|
+
}
|
|
11963
|
+
if (proof.providerInstanceId !== binding.providerInstanceId) {
|
|
11964
|
+
context.addIssue({
|
|
11965
|
+
code: z11.ZodIssueCode.custom,
|
|
11966
|
+
path: ["providerProof", "providerInstanceId"],
|
|
11967
|
+
message: "Provider proof instance mismatch"
|
|
11968
|
+
});
|
|
11969
|
+
}
|
|
11970
|
+
if (proof.repositoryExternalId !== binding.repositoryExternalId) {
|
|
11971
|
+
context.addIssue({
|
|
11972
|
+
code: z11.ZodIssueCode.custom,
|
|
11973
|
+
path: ["providerProof", "repositoryExternalId"],
|
|
11974
|
+
message: "Provider proof repository mismatch"
|
|
11975
|
+
});
|
|
11976
|
+
}
|
|
11977
|
+
if (proof.sourceCommitId !== receipt.sourceCommitId) {
|
|
11978
|
+
context.addIssue({
|
|
11979
|
+
code: z11.ZodIssueCode.custom,
|
|
11980
|
+
path: ["providerProof", "sourceCommitId"],
|
|
11981
|
+
message: "Provider proof source mismatch"
|
|
11982
|
+
});
|
|
11983
|
+
}
|
|
11984
|
+
}
|
|
11985
|
+
var evaluationReceiptSemanticV1Schema = z11.object(receiptSemanticShape).strict().superRefine(validateReceiptSemantics);
|
|
11986
|
+
function evaluationReceiptDigestV1(value) {
|
|
11987
|
+
const receipt = evaluationReceiptSemanticV1Schema.parse(value);
|
|
11988
|
+
return sha256Hex(
|
|
11989
|
+
canonicalPreimage({
|
|
11990
|
+
schema: "evaluation-receipt.v1",
|
|
11991
|
+
trust: receipt.trust,
|
|
11992
|
+
authority: receipt.authority,
|
|
11993
|
+
bindingDigest: repositoryBindingDigestV1(receipt.binding),
|
|
11994
|
+
sourceCommitId: receipt.sourceCommitId,
|
|
11995
|
+
fcid: receipt.fcid,
|
|
11996
|
+
analysisPlanDigest: receipt.analysisPlanDigest,
|
|
11997
|
+
factsDigest: receipt.factsDigest,
|
|
11998
|
+
inputDigest: receipt.inputDigest,
|
|
11999
|
+
resultDigest: receipt.resultDigest,
|
|
12000
|
+
evaluatorVersion: receipt.evaluatorVersion,
|
|
12001
|
+
providerProofDigest: receipt.providerProof?.proofDigest
|
|
12002
|
+
})
|
|
12003
|
+
);
|
|
12004
|
+
}
|
|
12005
|
+
var evaluationReceiptV1Schema = z11.object({
|
|
12006
|
+
receiptId: evaluationReceiptIdStringSchema,
|
|
12007
|
+
...receiptSemanticShape,
|
|
12008
|
+
mintedAt: z11.string().datetime({ offset: true }),
|
|
12009
|
+
digest: digestHexStringSchema
|
|
12010
|
+
}).strict().superRefine((receipt, context) => {
|
|
12011
|
+
validateReceiptSemantics(receipt, context);
|
|
12012
|
+
let digest;
|
|
12013
|
+
try {
|
|
12014
|
+
const { receiptId: _receiptId, mintedAt: _mintedAt, digest: _digest, ...semantic } = receipt;
|
|
12015
|
+
digest = evaluationReceiptDigestV1(semantic);
|
|
12016
|
+
} catch (error) {
|
|
12017
|
+
context.addIssue({
|
|
12018
|
+
code: z11.ZodIssueCode.custom,
|
|
12019
|
+
message: error instanceof Error ? error.message : "Invalid receipt semantics"
|
|
12020
|
+
});
|
|
12021
|
+
return;
|
|
12022
|
+
}
|
|
12023
|
+
if (digest !== receipt.digest) {
|
|
12024
|
+
context.addIssue({
|
|
12025
|
+
code: z11.ZodIssueCode.custom,
|
|
12026
|
+
path: ["digest"],
|
|
12027
|
+
message: "Receipt digest mismatch"
|
|
12028
|
+
});
|
|
12029
|
+
}
|
|
12030
|
+
if (evaluationReceiptIdFromDigest(digest) !== receipt.receiptId) {
|
|
12031
|
+
context.addIssue({
|
|
12032
|
+
code: z11.ZodIssueCode.custom,
|
|
12033
|
+
path: ["receiptId"],
|
|
12034
|
+
message: "Receipt ID mismatch"
|
|
12035
|
+
});
|
|
12036
|
+
}
|
|
12037
|
+
});
|
|
12038
|
+
function parseEvaluationReceiptV1(value) {
|
|
12039
|
+
return evaluationReceiptV1Schema.parse(value);
|
|
12040
|
+
}
|
|
12041
|
+
var evaluationReceiptMintInputV1Schema = z11.object({
|
|
12042
|
+
schemaVersion: z11.literal(1),
|
|
12043
|
+
trust: z11.enum(["ci_attested", "local", "unknown"]),
|
|
12044
|
+
binding: repositoryBindingKeyV1Schema,
|
|
12045
|
+
sourceCommitId: boundedString3(),
|
|
12046
|
+
fcid: digestHexStringSchema,
|
|
12047
|
+
analysisPlanDigest: digestHexStringSchema,
|
|
12048
|
+
factsDigest: digestHexStringSchema,
|
|
12049
|
+
inputDigest: digestHexStringSchema,
|
|
12050
|
+
resultDigest: digestHexStringSchema,
|
|
12051
|
+
evaluatorVersion: boundedString3()
|
|
12052
|
+
}).strict();
|
|
12053
|
+
|
|
12054
|
+
// src/evaluation/evaluate.ts
|
|
12055
|
+
var INTEGRITY_REASONS = /* @__PURE__ */ new Set([
|
|
12056
|
+
"zeroFileScan",
|
|
12057
|
+
"governanceInert",
|
|
12058
|
+
"contractUnpinned",
|
|
12059
|
+
"contractStale",
|
|
12060
|
+
"contractIdentityMismatch",
|
|
12061
|
+
"inertConfigPresent",
|
|
12062
|
+
"unknownPresetPresent"
|
|
12063
|
+
]);
|
|
12064
|
+
var BLOCK_REASONS = /* @__PURE__ */ new Set([
|
|
12065
|
+
"blockedFindings",
|
|
12066
|
+
"adoptionRegression",
|
|
12067
|
+
"expiredSuppression"
|
|
12068
|
+
]);
|
|
12069
|
+
var REASON_ORDER = [
|
|
12070
|
+
"zeroFileScan",
|
|
12071
|
+
"governanceInert",
|
|
12072
|
+
"contractUnpinned",
|
|
12073
|
+
"contractStale",
|
|
12074
|
+
"contractIdentityMismatch",
|
|
12075
|
+
"inertConfigPresent",
|
|
12076
|
+
"unknownPresetPresent",
|
|
12077
|
+
"blockedFindings",
|
|
12078
|
+
"adoptionRegression",
|
|
12079
|
+
"expiredSuppression",
|
|
12080
|
+
"pendingCloudTrust",
|
|
12081
|
+
"adoptionBaselineUnavailable"
|
|
12082
|
+
];
|
|
12083
|
+
function evaluate2(input) {
|
|
12084
|
+
return isEvaluationInputV2(input) ? evaluateV2(input) : evaluateV1(input);
|
|
12085
|
+
}
|
|
12086
|
+
function isEvaluationInputV2(input) {
|
|
12087
|
+
return "schemaVersion" in input && input.schemaVersion === 2;
|
|
12088
|
+
}
|
|
12089
|
+
function evaluateV1(input) {
|
|
12090
|
+
const reasons = /* @__PURE__ */ new Set();
|
|
12091
|
+
let fcidVerified = "unavailable";
|
|
12092
|
+
if (input.contract.state === "unpinned") {
|
|
12093
|
+
reasons.add("contractUnpinned");
|
|
12094
|
+
} else {
|
|
12095
|
+
if (input.contract.stale) reasons.add("contractStale");
|
|
12096
|
+
if (input.contract.preimage) {
|
|
12097
|
+
fcidVerified = contractHash(input.contract.preimage) === input.contract.fcid;
|
|
12098
|
+
if (!fcidVerified) reasons.add("contractIdentityMismatch");
|
|
12099
|
+
}
|
|
12100
|
+
}
|
|
12101
|
+
if (input.scope.kind === "full" && input.scope.coverage.filesScanned === 0) {
|
|
12102
|
+
reasons.add("zeroFileScan");
|
|
12103
|
+
}
|
|
12104
|
+
if (input.integrity.governance === "inert") {
|
|
12105
|
+
reasons.add("governanceInert");
|
|
12106
|
+
}
|
|
12107
|
+
if (input.policy.failOnInert === true && (input.integrity.inertConfigDiagnostics ?? 0) > 0) {
|
|
12108
|
+
reasons.add("inertConfigPresent");
|
|
12109
|
+
}
|
|
12110
|
+
if ((input.integrity.unknownPresets?.length ?? 0) > 0) {
|
|
12111
|
+
reasons.add("unknownPresetPresent");
|
|
12112
|
+
}
|
|
12113
|
+
if (input.adoption === "unavailable") {
|
|
12114
|
+
reasons.add("adoptionBaselineUnavailable");
|
|
12115
|
+
} else if (input.adoption?.regressed === true) {
|
|
12116
|
+
reasons.add("adoptionRegression");
|
|
12117
|
+
}
|
|
12118
|
+
const activeWaivers = /* @__PURE__ */ new Set();
|
|
12119
|
+
for (const waiver of input.waivers ?? []) {
|
|
12120
|
+
if (waiver.expiresAt !== void 0 && Number.isFinite(waiver.expiresAt) && waiver.expiresAt <= input.evaluatedAt) {
|
|
12121
|
+
reasons.add("expiredSuppression");
|
|
12122
|
+
} else {
|
|
12123
|
+
activeWaivers.add(waiver.fingerprint);
|
|
12124
|
+
}
|
|
12125
|
+
}
|
|
12126
|
+
const evidence = evidenceFindings(input);
|
|
12127
|
+
const findings = [...groupByFingerprint(evidence).values()].map((rows) => {
|
|
12128
|
+
const classified = rows.map((row) => classifyFinding(row, input, activeWaivers));
|
|
12129
|
+
return classified.reduce(
|
|
12130
|
+
(hardest, candidate) => STATE_RANK[candidate.state] < STATE_RANK[hardest.state] ? candidate : hardest
|
|
12131
|
+
);
|
|
12132
|
+
});
|
|
12133
|
+
const counts = { blocked: 0, advisory: 0, pendingCloudTrust: 0 };
|
|
12134
|
+
for (const finding of findings) {
|
|
12135
|
+
if (finding.state === "blocked") counts.blocked += 1;
|
|
12136
|
+
else if (finding.state === "pending_cloud_trust") counts.pendingCloudTrust += 1;
|
|
12137
|
+
else counts.advisory += 1;
|
|
12138
|
+
}
|
|
12139
|
+
if (counts.blocked > 0) reasons.add("blockedFindings");
|
|
12140
|
+
if (counts.pendingCloudTrust > 0) reasons.add("pendingCloudTrust");
|
|
12141
|
+
const ordered = REASON_ORDER.filter((reason) => reasons.has(reason));
|
|
12142
|
+
let verdict;
|
|
12143
|
+
if (ordered.some((reason) => INTEGRITY_REASONS.has(reason))) {
|
|
12144
|
+
verdict = "indeterminate";
|
|
12145
|
+
} else if (ordered.some((reason) => BLOCK_REASONS.has(reason))) {
|
|
12146
|
+
verdict = "block";
|
|
12147
|
+
} else if (ordered.length > 0) {
|
|
12148
|
+
verdict = "indeterminate";
|
|
12149
|
+
} else {
|
|
12150
|
+
verdict = "pass";
|
|
12151
|
+
}
|
|
12152
|
+
const derived = {
|
|
12153
|
+
warnPresent: evidence.some((finding) => finding.severity === "warn"),
|
|
12154
|
+
gatingFindingsPresent: counts.blocked > 0
|
|
12155
|
+
};
|
|
12156
|
+
const inputDigest = sha256Hex(canonicalPreimage(normalizeInputForDigest(input)));
|
|
12157
|
+
const partial = {
|
|
12158
|
+
evaluatorVersion: EVALUATOR_VERSION,
|
|
12159
|
+
verdict,
|
|
12160
|
+
reasons: ordered,
|
|
12161
|
+
findings,
|
|
12162
|
+
counts,
|
|
12163
|
+
derived,
|
|
12164
|
+
integrity: { fcidVerified }
|
|
12165
|
+
};
|
|
12166
|
+
return {
|
|
12167
|
+
...partial,
|
|
12168
|
+
inputDigest,
|
|
12169
|
+
resultDigest: sha256Hex(canonicalPreimage({ ...partial, inputDigest }))
|
|
12170
|
+
};
|
|
12171
|
+
}
|
|
12172
|
+
var V2_REASON_ORDER = [
|
|
12173
|
+
"analysisPlanIdentityMismatch",
|
|
12174
|
+
"requiredCoverageMissing",
|
|
12175
|
+
"requiredCoverageIncomplete",
|
|
12176
|
+
"factConflict",
|
|
12177
|
+
"unknownAnalysisProfile",
|
|
12178
|
+
...REASON_ORDER
|
|
12179
|
+
];
|
|
12180
|
+
var V2_INTEGRITY_REASONS = /* @__PURE__ */ new Set([
|
|
12181
|
+
...INTEGRITY_REASONS,
|
|
12182
|
+
"analysisPlanIdentityMismatch",
|
|
12183
|
+
"requiredCoverageMissing",
|
|
12184
|
+
"requiredCoverageIncomplete",
|
|
12185
|
+
"factConflict",
|
|
12186
|
+
"unknownAnalysisProfile"
|
|
12187
|
+
]);
|
|
12188
|
+
var SUPPORTED_FACT_SCHEMA_VERSIONS_V2 = /* @__PURE__ */ new Set(["facts:v1"]);
|
|
12189
|
+
var SUPPORTED_REACT_WEB_PROFILE_VERSIONS_V1 = /* @__PURE__ */ new Set(["1"]);
|
|
12190
|
+
function evaluateV2(rawInput) {
|
|
12191
|
+
if (rawInput.evaluatorVersion !== EVALUATOR_VERSION_V2) {
|
|
12192
|
+
throw new Error(`Unsupported evaluator version: ${rawInput.evaluatorVersion}`);
|
|
12193
|
+
}
|
|
12194
|
+
if (!SUPPORTED_FACT_SCHEMA_VERSIONS_V2.has(rawInput.factSchemaVersion)) {
|
|
12195
|
+
throw new Error(`Unsupported fact schema version: ${rawInput.factSchemaVersion}`);
|
|
12196
|
+
}
|
|
12197
|
+
const input = evaluationInputV2Schema.parse(rawInput);
|
|
12198
|
+
const coverageSummary = deriveCoverageSummaryV1(input.analysisPlan, input.coverage);
|
|
12199
|
+
const profileKnown = input.integrity.profile.state === "known" && input.analysisPlan.profile.id === "react-web-v1" && SUPPORTED_REACT_WEB_PROFILE_VERSIONS_V1.has(input.analysisPlan.profile.version);
|
|
12200
|
+
const compatibilityInput = {
|
|
12201
|
+
contract: {
|
|
12202
|
+
state: "pinned",
|
|
12203
|
+
fcid: input.contract.fcid,
|
|
12204
|
+
preimage: input.contract.preimage,
|
|
12205
|
+
...!input.contract.active ? { stale: true } : {}
|
|
12206
|
+
},
|
|
12207
|
+
scope: { kind: "full", coverage: { filesScanned: coverageSummary.analyzedFiles } },
|
|
12208
|
+
evidence: { kind: "facts", facts: input.facts },
|
|
12209
|
+
policy: input.policy,
|
|
12210
|
+
...input.baseline ? {
|
|
12211
|
+
baseline: {
|
|
12212
|
+
identityVerified: true,
|
|
12213
|
+
findingStates: input.baseline.findingStates
|
|
12214
|
+
}
|
|
12215
|
+
} : {},
|
|
12216
|
+
...input.adoption !== void 0 ? { adoption: input.adoption } : {},
|
|
12217
|
+
...input.trust !== void 0 ? { trust: input.trust } : {},
|
|
12218
|
+
waivers: input.waivers.flatMap(
|
|
12219
|
+
(waiver) => waiver.matchedFindingFingerprints.map((fingerprint) => ({
|
|
12220
|
+
fingerprint,
|
|
12221
|
+
...waiver.expiresAt !== void 0 ? { expiresAt: waiver.expiresAt } : {}
|
|
12222
|
+
}))
|
|
12223
|
+
),
|
|
12224
|
+
integrity: {
|
|
12225
|
+
governance: input.integrity.governance,
|
|
12226
|
+
...input.integrity.inertConfigDiagnosticCount > 0 ? { inertConfigDiagnostics: input.integrity.inertConfigDiagnosticCount } : {}
|
|
12227
|
+
},
|
|
12228
|
+
evaluatedAt: input.evaluatedAt
|
|
12229
|
+
};
|
|
12230
|
+
const compatibilityResult = evaluateV1(compatibilityInput);
|
|
12231
|
+
const requiredCoverage = coverageSummary.requiredRegions === 0 ? "no_required_regions" : coverageSummary.requiredByState.analyzed === coverageSummary.requiredRegions ? "complete" : "incomplete";
|
|
12232
|
+
const integrity = {
|
|
12233
|
+
fcidVerified: compatibilityResult.integrity.fcidVerified === true,
|
|
12234
|
+
analysisPlanVerified: true,
|
|
12235
|
+
factIntegrity: input.integrity.facts.state,
|
|
12236
|
+
requiredCoverage,
|
|
12237
|
+
governance: input.integrity.governance,
|
|
12238
|
+
profile: profileKnown ? "known" : "unknown"
|
|
12239
|
+
};
|
|
12240
|
+
const reasons = new Set(compatibilityResult.reasons);
|
|
12241
|
+
if (requiredCoverage === "no_required_regions") reasons.add("requiredCoverageMissing");
|
|
12242
|
+
if (requiredCoverage === "incomplete") reasons.add("requiredCoverageIncomplete");
|
|
12243
|
+
if (integrity.factIntegrity === "conflict") reasons.add("factConflict");
|
|
12244
|
+
if (integrity.profile === "unknown") reasons.add("unknownAnalysisProfile");
|
|
12245
|
+
const orderedReasons = V2_REASON_ORDER.filter((reason) => reasons.has(reason));
|
|
12246
|
+
let verdict = compatibilityResult.verdict;
|
|
12247
|
+
if (orderedReasons.some((reason) => V2_INTEGRITY_REASONS.has(reason))) {
|
|
12248
|
+
verdict = "indeterminate";
|
|
12249
|
+
}
|
|
12250
|
+
const inputDigest = sha256Hex(
|
|
12251
|
+
canonicalPreimage(normalizeInputV2ForDigest(input, coverageSummary))
|
|
12252
|
+
);
|
|
12253
|
+
const partial = {
|
|
12254
|
+
schemaVersion: 2,
|
|
12255
|
+
verdict,
|
|
12256
|
+
reasons: orderedReasons,
|
|
12257
|
+
findings: compatibilityResult.findings.map((finding) => ({
|
|
12258
|
+
...finding,
|
|
12259
|
+
stateReasons: [...finding.stateReasons]
|
|
12260
|
+
})),
|
|
12261
|
+
counts: { ...compatibilityResult.counts },
|
|
12262
|
+
derived: { ...compatibilityResult.derived },
|
|
12263
|
+
coverageSummary,
|
|
12264
|
+
integrity
|
|
12265
|
+
};
|
|
12266
|
+
const resultDigest = sha256Hex(
|
|
12267
|
+
canonicalPreimage({ schema: "evaluation-result:v2", ...partial, inputDigest })
|
|
12268
|
+
);
|
|
12269
|
+
return evaluationResultV2Schema.parse({ ...partial, inputDigest, resultDigest });
|
|
12270
|
+
}
|
|
12271
|
+
function normalizeInputV2ForDigest(input, coverageSummary) {
|
|
12272
|
+
const {
|
|
12273
|
+
analysisPlanId: _analysisPlanId,
|
|
12274
|
+
createdAt: _createdAt,
|
|
12275
|
+
digest: _planDigest,
|
|
12276
|
+
obligationsDigest: _obligationsDigest,
|
|
12277
|
+
...analysisPlanSemantic
|
|
12278
|
+
} = input.analysisPlan;
|
|
12279
|
+
return {
|
|
12280
|
+
schema: "evaluation-input:v2",
|
|
12281
|
+
binding: input.binding,
|
|
12282
|
+
analysisPlan: {
|
|
12283
|
+
...analysisPlanSemantic,
|
|
12284
|
+
analysisPlanDigest: input.analysisPlan.digest,
|
|
12285
|
+
obligationsDigest: input.analysisPlan.obligationsDigest
|
|
12286
|
+
},
|
|
12287
|
+
contract: input.contract,
|
|
12288
|
+
factSchemaVersion: input.factSchemaVersion,
|
|
12289
|
+
factsDigest: input.factsDigest,
|
|
12290
|
+
coverage: [...input.coverage].map((region) => ({
|
|
12291
|
+
...region,
|
|
12292
|
+
diagnosticIds: [...region.diagnosticIds].sort(compareCanonicalStrings)
|
|
12293
|
+
})).sort((left, right) => compareCanonicalStrings(left.regionId, right.regionId)),
|
|
12294
|
+
coverageSummary,
|
|
12295
|
+
policy: input.policy,
|
|
12296
|
+
baseline: input.baseline,
|
|
12297
|
+
adoption: input.adoption,
|
|
12298
|
+
trust: input.trust,
|
|
12299
|
+
waivers: input.waivers.map((waiver) => ({
|
|
12300
|
+
...waiver,
|
|
12301
|
+
matchedFindingFingerprints: [...waiver.matchedFindingFingerprints].sort(
|
|
12302
|
+
compareCanonicalStrings
|
|
12303
|
+
)
|
|
12304
|
+
})).sort((left, right) => compareCanonicalStrings(left.waiverId, right.waiverId)),
|
|
12305
|
+
integrity: input.integrity,
|
|
12306
|
+
evaluatedAt: input.evaluatedAt,
|
|
12307
|
+
evaluatorVersion: input.evaluatorVersion
|
|
12308
|
+
};
|
|
12309
|
+
}
|
|
12310
|
+
function evidenceFindings(input) {
|
|
12311
|
+
if (input.evidence.kind === "findings") return [...input.evidence.findings];
|
|
12312
|
+
const ruleConfig = readRuleConfig(input.evidence.facts);
|
|
12313
|
+
return runRules(input.evidence.facts).map((finding) => ({
|
|
12314
|
+
fingerprint: finding.fingerprint,
|
|
12315
|
+
ruleId: finding.ruleId,
|
|
12316
|
+
severity: severityLevel(configuredFindingSeverity(finding, ruleConfig)),
|
|
12317
|
+
advisory: finding.attributes?.advisory === true,
|
|
12318
|
+
evidenceGrade: finding.evidenceGrade
|
|
12319
|
+
}));
|
|
12320
|
+
}
|
|
12321
|
+
var STATE_RANK = { blocked: 0, pending_cloud_trust: 1, advisory: 2 };
|
|
12322
|
+
var SEVERITY_RANK2 = { error: 0, warn: 1, info: 2 };
|
|
12323
|
+
function canonicalRow(finding) {
|
|
12324
|
+
return {
|
|
12325
|
+
fingerprint: finding.fingerprint,
|
|
12326
|
+
ruleId: finding.ruleId,
|
|
12327
|
+
severity: finding.severity,
|
|
12328
|
+
advisory: finding.advisory === true,
|
|
12329
|
+
evidenceGrade: coerceEvidenceGrade(finding.evidenceGrade),
|
|
12330
|
+
waived: finding.waived === true,
|
|
12331
|
+
...finding.sourceTrust !== void 0 ? { sourceTrust: finding.sourceTrust } : {},
|
|
12332
|
+
...finding.mappingTrust !== void 0 ? { mappingTrust: finding.mappingTrust } : {},
|
|
12333
|
+
...finding.baselineState !== void 0 ? { baselineState: finding.baselineState } : {}
|
|
12334
|
+
};
|
|
12335
|
+
}
|
|
12336
|
+
function compareStrings(a, b) {
|
|
12337
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
12338
|
+
}
|
|
12339
|
+
function compareRows(a, b) {
|
|
12340
|
+
return compareStrings(a.fingerprint, b.fingerprint) || SEVERITY_RANK2[a.severity] - SEVERITY_RANK2[b.severity] || compareStrings(a.ruleId, b.ruleId) || Number(a.advisory ?? false) - Number(b.advisory ?? false) || compareStrings(a.evidenceGrade ?? "", b.evidenceGrade ?? "") || Number(a.waived ?? false) - Number(b.waived ?? false) || compareStrings(a.sourceTrust ?? "", b.sourceTrust ?? "") || compareStrings(a.mappingTrust ?? "", b.mappingTrust ?? "") || compareStrings(a.baselineState ?? "", b.baselineState ?? "");
|
|
12341
|
+
}
|
|
12342
|
+
function canonicalRows(findings) {
|
|
12343
|
+
const sorted = findings.map(canonicalRow).sort(compareRows);
|
|
12344
|
+
return sorted.filter((row, index) => index === 0 || compareRows(row, sorted[index - 1]) !== 0);
|
|
12345
|
+
}
|
|
12346
|
+
function groupByFingerprint(findings) {
|
|
12347
|
+
const groups = /* @__PURE__ */ new Map();
|
|
12348
|
+
for (const row of canonicalRows(findings)) {
|
|
12349
|
+
const group = groups.get(row.fingerprint);
|
|
12350
|
+
if (group) group.push(row);
|
|
12351
|
+
else groups.set(row.fingerprint, [row]);
|
|
12352
|
+
}
|
|
12353
|
+
return groups;
|
|
12354
|
+
}
|
|
12355
|
+
function classifyFinding(finding, input, activeWaivers) {
|
|
12356
|
+
const base = {
|
|
12357
|
+
fingerprint: finding.fingerprint,
|
|
12358
|
+
ruleId: finding.ruleId,
|
|
12359
|
+
severity: finding.severity
|
|
12360
|
+
};
|
|
12361
|
+
if (activeWaivers.has(finding.fingerprint) || finding.waived === true) {
|
|
12362
|
+
return { ...base, state: "advisory", stateReasons: ["waived"] };
|
|
12363
|
+
}
|
|
12364
|
+
const eligibility = eligibilityFor(finding, input.policy);
|
|
12365
|
+
if (eligibility !== null) {
|
|
12366
|
+
return { ...base, state: "advisory", stateReasons: [eligibility] };
|
|
12367
|
+
}
|
|
12368
|
+
const introduced = introducedFactFor(finding, input);
|
|
12369
|
+
if (introduced.state === "negative") {
|
|
12370
|
+
return { ...base, state: "advisory", stateReasons: ["baseline:existing"] };
|
|
12371
|
+
}
|
|
12372
|
+
const requirement = input.policy.rules?.[finding.ruleId]?.trust ?? defaultTrustRequirement(finding.ruleId);
|
|
12373
|
+
const mappingBinds = requirement === "canonical" || defaultTrustRequirement(finding.ruleId) === "canonical";
|
|
12374
|
+
if (requirement === "none") {
|
|
12375
|
+
const definitives = [sourceFact(finding, input)];
|
|
12376
|
+
if (mappingBinds) definitives.push(mappingFact(finding, input));
|
|
12377
|
+
const definitiveNegative = definitives.find(([, state]) => state === "negative");
|
|
12378
|
+
if (definitiveNegative) {
|
|
12379
|
+
return { ...base, state: "advisory", stateReasons: [`trust:${definitiveNegative[0]}`] };
|
|
12380
|
+
}
|
|
12381
|
+
return { ...base, state: "blocked", stateReasons: [`eligible:${finding.severity}`] };
|
|
12382
|
+
}
|
|
12383
|
+
const facts = [
|
|
12384
|
+
[`introduced:${introduced.detail}`, introduced.state],
|
|
12385
|
+
sourceFact(finding, input)
|
|
12386
|
+
];
|
|
12387
|
+
if (requirement === "canonical") {
|
|
12388
|
+
facts.push(mappingFact(finding, input));
|
|
12389
|
+
} else if (mappingBinds) {
|
|
12390
|
+
const mapping = mappingFact(finding, input);
|
|
12391
|
+
if (mapping[1] === "negative") facts.push(mapping);
|
|
12392
|
+
}
|
|
12393
|
+
const negative = facts.find(([, state]) => state === "negative");
|
|
12394
|
+
if (negative) {
|
|
12395
|
+
return { ...base, state: "advisory", stateReasons: [`trust:${negative[0]}`] };
|
|
12396
|
+
}
|
|
12397
|
+
const unknowns = facts.filter(([, state]) => state === "unknown");
|
|
12398
|
+
if (unknowns.length > 0) {
|
|
12399
|
+
return {
|
|
12400
|
+
...base,
|
|
12401
|
+
state: "pending_cloud_trust",
|
|
12402
|
+
stateReasons: unknowns.map(([label]) => `trust:${label}`)
|
|
12403
|
+
};
|
|
12404
|
+
}
|
|
12405
|
+
return { ...base, state: "blocked", stateReasons: [`eligible:${finding.severity}`, "trust:all"] };
|
|
12406
|
+
}
|
|
12407
|
+
function eligibilityFor(finding, policy) {
|
|
12408
|
+
if (finding.advisory === true) return "ineligible:advisory-tier";
|
|
12409
|
+
if (!canBlock(coerceEvidenceGrade(finding.evidenceGrade))) return "ineligible:evidence-grade";
|
|
12410
|
+
if (finding.severity === "error") return null;
|
|
12411
|
+
if (finding.severity === "warn") {
|
|
12412
|
+
return policy.failOnWarnings ? null : "ineligible:warn-not-gated";
|
|
12413
|
+
}
|
|
12414
|
+
return "ineligible:info";
|
|
12415
|
+
}
|
|
12416
|
+
function coerceEvidenceGrade(grade) {
|
|
12417
|
+
if (grade === void 0) return "source_backed";
|
|
12418
|
+
return EVIDENCE_ORDER.includes(grade) ? grade : "none";
|
|
12419
|
+
}
|
|
12420
|
+
function defaultTrustRequirement(ruleId) {
|
|
12421
|
+
return tierFor(ruleId) === "contract" ? "canonical" : "evidence";
|
|
12422
|
+
}
|
|
12423
|
+
function introducedFactFor(finding, input) {
|
|
12424
|
+
const baseline = input.baseline;
|
|
12425
|
+
if (!baseline) return { state: "unknown", detail: "no-baseline" };
|
|
12426
|
+
if (!baseline.identityVerified) return { state: "unknown", detail: "identity-unverified" };
|
|
12427
|
+
const recorded = finding.baselineState ?? baseline.findingStates?.[finding.fingerprint] ?? "introduced";
|
|
12428
|
+
if (recorded === "existing") return { state: "negative", detail: "existing" };
|
|
12429
|
+
if (recorded === "introduced") return { state: "affirmative", detail: "introduced" };
|
|
12430
|
+
return { state: "unknown", detail: "unknown" };
|
|
12431
|
+
}
|
|
12432
|
+
function sourceFact(finding, input) {
|
|
12433
|
+
const source = finding.sourceTrust ?? input.trust?.sources?.[finding.fingerprint] ?? input.trust?.source ?? "unknown";
|
|
12434
|
+
if (source === "verified") return ["source:verified", "affirmative"];
|
|
12435
|
+
if (source === "unverified") return ["source:non-reproduction", "negative"];
|
|
12436
|
+
return ["source:unknown", "unknown"];
|
|
12437
|
+
}
|
|
12438
|
+
function mappingFact(finding, input) {
|
|
12439
|
+
const mapping = finding.mappingTrust ?? input.trust?.mappings[finding.fingerprint] ?? "unknown";
|
|
12440
|
+
if (mapping === "confirmed") return ["mapping:confirmed", "affirmative"];
|
|
12441
|
+
if (mapping === "unconfirmed") return ["mapping:unconfirmed", "negative"];
|
|
12442
|
+
return ["mapping:unknown", "unknown"];
|
|
12443
|
+
}
|
|
12444
|
+
function normalizeInputForDigest(input) {
|
|
12445
|
+
return {
|
|
12446
|
+
schema: "evaluation-input:v1",
|
|
12447
|
+
contract: input.contract,
|
|
12448
|
+
scope: input.scope,
|
|
12449
|
+
evidence: canonicalRows(evidenceFindings(input)),
|
|
12450
|
+
policy: input.policy,
|
|
12451
|
+
baseline: input.baseline,
|
|
12452
|
+
adoption: input.adoption,
|
|
12453
|
+
trust: input.trust,
|
|
12454
|
+
waivers: canonicalWaivers(input.waivers ?? []),
|
|
12455
|
+
integrity: {
|
|
12456
|
+
...input.integrity,
|
|
12457
|
+
...input.integrity.unknownPresets ? { unknownPresets: [...new Set(input.integrity.unknownPresets)].sort() } : {}
|
|
12458
|
+
},
|
|
12459
|
+
evaluatedAt: input.evaluatedAt
|
|
12460
|
+
};
|
|
12461
|
+
}
|
|
12462
|
+
function canonicalWaivers(waivers) {
|
|
12463
|
+
const expiryOf = (waiver) => waiver.expiresAt === void 0 || Number.isNaN(waiver.expiresAt) ? Number.POSITIVE_INFINITY : waiver.expiresAt;
|
|
12464
|
+
const canonical = waivers.map((waiver) => {
|
|
12465
|
+
const expiresAt = expiryOf(waiver);
|
|
12466
|
+
return expiresAt === Number.POSITIVE_INFINITY ? { fingerprint: waiver.fingerprint } : { fingerprint: waiver.fingerprint, expiresAt };
|
|
12467
|
+
});
|
|
12468
|
+
const sorted = canonical.sort((a, b) => {
|
|
12469
|
+
if (a.fingerprint !== b.fingerprint) return a.fingerprint < b.fingerprint ? -1 : 1;
|
|
12470
|
+
const ea = expiryOf(a);
|
|
12471
|
+
const eb = expiryOf(b);
|
|
12472
|
+
return ea === eb ? 0 : ea < eb ? -1 : 1;
|
|
12473
|
+
});
|
|
12474
|
+
return sorted.filter(
|
|
12475
|
+
(waiver, index) => index === 0 || waiver.fingerprint !== sorted[index - 1].fingerprint || expiryOf(waiver) !== expiryOf(sorted[index - 1])
|
|
12476
|
+
);
|
|
12477
|
+
}
|
|
9939
12478
|
export {
|
|
9940
12479
|
AGENT_CONTEXT_RELATIVE_PATH,
|
|
12480
|
+
AGENT_FEATURE_CONTEXT_MAX_BYTES_V1,
|
|
9941
12481
|
AGENT_FORMAT_SCHEMA_VERSION,
|
|
12482
|
+
ANALYSIS_LIMIT_CEILINGS_V1,
|
|
12483
|
+
ANALYSIS_PLAN_MAX_CAPABILITIES_V1,
|
|
12484
|
+
ANALYSIS_PLAN_MAX_DIALECTS_PER_REGION_V1,
|
|
12485
|
+
ANALYSIS_PLAN_MAX_REGIONS_V1,
|
|
9942
12486
|
BLOCKING_RULE_ALLOWLIST,
|
|
9943
12487
|
BRAND,
|
|
12488
|
+
CANONICAL_FACT_MAX_CONFLICTS_V1,
|
|
12489
|
+
CANONICAL_FACT_MAX_PROVENANCE_PER_VALUE_V1,
|
|
12490
|
+
CANONICAL_FACT_MAX_VALUES_PER_CONFLICT_V1,
|
|
9944
12491
|
CATALOG_FIXTURE_A_FCID,
|
|
9945
12492
|
CODES,
|
|
12493
|
+
CONTRACT_DISPLAY_ONLY_FIELDS,
|
|
9946
12494
|
CONTRACT_DOMAINS,
|
|
12495
|
+
CONTRACT_ENFORCEMENT_FIELDS,
|
|
9947
12496
|
CONTRACT_PREIMAGE_CAPABILITY_HEADER,
|
|
9948
12497
|
CONTRACT_PREIMAGE_SCHEMA,
|
|
9949
12498
|
CompiledFragmentsFileValidationError,
|
|
12499
|
+
ContractCatalogValidationError,
|
|
12500
|
+
CoverageValidationErrorV1,
|
|
9950
12501
|
DEFAULTS,
|
|
9951
12502
|
DEFAULT_ENHANCED_STYLE_PROPERTIES,
|
|
9952
12503
|
DEFAULT_STYLE_PROPERTIES,
|
|
9953
12504
|
EFFECTIVE_GOVERNANCE_INPUTS_SCHEMA,
|
|
12505
|
+
EMPTY_VOCABULARY_MESSAGE,
|
|
12506
|
+
EVALUATION_MAX_FINDINGS_V2,
|
|
12507
|
+
EVALUATION_MAX_MAP_ENTRIES_V2,
|
|
12508
|
+
EVALUATION_MAX_POLICY_RULES_V2,
|
|
12509
|
+
EVALUATION_MAX_REASON_CODES_V2,
|
|
12510
|
+
EVALUATION_MAX_WAIVERS_V2,
|
|
12511
|
+
EVALUATION_MAX_WAIVER_MATCHES_V2,
|
|
12512
|
+
EVALUATION_RECEIPT_STRING_MAX_BYTES_V1,
|
|
12513
|
+
EVALUATOR_VERSION,
|
|
12514
|
+
EVALUATOR_VERSION_V2,
|
|
9954
12515
|
EVIDENCE_ORDER,
|
|
9955
12516
|
EXPLAIN_URL_BASE,
|
|
12517
|
+
FEATURE_PLAN_MAX_ACCEPTANCE_ITEMS_V1,
|
|
12518
|
+
FEATURE_PLAN_MAX_DECISIONS_V1,
|
|
12519
|
+
FEATURE_PLAN_MAX_EVIDENCE_REFS_V1,
|
|
12520
|
+
FEATURE_PLAN_MAX_GAPS_V1,
|
|
12521
|
+
FEATURE_PLAN_MAX_SCENARIOS_V1,
|
|
12522
|
+
FEATURE_PLAN_MAX_TEXT_BYTES_V1,
|
|
12523
|
+
FEATURE_PLAN_MAX_USES_PER_KIND_V1,
|
|
9956
12524
|
FRAGMENTS_INTERNAL_RULE_IDS,
|
|
12525
|
+
FRAGMENTS_MANIFEST_FILENAME,
|
|
12526
|
+
FRAGMENTS_MANIFEST_SCHEMA_VERSION,
|
|
12527
|
+
FRAGMENTS_MANIFEST_TOKEN_RULE,
|
|
12528
|
+
FRAGMENT_V3_SCHEMA_URL,
|
|
9957
12529
|
FactIndex,
|
|
9958
12530
|
GOVERNANCE_TELEMETRY_FIELDS,
|
|
9959
12531
|
GOVERNANCE_TELEMETRY_SOURCE_DISCLOSURE,
|
|
@@ -9963,13 +12535,18 @@ export {
|
|
|
9963
12535
|
PRESET_NAMES,
|
|
9964
12536
|
PROVE_DEFAULT_MAX_PASSES,
|
|
9965
12537
|
PROVE_MAX_PASSES,
|
|
12538
|
+
PROVIDER_ID_MAX_BYTES_V1,
|
|
9966
12539
|
RAW_HTML_ADVISORY_TAGS,
|
|
9967
12540
|
RAW_HTML_CANONICAL_TAGS,
|
|
9968
12541
|
RAW_HTML_INPUT_TYPE_CANONICALS,
|
|
9969
12542
|
RAW_HTML_ROLE_CANONICALS,
|
|
9970
12543
|
REGISTRY_ARTIFACT_SCHEMA_VERSION,
|
|
12544
|
+
REGISTRY_INDEX_SCHEMA_VERSION,
|
|
9971
12545
|
REGISTRY_INSTALL_RECEIPT_SCHEMA_VERSION,
|
|
9972
12546
|
REGISTRY_MANIFEST_SCHEMA_VERSION,
|
|
12547
|
+
REGISTRY_POINTER_SCHEMA_VERSION,
|
|
12548
|
+
REGISTRY_SHARD_SCHEMA_VERSION,
|
|
12549
|
+
REPOSITORY_BINDING_ID_MAX_BYTES_V1,
|
|
9973
12550
|
RULES,
|
|
9974
12551
|
RULE_FAMILY_IDS,
|
|
9975
12552
|
RULE_FAMILY_MEMBERS,
|
|
@@ -9978,12 +12555,27 @@ export {
|
|
|
9978
12555
|
SEVERITY_RANK,
|
|
9979
12556
|
SEVERITY_WEIGHTS,
|
|
9980
12557
|
agentErrorEnvelopeSchema,
|
|
12558
|
+
agentFeatureContextV1Schema2 as agentFeatureContextV1Schema,
|
|
9981
12559
|
agentFormatSchema,
|
|
9982
12560
|
agentIntegritySchema,
|
|
9983
12561
|
agentOutputSchema,
|
|
9984
12562
|
aiMetadataSchema,
|
|
12563
|
+
analysisLimitsV1Schema,
|
|
12564
|
+
analysisObligationsDigestV1,
|
|
12565
|
+
analysisPlanDigestV1,
|
|
12566
|
+
analysisPlanIdFromDigest,
|
|
12567
|
+
analysisPlanIdSchema,
|
|
12568
|
+
analysisPlanIdStringSchema,
|
|
12569
|
+
analysisPlanInputV1Schema,
|
|
12570
|
+
analysisPlanV1Schema,
|
|
12571
|
+
analysisRegionV1Schema,
|
|
9985
12572
|
analyzeComposition,
|
|
12573
|
+
approvedFeatureManifestInputV1Schema,
|
|
12574
|
+
approvedFeatureManifestRevisionDigestV1,
|
|
12575
|
+
approvedFeatureManifestV1Schema,
|
|
12576
|
+
artifactContentHash,
|
|
9986
12577
|
asComponentId,
|
|
12578
|
+
assembleRegistryArtifact,
|
|
9987
12579
|
assertPortableRegistryPath,
|
|
9988
12580
|
assertValidRegistryArtifact,
|
|
9989
12581
|
authorOwnedImport,
|
|
@@ -9992,11 +12584,15 @@ export {
|
|
|
9992
12584
|
bridgeSourceViolations,
|
|
9993
12585
|
budgetBar,
|
|
9994
12586
|
buildAgentFormat,
|
|
12587
|
+
buildAnalysisPlanV1,
|
|
12588
|
+
buildApprovedFeatureManifestV1,
|
|
9995
12589
|
buildComponentKey,
|
|
12590
|
+
buildFeatureProposalV1,
|
|
9996
12591
|
buildRegistryArtifact,
|
|
9997
12592
|
buildRegistryFile,
|
|
9998
12593
|
buildRegistryInstallPlan,
|
|
9999
12594
|
buildRegistryInstallReceipt,
|
|
12595
|
+
buildRegistryPointer,
|
|
10000
12596
|
buildSpacingTokenLookup,
|
|
10001
12597
|
bundleArtifactMetadataSchema,
|
|
10002
12598
|
bundleComponentShardSchema,
|
|
@@ -10014,14 +12610,18 @@ export {
|
|
|
10014
12610
|
canonicalBridgeIdentitySources,
|
|
10015
12611
|
canonicalBridgeV1Schema,
|
|
10016
12612
|
canonicalDirectionConflictsTarget,
|
|
12613
|
+
canonicalFactConflictV1Schema,
|
|
12614
|
+
canonicalFactConflictValueV1Schema,
|
|
12615
|
+
canonicalFactIntegrityV1Schema,
|
|
10017
12616
|
canonicalJson,
|
|
10018
12617
|
canonicalPreimage,
|
|
10019
12618
|
canonicalizeOwnedComponentId,
|
|
10020
12619
|
canonicalizeOwnedImport,
|
|
12620
|
+
capConfiguredSeverity,
|
|
12621
|
+
capabilityGapV1Schema,
|
|
10021
12622
|
catalogFixtureA,
|
|
10022
12623
|
catalogFixtureAContractPayload,
|
|
10023
12624
|
catalogFixtureATokensDtcg,
|
|
10024
|
-
checkStoryExclusion,
|
|
10025
12625
|
clampMaxPasses,
|
|
10026
12626
|
classifyComplexity,
|
|
10027
12627
|
classifyIdentity,
|
|
@@ -10041,45 +12641,79 @@ export {
|
|
|
10041
12641
|
compileEffectiveGovernanceInputs,
|
|
10042
12642
|
compileFragment,
|
|
10043
12643
|
compileGlobalGovernanceFacts,
|
|
10044
|
-
compileRecipe,
|
|
10045
12644
|
componentContractSchema,
|
|
10046
12645
|
componentGovernanceRecordSchema,
|
|
10047
12646
|
componentGovernanceRecordsSchema,
|
|
10048
12647
|
componentId,
|
|
10049
12648
|
componentRelationSchema,
|
|
12649
|
+
componentUseDecisionV1Schema,
|
|
10050
12650
|
compositionAuthoringEntrySchema,
|
|
10051
12651
|
compositionMetadataSchema,
|
|
10052
12652
|
compositionPatternSchema,
|
|
10053
12653
|
computeRegistryHash,
|
|
10054
12654
|
configDeclarationForDiagnostics,
|
|
10055
12655
|
configRecordShape,
|
|
12656
|
+
configuredFindingSeverity,
|
|
10056
12657
|
containsTailwindV4Theme,
|
|
10057
12658
|
contractComponentsFromFragments,
|
|
10058
12659
|
contractHash,
|
|
10059
12660
|
contractPolicyFromGovernanceConfig,
|
|
10060
12661
|
contractTierRuleIds,
|
|
10061
12662
|
contractTokenReferenceCensus,
|
|
12663
|
+
coverageArtifactDigestV1,
|
|
12664
|
+
coverageRegionV1Schema,
|
|
12665
|
+
coverageStateV1Schema,
|
|
12666
|
+
coverageSummaryV1Schema,
|
|
10062
12667
|
customerDefaultRuleStates,
|
|
12668
|
+
decisionRequestV1Schema,
|
|
12669
|
+
decisionResolutionV1Schema,
|
|
12670
|
+
defaultRegistryShardPath,
|
|
10063
12671
|
defineBlock,
|
|
10064
12672
|
defineConfig,
|
|
10065
12673
|
defineFragment,
|
|
10066
|
-
|
|
12674
|
+
deriveArtifactId,
|
|
12675
|
+
deriveCoverageSummaryV1,
|
|
10067
12676
|
describePolicyExclude,
|
|
10068
12677
|
detectOrphanGovernanceScales,
|
|
10069
|
-
detectSubComponentPaths,
|
|
10070
12678
|
detectUnconsumedConfigKeys,
|
|
10071
12679
|
detectUnmatchedPolicyExcludes,
|
|
10072
12680
|
diffContractDomains,
|
|
12681
|
+
digestHexSchema,
|
|
12682
|
+
digestHexStringSchema,
|
|
10073
12683
|
discoverComponents,
|
|
10074
12684
|
dtcgTokenFileSchema,
|
|
12685
|
+
effectiveEvaluationWaiverV2Schema,
|
|
10075
12686
|
emptyConformResult,
|
|
12687
|
+
emptyVocabularyConfigFile,
|
|
12688
|
+
evaluate2 as evaluate,
|
|
10076
12689
|
evaluateGovernanceIntegrity,
|
|
12690
|
+
evaluationInputV2Schema,
|
|
12691
|
+
evaluationReceiptDigestV1,
|
|
12692
|
+
evaluationReceiptIdFromDigest,
|
|
12693
|
+
evaluationReceiptIdSchema,
|
|
12694
|
+
evaluationReceiptIdStringSchema,
|
|
12695
|
+
evaluationReceiptMintInputV1Schema,
|
|
12696
|
+
evaluationReceiptV1Schema,
|
|
12697
|
+
evaluationResultV2Schema,
|
|
12698
|
+
evidenceRefV1Schema,
|
|
10077
12699
|
excludeGlobToRegExp,
|
|
12700
|
+
expandRegistryComponentClosure,
|
|
10078
12701
|
explainUrlForCode,
|
|
10079
12702
|
factEvidenceSchema,
|
|
10080
12703
|
factId,
|
|
10081
12704
|
factLocationSchema,
|
|
10082
12705
|
familyDistance,
|
|
12706
|
+
featureAcceptanceItemV1Schema,
|
|
12707
|
+
featurePinsV1Schema,
|
|
12708
|
+
featurePlanIdFromEntropy,
|
|
12709
|
+
featurePlanIdSchema,
|
|
12710
|
+
featurePlanIdStringSchema,
|
|
12711
|
+
featureProposalInputV1Schema,
|
|
12712
|
+
featureProposalRevisionDigestV1,
|
|
12713
|
+
featureProposalV1Schema,
|
|
12714
|
+
featureRevisionIdFromDigest,
|
|
12715
|
+
featureRevisionIdSchema,
|
|
12716
|
+
featureRevisionIdStringSchema,
|
|
10083
12717
|
figma,
|
|
10084
12718
|
figmaPropMappingSchema,
|
|
10085
12719
|
finalizeRegistryManifest,
|
|
@@ -10096,18 +12730,35 @@ export {
|
|
|
10096
12730
|
formatStampPin,
|
|
10097
12731
|
formatStampVersionHash,
|
|
10098
12732
|
formatTokenSummary,
|
|
12733
|
+
fragmentAnnotationsV3Schema,
|
|
10099
12734
|
fragmentBanSchema,
|
|
10100
12735
|
fragmentContractSchema,
|
|
10101
12736
|
fragmentDefinitionSchema,
|
|
10102
12737
|
fragmentDefinitionV2Schema,
|
|
12738
|
+
fragmentDefinitionV3BodySchema,
|
|
12739
|
+
fragmentDefinitionV3Schema,
|
|
12740
|
+
fragmentDesignV3Schema,
|
|
12741
|
+
fragmentDontExampleV3Schema,
|
|
10103
12742
|
fragmentGeneratedSchema,
|
|
12743
|
+
fragmentGuidanceV3Schema,
|
|
12744
|
+
fragmentMatrixV3Schema,
|
|
10104
12745
|
fragmentMetaSchema,
|
|
12746
|
+
fragmentMetaV3Schema,
|
|
12747
|
+
fragmentPreviewV3Schema,
|
|
10105
12748
|
fragmentProvenanceSchema,
|
|
12749
|
+
fragmentSourceValues,
|
|
12750
|
+
fragmentStateV3Schema,
|
|
10106
12751
|
fragmentUsageSchema,
|
|
10107
12752
|
fragmentVariantSchema,
|
|
10108
12753
|
fragmentsConfigSchema,
|
|
12754
|
+
fragmentsManifestFcid,
|
|
12755
|
+
fragmentsManifestGrammarSchema,
|
|
12756
|
+
fragmentsManifestPatternSchema,
|
|
12757
|
+
fragmentsManifestPrimitiveSchema,
|
|
12758
|
+
fragmentsManifestSchema,
|
|
10109
12759
|
fragmentsPresetRuleStates,
|
|
10110
12760
|
g,
|
|
12761
|
+
gapDispositionV1Schema,
|
|
10111
12762
|
gatesCi,
|
|
10112
12763
|
generateCSSCustomProperties,
|
|
10113
12764
|
generateContext,
|
|
@@ -10134,7 +12785,6 @@ export {
|
|
|
10134
12785
|
inferTokenGroup,
|
|
10135
12786
|
isColorLike,
|
|
10136
12787
|
isCompositionPattern,
|
|
10137
|
-
isConfigExcluded,
|
|
10138
12788
|
isContractFile,
|
|
10139
12789
|
isContractTierRule,
|
|
10140
12790
|
isDTCGFile,
|
|
@@ -10142,12 +12792,13 @@ export {
|
|
|
10142
12792
|
isEffectiveCanonicalSource,
|
|
10143
12793
|
isEnforceableHtmlEquivalent,
|
|
10144
12794
|
isFigmaPropMapping,
|
|
10145
|
-
isForceIncluded,
|
|
10146
12795
|
isPortableRepoPath,
|
|
10147
12796
|
isPresetSourcedRule,
|
|
10148
12797
|
isRawHtmlAdvisoryTier,
|
|
10149
12798
|
isReactComponent,
|
|
10150
12799
|
isRuleFamilyId,
|
|
12800
|
+
layoutConcernV1Schema,
|
|
12801
|
+
layoutOwnershipV1Schema,
|
|
10151
12802
|
localCanonicalContractMappings,
|
|
10152
12803
|
lowerCompositionContract,
|
|
10153
12804
|
makeA11yNameRequiredFact,
|
|
@@ -10215,15 +12866,21 @@ export {
|
|
|
10215
12866
|
mcpSourceTypeSchema,
|
|
10216
12867
|
mcpTokenDataSchema,
|
|
10217
12868
|
mcpTokenSchema,
|
|
12869
|
+
mintEvaluationReceiptId,
|
|
10218
12870
|
nearestByDeltaE,
|
|
10219
12871
|
nearestSignedScaleValue,
|
|
12872
|
+
normalizeAnalysisPlanInputV1,
|
|
12873
|
+
normalizeApprovedFeatureManifestInputV1,
|
|
12874
|
+
normalizeCanonicalFactIntegrityV1,
|
|
10220
12875
|
normalizeColor,
|
|
10221
12876
|
normalizeConfigPath,
|
|
10222
12877
|
normalizeExcludePath,
|
|
12878
|
+
normalizeFeatureProposalInputV1,
|
|
10223
12879
|
normalizeFinding,
|
|
10224
12880
|
normalizeGovernanceConfig,
|
|
10225
12881
|
normalizePolicyExcludes,
|
|
10226
12882
|
normalizeRegistryRepoPath,
|
|
12883
|
+
normalizeRepositoryBindingKeyV1,
|
|
10227
12884
|
normalizeSeverity,
|
|
10228
12885
|
normalizeStyleValue,
|
|
10229
12886
|
normalizeToV1,
|
|
@@ -10232,6 +12889,10 @@ export {
|
|
|
10232
12889
|
normalizeViolation,
|
|
10233
12890
|
overriddenRecordSeverityDiagnostic,
|
|
10234
12891
|
ownedImportEquivalents,
|
|
12892
|
+
parseAgentFeatureContextV1,
|
|
12893
|
+
parseAnalysisPlanId,
|
|
12894
|
+
parseAnalysisPlanV1,
|
|
12895
|
+
parseApprovedFeatureManifestV1,
|
|
10235
12896
|
parseColor,
|
|
10236
12897
|
parseColorToRgb,
|
|
10237
12898
|
parseCompiledFragmentsFile,
|
|
@@ -10240,25 +12901,39 @@ export {
|
|
|
10240
12901
|
parseCssTokens,
|
|
10241
12902
|
parseDtcgTokens as parseDTCGFile,
|
|
10242
12903
|
parseDesignTokenContent,
|
|
12904
|
+
parseDigestHex,
|
|
10243
12905
|
parseDtcgTokens,
|
|
12906
|
+
parseEvaluationReceiptId,
|
|
12907
|
+
parseEvaluationReceiptV1,
|
|
12908
|
+
parseFeaturePlanId,
|
|
12909
|
+
parseFeatureProposalV1,
|
|
12910
|
+
parseFeatureRevisionId,
|
|
12911
|
+
parseFragmentsManifest,
|
|
10244
12912
|
parseRgb,
|
|
10245
12913
|
parseScssTokens,
|
|
10246
12914
|
parseScssVariables,
|
|
10247
12915
|
parseTailwindV4Theme,
|
|
10248
12916
|
parseTokenFile,
|
|
10249
12917
|
parseTokens,
|
|
12918
|
+
patternStatusV1Schema,
|
|
12919
|
+
patternUseDecisionV1Schema,
|
|
12920
|
+
placementDecisionV1Schema,
|
|
10250
12921
|
policyExcludeMatchesPath,
|
|
10251
12922
|
policyExcludeSchema,
|
|
10252
12923
|
portableRepoPathError,
|
|
10253
12924
|
projectCanonicalDirectionConflicts,
|
|
10254
12925
|
projectContractPreimage,
|
|
12926
|
+
projectEnforcementContract,
|
|
10255
12927
|
projectSupersededImportPathPreferences,
|
|
10256
12928
|
projectV1OwnedComponentId,
|
|
10257
12929
|
projectV1OwnedImportIdentity,
|
|
12930
|
+
propAnnotationSchema,
|
|
10258
12931
|
propDefinitionSchema,
|
|
10259
12932
|
proveCompliant,
|
|
10260
12933
|
proveIssueCount,
|
|
10261
|
-
|
|
12934
|
+
providerProofDigestV1,
|
|
12935
|
+
providerProofV1Schema,
|
|
12936
|
+
readRuleConfig,
|
|
10262
12937
|
registryArtifactDigest,
|
|
10263
12938
|
registryArtifactSchema,
|
|
10264
12939
|
registryComponentExportSchema,
|
|
@@ -10270,25 +12945,39 @@ export {
|
|
|
10270
12945
|
registryFileRoleSchema,
|
|
10271
12946
|
registryFileSchema,
|
|
10272
12947
|
registryFileSize,
|
|
12948
|
+
registryIndexSchema,
|
|
10273
12949
|
registryInstallProfileSchema,
|
|
10274
12950
|
registryInstallReceiptComponentSchema,
|
|
10275
12951
|
registryInstallReceiptFileSchema,
|
|
10276
12952
|
registryInstallReceiptSchema,
|
|
10277
12953
|
registryManifestCanonicalPreimage,
|
|
10278
12954
|
registryManifestDraftSchema,
|
|
12955
|
+
registryManifestFileMetadata,
|
|
12956
|
+
registryManifestFilePaths,
|
|
10279
12957
|
registryManifestSchema,
|
|
12958
|
+
registryPointerSchema,
|
|
12959
|
+
registryShardSchema,
|
|
12960
|
+
registryShardsForPaths,
|
|
10280
12961
|
registrySourceSchema,
|
|
12962
|
+
repositoryBindingDigestV1,
|
|
12963
|
+
repositoryBindingKeyV1Schema,
|
|
10281
12964
|
resolveArea,
|
|
10282
12965
|
resolveCanonicalForAriaRole,
|
|
10283
12966
|
resolveCanonicalForRawHtml,
|
|
12967
|
+
resolveComponentGovernance,
|
|
10284
12968
|
resolveConfiguredAppPath,
|
|
10285
12969
|
resolveDesignTokenValue,
|
|
10286
12970
|
resolveFigmaMapping,
|
|
12971
|
+
resolveGovernanceRecordsForIdentity,
|
|
10287
12972
|
resolveOwnedPackageImport,
|
|
10288
12973
|
resolvePerformanceConfig,
|
|
10289
12974
|
resolveProveVerdict,
|
|
12975
|
+
resolveRegistryComponentId,
|
|
12976
|
+
resolveRegistryInstallSelection,
|
|
12977
|
+
resolveRegistryInstallSources,
|
|
10290
12978
|
resolveSpacingValue,
|
|
10291
12979
|
resolveTokenValue,
|
|
12980
|
+
responsiveDecisionV1Schema,
|
|
10292
12981
|
rgbToHex,
|
|
10293
12982
|
ruleA11yRequiredAccessibleName,
|
|
10294
12983
|
ruleA11yStandard,
|
|
@@ -10314,16 +13003,18 @@ export {
|
|
|
10314
13003
|
ruleTokensRequireDualFallback,
|
|
10315
13004
|
runRules,
|
|
10316
13005
|
scaleGovernanceRecordSchema,
|
|
10317
|
-
|
|
13006
|
+
scenarioRequirementV1Schema,
|
|
10318
13007
|
serializeContractStamp,
|
|
10319
13008
|
severityLevel,
|
|
10320
13009
|
severitySchema,
|
|
10321
13010
|
sha256Hex,
|
|
13011
|
+
shardRegistryArtifact,
|
|
10322
13012
|
sortBySeverity,
|
|
10323
13013
|
sourceToRegistryTargetPath,
|
|
10324
13014
|
suppressionDirectiveSchema,
|
|
10325
13015
|
tierFor,
|
|
10326
13016
|
tokenIncludesFromConfig,
|
|
13017
|
+
tokenUseDecisionV1Schema,
|
|
10327
13018
|
topologyBase,
|
|
10328
13019
|
validatorResultSchema,
|
|
10329
13020
|
verifiedContractPreimageFromPin,
|