@usefragments/core 1.10.2 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) 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 +3041 -350
  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/types.ts +258 -37
  118. package/dist/chunk-RANPUC6C.js +0 -72
  119. package/dist/chunk-RANPUC6C.js.map +0 -1
  120. package/dist/chunk-XN3LSDPY.js.map +0 -1
  121. package/dist/chunk-YF65VYRY.js.map +0 -1
  122. package/src/fragment-types.ts +0 -214
  123. package/src/react-create-element.test.ts +0 -22
  124. package/src/react-create-element.ts +0 -12
  125. package/src/storyFilters.test.ts +0 -350
  126. package/src/storyFilters.ts +0 -253
@@ -0,0 +1,207 @@
1
+ import { z } from "zod";
2
+ import {
3
+ analysisPlanIdStringSchema,
4
+ digestHexStringSchema,
5
+ type AnalysisPlanId,
6
+ type DigestHex,
7
+ } from "../domain-ids.js";
8
+ import {
9
+ repositoryBindingKeyV1Schema,
10
+ type RepositoryBindingKeyV1,
11
+ } from "../repository-binding.js";
12
+
13
+ export const ANALYSIS_PLAN_MAX_REGIONS_V1 = 1_000;
14
+ export const ANALYSIS_PLAN_MAX_CAPABILITIES_V1 = 256;
15
+ export const ANALYSIS_PLAN_MAX_DIALECTS_PER_REGION_V1 = 64;
16
+
17
+ export const ANALYSIS_LIMIT_CEILINGS_V1 = {
18
+ maxSourceFiles: 100_000,
19
+ maxSourceBytes: 1_073_741_824,
20
+ maxFileBytes: 10_485_760,
21
+ maxFacts: 1_000_000,
22
+ maxRegions: ANALYSIS_PLAN_MAX_REGIONS_V1,
23
+ maxDiagnostics: 100_000,
24
+ maxDurationMs: 900_000,
25
+ } as const;
26
+
27
+ const bounded = (max: number) => z.string().min(1).max(max);
28
+ const positiveBoundedInteger = (max: number) => z.number().int().positive().max(max);
29
+ const uniqueStrings = (values: readonly string[]): boolean =>
30
+ new Set(values).size === values.length;
31
+
32
+ export const coverageStateV1Schema = z.enum([
33
+ "analyzed",
34
+ "unsupported",
35
+ "excluded_by_contract",
36
+ "skipped_limit",
37
+ "failed",
38
+ ]);
39
+ export type CoverageStateV1 = z.infer<typeof coverageStateV1Schema>;
40
+
41
+ export const analysisLimitsV1Schema = z
42
+ .object({
43
+ maxSourceFiles: positiveBoundedInteger(ANALYSIS_LIMIT_CEILINGS_V1.maxSourceFiles),
44
+ maxSourceBytes: positiveBoundedInteger(ANALYSIS_LIMIT_CEILINGS_V1.maxSourceBytes),
45
+ maxFileBytes: positiveBoundedInteger(ANALYSIS_LIMIT_CEILINGS_V1.maxFileBytes),
46
+ maxFacts: positiveBoundedInteger(ANALYSIS_LIMIT_CEILINGS_V1.maxFacts),
47
+ maxRegions: positiveBoundedInteger(ANALYSIS_LIMIT_CEILINGS_V1.maxRegions),
48
+ maxDiagnostics: positiveBoundedInteger(ANALYSIS_LIMIT_CEILINGS_V1.maxDiagnostics),
49
+ maxDurationMs: positiveBoundedInteger(ANALYSIS_LIMIT_CEILINGS_V1.maxDurationMs),
50
+ })
51
+ .strict();
52
+ export type AnalysisLimitsV1 = z.infer<typeof analysisLimitsV1Schema>;
53
+
54
+ export const analysisRegionV1Schema = z
55
+ .object({
56
+ regionId: bounded(256),
57
+ pathPattern: bounded(4_096),
58
+ kind: z.enum(["component_source", "style_source", "token_source", "config"]),
59
+ language: bounded(64),
60
+ required: z.boolean(),
61
+ requiredDialects: z
62
+ .array(bounded(128))
63
+ .max(ANALYSIS_PLAN_MAX_DIALECTS_PER_REGION_V1)
64
+ .refine(uniqueStrings, "requiredDialects must be unique"),
65
+ analyzer: z
66
+ .object({
67
+ id: bounded(256),
68
+ interfaceVersion: bounded(128),
69
+ implementationVersion: bounded(128),
70
+ })
71
+ .strict(),
72
+ })
73
+ .strict();
74
+ export type AnalysisRegionV1 = z.infer<typeof analysisRegionV1Schema>;
75
+
76
+ export const coverageRegionV1Schema = z
77
+ .object({
78
+ regionId: bounded(256),
79
+ state: coverageStateV1Schema,
80
+ fileCount: z.number().int().nonnegative().max(ANALYSIS_LIMIT_CEILINGS_V1.maxSourceFiles),
81
+ byteCount: z.number().int().nonnegative().max(ANALYSIS_LIMIT_CEILINGS_V1.maxSourceBytes),
82
+ diagnosticIds: z
83
+ .array(bounded(256))
84
+ .max(ANALYSIS_LIMIT_CEILINGS_V1.maxDiagnostics)
85
+ .refine(uniqueStrings, "diagnosticIds must be unique"),
86
+ })
87
+ .strict();
88
+ export type CoverageRegionV1 = z.infer<typeof coverageRegionV1Schema>;
89
+
90
+ const coverageCountsV1Schema = z
91
+ .object({
92
+ analyzed: z.number().int().nonnegative(),
93
+ unsupported: z.number().int().nonnegative(),
94
+ excluded_by_contract: z.number().int().nonnegative(),
95
+ skipped_limit: z.number().int().nonnegative(),
96
+ failed: z.number().int().nonnegative(),
97
+ })
98
+ .strict();
99
+
100
+ export const coverageSummaryV1Schema = z
101
+ .object({
102
+ plannedRegions: z.number().int().nonnegative(),
103
+ observedRegions: z.number().int().nonnegative(),
104
+ requiredRegions: z.number().int().nonnegative(),
105
+ requiredByState: coverageCountsV1Schema,
106
+ optionalByState: coverageCountsV1Schema,
107
+ eligibleFiles: z.number().int().nonnegative(),
108
+ analyzedFiles: z.number().int().nonnegative(),
109
+ analyzedBytes: z.number().int().nonnegative(),
110
+ })
111
+ .strict();
112
+ export type CoverageSummaryV1 = z.infer<typeof coverageSummaryV1Schema>;
113
+
114
+ const analysisPlanBaseShape = {
115
+ binding: repositoryBindingKeyV1Schema,
116
+ source: z
117
+ .object({
118
+ commitId: bounded(256),
119
+ treeId: bounded(256).optional(),
120
+ defaultBranch: bounded(256),
121
+ acquiredBy: z.enum(["github_app", "local_worktree", "ci_attested"]),
122
+ })
123
+ .strict(),
124
+ contract: z
125
+ .object({
126
+ fcid: digestHexStringSchema,
127
+ artifactDigest: digestHexStringSchema,
128
+ })
129
+ .strict(),
130
+ config: z
131
+ .object({
132
+ path: bounded(4_096).refine(
133
+ (value) =>
134
+ !value.startsWith("/") && !value.includes("\\") && !value.split("/").includes(".."),
135
+ "config path must be a portable repository-relative path"
136
+ ),
137
+ digest: digestHexStringSchema,
138
+ })
139
+ .strict(),
140
+ profile: z
141
+ .object({
142
+ id: z.literal("react-web-v1"),
143
+ version: bounded(128),
144
+ capabilities: z
145
+ .array(bounded(128))
146
+ .max(ANALYSIS_PLAN_MAX_CAPABILITIES_V1)
147
+ .refine(uniqueStrings, "capabilities must be unique"),
148
+ })
149
+ .strict(),
150
+ regions: z
151
+ .array(analysisRegionV1Schema)
152
+ .max(ANALYSIS_PLAN_MAX_REGIONS_V1)
153
+ .refine(
154
+ (regions) => new Set(regions.map((region) => region.regionId)).size === regions.length,
155
+ "regionId values must be unique"
156
+ ),
157
+ limits: analysisLimitsV1Schema,
158
+ evaluatorVersion: bounded(128),
159
+ createdAt: z.string().datetime({ offset: true }),
160
+ };
161
+
162
+ function validatePlanLimits(
163
+ plan: { regions: readonly AnalysisRegionV1[]; limits: AnalysisLimitsV1 },
164
+ context: z.RefinementCtx
165
+ ): void {
166
+ if (plan.regions.length > plan.limits.maxRegions) {
167
+ context.addIssue({
168
+ code: z.ZodIssueCode.custom,
169
+ path: ["regions"],
170
+ message: "Planned regions exceed the plan's maxRegions limit",
171
+ });
172
+ }
173
+ if (plan.limits.maxFileBytes > plan.limits.maxSourceBytes) {
174
+ context.addIssue({
175
+ code: z.ZodIssueCode.custom,
176
+ path: ["limits", "maxFileBytes"],
177
+ message: "maxFileBytes cannot exceed maxSourceBytes",
178
+ });
179
+ }
180
+ }
181
+
182
+ export const analysisPlanInputV1Schema = z
183
+ .object(analysisPlanBaseShape)
184
+ .strict()
185
+ .superRefine(validatePlanLimits);
186
+ export type AnalysisPlanInputV1 = z.input<typeof analysisPlanInputV1Schema>;
187
+
188
+ export const analysisPlanV1Schema = z
189
+ .object({
190
+ schemaVersion: z.literal(1),
191
+ analysisPlanId: analysisPlanIdStringSchema,
192
+ ...analysisPlanBaseShape,
193
+ obligationsDigest: digestHexStringSchema,
194
+ digest: digestHexStringSchema,
195
+ })
196
+ .strict()
197
+ .superRefine(validatePlanLimits);
198
+
199
+ export interface AnalysisPlanV1 extends Omit<
200
+ z.output<typeof analysisPlanV1Schema>,
201
+ "analysisPlanId" | "digest" | "obligationsDigest"
202
+ > {
203
+ analysisPlanId: AnalysisPlanId;
204
+ binding: RepositoryBindingKeyV1;
205
+ obligationsDigest: DigestHex;
206
+ digest: DigestHex;
207
+ }
@@ -24,6 +24,15 @@ const SUBSYSTEM_EMITTED_CODES = [
24
24
  // sources are read before any rule runs, and an unreadable one aborts the
25
25
  // scan rather than producing a finding.
26
26
  "FUI9009",
27
+ // Emitted by the compiler, not the rule engine: a `.fragment` source whose
28
+ // definition fails Core's schema, or whose authored claims contradict the
29
+ // extracted component, is refused before any rule has a contract to run on.
30
+ "FUI9010",
31
+ "FUI9011",
32
+ // Emitted by tokens/css-vars-must-be-defined when the rule is active but the
33
+ // resolved contract vocabulary is empty — a config-level inert diagnostic,
34
+ // not a second rule id in RULES.
35
+ "FUI2018",
27
36
  ] as const;
28
37
 
29
38
  const RESERVED_CODES = {
@@ -273,6 +273,16 @@ export const CODES = [
273
273
  lifecycle: "experimental",
274
274
  evidenceRequired: true,
275
275
  }),
276
+ code({
277
+ code: "FUI2018",
278
+ ruleId: "config/empty-token-vocabulary",
279
+ category: "system",
280
+ defaultSeverity: "serious",
281
+ title: "Token sources resolved to 0 tokens",
282
+ lifecycle: "experimental",
283
+ fixAvailable: false,
284
+ evidenceRequired: true,
285
+ }),
276
286
  ruleCode({
277
287
  code: "FUI3001",
278
288
  ruleId: "a11y/required-accessible-name",
@@ -527,6 +537,26 @@ export const CODES = [
527
537
  fixAvailable: false,
528
538
  evidenceRequired: false,
529
539
  }),
540
+ code({
541
+ code: "FUI9010",
542
+ ruleId: "fragment/invalid-definition",
543
+ category: "system",
544
+ defaultSeverity: "critical",
545
+ title: "Fragment definition is not valid",
546
+ lifecycle: "experimental",
547
+ fixAvailable: false,
548
+ evidenceRequired: false,
549
+ }),
550
+ code({
551
+ code: "FUI9011",
552
+ ruleId: "fragment/source-drift",
553
+ category: "system",
554
+ defaultSeverity: "critical",
555
+ title: "Fragment definition drifted from its component source",
556
+ lifecycle: "experimental",
557
+ fixAvailable: false,
558
+ evidenceRequired: false,
559
+ }),
530
560
  ] as const satisfies readonly FuiCode[];
531
561
 
532
562
  export const byCode: ReadonlyMap<string, FuiCode> = new Map(