@usefragments/core 1.10.2 → 2.0.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 (130) 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-XN3LSDPY.js → chunk-BMPYIUZE.js} +612 -344
  6. package/dist/chunk-BMPYIUZE.js.map +1 -0
  7. package/dist/{chunk-YF65VYRY.js → chunk-ML5S6QNU.js} +191 -169
  8. package/dist/chunk-ML5S6QNU.js.map +1 -0
  9. package/dist/{chunk-3LLRNCPX.js → chunk-MZ2FS7U4.js} +1 -1
  10. package/dist/chunk-MZ2FS7U4.js.map +1 -0
  11. package/dist/chunk-PWIJMOI4.js +202 -0
  12. package/dist/chunk-PWIJMOI4.js.map +1 -0
  13. package/dist/chunk-RYFULE43.js +578 -0
  14. package/dist/chunk-RYFULE43.js.map +1 -0
  15. package/dist/codes/index.d.ts +2 -2
  16. package/dist/codes/index.js +3 -2
  17. package/dist/compiled-types/index.d.ts +327 -2
  18. package/dist/compiled-types/index.js +1 -1
  19. package/dist/generate/index.d.ts +3 -2
  20. package/dist/{governance-CLk_wkP9.d.ts → governance-hOPXGbbs.d.ts} +474 -515
  21. package/dist/governance-telemetry.d.ts +6 -0
  22. package/dist/governance-telemetry.js +1 -1
  23. package/dist/{index-_sxhUNqx.d.ts → index-C8bcXVav.d.ts} +448 -448
  24. package/dist/index.d.ts +3280 -1305
  25. package/dist/index.js +2414 -350
  26. package/dist/index.js.map +1 -1
  27. package/dist/manifest.d.ts +228 -0
  28. package/dist/manifest.js +24 -0
  29. package/dist/manifest.js.map +1 -0
  30. package/dist/preview/index.js +45 -1
  31. package/dist/preview/index.js.map +1 -1
  32. package/dist/preview-runtime.d.ts +1 -2
  33. package/dist/preview-runtime.js +150 -14
  34. package/dist/preview-runtime.js.map +1 -1
  35. package/dist/react-types.d.ts +1 -2
  36. package/dist/registry.d.ts +1412 -203
  37. package/dist/registry.js +30 -3
  38. package/dist/schemas/index.d.ts +1 -1
  39. package/dist/schemas/index.js +3 -2
  40. package/dist/storyAdapter.d.ts +1 -2
  41. package/dist/storyAdapter.js +11 -49
  42. package/dist/storyAdapter.js.map +1 -1
  43. package/dist/test-utils.d.ts +3 -2
  44. package/dist/topology/index.d.ts +1 -1
  45. package/dist/topology/index.js +1 -1
  46. package/package.json +8 -2
  47. package/src/__tests__/contract-parser.test.ts +318 -277
  48. package/src/__tests__/preview-runtime-hook.test.tsx +315 -0
  49. package/src/__tests__/preview-runtime.test.tsx +30 -8
  50. package/src/__tests__/schema.test.ts +191 -14
  51. package/src/analysis-plan/analysis-plan-v1.test.ts +320 -0
  52. package/src/analysis-plan/coverage.ts +181 -0
  53. package/src/analysis-plan/digest.ts +141 -0
  54. package/src/analysis-plan/index.ts +34 -0
  55. package/src/analysis-plan/types.ts +207 -0
  56. package/src/approved-contract-tokens.test.ts +39 -0
  57. package/src/approved-contract-tokens.ts +18 -0
  58. package/src/codes/__tests__/codes.test.ts +13 -0
  59. package/src/codes/codes.ts +40 -0
  60. package/src/compiled-types/index.ts +640 -39
  61. package/src/compiled-types/parse.test.ts +145 -4
  62. package/src/component-contract.ts +95 -53
  63. package/src/composition.ts +7 -13
  64. package/src/constants.ts +3 -6
  65. package/src/contract/hash.test.ts +20 -0
  66. package/src/contract/hash.ts +66 -9
  67. package/src/contract/index.ts +24 -1
  68. package/src/contract/manifest.test.ts +94 -0
  69. package/src/contract/manifest.ts +68 -0
  70. package/src/contract/preimage.test.ts +219 -1
  71. package/src/contract/preimage.ts +326 -6
  72. package/src/contract/stamp.test.ts +3 -0
  73. package/src/contract/stamp.ts +1 -1
  74. package/src/contract-parser.ts +54 -30
  75. package/src/defineFragment.test.ts +476 -91
  76. package/src/defineFragment.ts +204 -114
  77. package/src/domain-ids.test.ts +35 -0
  78. package/src/domain-ids.ts +61 -0
  79. package/src/evaluation/evaluate.test.ts +522 -0
  80. package/src/evaluation/evaluate.ts +690 -0
  81. package/src/evaluation/evaluation-v2-receipt-v1.test.ts +772 -0
  82. package/src/evaluation/index.ts +58 -0
  83. package/src/evaluation/receipt.ts +753 -0
  84. package/src/evaluation/types.ts +406 -0
  85. package/src/facts/builders.ts +2 -0
  86. package/src/facts/compile.ts +29 -6
  87. package/src/facts/fact-index.ts +13 -3
  88. package/src/facts/fact-integrity-v1.test.ts +172 -0
  89. package/src/facts/facts.test.ts +15 -0
  90. package/src/facts/ids.ts +46 -3
  91. package/src/facts/index.ts +14 -1
  92. package/src/facts/integrity.ts +134 -0
  93. package/src/facts/types.ts +36 -0
  94. package/src/governance-integrity.test.ts +1 -0
  95. package/src/governance-integrity.ts +5 -3
  96. package/src/governance-telemetry.ts +8 -0
  97. package/src/governance.ts +70 -8
  98. package/src/index.ts +230 -37
  99. package/src/preview/validation.test.ts +62 -0
  100. package/src/preview/validation.ts +48 -2
  101. package/src/preview-runtime.tsx +227 -20
  102. package/src/registry-install-plan.ts +200 -109
  103. package/src/registry-shards.test.ts +263 -0
  104. package/src/registry.ts +237 -0
  105. package/src/repository-binding.test.ts +50 -0
  106. package/src/repository-binding.ts +96 -0
  107. package/src/rules/families.test.ts +36 -0
  108. package/src/rules/finding.ts +7 -2
  109. package/src/rules/index.ts +17 -1
  110. package/src/rules/rule-config.test.ts +66 -0
  111. package/src/rules/rule-config.ts +73 -0
  112. package/src/rules/rules.test.ts +26 -0
  113. package/src/rules/tokens-css-vars-must-be-defined.test.ts +51 -2
  114. package/src/rules/tokens-css-vars-must-be-defined.ts +34 -1
  115. package/src/schema.ts +293 -113
  116. package/src/schemas/index.ts +1 -1
  117. package/src/storyAdapter.test.ts +68 -12
  118. package/src/storyAdapter.ts +44 -75
  119. package/src/topology/resolve-area.ts +1 -1
  120. package/src/types.ts +258 -40
  121. package/dist/chunk-3LLRNCPX.js.map +0 -1
  122. package/dist/chunk-RANPUC6C.js +0 -72
  123. package/dist/chunk-RANPUC6C.js.map +0 -1
  124. package/dist/chunk-XN3LSDPY.js.map +0 -1
  125. package/dist/chunk-YF65VYRY.js.map +0 -1
  126. package/src/fragment-types.ts +0 -214
  127. package/src/react-create-element.test.ts +0 -22
  128. package/src/react-create-element.ts +0 -12
  129. package/src/storyFilters.test.ts +0 -350
  130. package/src/storyFilters.ts +0 -253
package/src/index.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  // Brand and default constants
7
- export { BRAND, DEFAULTS } from "./constants.js";
7
+ export { BRAND, DEFAULTS, FRAGMENT_V3_SCHEMA_URL } from "./constants.js";
8
8
  export type { Brand, Defaults } from "./constants.js";
9
9
 
10
10
  export {
@@ -167,14 +167,20 @@ export type {
167
167
  FragmentsConfig,
168
168
  SnippetPolicyConfig,
169
169
  RegistryOptions,
170
+ FragmentIndex,
171
+ FragmentRegistry,
172
+ RegistryComponentEntry,
173
+ RegistryPropEntry,
174
+ FragmentContextOptions,
170
175
  CompiledFragment,
176
+ CompiledFragmentDesign,
177
+ CompiledFragmentMatrix,
178
+ CompiledFragmentPreview,
171
179
  CompiledFragmentsFile,
172
180
  ObservedComponentUsage,
173
181
  ObservedUsageProp,
174
182
  BlockDefinition,
175
183
  CompiledBlock,
176
- RecipeDefinition, // @deprecated - use BlockDefinition
177
- CompiledRecipe, // @deprecated - use CompiledBlock
178
184
  // Contract and provenance types
179
185
  FragmentContract,
180
186
  FragmentGenerated,
@@ -186,6 +192,18 @@ export type {
186
192
  CompositionMetadata,
187
193
  FragmentProvenance,
188
194
  FragmentDefinitionV2,
195
+ // v3 types (arity-discriminated)
196
+ FragmentMetaV3,
197
+ FragmentStateV3,
198
+ FragmentDontExampleV3,
199
+ FragmentGuidanceV3,
200
+ FragmentMatrixV3,
201
+ FragmentPreviewV3,
202
+ FragmentDesignV3,
203
+ PropAnnotation,
204
+ FragmentAnnotationsV3,
205
+ FragmentDefinitionV3Body,
206
+ FragmentDefinitionV3,
189
207
  // Screenshot types
190
208
  ScreenshotConfig,
191
209
  ServiceConfig,
@@ -207,8 +225,6 @@ export type {
207
225
  FigmaInstanceMapping,
208
226
  FigmaChildrenMapping,
209
227
  FigmaTextContentMapping,
210
- // Storybook filter configuration
211
- StorybookFilterConfig,
212
228
  // Token configuration
213
229
  AppConfig,
214
230
  DesignSystemConfig,
@@ -284,12 +300,18 @@ export type {
284
300
  // Fragments Registry Protocol contracts
285
301
  export {
286
302
  REGISTRY_ARTIFACT_SCHEMA_VERSION,
303
+ REGISTRY_INDEX_SCHEMA_VERSION,
287
304
  REGISTRY_INSTALL_RECEIPT_SCHEMA_VERSION,
288
305
  REGISTRY_MANIFEST_SCHEMA_VERSION,
306
+ REGISTRY_POINTER_SCHEMA_VERSION,
307
+ REGISTRY_SHARD_SCHEMA_VERSION,
308
+ assembleRegistryArtifact,
289
309
  assertValidRegistryArtifact,
290
310
  buildRegistryArtifact,
291
311
  buildRegistryFile,
312
+ buildRegistryPointer,
292
313
  computeRegistryHash,
314
+ defaultRegistryShardPath,
293
315
  finalizeRegistryManifest,
294
316
  hashRegistryFileContent,
295
317
  registryArtifactDigest,
@@ -303,14 +325,21 @@ export {
303
325
  registryFileRoleSchema,
304
326
  registryFileSchema,
305
327
  registryFileSize,
328
+ registryIndexSchema,
306
329
  registryInstallProfileSchema,
307
330
  registryInstallReceiptComponentSchema,
308
331
  registryInstallReceiptFileSchema,
309
332
  registryInstallReceiptSchema,
310
333
  registryManifestCanonicalPreimage,
311
334
  registryManifestDraftSchema,
335
+ registryManifestFileMetadata,
336
+ registryManifestFilePaths,
312
337
  registryManifestSchema,
338
+ registryPointerSchema,
339
+ registryShardSchema,
340
+ registryShardsForPaths,
313
341
  registrySourceSchema,
342
+ shardRegistryArtifact,
314
343
  } from "./registry.js";
315
344
  export type {
316
345
  RegistryArtifact,
@@ -324,13 +353,17 @@ export type {
324
353
  RegistryFileContent,
325
354
  RegistryFileInput,
326
355
  RegistryFileRole,
356
+ RegistryIndex,
327
357
  RegistryInstallProfile,
328
358
  RegistryInstallReceipt,
329
359
  RegistryInstallReceiptComponent,
330
360
  RegistryInstallReceiptFile,
331
361
  RegistryManifest,
332
362
  RegistryManifestDraft,
363
+ RegistryPointer,
364
+ RegistryShard,
333
365
  RegistrySource,
366
+ ShardedRegistryArtifact,
334
367
  } from "./registry.js";
335
368
 
336
369
  export {
@@ -338,13 +371,21 @@ export {
338
371
  buildRegistryInstallPlan,
339
372
  buildRegistryInstallReceipt,
340
373
  collectRegistryInstallDependencies,
374
+ expandRegistryComponentClosure,
341
375
  normalizeRegistryRepoPath,
342
- selectedRegistryComponentNames,
376
+ resolveRegistryComponentId,
377
+ resolveRegistryInstallSelection,
378
+ resolveRegistryInstallSources,
343
379
  sourceToRegistryTargetPath,
344
380
  } from "./registry-install-plan.js";
345
381
  export type {
346
382
  BuildRegistryInstallPlanInput,
347
383
  RegistryInstallPlan,
384
+ RegistryInstallSelection,
385
+ RegistryInstallSelectionInput,
386
+ RegistryInstallSourceFile,
387
+ RegistryInstallSources,
388
+ RegistryInstallSourcesInput,
348
389
  RegistryWritePlan,
349
390
  } from "./registry-install-plan.js";
350
391
 
@@ -427,10 +468,10 @@ export {
427
468
  figmaPropMappingSchema,
428
469
  // Contract and provenance schemas
429
470
  fragmentContractSchema,
471
+ fragmentSourceValues,
430
472
  fragmentGeneratedSchema,
431
473
  fragmentBanSchema,
432
474
  blockDefinitionSchema,
433
- recipeDefinitionSchema, // @deprecated - use blockDefinitionSchema
434
475
  // AI metadata schema
435
476
  aiMetadataSchema,
436
477
  // v2 schemas
@@ -438,6 +479,18 @@ export {
438
479
  fragmentProvenanceSchema,
439
480
  fragmentDefinitionV2Schema,
440
481
  governedFragmentDefinitionSchema,
482
+ // v3 schemas
483
+ fragmentMetaV3Schema,
484
+ fragmentStateV3Schema,
485
+ fragmentDontExampleV3Schema,
486
+ fragmentGuidanceV3Schema,
487
+ fragmentMatrixV3Schema,
488
+ fragmentPreviewV3Schema,
489
+ fragmentDesignV3Schema,
490
+ propAnnotationSchema,
491
+ fragmentAnnotationsV3Schema,
492
+ fragmentDefinitionV3BodySchema,
493
+ fragmentDefinitionV3Schema,
441
494
  } from "./schema.js";
442
495
 
443
496
  // Main API
@@ -448,8 +501,6 @@ export {
448
501
  normalizeToV1,
449
502
  defineBlock,
450
503
  compileBlock,
451
- defineRecipe,
452
- compileRecipe,
453
504
  } from "./defineFragment.js";
454
505
  export type { InferProps } from "./defineFragment.js";
455
506
 
@@ -457,6 +508,7 @@ export type { InferProps } from "./defineFragment.js";
457
508
  export {
458
509
  componentGovernanceRecordSchema,
459
510
  componentGovernanceRecordsSchema,
511
+ parseComponentGovernancePolicyJson,
460
512
  canonicalBridgeV1Schema,
461
513
  g,
462
514
  globalGovernanceRecordSchema,
@@ -467,6 +519,8 @@ export {
467
519
  isPresetSourcedRule,
468
520
  markPresetSourcedRules,
469
521
  normalizeGovernanceConfig,
522
+ resolveComponentGovernance,
523
+ resolveGovernanceRecordsForIdentity,
470
524
  scaleGovernanceRecordSchema,
471
525
  } from "./governance.js";
472
526
  export type {
@@ -501,15 +555,6 @@ export {
501
555
  } from "./policy-exclude.js";
502
556
  export type { PolicyExclude, PolicyExcludeInput } from "./policy-exclude.js";
503
557
 
504
- // Storybook adapter filtering
505
- export {
506
- checkStoryExclusion,
507
- detectSubComponentPaths,
508
- isForceIncluded,
509
- isConfigExcluded,
510
- } from "./storyFilters.js";
511
- export type { ExclusionReason, ExclusionResult, CheckStoryExclusionOpts } from "./storyFilters.js";
512
-
513
558
  // Context generation for AI agents
514
559
  export { generateContext } from "./context.js";
515
560
  export type { ContextOptions, ContextResult } from "./context.js";
@@ -517,23 +562,6 @@ export type { ContextOptions, ContextResult } from "./context.js";
517
562
  // Figma property mapping DSL
518
563
  export { figma, isFigmaPropMapping, resolveFigmaMapping } from "./figma.js";
519
564
 
520
- // Fragment JSON types (for .fragment.json files)
521
- export type {
522
- Fragment,
523
- FragmentFigma,
524
- FragmentUsage as FragmentJsonUsage,
525
- FragmentDoNotItem,
526
- FragmentPattern,
527
- FragmentAccessibility,
528
- FragmentRelated,
529
- FragmentMeta as FragmentJsonMeta,
530
- FragmentIndex,
531
- FragmentRegistry,
532
- RegistryComponentEntry,
533
- RegistryPropEntry,
534
- FragmentContextOptions,
535
- } from "./fragment-types.js";
536
-
537
565
  // Token parsing and token-domain helpers
538
566
  export {
539
567
  calculateDeltaE,
@@ -649,6 +677,12 @@ export {
649
677
  ruleA11yRequiredAccessibleName,
650
678
  ruleA11yStandard,
651
679
  } from "./rules/index.js";
680
+ export {
681
+ capConfiguredSeverity,
682
+ configuredFindingSeverity,
683
+ readRuleConfig,
684
+ type RuleConfigView,
685
+ } from "./rules/rule-config.js";
652
686
  export { indexComponentIdentityUsage, type ComponentIdentityUsage } from "./identity/usage.js";
653
687
  export { nearestSignedScaleValue } from "./rules/utils.js";
654
688
  export {
@@ -705,7 +739,11 @@ export type { RuleTier, PresetRuleState } from "./rules/index.js";
705
739
  // Contract-site health denominator: how many style-declaration sites the
706
740
  // token-vocabulary rule actually judged. Consumed by the CLI's per-scan
707
741
  // `contract-site-health:v1` metric next to the identity usage index.
708
- export { contractTokenReferenceCensus } from "./rules/index.js";
742
+ export {
743
+ contractTokenReferenceCensus,
744
+ EMPTY_VOCABULARY_MESSAGE,
745
+ emptyVocabularyConfigFile,
746
+ } from "./rules/index.js";
709
747
  export type { ContractTokenReferenceCensus } from "./rules/index.js";
710
748
 
711
749
  // Rule families — the ONE expansion of a broad `govern.rules` id (`tokens/hardcoded-values`)
@@ -826,24 +864,39 @@ export {
826
864
  } from "./facts/index.js";
827
865
  export type { SupersededImportPathPreference } from "./facts/index.js";
828
866
  export {
829
- canonicalPreimage,
830
867
  AGENT_CONTEXT_RELATIVE_PATH,
868
+ artifactContentHash,
831
869
  CATALOG_FIXTURE_A_FCID,
832
870
  catalogFixtureA,
833
871
  catalogFixtureAContractPayload,
834
872
  catalogFixtureATokensDtcg,
873
+ canonicalPreimage,
874
+ CONTRACT_DISPLAY_ONLY_FIELDS,
835
875
  CONTRACT_DOMAINS,
876
+ CONTRACT_ENFORCEMENT_FIELDS,
836
877
  CONTRACT_PREIMAGE_CAPABILITY_HEADER,
837
878
  CONTRACT_PREIMAGE_SCHEMA,
879
+ ContractCatalogValidationError,
838
880
  contractComponentsFromFragments,
839
881
  contractHash,
840
882
  contractPolicyFromGovernanceConfig,
883
+ deriveArtifactId,
841
884
  diffContractDomains,
842
885
  formatStampHeader,
843
886
  formatStampPin,
844
887
  formatStampVersionHash,
888
+ FRAGMENTS_MANIFEST_FILENAME,
889
+ FRAGMENTS_MANIFEST_SCHEMA_VERSION,
890
+ FRAGMENTS_MANIFEST_TOKEN_RULE,
891
+ fragmentsManifestFcid,
892
+ fragmentsManifestGrammarSchema,
893
+ fragmentsManifestPatternSchema,
894
+ fragmentsManifestPrimitiveSchema,
895
+ fragmentsManifestSchema,
845
896
  parseContractStamp,
897
+ parseFragmentsManifest,
846
898
  projectContractPreimage,
899
+ projectEnforcementContract,
847
900
  serializeContractStamp,
848
901
  sha256Hex,
849
902
  verifiedContractPreimageFromPin,
@@ -866,6 +919,7 @@ export type {
866
919
  ContractCatalogInput,
867
920
  ContractComponentInput,
868
921
  ContractDomain,
922
+ ContractEnforcementField,
869
923
  ContractIdentityPin,
870
924
  ContractPolicyInput,
871
925
  ContractPreimage,
@@ -874,6 +928,10 @@ export type {
874
928
  ContractStampRecord,
875
929
  ContractTokenInput,
876
930
  ContractWaiverInput,
931
+ FragmentsManifest,
932
+ FragmentsManifestGrammar,
933
+ FragmentsManifestPattern,
934
+ FragmentsManifestPrimitive,
877
935
  } from "./contract/index.js";
878
936
  export {
879
937
  governanceConfigWithLocalCanonical,
@@ -920,6 +978,9 @@ export type {
920
978
  FactLocation,
921
979
  FactEvidence,
922
980
  CanonicalCandidateFact,
981
+ CanonicalFactConflictV1,
982
+ CanonicalFactConflictValueV1,
983
+ CanonicalFactIntegrityV1,
923
984
  CanonicalMappingFact,
924
985
  CanonicalReplacementFact,
925
986
  ComponentLevelFact,
@@ -978,8 +1039,140 @@ export type {
978
1039
  SuppressionDirectiveFact,
979
1040
  ComponentFactInput,
980
1041
  } from "./facts/index.js";
1042
+ export {
1043
+ CANONICAL_FACT_MAX_CONFLICTS_V1,
1044
+ CANONICAL_FACT_MAX_PROVENANCE_PER_VALUE_V1,
1045
+ CANONICAL_FACT_MAX_VALUES_PER_CONFLICT_V1,
1046
+ canonicalFactConflictV1Schema,
1047
+ canonicalFactConflictValueV1Schema,
1048
+ canonicalFactIntegrityV1Schema,
1049
+ normalizeCanonicalFactIntegrityV1,
1050
+ } from "./facts/index.js";
1051
+
1052
+ // V1 authority and analysis contracts. These remain browser-safe and have no
1053
+ // Cloud, provider, engine, model, or Node-only dependency.
1054
+ export {
1055
+ analysisPlanIdFromDigest,
1056
+ analysisPlanIdSchema,
1057
+ analysisPlanIdStringSchema,
1058
+ digestHexSchema,
1059
+ digestHexStringSchema,
1060
+ evaluationReceiptIdFromDigest,
1061
+ mintEvaluationReceiptId,
1062
+ evaluationReceiptIdSchema,
1063
+ evaluationReceiptIdStringSchema,
1064
+ parseAnalysisPlanId,
1065
+ parseDigestHex,
1066
+ parseEvaluationReceiptId,
1067
+ } from "./domain-ids.js";
1068
+ export type { AnalysisPlanId, DigestHex, EvaluationReceiptId } from "./domain-ids.js";
1069
+ export {
1070
+ PROVIDER_ID_MAX_BYTES_V1,
1071
+ REPOSITORY_BINDING_ID_MAX_BYTES_V1,
1072
+ normalizeRepositoryBindingKeyV1,
1073
+ repositoryBindingDigestV1,
1074
+ repositoryBindingKeyV1Schema,
1075
+ } from "./repository-binding.js";
1076
+ export type { RepositoryBindingKeyV1, RepositoryBindingKeyV1Input } from "./repository-binding.js";
1077
+ export {
1078
+ ANALYSIS_LIMIT_CEILINGS_V1,
1079
+ ANALYSIS_PLAN_MAX_CAPABILITIES_V1,
1080
+ ANALYSIS_PLAN_MAX_DIALECTS_PER_REGION_V1,
1081
+ ANALYSIS_PLAN_MAX_REGIONS_V1,
1082
+ CoverageValidationErrorV1,
1083
+ analysisLimitsV1Schema,
1084
+ analysisObligationsDigestV1,
1085
+ analysisPlanDigestV1,
1086
+ analysisPlanInputV1Schema,
1087
+ analysisPlanV1Schema,
1088
+ analysisRegionV1Schema,
1089
+ buildAnalysisPlanV1,
1090
+ coverageArtifactDigestV1,
1091
+ coverageRegionV1Schema,
1092
+ coverageStateV1Schema,
1093
+ coverageSummaryV1Schema,
1094
+ deriveCoverageSummaryV1,
1095
+ normalizeAnalysisPlanInputV1,
1096
+ parseAnalysisPlanV1,
1097
+ } from "./analysis-plan/index.js";
1098
+ export type {
1099
+ AnalysisLimitsV1,
1100
+ AnalysisPlanInputV1,
1101
+ AnalysisPlanV1,
1102
+ AnalysisRegionV1,
1103
+ CoverageRegionV1,
1104
+ CoverageStateV1,
1105
+ CoverageSummaryV1,
1106
+ } from "./analysis-plan/index.js";
981
1107
 
982
1108
  // Topology — map file paths to product areas (area-scoped governance).
983
1109
  // Also available at the `@usefragments/core/topology` subpath.
984
1110
  export { resolveArea } from "./topology/index.js";
985
1111
  export type { Area, AreaCriticality, AreaMatch, Topology } from "./topology/index.js";
1112
+
1113
+ // Evaluation Module — the pure governance kernel (architecture spec §§1–2):
1114
+ // deterministic verdicts with kernel-owned FCID verification, four-state
1115
+ // finding classification, and three-state trust facts. Shipped in shadow mode
1116
+ // alongside the legacy CLI/Cloud verdict machines.
1117
+ export {
1118
+ EVALUATION_MAX_FINDINGS_V2,
1119
+ EVALUATION_MAX_MAP_ENTRIES_V2,
1120
+ EVALUATION_MAX_POLICY_RULES_V2,
1121
+ EVALUATION_MAX_REASON_CODES_V2,
1122
+ EVALUATION_MAX_WAIVERS_V2,
1123
+ EVALUATION_MAX_WAIVER_MATCHES_V2,
1124
+ EVALUATION_RECEIPT_STRING_MAX_BYTES_V1,
1125
+ EVALUATOR_VERSION,
1126
+ EVALUATOR_VERSION_V2,
1127
+ effectiveEvaluationWaiverV2Schema,
1128
+ evaluate,
1129
+ evaluationInputDigestV2,
1130
+ evaluationResultDigestV2,
1131
+ evaluationInputV2Schema,
1132
+ evaluationReceiptDigestV1,
1133
+ evaluationReceiptMintInputV1Schema,
1134
+ evaluationReceiptV1Schema,
1135
+ evaluationResultV2Schema,
1136
+ parseEvaluationReceiptV1,
1137
+ providerProofDigestV1,
1138
+ providerProofV1Schema,
1139
+ } from "./evaluation/index.js";
1140
+ export type {
1141
+ EffectivePolicy,
1142
+ EffectiveRulePolicy,
1143
+ EvaluatedFinding,
1144
+ EvaluationBaseline,
1145
+ EvaluationContractInput,
1146
+ EvaluationEvidence,
1147
+ EvaluationFindingInput,
1148
+ EvaluationFindingState,
1149
+ EvaluationInput,
1150
+ EvaluationIntegrityInput,
1151
+ EvaluationMappingTrust,
1152
+ EvaluationReason,
1153
+ EvaluationResult,
1154
+ EvaluationScope,
1155
+ EvaluationSourceTrust,
1156
+ EvaluationTrust,
1157
+ EvaluationVerdict,
1158
+ EvaluationWaiver,
1159
+ EffectiveEvaluationWaiverV2,
1160
+ EvaluationAuthorityV1,
1161
+ EvaluationEvidenceTrustV1,
1162
+ EvaluationInputV2,
1163
+ EvaluationIntegrityInputV2,
1164
+ EvaluationReasonV2,
1165
+ EvaluationReceiptMintInputV1,
1166
+ EvaluationReceiptSemanticV1,
1167
+ EvaluationReceiptV1,
1168
+ EvaluationResultV2,
1169
+ FindingV2,
1170
+ ProviderProofSemanticV1,
1171
+ ProviderProofV1,
1172
+ } from "./evaluation/index.js";
1173
+
1174
+ export {
1175
+ APPROVED_CONTRACT_TOKEN_MAX_NAMES,
1176
+ APPROVED_CONTRACT_TOKEN_MAX_NAME_LENGTH,
1177
+ isApprovedContractTokenNames,
1178
+ } from "./approved-contract-tokens.js";
@@ -128,6 +128,68 @@ describe("@usefragments/core/preview artifact validation", () => {
128
128
  ).toThrow(/unsupported source "storybook"/);
129
129
  });
130
130
 
131
+ it("requires component map keys to match unique normalized component keys", () => {
132
+ const mismatched = {
133
+ ...manifest,
134
+ components: {
135
+ RenamedButton: {
136
+ ...manifest.components.Button,
137
+ componentKey: "Button",
138
+ },
139
+ },
140
+ };
141
+ const duplicated = {
142
+ ...manifest,
143
+ components: {
144
+ Button: manifest.components.Button,
145
+ " Button ": {
146
+ ...manifest.components.Button,
147
+ componentKey: " Button ",
148
+ },
149
+ },
150
+ };
151
+
152
+ expect(() =>
153
+ definePreviewArtifactManifest(mismatched as unknown as PreviewArtifactManifest)
154
+ ).toThrow(/componentKey must match its components map key/);
155
+ expect(() =>
156
+ definePreviewArtifactManifest(duplicated as unknown as PreviewArtifactManifest)
157
+ ).toThrow(/duplicate normalized componentKey/);
158
+ });
159
+
160
+ it("requires supported previewability values and unique non-empty variant ids", () => {
161
+ const invalid = {
162
+ ...manifest,
163
+ components: {
164
+ Button: {
165
+ ...manifest.components.Button,
166
+ previewability: "unknown",
167
+ variants: [
168
+ ...manifest.components.Button.variants,
169
+ {
170
+ ...manifest.components.Button.variants[0],
171
+ id: " default ",
172
+ },
173
+ {
174
+ ...manifest.components.Button.variants[0],
175
+ id: " ",
176
+ },
177
+ ],
178
+ },
179
+ },
180
+ };
181
+
182
+ expect(() =>
183
+ definePreviewArtifactManifest(invalid as unknown as PreviewArtifactManifest)
184
+ ).toThrow(/previewability must be one of/);
185
+ expect(() =>
186
+ definePreviewArtifactManifest(invalid as unknown as PreviewArtifactManifest)
187
+ ).toThrow(/variants.1.id must be unique within the component/);
188
+ expect(() =>
189
+ definePreviewArtifactManifest(invalid as unknown as PreviewArtifactManifest)
190
+ ).toThrow(/variants.2.id must be a non-empty string/);
191
+ });
192
+
131
193
  it("rejects malformed design comparison evidence", () => {
132
194
  const invalid = {
133
195
  ...manifest,
@@ -1,4 +1,17 @@
1
- import type { PreviewArtifactManifest } from "./types";
1
+ import type { Previewability, PreviewArtifactManifest } from "./types";
2
+
3
+ const PREVIEWABILITY_VALUES = new Set<Previewability>([
4
+ "ready",
5
+ "building",
6
+ "needs-preview-provider",
7
+ "missing-dependency",
8
+ "missing-asset",
9
+ "server-only",
10
+ "unsupported-framework",
11
+ "runtime-error",
12
+ "build-error",
13
+ "docs-only",
14
+ ]);
2
15
 
3
16
  export interface PreviewArtifactValidationResult {
4
17
  ok: boolean;
@@ -96,12 +109,25 @@ function validateComponents(value: unknown, issues: string[]) {
96
109
  issues.push("components must be an object");
97
110
  return;
98
111
  }
112
+ const normalizedComponentKeys = new Set<string>();
99
113
  for (const [key, component] of Object.entries(value)) {
100
114
  if (!isRecord(component)) {
101
115
  issues.push(`components.${key} must be an object`);
102
116
  continue;
103
117
  }
104
- requireString(component, "componentKey", issues, `components.${key}`);
118
+ const componentKey = component.componentKey;
119
+ if (typeof componentKey !== "string" || !componentKey.trim()) {
120
+ issues.push(`components.${key}.componentKey must be a non-empty string`);
121
+ } else {
122
+ if (key !== componentKey) {
123
+ issues.push(`components.${key}.componentKey must match its components map key`);
124
+ }
125
+ const normalizedComponentKey = componentKey.trim();
126
+ if (normalizedComponentKeys.has(normalizedComponentKey)) {
127
+ issues.push(`components contains duplicate normalized componentKey ${componentKey}`);
128
+ }
129
+ normalizedComponentKeys.add(normalizedComponentKey);
130
+ }
105
131
  requireString(component, "publicRef", issues, `components.${key}`);
106
132
  requireString(component, "displayName", issues, `components.${key}`);
107
133
  requireString(component, "exportName", issues, `components.${key}`);
@@ -112,17 +138,33 @@ function validateComponents(value: unknown, issues: string[]) {
112
138
  `components.${key}.definitionSource must be one of typescript, fragment, manual, synthesized`
113
139
  );
114
140
  }
141
+ if (!isPreviewability(component.previewability)) {
142
+ issues.push(
143
+ `components.${key}.previewability must be one of ${[...PREVIEWABILITY_VALUES].join(", ")}`
144
+ );
145
+ }
115
146
  if (!isRecord(component.props)) {
116
147
  issues.push(`components.${key}.props must be an object`);
117
148
  }
118
149
  if (!Array.isArray(component.variants)) {
119
150
  issues.push(`components.${key}.variants must be an array`);
120
151
  } else {
152
+ const normalizedVariantIds = new Set<string>();
121
153
  component.variants.forEach((variant, index) => {
122
154
  if (!isRecord(variant)) {
123
155
  issues.push(`components.${key}.variants.${index} must be an object`);
124
156
  return;
125
157
  }
158
+ const variantPath = `components.${key}.variants.${index}`;
159
+ if (typeof variant.id !== "string" || !variant.id.trim()) {
160
+ issues.push(`${variantPath}.id must be a non-empty string`);
161
+ } else {
162
+ const normalizedVariantId = variant.id.trim();
163
+ if (normalizedVariantIds.has(normalizedVariantId)) {
164
+ issues.push(`${variantPath}.id must be unique within the component`);
165
+ }
166
+ normalizedVariantIds.add(normalizedVariantId);
167
+ }
126
168
  validateDesignReference(
127
169
  variant.design,
128
170
  issues,
@@ -297,6 +339,10 @@ function isPreviewDefinitionSource(value: unknown): boolean {
297
339
  );
298
340
  }
299
341
 
342
+ function isPreviewability(value: unknown): value is Previewability {
343
+ return typeof value === "string" && PREVIEWABILITY_VALUES.has(value as Previewability);
344
+ }
345
+
300
346
  function isFiniteNumber(value: unknown): value is number {
301
347
  return typeof value === "number" && Number.isFinite(value);
302
348
  }