@usefragments/core 1.2.0 → 1.3.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 (43) hide show
  1. package/dist/{chunk-BQQTMGLA.js → chunk-57QDBEHQ.js} +79 -6
  2. package/dist/chunk-57QDBEHQ.js.map +1 -0
  3. package/dist/{chunk-DBVTSUMT.js → chunk-MLRDNSSA.js} +20 -6
  4. package/dist/chunk-MLRDNSSA.js.map +1 -0
  5. package/dist/codes/index.d.ts +1 -1
  6. package/dist/codes/index.js +2 -2
  7. package/dist/index-h_yWj15D.d.ts +6981 -0
  8. package/dist/index.d.ts +106 -92
  9. package/dist/index.js +235 -98
  10. package/dist/index.js.map +1 -1
  11. package/dist/registry.d.ts +36 -36
  12. package/dist/schemas/index.d.ts +3 -3377
  13. package/dist/schemas/index.js +1 -1
  14. package/package.json +1 -1
  15. package/src/agent-format.test.ts +75 -3
  16. package/src/agent-format.ts +28 -6
  17. package/src/evidence.ts +27 -0
  18. package/src/facts/builders.ts +2 -0
  19. package/src/facts/fact-index.ts +22 -2
  20. package/src/facts/facts.test.ts +1 -1
  21. package/src/facts/types.ts +2 -0
  22. package/src/index.ts +4 -0
  23. package/src/rules/__tests__/fix-emission-invariant.test.ts +174 -0
  24. package/src/rules/__tests__/tokens-require-dual-fallback.test.ts +90 -0
  25. package/src/rules/emit-gate.test.ts +16 -0
  26. package/src/rules/emit-gate.ts +6 -3
  27. package/src/rules/finding.ts +3 -0
  28. package/src/rules/rules.test.ts +2 -1
  29. package/src/rules/spacing-resolution.ts +5 -8
  30. package/src/rules/styles-no-raw-color.ts +32 -23
  31. package/src/rules/styles-no-raw-dimensions.ts +31 -12
  32. package/src/rules/styles-no-raw-spacing.ts +33 -11
  33. package/src/rules/styles-no-raw-typography.ts +37 -15
  34. package/src/rules/taxonomy.test.ts +13 -0
  35. package/src/rules/tokens-require-dual-fallback.ts +54 -17
  36. package/src/rules/utils.ts +51 -0
  37. package/src/schemas/index.ts +81 -3
  38. package/src/token-types.ts +6 -0
  39. package/src/tokens/__tests__/source-names.test.ts +42 -0
  40. package/src/tokens/design-token-parser.test.ts +24 -5
  41. package/src/tokens/design-token-parser.ts +40 -8
  42. package/dist/chunk-BQQTMGLA.js.map +0 -1
  43. package/dist/chunk-DBVTSUMT.js.map +0 -1
@@ -18,6 +18,57 @@ import type {
18
18
  UsagePropResolvedFact,
19
19
  UsageTextChildFact,
20
20
  } from "../facts/index.js";
21
+ import type { FindingFix } from "./types.js";
22
+
23
+ export interface FixProof {
24
+ symbols: readonly string[];
25
+ editKind: FindingFix["kind"];
26
+ valuePreserving: boolean;
27
+ }
28
+
29
+ export interface FixEmission<F extends FindingFix = FindingFix> {
30
+ fix: F;
31
+ downgradeReason?: string;
32
+ }
33
+
34
+ /**
35
+ * Gate token-substitution fixes on explicit proof. Callers attach any returned
36
+ * downgradeReason to the finding attributes so machine consumers can explain
37
+ * why a suggestion was not auto-applicable.
38
+ */
39
+ export function emitFix<F extends FindingFix>(
40
+ fix: F,
41
+ proof: FixProof,
42
+ ix: FactIndex
43
+ ): FixEmission<F> {
44
+ const reasons: string[] = [];
45
+ if (proof.editKind !== fix.kind) reasons.push("edit kind does not match proof");
46
+ if (!proof.valuePreserving) reasons.push("value-preservation proof missing");
47
+ if (proof.symbols.length === 0) reasons.push("token-symbol proof missing");
48
+
49
+ const missingSymbols = proof.symbols.filter((symbol) => !ix.tokens.symbolExists(symbol));
50
+ if (missingSymbols.length > 0) {
51
+ reasons.push(`absent token symbol: ${missingSymbols.join(", ")}`);
52
+ }
53
+
54
+ const inapplicableSymbols = proof.symbols.filter((symbol) => {
55
+ const definition = ix.tokens.definitionForSymbol(symbol);
56
+ return definition !== undefined && !isApplicableTokenReference(definition.referenceFormat);
57
+ });
58
+ if (inapplicableSymbols.length > 0) {
59
+ reasons.push(`token reference is not directly applicable: ${inapplicableSymbols.join(", ")}`);
60
+ }
61
+
62
+ return {
63
+ fix: { ...fix, deterministic: reasons.length === 0 },
64
+ ...(reasons.length > 0 ? { downgradeReason: reasons.join("; ") } : {}),
65
+ };
66
+ }
67
+
68
+ /** Extract authored token symbols from a replacement string, preserving order. */
69
+ export function tokenSymbolsInText(value: string): string[] {
70
+ return [...new Set(value.match(/\$[A-Za-z0-9_-]+|--[A-Za-z0-9_-]+/g) ?? [])];
71
+ }
21
72
 
22
73
  export interface LengthScale {
23
74
  unit: "px" | "rem";
@@ -8,6 +8,15 @@ import {
8
8
  severitySchema,
9
9
  } from "../severity.js";
10
10
  import type { LegacySeverityLevel, Severity } from "../severity.js";
11
+ import type { EvidenceGrade } from "../evidence.js";
12
+
13
+ const evidenceGradeSchema: z.ZodType<EvidenceGrade> = z.enum([
14
+ "none",
15
+ "runtime_advisory",
16
+ "provenance_bound",
17
+ "source_backed",
18
+ "receipt_backed",
19
+ ]);
11
20
 
12
21
  export { legacySeverityLevelSchema, severityLevelSchema, severitySchema };
13
22
  export type { LegacySeverityLevel, Severity, SeverityLevel } from "../severity.js";
@@ -108,6 +117,7 @@ export const findingSchema = z.object({
108
117
  fingerprint: z.string(),
109
118
  location: factLocationSchema,
110
119
  evidence: z.array(factEvidenceSchema).min(1),
120
+ evidenceGrade: evidenceGradeSchema.optional(),
111
121
  fix: findingFixSchema.optional(),
112
122
  attributes: z.record(z.unknown()).optional(),
113
123
  /**
@@ -224,6 +234,7 @@ export const agentFindingSchema = z.object({
224
234
  severity: severitySchema,
225
235
  level: severityLevelSchema,
226
236
  message: z.string(),
237
+ evidenceGrade: evidenceGradeSchema.optional(),
227
238
  evidence: z.array(factEvidenceSchema),
228
239
  plan: agentPlanSchema,
229
240
  });
@@ -238,10 +249,34 @@ export const agentIntegritySchema = z.object({
238
249
  reasons: z.array(z.string()),
239
250
  });
240
251
 
241
- export const agentFormatSchema = z.object({
252
+ const agentRunProvenanceSchema = z.object({
253
+ runId: z.string().regex(/^run_[a-f0-9]{12}$/),
254
+ fcid: z.string().min(1),
255
+ baselineId: z.string().min(1).optional(),
256
+ scope: z.object({
257
+ method: z.enum([
258
+ "three-dot",
259
+ "tree-diff",
260
+ "status",
261
+ "fallback-full",
262
+ "explicit",
263
+ "full",
264
+ ]),
265
+ gitOk: z.boolean(),
266
+ }),
267
+ engineVersion: z.string().min(1),
268
+ scopeHash: z.string().regex(/^[a-f0-9]{64}$/),
269
+ inputFilesHash: z.string().regex(/^[a-f0-9]{64}$/),
270
+ });
271
+
272
+ const agentRunVerdictSchema = z.object({
273
+ exitCode: z.union([z.literal(0), z.literal(1)]),
274
+ reasons: z.array(z.string()),
275
+ gatingFindingCount: z.number().int().nonnegative(),
276
+ });
277
+
278
+ const agentFormatBaseSchema = z.object({
242
279
  schemaVersion: z.literal(AGENT_FORMAT_SCHEMA_VERSION),
243
- passed: z.boolean(),
244
- score: z.number(),
245
280
  summary: z.string(),
246
281
  integrity: agentIntegritySchema,
247
282
  fix_first: z.array(agentFindingSchema),
@@ -258,7 +293,45 @@ export const agentFormatSchema = z.object({
258
293
  }),
259
294
  findings: z.array(findingSchema).optional(),
260
295
  suppressions: z.array(suppressionDirectiveSchema).optional(),
296
+ provenance: agentRunProvenanceSchema.optional(),
297
+ verdict: agentRunVerdictSchema.optional(),
261
298
  });
299
+
300
+ export const agentFormatSchema = z.union([
301
+ agentFormatBaseSchema.extend({
302
+ passed: z.boolean(),
303
+ score: z.number(),
304
+ status: z.never().optional(),
305
+ reasons: z.never().optional(),
306
+ integrity: agentIntegritySchema.extend({
307
+ rulesLoaded: z.number().int().positive(),
308
+ }),
309
+ }),
310
+ agentFormatBaseSchema.extend({
311
+ passed: z.literal(false),
312
+ score: z.never().optional(),
313
+ status: z.literal("indeterminate"),
314
+ reasons: z.tuple([z.literal("zero_rules_loaded")]),
315
+ integrity: agentIntegritySchema.extend({
316
+ rulesLoaded: z.literal(0),
317
+ }),
318
+ }),
319
+ // A finalized Run can explicitly allow inert governance. Preserve the
320
+ // indeterminate integrity truth while making `passed` match that Run's sole
321
+ // verdict; requiring Run pins prevents generic zero-rule envelopes from
322
+ // accidentally becoming green.
323
+ agentFormatBaseSchema.extend({
324
+ passed: z.literal(true),
325
+ score: z.never().optional(),
326
+ status: z.literal("indeterminate"),
327
+ reasons: z.tuple([z.literal("zero_rules_loaded")]),
328
+ integrity: agentIntegritySchema.extend({
329
+ rulesLoaded: z.literal(0),
330
+ }),
331
+ provenance: agentRunProvenanceSchema,
332
+ verdict: agentRunVerdictSchema.extend({ exitCode: z.literal(0) }),
333
+ }),
334
+ ]);
262
335
  export type AgentFormat = z.infer<typeof agentFormatSchema>;
263
336
 
264
337
  export const agentErrorEnvelopeSchema = z.object({
@@ -268,6 +341,10 @@ export const agentErrorEnvelopeSchema = z.object({
268
341
  code: z.string().min(1),
269
342
  message: z.string().min(1),
270
343
  }),
344
+ provenance: agentRunProvenanceSchema.optional(),
345
+ verdict: agentRunVerdictSchema.optional(),
346
+ cloudReport: z.enum(["reported", "failed", "skipped"]).optional(),
347
+ notices: z.array(z.string()).optional(),
271
348
  });
272
349
  export type AgentErrorEnvelope = z.infer<typeof agentErrorEnvelopeSchema>;
273
350
 
@@ -285,6 +362,7 @@ export function normalizeFinding(
285
362
  ): Finding {
286
363
  return {
287
364
  ...input,
365
+ evidenceGrade: input.evidenceGrade ?? "source_backed",
288
366
  level: input.level ?? severityLevel(input.severity),
289
367
  };
290
368
  }
@@ -59,6 +59,12 @@ export interface DesignToken {
59
59
  /** Source file where this token was defined */
60
60
  sourceFile: string;
61
61
 
62
+ /** Authored reference form, when the parser can prove it from the source. */
63
+ referenceFormat?: "css-var" | "scss-var" | "scss-map" | "dtcg";
64
+
65
+ /** Authored spellings preserved before normalization (for example `$x` and `--x`). */
66
+ sourceNames?: string[];
67
+
62
68
  /** Line number in source file */
63
69
  lineNumber?: number;
64
70
 
@@ -0,0 +1,42 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { fileURLToPath } from "node:url";
3
+
4
+ import { describe, expect, it } from "vitest";
5
+
6
+ import { FactIndex, makeTokenDefinitionFact } from "../../facts/index.js";
7
+ import { parseDesignTokenContent } from "../design-token-parser.js";
8
+
9
+ const tokenFile = fileURLToPath(
10
+ new URL("../../../../../libs/ui/src/tokens/_variables.scss", import.meta.url)
11
+ );
12
+
13
+ describe("SCSS source-name provenance", () => {
14
+ it("preserves both authored spellings through parser, facts, and rule-time lookup", () => {
15
+ const parsed = parseDesignTokenContent(readFileSync(tokenFile, "utf8"), {
16
+ filePath: tokenFile,
17
+ });
18
+ const token = parsed.tokens.find((candidate) => candidate.name === "--fui-space-2");
19
+
20
+ expect(token?.sourceNames).toEqual(expect.arrayContaining(["--fui-space-2", "$fui-space-2"]));
21
+
22
+ const ix = new FactIndex();
23
+ ix.addMany(
24
+ parsed.tokens.map((candidate) =>
25
+ makeTokenDefinitionFact({
26
+ name: candidate.name,
27
+ value: candidate.resolvedValue,
28
+ category: candidate.category === "spacing" ? "spacing" : "other",
29
+ referenceFormat: candidate.referenceFormat,
30
+ sourceNames: candidate.sourceNames,
31
+ })
32
+ )
33
+ );
34
+
35
+ expect(ix.tokens.symbolExists("$fui-space-2")).toBe(true);
36
+ expect(ix.tokens.symbolExists("--fui-space-2")).toBe(true);
37
+ expect(ix.tokens.symbolExists("$fui-space-99")).toBe(false);
38
+ expect(ix.tokens.definitionForSymbol("$fui-space-2")?.sourceNames).toEqual(
39
+ expect.arrayContaining(["--fui-space-2", "$fui-space-2"])
40
+ );
41
+ });
42
+ });
@@ -67,15 +67,34 @@ describe("parseDesignTokenContent — DTCG/JSON format dispatch (#10)", () => {
67
67
  describe("parseDesignTokenContent — SCSS $-variable format dispatch (#32)", () => {
68
68
  it("parses SCSS $vars, normalizing $name to --name", () => {
69
69
  const content = "$fui-color-accent: #fff;\n$fui-space-2: 8px;";
70
- const tokens = names(content, "tokens.scss");
71
- expect(tokens).toContain("--fui-color-accent");
72
- expect(tokens).toContain("--fui-space-2");
70
+ const tokens = parseDesignTokenContent(content, { filePath: "tokens.scss" }).tokens;
71
+ expect(tokens).toEqual(
72
+ expect.arrayContaining([
73
+ expect.objectContaining({
74
+ name: "--fui-color-accent",
75
+ referenceFormat: "scss-var",
76
+ }),
77
+ expect.objectContaining({ name: "--fui-space-2", referenceFormat: "scss-var" }),
78
+ ])
79
+ );
73
80
  });
74
81
 
75
82
  it("dedupes a file declaring BOTH --fui-x and $fui-x to one --fui-x", () => {
76
83
  const content = ":root {\n --fui-x: red;\n}\n$fui-x: red;";
77
- const tokens = names(content, "tokens.scss");
78
- expect(tokens.filter((n) => n === "--fui-x")).toHaveLength(1);
84
+ const tokens = parseDesignTokenContent(content, { filePath: "tokens.scss" }).tokens.filter(
85
+ (token) => token.name === "--fui-x"
86
+ );
87
+ expect(tokens).toHaveLength(1);
88
+ expect(tokens[0].referenceFormat).toBe("scss-var");
89
+ });
90
+
91
+ it("marks a CSS-only declaration in SCSS as css-var", () => {
92
+ const content = ":root {\n --fui-color-accent: red;\n}";
93
+ const token = parseDesignTokenContent(content, { filePath: "tokens.scss" }).tokens.find(
94
+ (candidate) => candidate.name === "--fui-color-accent"
95
+ );
96
+
97
+ expect(token?.referenceFormat).toBe("css-var");
79
98
  });
80
99
 
81
100
  it("surfaces a NON-SILENT warning for a comment-only SCSS file (#32)", () => {
@@ -193,21 +193,51 @@ function parsedOutputToDesignTokens(output: TokenParseOutput, filePath: string):
193
193
  * and `$fui-x` yields one `--fui-x`.
194
194
  */
195
195
  function scssOutputToDesignTokens(output: TokenParseOutput, filePath: string): DesignToken[] {
196
- const names = new Set<string>();
197
- const tokens: DesignToken[] = [];
196
+ const tokensByName = new Map<
197
+ string,
198
+ {
199
+ parsed: ParsedToken;
200
+ referenceFormat: "css-var" | "scss-var";
201
+ sourceNames: Set<string>;
202
+ }
203
+ >();
198
204
  for (const cat of Object.values(output.categories)) {
199
205
  for (const t of cat) {
200
- const cssName = t.name.startsWith("$") ? `--${t.name.slice(1)}` : t.name;
201
- if (!cssName.startsWith("--") || names.has(cssName)) continue;
202
- names.add(cssName);
203
- tokens.push(designTokenFromParsed(cssName, t, filePath));
206
+ const isScssVariable = t.name.startsWith("$");
207
+ const cssName = isScssVariable ? `--${t.name.slice(1)}` : t.name;
208
+ if (!cssName.startsWith("--")) continue;
209
+
210
+ const existing = tokensByName.get(cssName);
211
+ if (!existing) {
212
+ tokensByName.set(cssName, {
213
+ parsed: t,
214
+ referenceFormat: isScssVariable ? "scss-var" : "css-var",
215
+ sourceNames: new Set([t.name]),
216
+ });
217
+ } else {
218
+ existing.sourceNames.add(t.name);
219
+ if (isScssVariable) {
220
+ existing.parsed = t;
221
+ existing.referenceFormat = "scss-var";
222
+ }
223
+ }
204
224
  }
205
225
  }
206
- return tokens;
226
+ return [...tokensByName].map(([name, token]) =>
227
+ designTokenFromParsed(name, token.parsed, filePath, token.referenceFormat, [
228
+ ...token.sourceNames,
229
+ ])
230
+ );
207
231
  }
208
232
 
209
233
  /** Build a `DesignToken` from a sibling-parser `ParsedToken` under a CSS name. */
210
- function designTokenFromParsed(name: string, parsed: ParsedToken, filePath: string): DesignToken {
234
+ function designTokenFromParsed(
235
+ name: string,
236
+ parsed: ParsedToken,
237
+ filePath: string,
238
+ referenceFormat?: DesignToken["referenceFormat"],
239
+ sourceNames?: string[]
240
+ ): DesignToken {
211
241
  return {
212
242
  name,
213
243
  rawValue: parsed.value ?? "",
@@ -220,6 +250,8 @@ function designTokenFromParsed(name: string, parsed: ParsedToken, filePath: stri
220
250
  level: 1,
221
251
  referenceChain: [],
222
252
  sourceFile: filePath,
253
+ referenceFormat,
254
+ ...(sourceNames?.length ? { sourceNames } : {}),
223
255
  theme: "default",
224
256
  selector: ":root",
225
257
  description: parsed.description,
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/schemas/index.ts"],"sourcesContent":["import { z } from \"zod\";\n\nimport {\n legacySeverityLevelSchema,\n severityFromLevel,\n severityLevel,\n severityLevelSchema,\n severitySchema,\n} from \"../severity.js\";\nimport type { LegacySeverityLevel, Severity } from \"../severity.js\";\n\nexport { legacySeverityLevelSchema, severityLevelSchema, severitySchema };\nexport type { LegacySeverityLevel, Severity, SeverityLevel } from \"../severity.js\";\n\nexport const factLocationSchema = z.object({\n file: z.string(),\n line: z.number().int().nonnegative(),\n column: z.number().int().nonnegative(),\n endLine: z.number().int().nonnegative().optional(),\n endColumn: z.number().int().nonnegative().optional(),\n});\nexport type FactLocation = z.infer<typeof factLocationSchema>;\n\nexport const findingReplacePropValueFixSchema = z.object({\n kind: z.literal(\"replacePropValue\"),\n title: z.string(),\n prop: z.string(),\n value: z.unknown(),\n deterministic: z.boolean().optional(),\n});\n\nexport const findingReplaceStyleValueFixSchema = z.object({\n kind: z.literal(\"replaceStyleValue\"),\n title: z.string(),\n property: z.string(),\n value: z.string(),\n deterministic: z.boolean().optional(),\n});\n\nexport const findingReplaceImportFixSchema = z.object({\n kind: z.literal(\"replaceImport\"),\n title: z.string(),\n from: z.string(),\n to: z.string(),\n deterministic: z.boolean().optional(),\n});\n\nexport const findingReplaceComponentFixSchema = z.object({\n kind: z.literal(\"replaceComponent\"),\n title: z.string(),\n from: z.string(),\n to: z.string(),\n deterministic: z.boolean().optional(),\n});\n\nexport const findingReplaceClassTokenFixSchema = z.object({\n kind: z.literal(\"replaceClassToken\"),\n title: z.string(),\n from: z.string(),\n to: z.string().nullable(),\n utility: z.string(),\n deterministic: z.boolean().optional(),\n});\n\nexport const findingFixSchema = z.discriminatedUnion(\"kind\", [\n findingReplacePropValueFixSchema,\n findingReplaceStyleValueFixSchema,\n findingReplaceImportFixSchema,\n findingReplaceComponentFixSchema,\n findingReplaceClassTokenFixSchema,\n]);\nexport type FindingFix = z.infer<typeof findingFixSchema>;\nexport type FindingReplacePropValueFix = z.infer<typeof findingReplacePropValueFixSchema>;\nexport type FindingReplaceStyleValueFix = z.infer<typeof findingReplaceStyleValueFixSchema>;\nexport type FindingReplaceImportFix = z.infer<typeof findingReplaceImportFixSchema>;\nexport type FindingReplaceComponentFix = z.infer<typeof findingReplaceComponentFixSchema>;\nexport type FindingReplaceClassTokenFix = z.infer<typeof findingReplaceClassTokenFixSchema>;\n\nexport interface FactEvidence {\n factId: string;\n fact: {\n kind: string;\n location?: FactLocation;\n };\n}\n\nexport const factEvidenceSchema: z.ZodType<FactEvidence> = z.object({\n factId: z.string(),\n fact: z\n .object({\n kind: z.string(),\n location: factLocationSchema.optional(),\n })\n .passthrough(),\n});\n\nexport const findingSchema = z.object({\n ruleId: z.string(),\n ruleVersion: z.string(),\n severity: severitySchema,\n level: severityLevelSchema,\n code: z\n .string()\n .regex(/^FUI\\d{4}$/)\n .optional(),\n helpUrl: z.string().url().optional(),\n message: z.string(),\n fingerprint: z.string(),\n location: factLocationSchema,\n evidence: z.array(factEvidenceSchema).min(1),\n fix: findingFixSchema.optional(),\n attributes: z.record(z.unknown()).optional(),\n /**\n * Product area this finding's file resolved to (topology layer). Optional —\n * absent when the repo has no `topology` config. See `topology/resolve-area`.\n */\n area: z\n .object({\n areaId: z.string(),\n areaName: z.string(),\n criticality: z.enum([\"low\", \"medium\", \"high\", \"revenue\", \"regulated\"]),\n owners: z.array(z.string()),\n matchedGlob: z.string(),\n })\n .optional(),\n});\nexport type Finding = z.infer<typeof findingSchema>;\n\nexport const violationSchema = z.object({\n nodeId: z.string(),\n nodeType: z.string(),\n rule: z.string(),\n severity: severitySchema,\n level: severityLevelSchema.optional(),\n code: z\n .string()\n .regex(/^FUI\\d{4}$/)\n .optional(),\n helpUrl: z.string().url().optional(),\n message: z.string(),\n path: z.string().optional(),\n suggestion: z.string().optional(),\n prop: z.string().optional(),\n filePath: z.string().optional(),\n line: z.number().int().nonnegative().optional(),\n column: z.number().int().nonnegative().optional(),\n rawValue: z.string().optional(),\n extra: z.record(z.unknown()).optional(),\n});\nexport type Violation = z.infer<typeof violationSchema>;\n\nexport const fixSchema = z.object({\n nodeId: z.string(),\n prop: z.string().optional(),\n action: z.enum([\"remove\", \"replace\", \"add\"]),\n value: z.unknown().optional(),\n description: z.string(),\n});\nexport type Fix = z.infer<typeof fixSchema>;\n\nexport const validatorResultSchema = z.object({\n validator: z.string(),\n severity: severitySchema,\n passed: z.boolean(),\n violations: z.array(violationSchema),\n findings: z.array(findingSchema).optional(),\n suggestions: z.array(fixSchema).optional(),\n});\nexport type ValidatorResult = z.infer<typeof validatorResultSchema>;\n\nexport const governanceVerdictMetadataSchema = z.object({\n runner: z.string(),\n policyVersion: z.string().optional(),\n duration: z.number().nonnegative(),\n nodeCount: z.number().int().nonnegative(),\n componentTypes: z.array(z.string()),\n});\nexport type GovernanceVerdictMetadata = z.infer<typeof governanceVerdictMetadataSchema>;\n\nexport const governanceVerdictSchema = z.object({\n verdict: z.enum([\"pass\", \"warn\", \"fail\"]).optional(),\n passed: z.boolean(),\n score: z.number(),\n results: z.array(validatorResultSchema),\n metadata: governanceVerdictMetadataSchema,\n});\nexport type GovernanceVerdict = z.infer<typeof governanceVerdictSchema>;\n\nexport const suppressionDirectiveSchema = z.object({\n ruleId: z.string().optional(),\n reason: z.string().min(1),\n expiresAt: z.string().datetime().optional(),\n expiresOn: z\n .string()\n .regex(/^\\d{4}-\\d{2}-\\d{2}$/)\n .optional(),\n scope: z.enum([\"line\", \"block\", \"file\"]).default(\"line\"),\n code: z\n .string()\n .regex(/^FUI\\d{4}$/)\n .optional(),\n});\nexport type SuppressionDirective = z.infer<typeof suppressionDirectiveSchema>;\n\nexport const agentPlanSchema = z.object({\n tool: z.enum([\n \"design_system/list_primitives\",\n \"design_system/conform\",\n \"design_system/prove_compliant\",\n ]),\n args: z.record(z.unknown()),\n confidence: z.number().min(0).max(1),\n});\n\nexport const agentFindingSchema = z.object({\n code: z\n .string()\n .regex(/^FUI\\d{4}$/)\n .optional(),\n ruleId: z.string(),\n filePath: z.string(),\n line: z.number().int().nonnegative(),\n col: z.number().int().nonnegative(),\n severity: severitySchema,\n level: severityLevelSchema,\n message: z.string(),\n evidence: z.array(factEvidenceSchema),\n plan: agentPlanSchema,\n});\n\nexport const AGENT_FORMAT_SCHEMA_VERSION = \"typestyle.agent.v2\" as const;\n\nexport const agentIntegritySchema = z.object({\n rulesLoaded: z.number().int().nonnegative(),\n status: z.enum([\"healthy\", \"degraded\", \"inert\"]),\n healthy: z.boolean(),\n inert: z.boolean(),\n reasons: z.array(z.string()),\n});\n\nexport const agentFormatSchema = z.object({\n schemaVersion: z.literal(AGENT_FORMAT_SCHEMA_VERSION),\n passed: z.boolean(),\n score: z.number(),\n summary: z.string(),\n integrity: agentIntegritySchema,\n fix_first: z.array(agentFindingSchema),\n remaining: z.array(agentFindingSchema),\n suppression_template: z.object({\n directive: z.string(),\n requiredFields: z.array(z.string()),\n example: z.string(),\n }),\n budget: z.object({\n iteration: z.number().int().nonnegative(),\n maxIterations: z.number().int().positive(),\n scoreDelta: z.number(),\n }),\n findings: z.array(findingSchema).optional(),\n suppressions: z.array(suppressionDirectiveSchema).optional(),\n});\nexport type AgentFormat = z.infer<typeof agentFormatSchema>;\n\nexport const agentErrorEnvelopeSchema = z.object({\n schemaVersion: z.literal(AGENT_FORMAT_SCHEMA_VERSION),\n passed: z.literal(false),\n error: z.object({\n code: z.string().min(1),\n message: z.string().min(1),\n }),\n});\nexport type AgentErrorEnvelope = z.infer<typeof agentErrorEnvelopeSchema>;\n\nexport const agentOutputSchema = z.union([agentFormatSchema, agentErrorEnvelopeSchema]);\nexport type AgentOutput = z.infer<typeof agentOutputSchema>;\n\nexport function normalizeSeverity(severity: Severity | LegacySeverityLevel): Severity {\n return severitySchema.safeParse(severity).success\n ? (severity as Severity)\n : severityFromLevel(legacySeverityLevelSchema.parse(severity));\n}\n\nexport function normalizeFinding(\n input: Omit<Finding, \"level\"> & { level?: Finding[\"level\"] }\n): Finding {\n return {\n ...input,\n level: input.level ?? severityLevel(input.severity),\n };\n}\n\nexport function normalizeViolation(\n input: Omit<Violation, \"level\"> & { level?: Violation[\"level\"] }\n): Violation {\n return {\n ...input,\n level: input.level ?? severityLevel(input.severity),\n };\n}\n"],"mappings":"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","names":[]}