@usefragments/core 1.5.2 → 1.6.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 (41) hide show
  1. package/dist/{chunk-BAHCOAVG.js → chunk-WVFNDPM4.js} +423 -189
  2. package/dist/chunk-WVFNDPM4.js.map +1 -0
  3. package/dist/codes/index.d.ts +1 -1
  4. package/dist/codes/index.js +1 -1
  5. package/dist/compiled-types/index.d.ts +1 -1
  6. package/dist/generate/index.d.ts +1 -1
  7. package/dist/{governance-pKrfh517.d.ts → governance-DxFipN5V.d.ts} +609 -20
  8. package/dist/index.d.ts +638 -43
  9. package/dist/index.js +304 -37
  10. package/dist/index.js.map +1 -1
  11. package/dist/react-types.d.ts +1 -1
  12. package/dist/test-utils.d.ts +1 -1
  13. package/package.json +1 -1
  14. package/src/__tests__/policy-exclude.test.ts +180 -0
  15. package/src/canonical-bridge.ts +69 -1
  16. package/src/canonical-direction.test.ts +118 -0
  17. package/src/canonical-direction.ts +43 -2
  18. package/src/codes/__tests__/codes.test.ts +14 -1
  19. package/src/codes/codes.ts +40 -0
  20. package/src/facts/builders.ts +35 -0
  21. package/src/facts/compile.ts +135 -21
  22. package/src/facts/fact-index.ts +15 -2
  23. package/src/facts/facts.test.ts +6 -2
  24. package/src/facts/index.ts +9 -6
  25. package/src/facts/types.ts +45 -9
  26. package/src/governance-integrity.test.ts +174 -3
  27. package/src/governance-integrity.ts +305 -5
  28. package/src/governance.ts +87 -1
  29. package/src/index.ts +38 -1
  30. package/src/policy-exclude.ts +113 -0
  31. package/src/rules/families.test.ts +69 -0
  32. package/src/rules/families.ts +52 -0
  33. package/src/rules/index.ts +6 -0
  34. package/src/rules/jsx-preferred-import-path.ts +29 -11
  35. package/src/rules/rules.test.ts +125 -1
  36. package/src/rules/styles-no-raw-color.ts +13 -4
  37. package/src/rules/styles-no-raw-dimensions.ts +13 -4
  38. package/src/rules/styles-no-raw-spacing.ts +12 -4
  39. package/src/rules/styles-no-raw-typography.ts +13 -4
  40. package/src/rules/utils.ts +39 -0
  41. package/dist/chunk-BAHCOAVG.js.map +0 -1
@@ -495,6 +495,46 @@ var CODES = [
495
495
  lifecycle: "experimental",
496
496
  fixAvailable: false,
497
497
  evidenceRequired: false
498
+ }),
499
+ code({
500
+ code: "FUI9006",
501
+ ruleId: "config/unmatched-exclude",
502
+ category: "system",
503
+ defaultSeverity: "moderate",
504
+ title: "Rule exclude matched no scanned file",
505
+ lifecycle: "experimental",
506
+ fixAvailable: false,
507
+ evidenceRequired: false
508
+ }),
509
+ code({
510
+ code: "FUI9007",
511
+ ruleId: "config/colliding-record",
512
+ category: "system",
513
+ defaultSeverity: "moderate",
514
+ title: "Governance record was dropped as a duplicate",
515
+ lifecycle: "experimental",
516
+ fixAvailable: false,
517
+ evidenceRequired: false
518
+ }),
519
+ code({
520
+ code: "FUI9008",
521
+ ruleId: "config/overridden-record-severity",
522
+ category: "system",
523
+ defaultSeverity: "moderate",
524
+ title: "Rule override outranks a record's authored severity",
525
+ lifecycle: "experimental",
526
+ fixAvailable: false,
527
+ evidenceRequired: false
528
+ }),
529
+ code({
530
+ code: "FUI9009",
531
+ ruleId: "contract/unreadable-token-source",
532
+ category: "system",
533
+ defaultSeverity: "critical",
534
+ title: "Contract token source cannot be read",
535
+ lifecycle: "experimental",
536
+ fixAvailable: false,
537
+ evidenceRequired: false
498
538
  })
499
539
  ];
500
540
  var byCode = new Map(
@@ -575,6 +615,9 @@ function projectFactIdentityV1(kind, identity) {
575
615
  }
576
616
 
577
617
  // src/facts/builders.ts
618
+ function policyExcludeField(exclude) {
619
+ return exclude?.length ? { exclude: exclude.map((entry) => ({ ...entry })) } : {};
620
+ }
578
621
  function makeComponentMetadataFact(input) {
579
622
  return {
580
623
  id: factId("component", { componentId: input.componentId }),
@@ -770,7 +813,8 @@ function makeStyleRawColorForbiddenFact(input) {
770
813
  kind: "style_raw_color_forbidden",
771
814
  except: [...input.except],
772
815
  prefer: input.prefer,
773
- severity: input.severity
816
+ severity: input.severity,
817
+ ...policyExcludeField(input.exclude)
774
818
  };
775
819
  }
776
820
  function makeStyleRawDimensionForbiddenFact(input) {
@@ -779,7 +823,8 @@ function makeStyleRawDimensionForbiddenFact(input) {
779
823
  kind: "style_raw_dimension_forbidden",
780
824
  appliesTo: [...input.appliesTo],
781
825
  prefer: input.prefer,
782
- severity: input.severity
826
+ severity: input.severity,
827
+ ...policyExcludeField(input.exclude)
783
828
  };
784
829
  }
785
830
  function makeStylePropertyScaleFact(input) {
@@ -788,7 +833,8 @@ function makeStylePropertyScaleFact(input) {
788
833
  kind: "style_property_scale",
789
834
  property: input.property,
790
835
  scale: input.scale,
791
- severity: input.severity
836
+ severity: input.severity,
837
+ ...policyExcludeField(input.exclude)
792
838
  };
793
839
  }
794
840
  function makeStyleFontSizeScaleFact(input) {
@@ -796,14 +842,16 @@ function makeStyleFontSizeScaleFact(input) {
796
842
  id: factId("style_font_size_scale", {}),
797
843
  kind: "style_font_size_scale",
798
844
  scale: input.scale,
799
- severity: input.severity
845
+ severity: input.severity,
846
+ ...policyExcludeField(input.exclude)
800
847
  };
801
848
  }
802
849
  function makeStyleCssVarsMustBeDefinedFact(input) {
803
850
  return {
804
851
  id: factId("style_css_vars_must_be_defined", {}),
805
852
  kind: "style_css_vars_must_be_defined",
806
- severity: input.severity
853
+ severity: input.severity,
854
+ ...policyExcludeField(input.exclude)
807
855
  };
808
856
  }
809
857
  function makeContractTokenFact(input) {
@@ -818,7 +866,8 @@ function makeJsxUnknownPropsForbiddenFact(input) {
818
866
  return {
819
867
  id: factId("jsx_unknown_props_forbidden", {}),
820
868
  kind: "jsx_unknown_props_forbidden",
821
- severity: input.severity
869
+ severity: input.severity,
870
+ ...policyExcludeField(input.exclude)
822
871
  };
823
872
  }
824
873
  function makeJsxInlineStyleForbiddenRawFact(input) {
@@ -826,7 +875,8 @@ function makeJsxInlineStyleForbiddenRawFact(input) {
826
875
  id: factId("jsx_inline_style_forbidden_raw", { property: input.property }),
827
876
  kind: "jsx_inline_style_forbidden_raw",
828
877
  property: input.property,
829
- severity: input.severity
878
+ severity: input.severity,
879
+ ...policyExcludeField(input.exclude)
830
880
  };
831
881
  }
832
882
  function makeJsxImportPathPreferredFact(input) {
@@ -848,7 +898,8 @@ function makeJsxImportPathPreferredFact(input) {
848
898
  ...input.bridge,
849
899
  implementationFiles: [...input.bridge.implementationFiles]
850
900
  }
851
- } : {}
901
+ } : {},
902
+ ...policyExcludeField(input.exclude)
852
903
  };
853
904
  }
854
905
  function makeJsxComponentPreferredFact(input) {
@@ -861,7 +912,8 @@ function makeJsxComponentPreferredFact(input) {
861
912
  from: input.from,
862
913
  to: input.to,
863
914
  because: input.because,
864
- severity: input.severity
915
+ severity: input.severity,
916
+ ...policyExcludeField(input.exclude)
865
917
  };
866
918
  }
867
919
  function makeTokenDefinitionFact(input) {
@@ -982,7 +1034,8 @@ function makeUsageInlineStyleFact(input) {
982
1034
  nodeId: input.nodeId,
983
1035
  property: input.property,
984
1036
  valueKind: input.valueKind,
985
- value: input.value
1037
+ value: input.value,
1038
+ ...input.valueFrom ? { valueFrom: input.valueFrom } : {}
986
1039
  };
987
1040
  }
988
1041
  function makeUsageTextChildFact(input) {
@@ -1094,7 +1147,8 @@ function makeStyleDeclarationFact(input) {
1094
1147
  property: input.property,
1095
1148
  value: input.value,
1096
1149
  location: input.location,
1097
- ...input.declaredTokenSource ? { declaredTokenSource: true } : {}
1150
+ ...input.declaredTokenSource ? { declaredTokenSource: true } : {},
1151
+ ...input.valueFrom ? { valueFrom: input.valueFrom } : {}
1098
1152
  };
1099
1153
  }
1100
1154
  function makeStyleUnsupportedFact(input) {
@@ -1204,7 +1258,8 @@ var FactIndex = class {
1204
1258
  if (existing) {
1205
1259
  if (canonicalJson(logicalFactForComparison(existing)) !== canonicalJson(logicalFactForComparison(fact))) {
1206
1260
  this.options.onConflict?.(
1207
- `FactIndex: conflicting facts for id ${fact.id} \u2014 keeping ${describeFactForConflict(existing)}, skipping ${describeFactForConflict(fact)}`
1261
+ `FactIndex: conflicting facts for id ${fact.id} \u2014 keeping ${describeFactForConflict(existing)}, skipping ${describeFactForConflict(fact)}`,
1262
+ { kept: existing, skipped: fact }
1208
1263
  );
1209
1264
  }
1210
1265
  return;
@@ -1424,81 +1479,143 @@ function describeFactForConflict(fact) {
1424
1479
  }
1425
1480
 
1426
1481
  // src/governance.ts
1482
+ import { z as z2 } from "zod";
1483
+
1484
+ // src/policy-exclude.ts
1427
1485
  import { z } from "zod";
1428
- var governanceSeveritySchema = z.enum(["error", "warn", "info"]);
1429
- var scaleGovernanceRecordSchema = z.object({
1430
- kind: z.literal("scale").default("scale"),
1431
- name: z.string().min(1).optional(),
1432
- unit: z.enum(["px", "rem"]),
1433
- values: z.array(z.number()),
1434
- rootFontSizePx: z.number().positive().optional(),
1435
- emBasePx: z.number().positive().optional()
1486
+ var policyExcludeSchema = z.array(
1487
+ z.union([
1488
+ z.string().min(1),
1489
+ z.object({
1490
+ glob: z.string().min(1),
1491
+ reason: z.string().min(1).optional()
1492
+ })
1493
+ ])
1494
+ );
1495
+ function normalizePolicyExcludes(value) {
1496
+ if (!Array.isArray(value)) return void 0;
1497
+ const out = [];
1498
+ for (const entry of value) {
1499
+ if (typeof entry === "string") {
1500
+ if (entry.length > 0) out.push({ glob: entry });
1501
+ continue;
1502
+ }
1503
+ if (!entry || typeof entry !== "object") continue;
1504
+ const record = entry;
1505
+ if (typeof record.glob !== "string" || record.glob.length === 0) continue;
1506
+ out.push({
1507
+ glob: record.glob,
1508
+ ...typeof record.reason === "string" && record.reason.length > 0 ? { reason: record.reason } : {}
1509
+ });
1510
+ }
1511
+ return out.length > 0 ? out : void 0;
1512
+ }
1513
+ function normalizeExcludePath(path) {
1514
+ return path.replaceAll("\\", "/").replace(/^\.\//, "");
1515
+ }
1516
+ function excludeGlobToRegExp(glob) {
1517
+ const source = normalizeExcludePath(glob).split("**").map(
1518
+ (part) => part.split("*").map((segment) => segment.replace(/[|\\{}()[\]^$+?.]/g, "\\$&")).join("[^/]*")
1519
+ ).join(".*");
1520
+ return new RegExp(`^${source}$`);
1521
+ }
1522
+ function policyExcludeMatchesPath(exclude, filePath) {
1523
+ return excludeGlobToRegExp(exclude.glob).test(normalizeExcludePath(filePath));
1524
+ }
1525
+ function matchPolicyExclude(excludes, filePath) {
1526
+ if (!excludes?.length) return void 0;
1527
+ const normalized = normalizeExcludePath(filePath);
1528
+ return excludes.find((exclude) => excludeGlobToRegExp(exclude.glob).test(normalized));
1529
+ }
1530
+ function describePolicyExclude(scope, exclude) {
1531
+ return `${scope} exclude matched ${exclude.glob}${exclude.reason ? ` \u2014 ${exclude.reason}` : ""}`;
1532
+ }
1533
+
1534
+ // src/governance.ts
1535
+ var governanceSeveritySchema = z2.enum(["error", "warn", "info"]);
1536
+ var recordExcludeSchema = policyExcludeSchema.optional();
1537
+ var scaleGovernanceRecordSchema = z2.object({
1538
+ kind: z2.literal("scale").default("scale"),
1539
+ name: z2.string().min(1).optional(),
1540
+ unit: z2.enum(["px", "rem"]),
1541
+ values: z2.array(z2.number()),
1542
+ rootFontSizePx: z2.number().positive().optional(),
1543
+ emBasePx: z2.number().positive().optional()
1436
1544
  });
1437
- var styleRawColorsForbidRecordSchema = z.object({
1438
- kind: z.literal("style.rawColors.forbid"),
1439
- except: z.array(z.string()),
1440
- prefer: z.enum(["token", "css-variable"]),
1441
- severity: governanceSeveritySchema
1545
+ var styleRawColorsForbidRecordSchema = z2.object({
1546
+ kind: z2.literal("style.rawColors.forbid"),
1547
+ except: z2.array(z2.string()),
1548
+ prefer: z2.enum(["token", "css-variable"]),
1549
+ severity: governanceSeveritySchema,
1550
+ exclude: recordExcludeSchema
1442
1551
  });
1443
- var styleRawDimensionsForbidRecordSchema = z.object({
1444
- kind: z.literal("style.rawDimensions.forbid"),
1445
- appliesTo: z.array(z.string().min(1)),
1446
- prefer: z.enum(["token", "css-variable"]),
1447
- severity: governanceSeveritySchema
1552
+ var styleRawDimensionsForbidRecordSchema = z2.object({
1553
+ kind: z2.literal("style.rawDimensions.forbid"),
1554
+ appliesTo: z2.array(z2.string().min(1)),
1555
+ prefer: z2.enum(["token", "css-variable"]),
1556
+ severity: governanceSeveritySchema,
1557
+ exclude: recordExcludeSchema
1448
1558
  });
1449
- var styleRawSpacingMustMatchScaleRecordSchema = z.object({
1450
- kind: z.literal("style.rawSpacing.mustMatchScale"),
1451
- scale: z.string().min(1),
1452
- appliesTo: z.array(z.string().min(1)),
1453
- severity: governanceSeveritySchema
1559
+ var styleRawSpacingMustMatchScaleRecordSchema = z2.object({
1560
+ kind: z2.literal("style.rawSpacing.mustMatchScale"),
1561
+ scale: z2.string().min(1),
1562
+ appliesTo: z2.array(z2.string().min(1)),
1563
+ severity: governanceSeveritySchema,
1564
+ exclude: recordExcludeSchema
1454
1565
  });
1455
- var styleFontSizeMustMatchScaleRecordSchema = z.object({
1456
- kind: z.literal("style.fontSize.mustMatchScale"),
1457
- scale: z.string().min(1),
1458
- severity: governanceSeveritySchema
1566
+ var styleFontSizeMustMatchScaleRecordSchema = z2.object({
1567
+ kind: z2.literal("style.fontSize.mustMatchScale"),
1568
+ scale: z2.string().min(1),
1569
+ severity: governanceSeveritySchema,
1570
+ exclude: recordExcludeSchema
1459
1571
  });
1460
- var styleCssVarsMustBeDefinedRecordSchema = z.object({
1461
- kind: z.literal("style.cssVars.mustBeDefined"),
1462
- severity: governanceSeveritySchema
1572
+ var styleCssVarsMustBeDefinedRecordSchema = z2.object({
1573
+ kind: z2.literal("style.cssVars.mustBeDefined"),
1574
+ severity: governanceSeveritySchema,
1575
+ exclude: recordExcludeSchema
1463
1576
  });
1464
- var globalStyleGovernanceRecordSchema = z.discriminatedUnion("kind", [
1577
+ var globalStyleGovernanceRecordSchema = z2.discriminatedUnion("kind", [
1465
1578
  styleRawColorsForbidRecordSchema,
1466
1579
  styleRawDimensionsForbidRecordSchema,
1467
1580
  styleRawSpacingMustMatchScaleRecordSchema,
1468
1581
  styleFontSizeMustMatchScaleRecordSchema,
1469
1582
  styleCssVarsMustBeDefinedRecordSchema
1470
1583
  ]);
1471
- var jsxUnknownPropsForbidRecordSchema = z.object({
1472
- kind: z.literal("jsx.unknownProps.forbid"),
1473
- severity: governanceSeveritySchema
1584
+ var jsxUnknownPropsForbidRecordSchema = z2.object({
1585
+ kind: z2.literal("jsx.unknownProps.forbid"),
1586
+ severity: governanceSeveritySchema,
1587
+ exclude: recordExcludeSchema
1474
1588
  });
1475
- var jsxInlineStyleForbidRawRecordSchema = z.object({
1476
- kind: z.literal("jsx.inlineStyle.forbidRaw"),
1477
- properties: z.array(z.string().min(1)),
1478
- severity: governanceSeveritySchema
1589
+ var jsxInlineStyleForbidRawRecordSchema = z2.object({
1590
+ kind: z2.literal("jsx.inlineStyle.forbidRaw"),
1591
+ properties: z2.array(z2.string().min(1)),
1592
+ severity: governanceSeveritySchema,
1593
+ exclude: recordExcludeSchema
1479
1594
  });
1480
- var jsxImportPathPreferRecordSchema = z.object({
1481
- kind: z.literal("jsx.importPath.prefer"),
1482
- from: z.string().min(1),
1483
- to: z.string().min(1),
1484
- imported: z.string().min(1).optional(),
1485
- because: z.string().optional(),
1486
- severity: governanceSeveritySchema
1595
+ var jsxImportPathPreferRecordSchema = z2.object({
1596
+ kind: z2.literal("jsx.importPath.prefer"),
1597
+ from: z2.string().min(1),
1598
+ to: z2.string().min(1),
1599
+ imported: z2.string().min(1).optional(),
1600
+ because: z2.string().optional(),
1601
+ severity: governanceSeveritySchema,
1602
+ exclude: recordExcludeSchema
1487
1603
  });
1488
- var jsxComponentPreferRecordSchema = z.object({
1489
- kind: z.literal("jsx.component.prefer"),
1490
- from: z.string().min(1),
1491
- to: z.string().min(1),
1492
- because: z.string().optional(),
1493
- severity: governanceSeveritySchema
1604
+ var jsxComponentPreferRecordSchema = z2.object({
1605
+ kind: z2.literal("jsx.component.prefer"),
1606
+ from: z2.string().min(1),
1607
+ to: z2.string().min(1),
1608
+ because: z2.string().optional(),
1609
+ severity: governanceSeveritySchema,
1610
+ exclude: recordExcludeSchema
1494
1611
  });
1495
- var globalJsxGovernanceRecordSchema = z.discriminatedUnion("kind", [
1612
+ var globalJsxGovernanceRecordSchema = z2.discriminatedUnion("kind", [
1496
1613
  jsxUnknownPropsForbidRecordSchema,
1497
1614
  jsxInlineStyleForbidRawRecordSchema,
1498
1615
  jsxImportPathPreferRecordSchema,
1499
1616
  jsxComponentPreferRecordSchema
1500
1617
  ]);
1501
- var globalGovernanceRecordSchema = z.discriminatedUnion("kind", [
1618
+ var globalGovernanceRecordSchema = z2.discriminatedUnion("kind", [
1502
1619
  scaleGovernanceRecordSchema,
1503
1620
  styleRawColorsForbidRecordSchema,
1504
1621
  styleRawDimensionsForbidRecordSchema,
@@ -1510,99 +1627,99 @@ var globalGovernanceRecordSchema = z.discriminatedUnion("kind", [
1510
1627
  jsxImportPathPreferRecordSchema,
1511
1628
  jsxComponentPreferRecordSchema
1512
1629
  ]);
1513
- var componentCapabilityRecordSchema = z.object({
1514
- kind: z.literal("capability"),
1515
- capability: z.string().min(1)
1630
+ var componentCapabilityRecordSchema = z2.object({
1631
+ kind: z2.literal("capability"),
1632
+ capability: z2.string().min(1)
1516
1633
  });
1517
- var propValueAvoidRecordSchema = z.object({
1518
- kind: z.literal("prop.value.avoid"),
1519
- prop: z.string().min(1),
1520
- value: z.unknown(),
1521
- because: z.string(),
1522
- suggest: z.string().optional(),
1634
+ var propValueAvoidRecordSchema = z2.object({
1635
+ kind: z2.literal("prop.value.avoid"),
1636
+ prop: z2.string().min(1),
1637
+ value: z2.unknown(),
1638
+ because: z2.string(),
1639
+ suggest: z2.string().optional(),
1523
1640
  severity: governanceSeveritySchema
1524
1641
  });
1525
- var propValueForbidRecordSchema = z.object({
1526
- kind: z.literal("prop.value.forbid"),
1527
- prop: z.string().min(1),
1528
- value: z.unknown(),
1529
- when: z.object({ path: z.string().min(1).optional() }).optional(),
1530
- because: z.string(),
1531
- fix: z.object({ replaceWith: z.unknown() }).optional(),
1642
+ var propValueForbidRecordSchema = z2.object({
1643
+ kind: z2.literal("prop.value.forbid"),
1644
+ prop: z2.string().min(1),
1645
+ value: z2.unknown(),
1646
+ when: z2.object({ path: z2.string().min(1).optional() }).optional(),
1647
+ because: z2.string(),
1648
+ fix: z2.object({ replaceWith: z2.unknown() }).optional(),
1532
1649
  severity: governanceSeveritySchema
1533
1650
  });
1534
- var a11yRequireNameRecordSchema = z.object({
1535
- kind: z.literal("a11y.requireName"),
1536
- because: z.string(),
1651
+ var a11yRequireNameRecordSchema = z2.object({
1652
+ kind: z2.literal("a11y.requireName"),
1653
+ because: z2.string(),
1537
1654
  severity: governanceSeveritySchema
1538
1655
  });
1539
- var componentGovernanceRecordSchema = z.discriminatedUnion("kind", [
1656
+ var componentGovernanceRecordSchema = z2.discriminatedUnion("kind", [
1540
1657
  componentCapabilityRecordSchema,
1541
1658
  propValueAvoidRecordSchema,
1542
1659
  propValueForbidRecordSchema,
1543
1660
  a11yRequireNameRecordSchema
1544
1661
  ]);
1545
- var componentGovernanceRecordsSchema = z.array(componentGovernanceRecordSchema);
1546
- var componentPolicyMatchSchema = z.object({
1547
- componentKey: z.string().min(1).optional(),
1548
- componentId: z.string().min(1).optional(),
1549
- publicRef: z.string().min(1).optional(),
1550
- importPath: z.string().min(1).optional(),
1551
- sourcePath: z.string().min(1).optional(),
1552
- path: z.string().min(1).optional(),
1553
- exportName: z.string().min(1).optional(),
1554
- export: z.string().min(1).optional(),
1555
- name: z.string().min(1).optional(),
1556
- scope: z.enum(["one", "all"]).optional()
1662
+ var componentGovernanceRecordsSchema = z2.array(componentGovernanceRecordSchema);
1663
+ var componentPolicyMatchSchema = z2.object({
1664
+ componentKey: z2.string().min(1).optional(),
1665
+ componentId: z2.string().min(1).optional(),
1666
+ publicRef: z2.string().min(1).optional(),
1667
+ importPath: z2.string().min(1).optional(),
1668
+ sourcePath: z2.string().min(1).optional(),
1669
+ path: z2.string().min(1).optional(),
1670
+ exportName: z2.string().min(1).optional(),
1671
+ export: z2.string().min(1).optional(),
1672
+ name: z2.string().min(1).optional(),
1673
+ scope: z2.enum(["one", "all"]).optional()
1557
1674
  }).strict();
1558
- var componentPolicyRecordSchema = z.object({
1675
+ var componentPolicyRecordSchema = z2.object({
1559
1676
  rules: componentGovernanceRecordsSchema,
1560
- status: z.enum(["active", "draft", "disabled"]).optional()
1677
+ status: z2.enum(["active", "draft", "disabled"]).optional()
1561
1678
  }).strict();
1562
- var componentPolicyOverrideSchema = z.object({
1679
+ var componentPolicyOverrideSchema = z2.object({
1563
1680
  match: componentPolicyMatchSchema,
1564
1681
  rules: componentGovernanceRecordsSchema,
1565
- status: z.enum(["active", "draft", "disabled"]).optional()
1682
+ status: z2.enum(["active", "draft", "disabled"]).optional()
1566
1683
  }).strict();
1567
- var canonicalSourcePathSchema = z.string().min(1).superRefine((value, ctx) => {
1684
+ var canonicalSourcePathSchema = z2.string().min(1).superRefine((value, ctx) => {
1568
1685
  const error = portableRepoPathError(value);
1569
1686
  if (error) {
1570
- ctx.addIssue({ code: z.ZodIssueCode.custom, message: error });
1687
+ ctx.addIssue({ code: z2.ZodIssueCode.custom, message: error });
1571
1688
  }
1572
1689
  });
1573
- var canonicalSourceRegistryHashSchema = z.string().regex(/^[0-9a-f]{64}$/);
1574
- var canonicalBridgeModuleSpecifierSchema = z.string().min(1).superRefine((value, ctx) => {
1690
+ var canonicalSourceRegistryHashSchema = z2.string().regex(/^[0-9a-f]{64}$/);
1691
+ var canonicalBridgeModuleSpecifierSchema = z2.string().min(1).superRefine((value, ctx) => {
1575
1692
  const normalized = value.replace(/\\/gu, "/");
1576
1693
  if (normalized.startsWith("/") || /^[A-Za-z]:\//u.test(normalized)) {
1577
1694
  ctx.addIssue({
1578
- code: z.ZodIssueCode.custom,
1695
+ code: z2.ZodIssueCode.custom,
1579
1696
  message: "Canonical bridge moduleSpecifier must be a portable import specifier"
1580
1697
  });
1581
1698
  }
1582
1699
  if (normalized.split("/").includes("..")) {
1583
1700
  ctx.addIssue({
1584
- code: z.ZodIssueCode.custom,
1701
+ code: z2.ZodIssueCode.custom,
1585
1702
  message: "Canonical bridge moduleSpecifier must not traverse outside the project"
1586
1703
  });
1587
1704
  }
1588
1705
  });
1589
- var canonicalBridgeV1Schema = z.object({
1590
- underlying: z.object({
1591
- packageName: z.string().min(1),
1592
- exportName: z.string().min(1)
1706
+ var canonicalBridgeV1Schema = z2.object({
1707
+ underlying: z2.object({
1708
+ packageName: z2.string().min(1),
1709
+ exportName: z2.string().min(1)
1593
1710
  }).strict(),
1594
- local: z.object({
1595
- componentKey: z.string().min(1),
1711
+ local: z2.object({
1712
+ componentKey: z2.string().min(1),
1596
1713
  moduleSpecifier: canonicalBridgeModuleSpecifierSchema,
1597
- exportName: z.string().min(1),
1598
- implementationFiles: z.array(canonicalSourcePathSchema).min(1)
1714
+ exportName: z2.string().min(1),
1715
+ implementationFiles: z2.array(canonicalSourcePathSchema).min(1)
1599
1716
  }).strict(),
1600
- decision: z.object({
1601
- state: z.literal("confirmed"),
1602
- source: z.enum(["authored", "migration"])
1717
+ decision: z2.object({
1718
+ state: z2.literal("confirmed"),
1719
+ source: z2.enum(["authored", "migration"])
1603
1720
  }).strict()
1604
1721
  }).strict();
1605
- var canonicalBridgesV1Schema = z.array(canonicalBridgeV1Schema).superRefine((bridges, ctx) => {
1722
+ var canonicalBridgesV1Schema = z2.array(canonicalBridgeV1Schema).superRefine((bridges, ctx) => {
1606
1723
  const underlying = /* @__PURE__ */ new Map();
1607
1724
  const componentKeys = /* @__PURE__ */ new Map();
1608
1725
  for (const [index, bridge] of bridges.entries()) {
@@ -1610,7 +1727,7 @@ var canonicalBridgesV1Schema = z.array(canonicalBridgeV1Schema).superRefine((bri
1610
1727
  const previousUnderlying = underlying.get(underlyingKey);
1611
1728
  if (previousUnderlying !== void 0) {
1612
1729
  ctx.addIssue({
1613
- code: z.ZodIssueCode.custom,
1730
+ code: z2.ZodIssueCode.custom,
1614
1731
  message: `Duplicate confirmed bridge target for ${bridge.underlying.packageName}#${bridge.underlying.exportName} (also at canonicalBridges.${previousUnderlying})`,
1615
1732
  path: [index, "underlying"]
1616
1733
  });
@@ -1620,7 +1737,7 @@ var canonicalBridgesV1Schema = z.array(canonicalBridgeV1Schema).superRefine((bri
1620
1737
  const previousComponent = componentKeys.get(bridge.local.componentKey);
1621
1738
  if (previousComponent !== void 0) {
1622
1739
  ctx.addIssue({
1623
- code: z.ZodIssueCode.custom,
1740
+ code: z2.ZodIssueCode.custom,
1624
1741
  message: `Local component key overlaps canonicalBridges.${previousComponent}`,
1625
1742
  path: [index, "local", "componentKey"]
1626
1743
  });
@@ -1629,65 +1746,81 @@ var canonicalBridgesV1Schema = z.array(canonicalBridgeV1Schema).superRefine((bri
1629
1746
  }
1630
1747
  }
1631
1748
  });
1632
- var canonicalSourceSchema = z.discriminatedUnion("kind", [
1633
- z.object({
1634
- kind: z.literal("npm"),
1635
- specifier: z.string().min(1),
1636
- implementationPath: z.string().min(1).optional(),
1637
- include: z.array(z.string().min(1)).optional(),
1638
- exclude: z.array(z.string().min(1)).optional()
1749
+ var canonicalSourceSchema = z2.discriminatedUnion("kind", [
1750
+ z2.object({
1751
+ kind: z2.literal("npm"),
1752
+ specifier: z2.string().min(1),
1753
+ implementationPath: z2.string().min(1).optional(),
1754
+ include: z2.array(z2.string().min(1)).optional(),
1755
+ exclude: z2.array(z2.string().min(1)).optional()
1639
1756
  }),
1640
- z.object({
1641
- kind: z.literal("directory"),
1642
- path: z.string().min(1),
1643
- include: z.array(z.string().min(1)).optional(),
1644
- exclude: z.array(z.string().min(1)).optional()
1757
+ z2.object({
1758
+ kind: z2.literal("directory"),
1759
+ path: z2.string().min(1),
1760
+ include: z2.array(z2.string().min(1)).optional(),
1761
+ exclude: z2.array(z2.string().min(1)).optional()
1645
1762
  }),
1646
- z.object({
1647
- kind: z.literal("registry"),
1648
- registryId: z.string().min(1),
1763
+ z2.object({
1764
+ kind: z2.literal("registry"),
1765
+ registryId: z2.string().min(1),
1649
1766
  registryHash: canonicalSourceRegistryHashSchema.optional(),
1650
1767
  receiptPath: canonicalSourcePathSchema.default(".fragments/registry-lock.json"),
1651
1768
  installPath: canonicalSourcePathSchema,
1652
- importPath: z.string().min(1).optional(),
1653
- include: z.array(z.string().min(1)).optional(),
1654
- exclude: z.array(z.string().min(1)).optional(),
1769
+ importPath: z2.string().min(1).optional(),
1770
+ include: z2.array(z2.string().min(1)).optional(),
1771
+ exclude: z2.array(z2.string().min(1)).optional(),
1655
1772
  severity: governanceSeveritySchema.optional()
1656
1773
  })
1657
1774
  ]);
1658
- var governanceConfigSchema = z.object({
1659
- extends: z.array(z.string()).optional(),
1775
+ var governanceConfigSchema = z2.object({
1776
+ extends: z2.array(z2.string()).optional(),
1660
1777
  severity: governanceSeveritySchema.optional(),
1661
- rules: z.record(z.string(), z.unknown()).optional(),
1662
- agents: z.record(
1663
- z.string(),
1664
- z.object({
1665
- rules: z.record(z.string(), z.unknown()).optional()
1778
+ rules: z2.record(z2.string(), z2.unknown()).optional(),
1779
+ agents: z2.record(
1780
+ z2.string(),
1781
+ z2.object({
1782
+ rules: z2.record(z2.string(), z2.unknown()).optional()
1666
1783
  }).passthrough()
1667
1784
  ).optional(),
1668
- audit: z.object({}).passthrough().optional(),
1669
- runners: z.record(z.string(), z.object({}).passthrough()).optional(),
1670
- canonicalSources: z.array(canonicalSourceSchema).optional(),
1785
+ audit: z2.object({}).passthrough().optional(),
1786
+ runners: z2.record(z2.string(), z2.object({}).passthrough()).optional(),
1787
+ canonicalSources: z2.array(canonicalSourceSchema).optional(),
1671
1788
  canonicalBridges: canonicalBridgesV1Schema.optional(),
1672
- presets: z.array(z.string()).optional(),
1673
- scales: z.record(z.string(), scaleGovernanceRecordSchema).optional(),
1674
- styles: z.array(globalStyleGovernanceRecordSchema).optional(),
1675
- jsx: z.array(globalJsxGovernanceRecordSchema).optional(),
1676
- tailwind: z.object({
1677
- palette: z.object({
1678
- allow: z.array(z.string().min(1)).optional(),
1679
- deny: z.array(z.string().min(1)).optional()
1789
+ presets: z2.array(z2.string()).optional(),
1790
+ scales: z2.record(z2.string(), scaleGovernanceRecordSchema).optional(),
1791
+ styles: z2.array(globalStyleGovernanceRecordSchema).optional(),
1792
+ jsx: z2.array(globalJsxGovernanceRecordSchema).optional(),
1793
+ tailwind: z2.object({
1794
+ palette: z2.object({
1795
+ allow: z2.array(z2.string().min(1)).optional(),
1796
+ deny: z2.array(z2.string().min(1)).optional()
1680
1797
  }).optional()
1681
1798
  }).passthrough().optional(),
1682
- agent: z.object({
1683
- repairOrder: z.array(z.string().min(1)).optional()
1799
+ agent: z2.object({
1800
+ repairOrder: z2.array(z2.string().min(1)).optional()
1684
1801
  }).passthrough().optional(),
1685
- components: z.record(componentPolicyRecordSchema).optional(),
1686
- overrides: z.array(componentPolicyOverrideSchema).optional(),
1687
- ci: z.object({
1688
- failOnWarnings: z.boolean().optional()
1802
+ components: z2.record(componentPolicyRecordSchema).optional(),
1803
+ overrides: z2.array(componentPolicyOverrideSchema).optional(),
1804
+ ci: z2.object({
1805
+ failOnWarnings: z2.boolean().optional(),
1806
+ failOnInert: z2.boolean().optional()
1689
1807
  }).passthrough().optional()
1690
1808
  }).strict();
1809
+ var PRESET_SOURCED_RULE = /* @__PURE__ */ Symbol.for("@usefragments/core:preset-sourced-rule");
1810
+ function markPresetSourcedRules(rules) {
1811
+ if (!rules) return rules;
1812
+ const out = {};
1813
+ for (const [ruleId, entry] of Object.entries(rules)) {
1814
+ out[ruleId] = entry && typeof entry === "object" && !Array.isArray(entry) ? Object.defineProperty({ ...entry }, PRESET_SOURCED_RULE, {
1815
+ value: true,
1816
+ enumerable: false
1817
+ }) : entry;
1818
+ }
1819
+ return out;
1820
+ }
1821
+ function isPresetSourcedRule(entry) {
1822
+ return !!entry && typeof entry === "object" && entry[PRESET_SOURCED_RULE] === true;
1823
+ }
1691
1824
  function createComponentGovernanceBuilder() {
1692
1825
  return {
1693
1826
  capability(capability) {
@@ -1865,7 +1998,56 @@ var g = {
1865
1998
  component: createComponentGovernanceBuilder()
1866
1999
  };
1867
2000
 
2001
+ // src/rules/families.ts
2002
+ var RULE_FAMILY_MEMBERS = {
2003
+ "tokens/hardcoded-values": [
2004
+ "styles/no-raw-color",
2005
+ "styles/no-raw-spacing",
2006
+ "styles/no-raw-typography",
2007
+ "tokens/require-dual-fallback",
2008
+ "theme/no-theme-coupled-literal"
2009
+ ],
2010
+ "components/usage": [
2011
+ "components/forbidden-prop-value",
2012
+ "components/preferred-component",
2013
+ "components/unknown-prop",
2014
+ "props/invalid-value"
2015
+ ],
2016
+ "a11y/wcag": ["a11y/required-accessible-name"]
2017
+ };
2018
+ var RULE_FAMILY_IDS = new Set(Object.keys(RULE_FAMILY_MEMBERS));
2019
+ function isRuleFamilyId(ruleId) {
2020
+ return RULE_FAMILY_IDS.has(ruleId);
2021
+ }
2022
+ function ruleFamilyMembers(ruleId) {
2023
+ return RULE_FAMILY_MEMBERS[ruleId] ?? [ruleId];
2024
+ }
2025
+
1868
2026
  // src/facts/compile.ts
2027
+ function recordExclude(record) {
2028
+ const exclude = normalizePolicyExcludes(record.exclude);
2029
+ return exclude ? { exclude } : {};
2030
+ }
2031
+ function unionExcludesBySharedFactId(facts) {
2032
+ const byId = /* @__PURE__ */ new Map();
2033
+ for (const fact of facts) {
2034
+ const exclude = fact.exclude;
2035
+ if (!exclude?.length) continue;
2036
+ const merged = byId.get(fact.id) ?? [];
2037
+ for (const entry of exclude) {
2038
+ if (!merged.some((seen) => seen.glob === entry.glob && seen.reason === entry.reason)) {
2039
+ merged.push(entry);
2040
+ }
2041
+ }
2042
+ byId.set(fact.id, merged);
2043
+ }
2044
+ if (byId.size === 0) return facts;
2045
+ return facts.map((fact) => {
2046
+ const merged = byId.get(fact.id);
2047
+ if (!merged) return fact;
2048
+ return { ...fact, exclude: merged.map((entry) => ({ ...entry })) };
2049
+ });
2050
+ }
1869
2051
  function compileGlobalGovernanceFacts(govern) {
1870
2052
  if (!govern) return [];
1871
2053
  const out = [];
@@ -1892,7 +2074,8 @@ function compileGlobalGovernanceFacts(govern) {
1892
2074
  makeStyleRawColorForbiddenFact({
1893
2075
  except: style.except,
1894
2076
  prefer: style.prefer,
1895
- severity: style.severity
2077
+ severity: style.severity,
2078
+ ...recordExclude(style)
1896
2079
  })
1897
2080
  );
1898
2081
  break;
@@ -1901,7 +2084,8 @@ function compileGlobalGovernanceFacts(govern) {
1901
2084
  makeStyleRawDimensionForbiddenFact({
1902
2085
  appliesTo: style.appliesTo,
1903
2086
  prefer: style.prefer,
1904
- severity: style.severity
2087
+ severity: style.severity,
2088
+ ...recordExclude(style)
1905
2089
  })
1906
2090
  );
1907
2091
  break;
@@ -1911,16 +2095,28 @@ function compileGlobalGovernanceFacts(govern) {
1911
2095
  makeStylePropertyScaleFact({
1912
2096
  property,
1913
2097
  scale: style.scale,
1914
- severity: style.severity
2098
+ severity: style.severity,
2099
+ ...recordExclude(style)
1915
2100
  })
1916
2101
  );
1917
2102
  }
1918
2103
  break;
1919
2104
  case "style.fontSize.mustMatchScale":
1920
- out.push(makeStyleFontSizeScaleFact({ scale: style.scale, severity: style.severity }));
2105
+ out.push(
2106
+ makeStyleFontSizeScaleFact({
2107
+ scale: style.scale,
2108
+ severity: style.severity,
2109
+ ...recordExclude(style)
2110
+ })
2111
+ );
1921
2112
  break;
1922
2113
  case "style.cssVars.mustBeDefined":
1923
- out.push(makeStyleCssVarsMustBeDefinedFact({ severity: style.severity }));
2114
+ out.push(
2115
+ makeStyleCssVarsMustBeDefinedFact({
2116
+ severity: style.severity,
2117
+ ...recordExclude(style)
2118
+ })
2119
+ );
1924
2120
  break;
1925
2121
  }
1926
2122
  }
@@ -1929,14 +2125,20 @@ function compileGlobalGovernanceFacts(govern) {
1929
2125
  for (const jsx of govern.jsx) {
1930
2126
  switch (jsx.kind) {
1931
2127
  case "jsx.unknownProps.forbid":
1932
- out.push(makeJsxUnknownPropsForbiddenFact({ severity: jsx.severity }));
2128
+ out.push(
2129
+ makeJsxUnknownPropsForbiddenFact({
2130
+ severity: jsx.severity,
2131
+ ...recordExclude(jsx)
2132
+ })
2133
+ );
1933
2134
  break;
1934
2135
  case "jsx.inlineStyle.forbidRaw":
1935
2136
  for (const property of jsx.properties) {
1936
2137
  out.push(
1937
2138
  makeJsxInlineStyleForbiddenRawFact({
1938
2139
  property,
1939
- severity: jsx.severity
2140
+ severity: jsx.severity,
2141
+ ...recordExclude(jsx)
1940
2142
  })
1941
2143
  );
1942
2144
  }
@@ -1948,7 +2150,8 @@ function compileGlobalGovernanceFacts(govern) {
1948
2150
  to: jsx.to,
1949
2151
  imported: jsx.imported,
1950
2152
  because: jsx.because,
1951
- severity: jsx.severity
2153
+ severity: jsx.severity,
2154
+ ...recordExclude(jsx)
1952
2155
  })
1953
2156
  );
1954
2157
  break;
@@ -1958,7 +2161,8 @@ function compileGlobalGovernanceFacts(govern) {
1958
2161
  from: asComponentId(jsx.from),
1959
2162
  to: asComponentId(jsx.to),
1960
2163
  because: jsx.because,
1961
- severity: jsx.severity
2164
+ severity: jsx.severity,
2165
+ ...recordExclude(jsx)
1962
2166
  })
1963
2167
  );
1964
2168
  break;
@@ -1983,6 +2187,38 @@ function compileGlobalGovernanceFacts(govern) {
1983
2187
  })
1984
2188
  );
1985
2189
  }
2190
+ compileTailwindAndRuleConfigFacts(govern, out);
2191
+ return unionExcludesBySharedFactId(out);
2192
+ }
2193
+ function projectSupersededImportPathPreferences(govern) {
2194
+ const bridges = govern?.canonicalBridges ?? [];
2195
+ if (bridges.length === 0 || !govern?.jsx) return [];
2196
+ const out = [];
2197
+ for (const record of govern.jsx) {
2198
+ if (record.kind !== "jsx.importPath.prefer") continue;
2199
+ const bridge = bridges.find((candidate) => importPathRecordOverlapsBridge(record, candidate));
2200
+ if (!bridge) continue;
2201
+ out.push({
2202
+ from: record.from,
2203
+ ...record.imported !== void 0 ? { imported: record.imported } : {},
2204
+ to: record.to,
2205
+ packageName: bridge.underlying.packageName,
2206
+ underlyingExportName: bridge.underlying.exportName,
2207
+ localExportName: bridge.local.exportName
2208
+ });
2209
+ }
2210
+ return out;
2211
+ }
2212
+ function importPathRecordOverlapsBridge(record, bridge) {
2213
+ if (!ownedImportMatchesRoot(record.from, bridge.underlying.packageName)) return false;
2214
+ if (ownedImportsEqual(record.from, bridge.underlying.packageName)) {
2215
+ return record.imported === void 0 || record.imported === bridge.underlying.exportName;
2216
+ }
2217
+ const subpath = record.from.slice(bridge.underlying.packageName.length + 1);
2218
+ const leaf = subpath.split("/").at(-1);
2219
+ return leaf === bridge.underlying.exportName && (record.imported === void 0 || record.imported === "default" || record.imported === bridge.underlying.exportName);
2220
+ }
2221
+ function compileTailwindAndRuleConfigFacts(govern, out) {
1986
2222
  const tailwindPalette = govern.tailwind?.palette;
1987
2223
  const forbiddenPaletteSeverity = ruleSeverity(
1988
2224
  govern.rules?.["tailwind/forbidden-palette"],
@@ -2012,23 +2248,7 @@ function compileGlobalGovernanceFacts(govern) {
2012
2248
  out.push(makeTailwindUnknownClassEnabledFact({ severity: unknownClassSeverity }));
2013
2249
  }
2014
2250
  out.push(...compileRuleConfigFacts(govern));
2015
- return out;
2016
2251
  }
2017
- var RULE_FAMILY_MEMBERS = {
2018
- "tokens/hardcoded-values": [
2019
- "styles/no-raw-color",
2020
- "styles/no-raw-spacing",
2021
- "tokens/require-dual-fallback",
2022
- "theme/no-theme-coupled-literal"
2023
- ],
2024
- "components/usage": [
2025
- "components/forbidden-prop-value",
2026
- "components/preferred-component",
2027
- "components/unknown-prop",
2028
- "props/invalid-value"
2029
- ],
2030
- "a11y/wcag": ["a11y/required-accessible-name"]
2031
- };
2032
2252
  function compileRuleConfigFacts(govern) {
2033
2253
  const rules = govern.rules;
2034
2254
  if (!rules && !govern.canonicalSources?.length) return [];
@@ -2330,6 +2550,13 @@ export {
2330
2550
  ownedComponentIdsEqual,
2331
2551
  matchesGlob,
2332
2552
  FactIndex,
2553
+ policyExcludeSchema,
2554
+ normalizePolicyExcludes,
2555
+ normalizeExcludePath,
2556
+ excludeGlobToRegExp,
2557
+ policyExcludeMatchesPath,
2558
+ matchPolicyExclude,
2559
+ describePolicyExclude,
2333
2560
  governanceSeveritySchema,
2334
2561
  scaleGovernanceRecordSchema,
2335
2562
  globalStyleGovernanceRecordSchema,
@@ -2339,12 +2566,19 @@ export {
2339
2566
  componentGovernanceRecordsSchema,
2340
2567
  canonicalBridgeV1Schema,
2341
2568
  governanceConfigSchema,
2569
+ markPresetSourcedRules,
2570
+ isPresetSourcedRule,
2342
2571
  resolveComponentGovernance,
2343
2572
  normalizeGovernanceConfig,
2344
2573
  g,
2574
+ RULE_FAMILY_MEMBERS,
2575
+ RULE_FAMILY_IDS,
2576
+ isRuleFamilyId,
2577
+ ruleFamilyMembers,
2345
2578
  compileGlobalGovernanceFacts,
2579
+ projectSupersededImportPathPreferences,
2346
2580
  compileComponentFacts,
2347
2581
  bridgeSourceViolation,
2348
2582
  bridgeSourceViolations
2349
2583
  };
2350
- //# sourceMappingURL=chunk-BAHCOAVG.js.map
2584
+ //# sourceMappingURL=chunk-WVFNDPM4.js.map