@usefragments/core 1.10.1 → 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.
Files changed (128) hide show
  1. package/dist/{chunk-MZ4SW3TP.js → chunk-3IOWHECM.js} +8 -1
  2. package/dist/{chunk-MZ4SW3TP.js.map → chunk-3IOWHECM.js.map} +1 -1
  3. package/dist/chunk-7ULGH74M.js +66 -0
  4. package/dist/chunk-7ULGH74M.js.map +1 -0
  5. package/dist/{chunk-YF65VYRY.js → chunk-ML5S6QNU.js} +191 -169
  6. package/dist/chunk-ML5S6QNU.js.map +1 -0
  7. package/dist/chunk-PWIJMOI4.js +202 -0
  8. package/dist/chunk-PWIJMOI4.js.map +1 -0
  9. package/dist/{chunk-XN3LSDPY.js → chunk-RPSEABY3.js} +622 -344
  10. package/dist/chunk-RPSEABY3.js.map +1 -0
  11. package/dist/chunk-RYFULE43.js +578 -0
  12. package/dist/chunk-RYFULE43.js.map +1 -0
  13. package/dist/codes/index.d.ts +2 -2
  14. package/dist/codes/index.js +3 -2
  15. package/dist/compiled-types/index.d.ts +327 -2
  16. package/dist/compiled-types/index.js +1 -1
  17. package/dist/generate/index.d.ts +3 -2
  18. package/dist/{governance-CLk_wkP9.d.ts → governance-BAsy1k2H.d.ts} +472 -513
  19. package/dist/governance-telemetry.d.ts +6 -0
  20. package/dist/governance-telemetry.js +1 -1
  21. package/dist/{index-_sxhUNqx.d.ts → index-C8bcXVav.d.ts} +448 -448
  22. package/dist/index.d.ts +9165 -1297
  23. package/dist/index.js +3044 -352
  24. package/dist/index.js.map +1 -1
  25. package/dist/manifest.d.ts +228 -0
  26. package/dist/manifest.js +24 -0
  27. package/dist/manifest.js.map +1 -0
  28. package/dist/preview/index.js +45 -1
  29. package/dist/preview/index.js.map +1 -1
  30. package/dist/preview-runtime.d.ts +1 -2
  31. package/dist/preview-runtime.js +150 -14
  32. package/dist/preview-runtime.js.map +1 -1
  33. package/dist/react-types.d.ts +1 -2
  34. package/dist/registry.d.ts +1412 -203
  35. package/dist/registry.js +30 -3
  36. package/dist/schemas/index.d.ts +1 -1
  37. package/dist/schemas/index.js +3 -2
  38. package/dist/storyAdapter.d.ts +1 -2
  39. package/dist/storyAdapter.js +11 -49
  40. package/dist/storyAdapter.js.map +1 -1
  41. package/dist/test-utils.d.ts +3 -2
  42. package/package.json +8 -2
  43. package/src/__tests__/contract-parser.test.ts +318 -277
  44. package/src/__tests__/preview-runtime-hook.test.tsx +315 -0
  45. package/src/__tests__/preview-runtime.test.tsx +30 -8
  46. package/src/__tests__/schema.test.ts +191 -14
  47. package/src/analysis-plan/analysis-plan-v1.test.ts +320 -0
  48. package/src/analysis-plan/coverage.ts +181 -0
  49. package/src/analysis-plan/digest.ts +141 -0
  50. package/src/analysis-plan/index.ts +34 -0
  51. package/src/analysis-plan/types.ts +207 -0
  52. package/src/codes/__tests__/codes.test.ts +9 -0
  53. package/src/codes/codes.ts +30 -0
  54. package/src/compiled-types/index.ts +640 -39
  55. package/src/compiled-types/parse.test.ts +145 -4
  56. package/src/component-contract.ts +95 -53
  57. package/src/composition.ts +7 -13
  58. package/src/constants.ts +3 -6
  59. package/src/contract/hash.test.ts +20 -0
  60. package/src/contract/hash.ts +66 -9
  61. package/src/contract/index.ts +24 -1
  62. package/src/contract/manifest.test.ts +94 -0
  63. package/src/contract/manifest.ts +68 -0
  64. package/src/contract/preimage.test.ts +219 -1
  65. package/src/contract/preimage.ts +326 -6
  66. package/src/contract/stamp.test.ts +3 -0
  67. package/src/contract/stamp.ts +1 -1
  68. package/src/contract-parser.ts +54 -30
  69. package/src/defineFragment.test.ts +476 -91
  70. package/src/defineFragment.ts +204 -114
  71. package/src/domain-ids.test.ts +52 -0
  72. package/src/domain-ids.ts +106 -0
  73. package/src/evaluation/evaluate.test.ts +522 -0
  74. package/src/evaluation/evaluate.ts +680 -0
  75. package/src/evaluation/evaluation-v2-receipt-v1.test.ts +760 -0
  76. package/src/evaluation/index.ts +58 -0
  77. package/src/evaluation/receipt.ts +753 -0
  78. package/src/evaluation/types.ts +406 -0
  79. package/src/facts/builders.ts +2 -0
  80. package/src/facts/compile.ts +29 -6
  81. package/src/facts/fact-index.ts +13 -3
  82. package/src/facts/fact-integrity-v1.test.ts +172 -0
  83. package/src/facts/facts.test.ts +15 -0
  84. package/src/facts/ids.ts +46 -3
  85. package/src/facts/index.ts +14 -1
  86. package/src/facts/integrity.ts +134 -0
  87. package/src/facts/types.ts +36 -0
  88. package/src/feature-plan/digest.ts +217 -0
  89. package/src/feature-plan/feature-plan-v1.test.ts +529 -0
  90. package/src/feature-plan/index.ts +65 -0
  91. package/src/feature-plan/types.ts +628 -0
  92. package/src/governance-integrity.test.ts +1 -0
  93. package/src/governance-integrity.ts +5 -3
  94. package/src/governance-telemetry.ts +8 -0
  95. package/src/governance.ts +52 -8
  96. package/src/index.ts +299 -37
  97. package/src/preview/validation.test.ts +62 -0
  98. package/src/preview/validation.ts +48 -2
  99. package/src/preview-runtime.tsx +227 -20
  100. package/src/registry-install-plan.ts +200 -109
  101. package/src/registry-shards.test.ts +263 -0
  102. package/src/registry.ts +237 -0
  103. package/src/repository-binding.test.ts +50 -0
  104. package/src/repository-binding.ts +96 -0
  105. package/src/rules/families.test.ts +36 -0
  106. package/src/rules/finding.ts +7 -2
  107. package/src/rules/index.ts +17 -1
  108. package/src/rules/rule-config.test.ts +66 -0
  109. package/src/rules/rule-config.ts +73 -0
  110. package/src/rules/rules.test.ts +26 -0
  111. package/src/rules/tokens-css-vars-must-be-defined.test.ts +51 -2
  112. package/src/rules/tokens-css-vars-must-be-defined.ts +34 -1
  113. package/src/schema.ts +293 -113
  114. package/src/schemas/index.ts +1 -1
  115. package/src/storyAdapter.test.ts +68 -12
  116. package/src/storyAdapter.ts +44 -75
  117. package/src/tokens/scss.test.ts +32 -1
  118. package/src/tokens/scss.ts +12 -7
  119. package/src/types.ts +258 -37
  120. package/dist/chunk-RANPUC6C.js +0 -72
  121. package/dist/chunk-RANPUC6C.js.map +0 -1
  122. package/dist/chunk-XN3LSDPY.js.map +0 -1
  123. package/dist/chunk-YF65VYRY.js.map +0 -1
  124. package/src/fragment-types.ts +0 -214
  125. package/src/react-create-element.test.ts +0 -22
  126. package/src/react-create-element.ts +0 -12
  127. package/src/storyFilters.test.ts +0 -350
  128. 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-RANPUC6C.js";
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-XN3LSDPY.js";
211
+ } from "./chunk-RPSEABY3.js";
122
212
  import {
123
- resolveArea
124
- } from "./chunk-3LLRNCPX.js";
213
+ isPortableRepoPath,
214
+ normalizeConfigPath,
215
+ portableRepoPathError,
216
+ resolveConfiguredAppPath,
217
+ tokenIncludesFromConfig,
218
+ topologyBase
219
+ } from "./chunk-EIYNNS77.js";
125
220
  import {
126
- GOVERNANCE_TELEMETRY_FIELDS,
127
- GOVERNANCE_TELEMETRY_SOURCE_DISCLOSURE,
128
- GOVERNANCE_TELEMETRY_TOP_LEVEL_FIELDS
129
- } from "./chunk-MZ4SW3TP.js";
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 selectedRegistryComponentNames(artifact, requested, all) {
753
- if (all || requested.includes("*")) {
754
- return Object.keys(artifact.manifest.components).sort(
755
- (left, right) => left.localeCompare(right)
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
- if (requested.length === 0) {
759
- throw new Error("Choose at least one registry component to install.");
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
- for (const name of requested) {
762
- if (!artifact.manifest.components[name]) {
763
- throw new Error(`Unknown registry component ${name}`);
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
- return [...new Set(requested)].sort();
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(artifact, componentNames) {
769
- const allComponents = Object.keys(artifact.manifest.components);
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 file.role !== "test" && file.role !== "story";
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
- for (const dependency of artifact.manifest.dependencies) {
782
- dependencies.set(dependencyKey(dependency), dependency);
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 collectComponentWritePlan(args) {
793
- const writes = /* @__PURE__ */ new Map();
794
- for (const componentName of args.componentNames) {
795
- const component = args.artifact.manifest.components[componentName];
796
- for (const file of component.files) {
797
- if (!shouldInstallFile(file, args.includeTests)) continue;
798
- const content = args.artifact.files[file.path];
799
- if (!content) throw new Error(`Artifact is missing file content for ${file.path}`);
800
- const target = sourceToRegistryTargetPath(args.targetPath, file.path);
801
- writes.set(target, {
802
- path: target,
803
- sourcePath: file.path,
804
- content: content.content,
805
- componentId: component.componentId
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
- return [...writes.values()].sort((left, right) => left.path.localeCompare(right.path));
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 collectPackageWritePlan(args) {
847
- const writes = /* @__PURE__ */ new Map();
848
- const packageFiles = new Map(
849
- args.artifact.manifest.packageFiles.map((file) => [file.path, file])
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.artifact.manifest.components[name];
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 componentNames = selectedRegistryComponentNames(
908
- input.artifact,
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 isCompleteInstall = installsCompleteRegistry(input.artifact, componentNames);
914
- const hasPackageRoot = input.artifact.manifest.entrypoints.some(
915
- (entrypoint) => entrypoint.specifier === "."
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
- ...isCompleteInstall ? collectPackageWritePlan({
919
- artifact: input.artifact,
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 { componentNames, plans, dependencies };
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 z8 = (r * 0.0193339 + g2 * 0.119192 + b * 0.9503041) / 1.08883;
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
- z8 = z8 > 8856e-6 ? Math.pow(z8, 1 / 3) : 7.787 * z8 + 16 / 116;
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 - z8)
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: z4.unknown(), false: z4.unknown() }).optional()
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(["storybook", "manual", "ai"]),
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(["storybook", "manual", "ai", "scan"]),
1936
+ source: z4.enum(fragmentSourceValues),
1834
1937
  sourceFile: z4.string().optional(),
1835
1938
  confidence: z4.number().min(0).max(1).optional(),
1836
- timestamp: z4.string().datetime().optional(),
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 recipeDefinitionSchema = blockDefinitionSchema;
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
- return "govern" in def || "governance" in def;
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 === "scan" ? "ai" : 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 defineFragment(definition) {
1930
- if (process.env.NODE_ENV !== "production") {
1931
- const governed = isGovernedDefinition(definition);
1932
- const v2 = isV2Definition(definition);
1933
- const schema = governed ? governedFragmentDefinitionSchema : v2 ? fragmentDefinitionV2Schema : fragmentDefinitionSchema;
1934
- const result = schema.safeParse(definition);
1935
- if (!result.success) {
1936
- const name = definition.meta?.name || "unknown";
1937
- const errors = result.error.errors.map((e) => ` - ${e.path.join(".")}: ${e.message}`).join("\n");
1938
- throw new Error(`Invalid fragment definition for "${name}":
1939
- ${errors}`);
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 === "scan" ? "ai" : 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
- if (process.env.NODE_ENV !== "production") {
1990
- const result = blockDefinitionSchema.safeParse(definition);
1991
- if (!result.success) {
1992
- const errors = result.error.errors.map((e) => ` - ${e.path.join(".")}: ${e.message}`).join("\n");
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) {
@@ -2699,11 +2891,11 @@ function detectTokenPrefix(names) {
2699
2891
  }
2700
2892
  function parseScssVariables(content) {
2701
2893
  const vars = /* @__PURE__ */ new Map();
2702
- const scssVarRegex = /^\s*(\$[\w-]+)\s*:\s*(.+?)\s*(?:!default\s*)?;/gm;
2894
+ const scssVarRegex = /^\s*(\$[\w-]+)\s*:\s*([\s\S]*?)\s*(?:!default\s*)?;/gm;
2703
2895
  let match;
2704
2896
  while ((match = scssVarRegex.exec(content)) !== null) {
2705
2897
  const name = match[1];
2706
- const value = match[2].replace(/\s*\/\/.*$/, "").trim();
2898
+ const value = match[2].replace(/\s*\/\/[^\n]*$/gm, "").replace(/\s+/g, " ").trim();
2707
2899
  if (!vars.has(name)) {
2708
2900
  vars.set(name, value);
2709
2901
  }
@@ -2776,6 +2968,7 @@ function parseScssTokens(content, filePath = "tokens.scss") {
2776
2968
  }
2777
2969
  for (const [name, value] of scssVars) {
2778
2970
  if (seenNames.has(name)) continue;
2971
+ if (value.startsWith("(")) continue;
2779
2972
  seenNames.add(name);
2780
2973
  tokens.push({
2781
2974
  name,
@@ -3693,24 +3886,37 @@ var contractExampleSchema = z6.object({
3693
3886
  });
3694
3887
  var contractRelationSchema = z6.object({
3695
3888
  component: z6.string(),
3696
- relationship: z6.enum(["alternative", "parent", "child", "sibling", "composition", "complementary", "used-by"]),
3889
+ relationship: z6.enum([
3890
+ "alternative",
3891
+ "parent",
3892
+ "child",
3893
+ "sibling",
3894
+ "composition",
3895
+ "complementary",
3896
+ "used-by"
3897
+ ]),
3697
3898
  note: z6.string()
3698
3899
  });
3699
3900
  var contractContractSchema = z6.object({
3700
3901
  propsSummary: z6.array(z6.string()).optional(),
3701
3902
  scenarioTags: z6.array(z6.string()).optional(),
3702
3903
  a11yRules: z6.array(z6.string()).optional(),
3703
- bans: z6.array(z6.object({
3704
- pattern: z6.string(),
3705
- message: z6.string()
3706
- })).optional(),
3707
- compoundChildren: z6.record(z6.string(), z6.object({
3708
- required: z6.boolean().optional(),
3709
- accepts: z6.array(z6.string()).optional(),
3710
- description: z6.string().optional()
3711
- })).optional(),
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(),
3712
3918
  canonicalUsage: z6.array(z6.string()).optional(),
3713
- performanceBudget: z6.number().optional()
3919
+ performanceBudget: z6.number().positive().finite().optional()
3714
3920
  });
3715
3921
  var contractAiSchema = z6.object({
3716
3922
  compositionPattern: z6.enum(["compound", "simple", "controlled", "wrapper"]).optional(),
@@ -3734,11 +3940,14 @@ var contractProvenanceSchema = z6.object({
3734
3940
  });
3735
3941
  var contractFigmaSchema = z6.object({
3736
3942
  nodeUrl: z6.string().optional(),
3737
- propMappings: z6.record(z6.string(), z6.object({
3738
- type: z6.enum(["string", "boolean", "enum", "instance", "children", "textContent"]),
3739
- figmaProperty: z6.string(),
3740
- values: z6.record(z6.string(), z6.string()).optional()
3741
- })).optional()
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()
3742
3951
  });
3743
3952
  var componentContractSchema = z6.object({
3744
3953
  $schema: z6.string(),
@@ -3748,11 +3957,13 @@ var componentContractSchema = z6.object({
3748
3957
  tags: z6.array(z6.string()).optional(),
3749
3958
  status: z6.enum(["stable", "beta", "deprecated", "experimental"]).optional(),
3750
3959
  framework: z6.enum(["react", "vue", "svelte", "web-components", "angular"]).optional(),
3751
- dependencies: z6.array(z6.object({
3752
- name: z6.string(),
3753
- version: z6.string(),
3754
- reason: z6.string().optional()
3755
- })).optional(),
3960
+ dependencies: z6.array(
3961
+ z6.object({
3962
+ name: z6.string(),
3963
+ version: z6.string(),
3964
+ reason: z6.string().optional()
3965
+ })
3966
+ ).optional(),
3756
3967
  sourcePath: z6.string(),
3757
3968
  exportName: z6.string(),
3758
3969
  propsSummary: z6.array(z6.string()),
@@ -3803,6 +4014,8 @@ function parseComponentContract(content, filePath) {
3803
4014
  } : {
3804
4015
  propsSummary: validated.propsSummary
3805
4016
  },
4017
+ preview: validated.preview,
4018
+ tokens: validated.tokens,
3806
4019
  framework: validated.framework,
3807
4020
  ai: validated.ai,
3808
4021
  propsSummary: validated.propsSummary,
@@ -4014,6 +4227,7 @@ function parseFigmaValue(cssValue, category) {
4014
4227
  // src/composition.ts
4015
4228
  var CATEGORY_AFFINITIES = {
4016
4229
  forms: ["feedback"],
4230
+ inputs: ["feedback"],
4017
4231
  actions: ["feedback"]
4018
4232
  };
4019
4233
  function analyzeComposition(fragments, componentNames, _context, options) {
@@ -4119,9 +4333,7 @@ function analyzeComposition(fragments, componentNames, _context, options) {
4119
4333
  });
4120
4334
  }
4121
4335
  }
4122
- const selectedCategories = new Set(
4123
- components.map((name) => fragments[name].meta.category)
4124
- );
4336
+ const selectedCategories = new Set(components.map((name) => fragments[name].meta.category));
4125
4337
  for (const [category, affinities] of Object.entries(CATEGORY_AFFINITIES)) {
4126
4338
  if (!selectedCategories.has(category)) continue;
4127
4339
  for (const neededCategory of affinities) {
@@ -4137,9 +4349,7 @@ function analyzeComposition(fragments, componentNames, _context, options) {
4137
4349
  component: candidate,
4138
4350
  reason: `Compositions using "${category}" components often benefit from a "${neededCategory}" component`,
4139
4351
  relationship: "category_gap",
4140
- sourceComponent: components.find(
4141
- (n) => fragments[n].meta.category === category
4142
- )
4352
+ sourceComponent: components.find((n) => fragments[n].meta.category === category)
4143
4353
  });
4144
4354
  suggestedSet.add(candidate);
4145
4355
  }
@@ -4262,7 +4472,7 @@ function makeFinding(input) {
4262
4472
  canonicalJson({ ruleId: input.ruleId, ...input.fingerprintIdentity })
4263
4473
  );
4264
4474
  const previousFingerprint = input.previousFingerprintIdentity ? hash64Hex(canonicalJson({ ruleId: input.ruleId, ...input.previousFingerprintIdentity })) : void 0;
4265
- const code = byRuleId.get(input.ruleId);
4475
+ const code = input.code ? byCode.get(input.code) : byRuleId.get(input.ruleId);
4266
4476
  return normalizeFinding({
4267
4477
  ruleId: input.ruleId,
4268
4478
  ruleVersion: input.ruleVersion,
@@ -8373,6 +8583,14 @@ function indexTokensByCssVariable(tokens) {
8373
8583
  // src/rules/tokens-css-vars-must-be-defined.ts
8374
8584
  var RULE_ID22 = "tokens/css-vars-must-be-defined";
8375
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
+ }
8376
8594
  var CSS_VAR_REFERENCE = /var\(\s*(--[A-Za-z0-9_-]+)/gi;
8377
8595
  function contractVocabularyContext(ix) {
8378
8596
  if (!ix.policy.cssVarsMustBeDefined()) return void 0;
@@ -8394,7 +8612,7 @@ function ruleTokensCssVarsMustBeDefined(ix) {
8394
8612
  const policy = ix.policy.cssVarsMustBeDefined();
8395
8613
  if (!policy) return [];
8396
8614
  const context = contractVocabularyContext(ix);
8397
- if (!context) return [];
8615
+ if (!context) return [emptyVocabularyFinding(ix, policy)];
8398
8616
  const { vocabulary } = context;
8399
8617
  const findings = [];
8400
8618
  for (const decl of ix.byKind("style_declaration")) {
@@ -8435,6 +8653,27 @@ function ruleTokensCssVarsMustBeDefined(ix) {
8435
8653
  }
8436
8654
  return findings;
8437
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
+ }
8438
8677
  function sharesContractPrefix(name, prefixes) {
8439
8678
  for (const prefix of prefixes) {
8440
8679
  if (name.startsWith(prefix)) return true;
@@ -8525,6 +8764,30 @@ function ruleTokensUpstreamDrift(ix) {
8525
8764
  return findings;
8526
8765
  }
8527
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
+
8528
8791
  // src/rules/emit-gate.ts
8529
8792
  var BLOCKING_RULE_ALLOWLIST = /* @__PURE__ */ new Set([
8530
8793
  "styles/no-raw-color",
@@ -8777,8 +9040,12 @@ var RULES = [
8777
9040
  }
8778
9041
  ];
8779
9042
  function runRules(ix) {
9043
+ const { disabled } = readRuleConfig(ix);
8780
9044
  const findings = [];
8781
- for (const rule of RULES) findings.push(...rule.run(ix));
9045
+ for (const rule of RULES) {
9046
+ if (disabled.has(rule.id)) continue;
9047
+ findings.push(...rule.run(ix));
9048
+ }
8782
9049
  return sortFindings(findings);
8783
9050
  }
8784
9051
  function sortFindings(findings) {
@@ -8868,7 +9135,7 @@ var PASSTHROUGH_KEYS = [
8868
9135
  },
8869
9136
  {
8870
9137
  path: ["registry"],
8871
- keys: ["requireStory", "publicOnly", "categoryDepth", "includeProps", "embedFragments"]
9138
+ keys: ["requireStory", "publicOnly", "categoryDepth", "includeProps"]
8872
9139
  },
8873
9140
  {
8874
9141
  path: ["govern", "tailwind"],
@@ -9122,11 +9389,11 @@ function collectPassthroughRecordValues(authored, path, allowed, diagnostics) {
9122
9389
  }
9123
9390
  }
9124
9391
  function stableConfigDiagnostics(diagnostics) {
9125
- const unique = /* @__PURE__ */ new Map();
9392
+ const unique3 = /* @__PURE__ */ new Map();
9126
9393
  for (const diagnostic of diagnostics) {
9127
- unique.set(`${diagnostic.code}\0${diagnostic.path}`, diagnostic);
9394
+ unique3.set(`${diagnostic.code}\0${diagnostic.path}`, diagnostic);
9128
9395
  }
9129
- return [...unique.values()].sort(
9396
+ return [...unique3.values()].sort(
9130
9397
  (left, right) => left.path.localeCompare(right.path) || left.code.localeCompare(right.code) || left.message.localeCompare(right.message)
9131
9398
  );
9132
9399
  }
@@ -9352,10 +9619,11 @@ function evaluateGovernanceIntegrity(input) {
9352
9619
  const activeRuleCount = [...configs.entries()].filter(
9353
9620
  ([ruleId, config]) => CONSUMED_RULE_IDS.has(ruleId) && config.enabled
9354
9621
  ).length;
9622
+ const tokensVocabularyInert = !tokensArmed && tokensFamily.reason === "no token vocabulary" ? 1 : 0;
9355
9623
  const roster = {
9356
9624
  configured: configuredRuleCount + configDiagnostics.length,
9357
- active: activeRuleCount,
9358
- inert: configDiagnostics.length
9625
+ active: Math.max(0, activeRuleCount - tokensVocabularyInert),
9626
+ inert: configDiagnostics.length + tokensVocabularyInert
9359
9627
  };
9360
9628
  return {
9361
9629
  status,
@@ -9453,7 +9721,30 @@ function sortRecords(values) {
9453
9721
  }
9454
9722
 
9455
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
+ ];
9456
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
+ };
9457
9748
  var CONTRACT_PREIMAGE_SCHEMA = "fcid-preimage:v1";
9458
9749
  var CONTRACT_PREIMAGE_CAPABILITY_HEADER = "X-Fragments-Contract-Preimage";
9459
9750
  var SHA256_HEX_PATTERN = /^[0-9a-f]{64}$/u;
@@ -9481,13 +9772,225 @@ function verifiedContractPreimageFromPin(pin) {
9481
9772
  function sortCanonical(items) {
9482
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);
9483
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
+ }
9484
9986
  function projectComponents(components) {
9485
9987
  return sortCanonical(
9486
9988
  (components ?? []).map((component) => ({
9487
9989
  name: component.name,
9488
9990
  parentName: component.parentName,
9489
9991
  props: component.props ? [...component.props].sort() : void 0,
9490
- contract: component.contract,
9992
+ contract: projectEnforcementContract(component.contract),
9993
+ governance: projectGovernanceRecords(component.governance),
9491
9994
  compoundChildren: component.compoundChildren ? [...component.compoundChildren].sort() : void 0
9492
9995
  }))
9493
9996
  );
@@ -9569,6 +10072,7 @@ function projectPolicy(policy) {
9569
10072
  };
9570
10073
  }
9571
10074
  function projectContractPreimage(catalog) {
10075
+ validateContractCatalog(catalog);
9572
10076
  return {
9573
10077
  schema: CONTRACT_PREIMAGE_SCHEMA,
9574
10078
  domains: {
@@ -9608,16 +10112,31 @@ function contractComponentsFromFragments(fragments) {
9608
10112
  const parentName = fragment?.meta?.parentComponentName;
9609
10113
  const rawChildren = fragment?.structure?.compoundChildren;
9610
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
+ });
9611
10119
  components.push({
9612
10120
  name,
9613
10121
  parentName: typeof parentName === "string" ? parentName : void 0,
9614
10122
  props: Object.keys(fragment?.props ?? {}),
9615
10123
  contract: fragment?.contract,
10124
+ governance,
9616
10125
  compoundChildren
9617
10126
  });
9618
10127
  }
9619
10128
  return components;
9620
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
+ }
9621
10140
 
9622
10141
  // src/contract/stamp.ts
9623
10142
  var AGENT_CONTEXT_RELATIVE_PATH = ".fragments/agent-context.md";
@@ -9649,7 +10168,7 @@ function parseContractStamp(text) {
9649
10168
  const fcidLine = STAMP_FCID_LINE.exec(text);
9650
10169
  if (!header || !fcidLine) return null;
9651
10170
  const contractVersion = Number(header[1]);
9652
- if (!Number.isSafeInteger(contractVersion)) return null;
10171
+ if (!Number.isSafeInteger(contractVersion) || contractVersion < 1) return null;
9653
10172
  const fcid = fcidLine[1];
9654
10173
  if (!fcid.startsWith(header[2])) return null;
9655
10174
  const domainsLine = STAMP_DOMAINS_LINE.exec(text);
@@ -9935,24 +10454,2078 @@ function strongOverlap(overlap) {
9935
10454
  function withTarget(state, confidence, canonicalTarget) {
9936
10455
  return canonicalTarget ? { state, confidence, canonicalTarget } : { state, confidence };
9937
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
+ }
9938
12478
  export {
9939
12479
  AGENT_CONTEXT_RELATIVE_PATH,
12480
+ AGENT_FEATURE_CONTEXT_MAX_BYTES_V1,
9940
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,
9941
12486
  BLOCKING_RULE_ALLOWLIST,
9942
12487
  BRAND,
12488
+ CANONICAL_FACT_MAX_CONFLICTS_V1,
12489
+ CANONICAL_FACT_MAX_PROVENANCE_PER_VALUE_V1,
12490
+ CANONICAL_FACT_MAX_VALUES_PER_CONFLICT_V1,
9943
12491
  CATALOG_FIXTURE_A_FCID,
9944
12492
  CODES,
12493
+ CONTRACT_DISPLAY_ONLY_FIELDS,
9945
12494
  CONTRACT_DOMAINS,
12495
+ CONTRACT_ENFORCEMENT_FIELDS,
9946
12496
  CONTRACT_PREIMAGE_CAPABILITY_HEADER,
9947
12497
  CONTRACT_PREIMAGE_SCHEMA,
9948
12498
  CompiledFragmentsFileValidationError,
12499
+ ContractCatalogValidationError,
12500
+ CoverageValidationErrorV1,
9949
12501
  DEFAULTS,
9950
12502
  DEFAULT_ENHANCED_STYLE_PROPERTIES,
9951
12503
  DEFAULT_STYLE_PROPERTIES,
9952
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,
9953
12515
  EVIDENCE_ORDER,
9954
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,
9955
12524
  FRAGMENTS_INTERNAL_RULE_IDS,
12525
+ FRAGMENTS_MANIFEST_FILENAME,
12526
+ FRAGMENTS_MANIFEST_SCHEMA_VERSION,
12527
+ FRAGMENTS_MANIFEST_TOKEN_RULE,
12528
+ FRAGMENT_V3_SCHEMA_URL,
9956
12529
  FactIndex,
9957
12530
  GOVERNANCE_TELEMETRY_FIELDS,
9958
12531
  GOVERNANCE_TELEMETRY_SOURCE_DISCLOSURE,
@@ -9962,13 +12535,18 @@ export {
9962
12535
  PRESET_NAMES,
9963
12536
  PROVE_DEFAULT_MAX_PASSES,
9964
12537
  PROVE_MAX_PASSES,
12538
+ PROVIDER_ID_MAX_BYTES_V1,
9965
12539
  RAW_HTML_ADVISORY_TAGS,
9966
12540
  RAW_HTML_CANONICAL_TAGS,
9967
12541
  RAW_HTML_INPUT_TYPE_CANONICALS,
9968
12542
  RAW_HTML_ROLE_CANONICALS,
9969
12543
  REGISTRY_ARTIFACT_SCHEMA_VERSION,
12544
+ REGISTRY_INDEX_SCHEMA_VERSION,
9970
12545
  REGISTRY_INSTALL_RECEIPT_SCHEMA_VERSION,
9971
12546
  REGISTRY_MANIFEST_SCHEMA_VERSION,
12547
+ REGISTRY_POINTER_SCHEMA_VERSION,
12548
+ REGISTRY_SHARD_SCHEMA_VERSION,
12549
+ REPOSITORY_BINDING_ID_MAX_BYTES_V1,
9972
12550
  RULES,
9973
12551
  RULE_FAMILY_IDS,
9974
12552
  RULE_FAMILY_MEMBERS,
@@ -9977,12 +12555,27 @@ export {
9977
12555
  SEVERITY_RANK,
9978
12556
  SEVERITY_WEIGHTS,
9979
12557
  agentErrorEnvelopeSchema,
12558
+ agentFeatureContextV1Schema2 as agentFeatureContextV1Schema,
9980
12559
  agentFormatSchema,
9981
12560
  agentIntegritySchema,
9982
12561
  agentOutputSchema,
9983
12562
  aiMetadataSchema,
12563
+ analysisLimitsV1Schema,
12564
+ analysisObligationsDigestV1,
12565
+ analysisPlanDigestV1,
12566
+ analysisPlanIdFromDigest,
12567
+ analysisPlanIdSchema,
12568
+ analysisPlanIdStringSchema,
12569
+ analysisPlanInputV1Schema,
12570
+ analysisPlanV1Schema,
12571
+ analysisRegionV1Schema,
9984
12572
  analyzeComposition,
12573
+ approvedFeatureManifestInputV1Schema,
12574
+ approvedFeatureManifestRevisionDigestV1,
12575
+ approvedFeatureManifestV1Schema,
12576
+ artifactContentHash,
9985
12577
  asComponentId,
12578
+ assembleRegistryArtifact,
9986
12579
  assertPortableRegistryPath,
9987
12580
  assertValidRegistryArtifact,
9988
12581
  authorOwnedImport,
@@ -9991,11 +12584,15 @@ export {
9991
12584
  bridgeSourceViolations,
9992
12585
  budgetBar,
9993
12586
  buildAgentFormat,
12587
+ buildAnalysisPlanV1,
12588
+ buildApprovedFeatureManifestV1,
9994
12589
  buildComponentKey,
12590
+ buildFeatureProposalV1,
9995
12591
  buildRegistryArtifact,
9996
12592
  buildRegistryFile,
9997
12593
  buildRegistryInstallPlan,
9998
12594
  buildRegistryInstallReceipt,
12595
+ buildRegistryPointer,
9999
12596
  buildSpacingTokenLookup,
10000
12597
  bundleArtifactMetadataSchema,
10001
12598
  bundleComponentShardSchema,
@@ -10013,14 +12610,18 @@ export {
10013
12610
  canonicalBridgeIdentitySources,
10014
12611
  canonicalBridgeV1Schema,
10015
12612
  canonicalDirectionConflictsTarget,
12613
+ canonicalFactConflictV1Schema,
12614
+ canonicalFactConflictValueV1Schema,
12615
+ canonicalFactIntegrityV1Schema,
10016
12616
  canonicalJson,
10017
12617
  canonicalPreimage,
10018
12618
  canonicalizeOwnedComponentId,
10019
12619
  canonicalizeOwnedImport,
12620
+ capConfiguredSeverity,
12621
+ capabilityGapV1Schema,
10020
12622
  catalogFixtureA,
10021
12623
  catalogFixtureAContractPayload,
10022
12624
  catalogFixtureATokensDtcg,
10023
- checkStoryExclusion,
10024
12625
  clampMaxPasses,
10025
12626
  classifyComplexity,
10026
12627
  classifyIdentity,
@@ -10040,45 +12641,79 @@ export {
10040
12641
  compileEffectiveGovernanceInputs,
10041
12642
  compileFragment,
10042
12643
  compileGlobalGovernanceFacts,
10043
- compileRecipe,
10044
12644
  componentContractSchema,
10045
12645
  componentGovernanceRecordSchema,
10046
12646
  componentGovernanceRecordsSchema,
10047
12647
  componentId,
10048
12648
  componentRelationSchema,
12649
+ componentUseDecisionV1Schema,
10049
12650
  compositionAuthoringEntrySchema,
10050
12651
  compositionMetadataSchema,
10051
12652
  compositionPatternSchema,
10052
12653
  computeRegistryHash,
10053
12654
  configDeclarationForDiagnostics,
10054
12655
  configRecordShape,
12656
+ configuredFindingSeverity,
10055
12657
  containsTailwindV4Theme,
10056
12658
  contractComponentsFromFragments,
10057
12659
  contractHash,
10058
12660
  contractPolicyFromGovernanceConfig,
10059
12661
  contractTierRuleIds,
10060
12662
  contractTokenReferenceCensus,
12663
+ coverageArtifactDigestV1,
12664
+ coverageRegionV1Schema,
12665
+ coverageStateV1Schema,
12666
+ coverageSummaryV1Schema,
10061
12667
  customerDefaultRuleStates,
12668
+ decisionRequestV1Schema,
12669
+ decisionResolutionV1Schema,
12670
+ defaultRegistryShardPath,
10062
12671
  defineBlock,
10063
12672
  defineConfig,
10064
12673
  defineFragment,
10065
- defineRecipe,
12674
+ deriveArtifactId,
12675
+ deriveCoverageSummaryV1,
10066
12676
  describePolicyExclude,
10067
12677
  detectOrphanGovernanceScales,
10068
- detectSubComponentPaths,
10069
12678
  detectUnconsumedConfigKeys,
10070
12679
  detectUnmatchedPolicyExcludes,
10071
12680
  diffContractDomains,
12681
+ digestHexSchema,
12682
+ digestHexStringSchema,
10072
12683
  discoverComponents,
10073
12684
  dtcgTokenFileSchema,
12685
+ effectiveEvaluationWaiverV2Schema,
10074
12686
  emptyConformResult,
12687
+ emptyVocabularyConfigFile,
12688
+ evaluate2 as evaluate,
10075
12689
  evaluateGovernanceIntegrity,
12690
+ evaluationInputV2Schema,
12691
+ evaluationReceiptDigestV1,
12692
+ evaluationReceiptIdFromDigest,
12693
+ evaluationReceiptIdSchema,
12694
+ evaluationReceiptIdStringSchema,
12695
+ evaluationReceiptMintInputV1Schema,
12696
+ evaluationReceiptV1Schema,
12697
+ evaluationResultV2Schema,
12698
+ evidenceRefV1Schema,
10076
12699
  excludeGlobToRegExp,
12700
+ expandRegistryComponentClosure,
10077
12701
  explainUrlForCode,
10078
12702
  factEvidenceSchema,
10079
12703
  factId,
10080
12704
  factLocationSchema,
10081
12705
  familyDistance,
12706
+ featureAcceptanceItemV1Schema,
12707
+ featurePinsV1Schema,
12708
+ featurePlanIdFromEntropy,
12709
+ featurePlanIdSchema,
12710
+ featurePlanIdStringSchema,
12711
+ featureProposalInputV1Schema,
12712
+ featureProposalRevisionDigestV1,
12713
+ featureProposalV1Schema,
12714
+ featureRevisionIdFromDigest,
12715
+ featureRevisionIdSchema,
12716
+ featureRevisionIdStringSchema,
10082
12717
  figma,
10083
12718
  figmaPropMappingSchema,
10084
12719
  finalizeRegistryManifest,
@@ -10095,18 +12730,35 @@ export {
10095
12730
  formatStampPin,
10096
12731
  formatStampVersionHash,
10097
12732
  formatTokenSummary,
12733
+ fragmentAnnotationsV3Schema,
10098
12734
  fragmentBanSchema,
10099
12735
  fragmentContractSchema,
10100
12736
  fragmentDefinitionSchema,
10101
12737
  fragmentDefinitionV2Schema,
12738
+ fragmentDefinitionV3BodySchema,
12739
+ fragmentDefinitionV3Schema,
12740
+ fragmentDesignV3Schema,
12741
+ fragmentDontExampleV3Schema,
10102
12742
  fragmentGeneratedSchema,
12743
+ fragmentGuidanceV3Schema,
12744
+ fragmentMatrixV3Schema,
10103
12745
  fragmentMetaSchema,
12746
+ fragmentMetaV3Schema,
12747
+ fragmentPreviewV3Schema,
10104
12748
  fragmentProvenanceSchema,
12749
+ fragmentSourceValues,
12750
+ fragmentStateV3Schema,
10105
12751
  fragmentUsageSchema,
10106
12752
  fragmentVariantSchema,
10107
12753
  fragmentsConfigSchema,
12754
+ fragmentsManifestFcid,
12755
+ fragmentsManifestGrammarSchema,
12756
+ fragmentsManifestPatternSchema,
12757
+ fragmentsManifestPrimitiveSchema,
12758
+ fragmentsManifestSchema,
10108
12759
  fragmentsPresetRuleStates,
10109
12760
  g,
12761
+ gapDispositionV1Schema,
10110
12762
  gatesCi,
10111
12763
  generateCSSCustomProperties,
10112
12764
  generateContext,
@@ -10133,7 +12785,6 @@ export {
10133
12785
  inferTokenGroup,
10134
12786
  isColorLike,
10135
12787
  isCompositionPattern,
10136
- isConfigExcluded,
10137
12788
  isContractFile,
10138
12789
  isContractTierRule,
10139
12790
  isDTCGFile,
@@ -10141,12 +12792,13 @@ export {
10141
12792
  isEffectiveCanonicalSource,
10142
12793
  isEnforceableHtmlEquivalent,
10143
12794
  isFigmaPropMapping,
10144
- isForceIncluded,
10145
12795
  isPortableRepoPath,
10146
12796
  isPresetSourcedRule,
10147
12797
  isRawHtmlAdvisoryTier,
10148
12798
  isReactComponent,
10149
12799
  isRuleFamilyId,
12800
+ layoutConcernV1Schema,
12801
+ layoutOwnershipV1Schema,
10150
12802
  localCanonicalContractMappings,
10151
12803
  lowerCompositionContract,
10152
12804
  makeA11yNameRequiredFact,
@@ -10214,15 +12866,21 @@ export {
10214
12866
  mcpSourceTypeSchema,
10215
12867
  mcpTokenDataSchema,
10216
12868
  mcpTokenSchema,
12869
+ mintEvaluationReceiptId,
10217
12870
  nearestByDeltaE,
10218
12871
  nearestSignedScaleValue,
12872
+ normalizeAnalysisPlanInputV1,
12873
+ normalizeApprovedFeatureManifestInputV1,
12874
+ normalizeCanonicalFactIntegrityV1,
10219
12875
  normalizeColor,
10220
12876
  normalizeConfigPath,
10221
12877
  normalizeExcludePath,
12878
+ normalizeFeatureProposalInputV1,
10222
12879
  normalizeFinding,
10223
12880
  normalizeGovernanceConfig,
10224
12881
  normalizePolicyExcludes,
10225
12882
  normalizeRegistryRepoPath,
12883
+ normalizeRepositoryBindingKeyV1,
10226
12884
  normalizeSeverity,
10227
12885
  normalizeStyleValue,
10228
12886
  normalizeToV1,
@@ -10231,6 +12889,10 @@ export {
10231
12889
  normalizeViolation,
10232
12890
  overriddenRecordSeverityDiagnostic,
10233
12891
  ownedImportEquivalents,
12892
+ parseAgentFeatureContextV1,
12893
+ parseAnalysisPlanId,
12894
+ parseAnalysisPlanV1,
12895
+ parseApprovedFeatureManifestV1,
10234
12896
  parseColor,
10235
12897
  parseColorToRgb,
10236
12898
  parseCompiledFragmentsFile,
@@ -10239,25 +12901,39 @@ export {
10239
12901
  parseCssTokens,
10240
12902
  parseDtcgTokens as parseDTCGFile,
10241
12903
  parseDesignTokenContent,
12904
+ parseDigestHex,
10242
12905
  parseDtcgTokens,
12906
+ parseEvaluationReceiptId,
12907
+ parseEvaluationReceiptV1,
12908
+ parseFeaturePlanId,
12909
+ parseFeatureProposalV1,
12910
+ parseFeatureRevisionId,
12911
+ parseFragmentsManifest,
10243
12912
  parseRgb,
10244
12913
  parseScssTokens,
10245
12914
  parseScssVariables,
10246
12915
  parseTailwindV4Theme,
10247
12916
  parseTokenFile,
10248
12917
  parseTokens,
12918
+ patternStatusV1Schema,
12919
+ patternUseDecisionV1Schema,
12920
+ placementDecisionV1Schema,
10249
12921
  policyExcludeMatchesPath,
10250
12922
  policyExcludeSchema,
10251
12923
  portableRepoPathError,
10252
12924
  projectCanonicalDirectionConflicts,
10253
12925
  projectContractPreimage,
12926
+ projectEnforcementContract,
10254
12927
  projectSupersededImportPathPreferences,
10255
12928
  projectV1OwnedComponentId,
10256
12929
  projectV1OwnedImportIdentity,
12930
+ propAnnotationSchema,
10257
12931
  propDefinitionSchema,
10258
12932
  proveCompliant,
10259
12933
  proveIssueCount,
10260
- recipeDefinitionSchema,
12934
+ providerProofDigestV1,
12935
+ providerProofV1Schema,
12936
+ readRuleConfig,
10261
12937
  registryArtifactDigest,
10262
12938
  registryArtifactSchema,
10263
12939
  registryComponentExportSchema,
@@ -10269,25 +12945,39 @@ export {
10269
12945
  registryFileRoleSchema,
10270
12946
  registryFileSchema,
10271
12947
  registryFileSize,
12948
+ registryIndexSchema,
10272
12949
  registryInstallProfileSchema,
10273
12950
  registryInstallReceiptComponentSchema,
10274
12951
  registryInstallReceiptFileSchema,
10275
12952
  registryInstallReceiptSchema,
10276
12953
  registryManifestCanonicalPreimage,
10277
12954
  registryManifestDraftSchema,
12955
+ registryManifestFileMetadata,
12956
+ registryManifestFilePaths,
10278
12957
  registryManifestSchema,
12958
+ registryPointerSchema,
12959
+ registryShardSchema,
12960
+ registryShardsForPaths,
10279
12961
  registrySourceSchema,
12962
+ repositoryBindingDigestV1,
12963
+ repositoryBindingKeyV1Schema,
10280
12964
  resolveArea,
10281
12965
  resolveCanonicalForAriaRole,
10282
12966
  resolveCanonicalForRawHtml,
12967
+ resolveComponentGovernance,
10283
12968
  resolveConfiguredAppPath,
10284
12969
  resolveDesignTokenValue,
10285
12970
  resolveFigmaMapping,
12971
+ resolveGovernanceRecordsForIdentity,
10286
12972
  resolveOwnedPackageImport,
10287
12973
  resolvePerformanceConfig,
10288
12974
  resolveProveVerdict,
12975
+ resolveRegistryComponentId,
12976
+ resolveRegistryInstallSelection,
12977
+ resolveRegistryInstallSources,
10289
12978
  resolveSpacingValue,
10290
12979
  resolveTokenValue,
12980
+ responsiveDecisionV1Schema,
10291
12981
  rgbToHex,
10292
12982
  ruleA11yRequiredAccessibleName,
10293
12983
  ruleA11yStandard,
@@ -10313,16 +13003,18 @@ export {
10313
13003
  ruleTokensRequireDualFallback,
10314
13004
  runRules,
10315
13005
  scaleGovernanceRecordSchema,
10316
- selectedRegistryComponentNames,
13006
+ scenarioRequirementV1Schema,
10317
13007
  serializeContractStamp,
10318
13008
  severityLevel,
10319
13009
  severitySchema,
10320
13010
  sha256Hex,
13011
+ shardRegistryArtifact,
10321
13012
  sortBySeverity,
10322
13013
  sourceToRegistryTargetPath,
10323
13014
  suppressionDirectiveSchema,
10324
13015
  tierFor,
10325
13016
  tokenIncludesFromConfig,
13017
+ tokenUseDecisionV1Schema,
10326
13018
  topologyBase,
10327
13019
  validatorResultSchema,
10328
13020
  verifiedContractPreimageFromPin,