@habitat-ai/cli 0.2.0 → 0.2.1

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.
package/dist/nx-plugin.js CHANGED
@@ -1742,50 +1742,46 @@ function createHabitatNxPlugin(binding) {
1742
1742
  const result = await client.catalog.resolve({});
1743
1743
  if (result._tag === "Rejected")
1744
1744
  throw rejectedCatalogError(result);
1745
- return projectApplications(matchedFiles, result.catalog, binding.runtimeInputs);
1745
+ return projectCatalogTargets(matchedFiles, result.catalog, binding.runtimeInputs);
1746
1746
  }
1747
1747
  ];
1748
1748
  return Object.freeze({ createNodes });
1749
1749
  }
1750
- function projectApplications(matchedFiles, catalog, runtimeInputs) {
1751
- if (catalog.applications.length === 0)
1750
+ function projectCatalogTargets(matchedFiles, catalog, runtimeInputs) {
1751
+ if (catalog.applications.length === 0 && catalog.compatibility.rules.length === 0)
1752
1752
  return [];
1753
1753
  const authorityFiles = new Set(matchedFiles);
1754
1754
  const instances = indexInstances(catalog.instances);
1755
1755
  const rootsByOwner = new Map;
1756
+ const ownersByRoot = new Map;
1756
1757
  const projects = new Map;
1758
+ for (const [ownerProject, ownerRoot] of Object.entries(catalog.compatibility.ownerRoots).sort(([left], [right]) => compareText(left, right))) {
1759
+ recordOwnerRoot(ownerProject, ownerRoot, rootsByOwner, ownersByRoot);
1760
+ }
1757
1761
  for (const application of catalog.applications) {
1758
1762
  const instance = requireApplicationInstance(application, instances);
1759
- const manifestPath = normalizeWorkspacePath(application.manifestPath);
1760
- if (!authorityFiles.has(manifestPath)) {
1761
- throw new Error(`Habitat Nx projection rejected instance '${instance.id}': manifest '${manifestPath}' is outside the matched authority files.`);
1762
- }
1763
- const root = projectRootFor(manifestPath);
1764
- const priorRoot = rootsByOwner.get(application.ownerProject);
1765
- if (priorRoot !== undefined && priorRoot !== root) {
1766
- throw new Error(`Habitat Nx projection rejected owner '${application.ownerProject}': roots '${priorRoot}' and '${root}' collide.`);
1767
- }
1768
- rootsByOwner.set(application.ownerProject, root);
1769
- const project = projects.get(root) ?? {
1770
- manifestPath,
1771
- ownerProject: application.ownerProject,
1772
- targets: {}
1773
- };
1774
- if (project.ownerProject !== application.ownerProject) {
1775
- throw new Error(`Habitat Nx projection rejected root '${root}': owners '${project.ownerProject}' and '${application.ownerProject}' collide.`);
1776
- }
1763
+ const manifestPath = requireMatchedManifest(application.manifestPath, authorityFiles, `instance '${instance.id}'`);
1764
+ const root = recordOwnerRoot(application.ownerProject, projectRootFor(manifestPath), rootsByOwner, ownersByRoot);
1765
+ const project = projectFor(projects, root, application.ownerProject);
1766
+ project.applicationManifests.add(manifestPath);
1777
1767
  const targetName = applicationTargetName(application);
1778
- if (Object.hasOwn(project.targets, targetName)) {
1779
- throw new Error(`Habitat Nx projection rejected duplicate target '${application.ownerProject}:${targetName}'.`);
1768
+ addLeafTarget(project, targetName, applicationTarget(application, runtimeInputs));
1769
+ }
1770
+ for (const rule of catalog.compatibility.rules) {
1771
+ const root = rootsByOwner.get(rule.ownerProject);
1772
+ if (root === undefined) {
1773
+ throw new Error(`Habitat Nx projection rejected compatibility rule '${rule.ruleId}': owner '${rule.ownerProject}' has no root.`);
1780
1774
  }
1781
- project.targets[targetName] = applicationTarget(application, runtimeInputs);
1782
- projects.set(root, project);
1775
+ const manifestPath = requireMatchedManifest(rule.manifestPath, authorityFiles, `compatibility rule '${rule.ruleId}'`);
1776
+ const project = projectFor(projects, root, rule.ownerProject);
1777
+ project.compatibilityManifests.add(manifestPath);
1778
+ addLeafTarget(project, compatibilityTargetName(rule), compatibilityTarget(rule, runtimeInputs));
1783
1779
  }
1784
1780
  return [...projects.entries()].sort(([left], [right]) => compareText(left, right)).map(([root, project]) => {
1785
1781
  const leafTargets = Object.keys(project.targets).sort();
1786
- project.targets[DEFAULT_CHECK_TARGET] = ownerTarget(project.ownerProject, leafTargets);
1782
+ project.targets[DEFAULT_CHECK_TARGET] = ownerTarget(project.ownerProject, leafTargets, project.compatibilityManifests.size > 0);
1787
1783
  return [
1788
- project.manifestPath,
1784
+ projectionSource(project),
1789
1785
  {
1790
1786
  projects: {
1791
1787
  [root]: {
@@ -1796,6 +1792,60 @@ function projectApplications(matchedFiles, catalog, runtimeInputs) {
1796
1792
  ];
1797
1793
  });
1798
1794
  }
1795
+ function recordOwnerRoot(ownerProject, ownerRoot, rootsByOwner, ownersByRoot) {
1796
+ const root = normalizeWorkspacePath(ownerRoot);
1797
+ const priorRoot = rootsByOwner.get(ownerProject);
1798
+ if (priorRoot !== undefined && priorRoot !== root) {
1799
+ throw new Error(`Habitat Nx projection rejected owner '${ownerProject}': roots '${priorRoot}' and '${root}' collide.`);
1800
+ }
1801
+ const priorOwner = ownersByRoot.get(root);
1802
+ if (priorOwner !== undefined && priorOwner !== ownerProject) {
1803
+ throw new Error(`Habitat Nx projection rejected root '${root}': owners '${priorOwner}' and '${ownerProject}' collide.`);
1804
+ }
1805
+ rootsByOwner.set(ownerProject, root);
1806
+ ownersByRoot.set(root, ownerProject);
1807
+ return root;
1808
+ }
1809
+ function projectFor(projects, root, ownerProject) {
1810
+ const project = projects.get(root);
1811
+ if (project !== undefined) {
1812
+ if (project.ownerProject !== ownerProject) {
1813
+ throw new Error(`Habitat Nx projection rejected root '${root}': owners '${project.ownerProject}' and '${ownerProject}' collide.`);
1814
+ }
1815
+ return project;
1816
+ }
1817
+ const created = {
1818
+ ownerProject,
1819
+ applicationManifests: new Set,
1820
+ compatibilityManifests: new Set,
1821
+ targets: {}
1822
+ };
1823
+ projects.set(root, created);
1824
+ return created;
1825
+ }
1826
+ function requireMatchedManifest(path, authorityFiles, subject) {
1827
+ const manifestPath = normalizeWorkspacePath(path);
1828
+ if (!authorityFiles.has(manifestPath)) {
1829
+ throw new Error(`Habitat Nx projection rejected ${subject}: manifest '${manifestPath}' is outside the matched authority files.`);
1830
+ }
1831
+ return manifestPath;
1832
+ }
1833
+ function addLeafTarget(project, targetName, target) {
1834
+ if (Object.hasOwn(project.targets, targetName)) {
1835
+ throw new Error(`Habitat Nx projection rejected duplicate target '${project.ownerProject}:${targetName}'.`);
1836
+ }
1837
+ project.targets[targetName] = target;
1838
+ }
1839
+ function projectionSource(project) {
1840
+ const applicationManifest = [...project.applicationManifests].sort(compareText)[0];
1841
+ if (applicationManifest !== undefined)
1842
+ return applicationManifest;
1843
+ const compatibilityManifest = [...project.compatibilityManifests].sort(compareText)[0];
1844
+ if (compatibilityManifest === undefined) {
1845
+ throw new Error(`Habitat Nx projection rejected owner '${project.ownerProject}': projected targets have no manifest.`);
1846
+ }
1847
+ return compatibilityManifest;
1848
+ }
1799
1849
  function requireApplicationInstance(application, instances) {
1800
1850
  const instance = instances.get(application.instanceId);
1801
1851
  if (!instance) {
@@ -1825,6 +1875,9 @@ function indexInstances(instances) {
1825
1875
  function applicationTargetName(application) {
1826
1876
  return `habitat:application:${application.instanceId}:${application.ruleId}`;
1827
1877
  }
1878
+ function compatibilityTargetName(rule) {
1879
+ return `habitat:rule:${rule.ruleId}`;
1880
+ }
1828
1881
  function applicationTarget(application, runtimeInputs) {
1829
1882
  return {
1830
1883
  command: `${HABITAT_EXECUTABLE} check --instance ${application.instanceId} --rule ${application.ruleId}`,
@@ -1837,13 +1890,25 @@ function applicationTarget(application, runtimeInputs) {
1837
1890
  }
1838
1891
  };
1839
1892
  }
1840
- function ownerTarget(ownerProject, leafTargets) {
1893
+ function compatibilityTarget(rule, runtimeInputs) {
1894
+ return {
1895
+ command: `${HABITAT_EXECUTABLE} check --rule ${rule.ruleId}`,
1896
+ cache: true,
1897
+ inputs: compatibilityInputs(rule, runtimeInputs),
1898
+ outputs: [],
1899
+ options: { cwd: "{workspaceRoot}" },
1900
+ metadata: { description: `Check Habitat compatibility rule ${rule.ruleId}` }
1901
+ };
1902
+ }
1903
+ function ownerTarget(ownerProject, leafTargets, hasCompatibility) {
1841
1904
  return {
1842
1905
  executor: "nx:noop",
1843
1906
  cache: false,
1844
1907
  outputs: [],
1845
1908
  dependsOn: leafTargets.map((target) => ({ target })),
1846
- metadata: { description: `Check resolved Habitat applications owned by ${ownerProject}` }
1909
+ metadata: {
1910
+ description: hasCompatibility ? `Check resolved Habitat policy owned by ${ownerProject}` : `Check resolved Habitat applications owned by ${ownerProject}`
1911
+ }
1847
1912
  };
1848
1913
  }
1849
1914
  function applicationInputs(application, runtimeInputs) {
@@ -1862,6 +1927,16 @@ function applicationInputs(application, runtimeInputs) {
1862
1927
  }
1863
1928
  return [...runtimeInputs, ...[...files].sort()];
1864
1929
  }
1930
+ function compatibilityInputs(rule, runtimeInputs) {
1931
+ const files = new Set(HABITAT_CATALOG_PATHS.map(workspaceInput));
1932
+ files.add(workspaceInput(".habitat/**"));
1933
+ files.add(workspaceInput(rule.manifestPath));
1934
+ files.add(workspaceInput(rule.baseline.relativePath));
1935
+ for (const pattern of rule.coveragePatterns)
1936
+ files.add(workspaceInput(pattern));
1937
+ files.add(workspaceInput(rule.runner.name === "grit" ? rule.runner.pattern.relativePath : rule.runner.structure.relativePath));
1938
+ return [...runtimeInputs, ...[...files].sort(compareText)];
1939
+ }
1865
1940
  function addSubjectInputs(target, path, kind) {
1866
1941
  const exact = workspaceInput(path);
1867
1942
  target.add(exact);
@@ -48484,11 +48559,142 @@ var ResolvedRuleApplicationSchema = exports_typebox.Object({
48484
48559
  description: "Fully resolved runner and acquisition facts."
48485
48560
  })
48486
48561
  }, { additionalProperties: false, description: "One resolved instance/rule application." });
48487
- var CompatibilityRuleSchema = exports_typebox.Object({
48562
+ var CompatibilityPlacementSchema = exports_typebox.Object({
48563
+ niche: exports_typebox.String({
48564
+ minLength: 1,
48565
+ description: "Frozen version-two niche classification."
48566
+ }),
48567
+ blueprint: exports_typebox.String({
48568
+ minLength: 1,
48569
+ description: "Frozen version-two blueprint classification."
48570
+ }),
48571
+ category: exports_typebox.Union([
48572
+ exports_typebox.Literal("boundary"),
48573
+ exports_typebox.Literal("contract"),
48574
+ exports_typebox.Literal("execution"),
48575
+ exports_typebox.Literal("output"),
48576
+ exports_typebox.Literal("policy"),
48577
+ exports_typebox.Literal("quality"),
48578
+ exports_typebox.Literal("structure")
48579
+ ], { description: "Frozen version-two rule category." })
48580
+ }, { additionalProperties: false, description: "Legacy rule classification metadata." });
48581
+ var CompatibilityPathCoverageSchema = exports_typebox.Object({
48582
+ kind: exports_typebox.Literal("exact-path", {
48583
+ description: "Legacy exact repository-path subject declaration."
48584
+ }),
48585
+ patterns: exports_typebox.Array(exports_typebox.String({
48586
+ minLength: 1,
48587
+ maxLength: 4096,
48588
+ description: "Repository-relative path or glob admitted for checking and caching."
48589
+ }), {
48590
+ minItems: 1,
48591
+ uniqueItems: true,
48592
+ description: "Unique repository path patterns covered by the rule."
48593
+ })
48594
+ }, { additionalProperties: false, description: "Legacy exact-path coverage entry." });
48595
+ var CompatibilitySupportFilesSchema = exports_typebox.Object({
48596
+ baseline: RelativePathSchema
48597
+ }, { additionalProperties: false, description: "Legacy rule support-file locators." });
48598
+ var CompatibilityGritRunnerSourceSchema = exports_typebox.Object({
48599
+ name: exports_typebox.Literal("grit", { description: "Grit runner identity." }),
48600
+ files: exports_typebox.Object({
48601
+ pattern: RelativePathSchema
48602
+ }, { additionalProperties: false, description: "Grit rule asset locator." }),
48603
+ patternName: PatternNameSchema,
48604
+ acquisition: exports_typebox.Object({
48605
+ kind: exports_typebox.Literal("check", { description: "Supported compatibility operation." }),
48606
+ roots: exports_typebox.Array(RelativePathSchema, {
48607
+ minItems: 1,
48608
+ uniqueItems: true,
48609
+ description: "Concrete repository roots supplied to Grit."
48610
+ })
48611
+ }, { additionalProperties: false, description: "Compatibility Grit acquisition roots." })
48612
+ }, { additionalProperties: false, description: "Supported legacy Grit runner declaration." });
48613
+ var CompatibilityStructureRunnerSourceSchema = exports_typebox.Object({
48614
+ name: exports_typebox.Literal("habitat", { description: "Native Habitat runner identity." }),
48615
+ mode: exports_typebox.Literal("structure", { description: "Native structure evaluation mode." }),
48616
+ files: exports_typebox.Object({
48617
+ structure: RelativePathSchema
48618
+ }, { additionalProperties: false, description: "Structure rule asset locator." })
48619
+ }, { additionalProperties: false, description: "Supported legacy structure runner declaration." });
48620
+ var CompatibilityRuleSourceCommon = {
48621
+ schemaVersion: exports_typebox.Literal(2, { description: "Legacy rule schema version." }),
48488
48622
  id: IdSchema,
48623
+ title: exports_typebox.String({ minLength: 1, maxLength: 500, description: "Legacy rule title." }),
48624
+ placement: CompatibilityPlacementSchema,
48625
+ operation: exports_typebox.Object({
48626
+ kind: exports_typebox.Literal("check", { description: "Only admitted compatibility operation." })
48627
+ }, { additionalProperties: false, description: "Legacy rule operation." }),
48628
+ ownerProject: ProjectIdSchema,
48629
+ lane: exports_typebox.Literal("enforced", { description: "Only admitted compatibility policy lane." }),
48630
+ forbids: exports_typebox.String({
48631
+ minLength: 1,
48632
+ maxLength: 16384,
48633
+ description: "State excluded by the compatibility rule."
48634
+ }),
48635
+ why: exports_typebox.String({
48636
+ minLength: 1,
48637
+ maxLength: 16384,
48638
+ description: "Reason the compatibility rule exists."
48639
+ }),
48640
+ remediate: exports_typebox.String({
48641
+ minLength: 1,
48642
+ maxLength: 16384,
48643
+ description: "Operator remediation for one finding."
48644
+ }),
48645
+ message: RuleMessageSchema,
48646
+ pathCoverage: exports_typebox.Tuple([CompatibilityPathCoverageSchema], {
48647
+ description: "Single exact-path cache boundary for the compatibility rule."
48648
+ }),
48649
+ supportFiles: CompatibilitySupportFilesSchema
48650
+ };
48651
+ var CompatibilityGritRuleSourceSchema = exports_typebox.Object({
48652
+ ...CompatibilityRuleSourceCommon,
48653
+ hookCheck: exports_typebox.Literal(true, {
48654
+ description: "The legacy hook executes this Grit check."
48655
+ }),
48656
+ runner: CompatibilityGritRunnerSourceSchema
48657
+ }, { additionalProperties: false, description: "Supported legacy Grit rule source." });
48658
+ var CompatibilityStructureRuleSourceSchema = exports_typebox.Object({
48659
+ ...CompatibilityRuleSourceCommon,
48660
+ runner: CompatibilityStructureRunnerSourceSchema
48661
+ }, { additionalProperties: false, description: "Supported legacy structure rule source." });
48662
+ var ResolvedCompatibilityGritRunnerSchema = exports_typebox.Object({
48663
+ name: exports_typebox.Literal("grit", { description: "Grit runner identity." }),
48664
+ pattern: ResolvedRuleAssetSchema,
48665
+ patternName: PatternNameSchema,
48666
+ acquisition: exports_typebox.Object({
48667
+ kind: exports_typebox.Literal("check", { description: "Resolved compatibility operation." }),
48668
+ entries: exports_typebox.Array(exports_typebox.Object({
48669
+ kind: PathKindSchema,
48670
+ path: RelativePathSchema
48671
+ }, { additionalProperties: false, description: "Resolved compatibility subject root." }), {
48672
+ minItems: 1,
48673
+ description: "Concrete compatibility roots in declared order."
48674
+ })
48675
+ }, { additionalProperties: false, description: "Resolved compatibility Grit acquisition." })
48676
+ }, { additionalProperties: false, description: "Resolved compatibility Grit runner." });
48677
+ var ResolvedCompatibilityStructureRunnerSchema = exports_typebox.Object({
48678
+ name: exports_typebox.Literal("habitat", { description: "Native Habitat runner identity." }),
48679
+ mode: exports_typebox.Literal("structure", { description: "Native structure evaluation mode." }),
48680
+ structure: ResolvedRuleAssetSchema
48681
+ }, { additionalProperties: false, description: "Resolved compatibility structure runner." });
48682
+ var CompatibilityRuleSchema = exports_typebox.Object({
48683
+ ruleId: IdSchema,
48489
48684
  ownerProject: ProjectIdSchema,
48490
- manifestPath: RelativePathSchema
48491
- }, { additionalProperties: false, description: "Inert version 2 rule identity summary." });
48685
+ manifestPath: RelativePathSchema,
48686
+ lane: exports_typebox.Literal("enforced", { description: "Compatibility rule policy lane." }),
48687
+ message: RuleMessageSchema,
48688
+ remediate: RuleRemediationSchema,
48689
+ provenance: LocalAuthorityProvenanceSchema,
48690
+ coveragePatterns: exports_typebox.Array(exports_typebox.String({ minLength: 1, maxLength: 4096 }), {
48691
+ minItems: 1,
48692
+ uniqueItems: true,
48693
+ description: "Repository path patterns that define compatibility subjects and cache inputs."
48694
+ }),
48695
+ baseline: ResolvedRuleAssetSchema,
48696
+ runner: exports_typebox.Union([ResolvedCompatibilityStructureRunnerSchema, ResolvedCompatibilityGritRunnerSchema], { description: "Resolved compatibility runner and its concrete assets." })
48697
+ }, { additionalProperties: false, description: "One executable version 2 compatibility rule." });
48492
48698
  var CompatibilityIndexSchema = exports_typebox.Object({
48493
48699
  $comment: exports_typebox.Optional(exports_typebox.String({ description: "Optional legacy index comment." })),
48494
48700
  schemaVersion: exports_typebox.Literal(2, { description: "Legacy registry schema version." }),
@@ -48497,20 +48703,19 @@ var CompatibilityIndexSchema = exports_typebox.Object({
48497
48703
  description: "Legacy owner roots keyed by project identity."
48498
48704
  })
48499
48705
  }, { additionalProperties: false, description: "Legacy version 2 registry index." });
48500
- var CompatibilityRuleSourceSchema = exports_typebox.Object({
48501
- schemaVersion: exports_typebox.Literal(2, { description: "Legacy rule schema version." }),
48502
- id: IdSchema,
48503
- ownerProject: ProjectIdSchema
48504
- }, { additionalProperties: true, description: "Legacy rule source identity projected inertly." });
48706
+ var CompatibilityRuleSourceSchema = exports_typebox.Union([CompatibilityGritRuleSourceSchema, CompatibilityStructureRuleSourceSchema], { description: "Supported version 2 compatibility rule source." });
48707
+ var CompatibilityBaselineSchema = exports_typebox.Tuple([], {
48708
+ description: "Empty compatibility baseline; every observed finding remains live."
48709
+ });
48505
48710
  var CompatibilityCatalogSchema = exports_typebox.Object({
48506
48711
  schemaVersion: exports_typebox.Literal(2, { description: "Legacy compatibility catalog version." }),
48507
48712
  ownerRoots: exports_typebox.Record(ProjectIdSchema, RelativePathSchema, {
48508
48713
  description: "Validated legacy owner roots keyed by project identity."
48509
48714
  }),
48510
48715
  rules: exports_typebox.Array(CompatibilityRuleSchema, {
48511
- description: "Stable inert legacy rule identity summaries."
48716
+ description: "Resolved executable compatibility rules in stable identity order."
48512
48717
  })
48513
- }, { additionalProperties: false, description: "Inert version 2 compatibility facts." });
48718
+ }, { additionalProperties: false, description: "Version 2 compatibility rule catalog." });
48514
48719
  var ResolvedPolicyPackSchema = exports_typebox.Object({
48515
48720
  name: PackageNameSchema,
48516
48721
  version: PackageVersionSchema,
@@ -48622,6 +48827,44 @@ var CheckSelectionIssueSchema = exports_typebox.Object({
48622
48827
  additionalProperties: false,
48623
48828
  description: "One expected application-selection refusal."
48624
48829
  });
48830
+ var ReportOwnerProjectSchema = exports_typebox.String({
48831
+ minLength: 1,
48832
+ maxLength: 250,
48833
+ description: "Repository project that owns the checked rule."
48834
+ });
48835
+ var ReportInstanceIdSchema = exports_typebox.String({
48836
+ minLength: 1,
48837
+ maxLength: 250,
48838
+ description: "Repository-unique version-three instance identity."
48839
+ });
48840
+ var ReportRuleIdSchema = exports_typebox.String({
48841
+ minLength: 1,
48842
+ maxLength: 200,
48843
+ description: "Resolved rule identity."
48844
+ });
48845
+ var ReportLaneSchema = exports_typebox.Union([exports_typebox.Literal("enforced"), exports_typebox.Literal("advisory")], {
48846
+ description: "Rule lane that determines finding severity and terminal status."
48847
+ });
48848
+ var ReportMessageSchema = exports_typebox.String({
48849
+ minLength: 1,
48850
+ maxLength: 8192,
48851
+ description: "Rule-authored diagnostic message."
48852
+ });
48853
+ var ReportRemediationSchema = exports_typebox.Union([exports_typebox.String({ maxLength: 16384 }), exports_typebox.Null()], {
48854
+ description: "Rule-authored remediation when supplied."
48855
+ });
48856
+ var InstanceReportLockSchema = exports_typebox.Literal(false, {
48857
+ description: "Version-three applications do not use compatibility baseline locking."
48858
+ });
48859
+ var CompatibilityReportLockSchema = exports_typebox.Literal(true, {
48860
+ description: "The compatibility rule has an admitted exact empty baseline."
48861
+ });
48862
+ var GritRunnerSchema = exports_typebox.Literal("grit", {
48863
+ description: "Mechanical Grit runner used by this check."
48864
+ });
48865
+ var StructureRunnerSchema = exports_typebox.Literal("habitat", {
48866
+ description: "Native Habitat structure runner used by this check."
48867
+ });
48625
48868
  var GritCheckFindingSchema = exports_typebox.Object({
48626
48869
  path: exports_typebox.String({
48627
48870
  minLength: 1,
@@ -48637,7 +48880,7 @@ var GritCheckFindingSchema = exports_typebox.Object({
48637
48880
  description: "Service-owned severity derived from the application lane."
48638
48881
  }),
48639
48882
  baselined: exports_typebox.Literal(false, {
48640
- description: "Version-three findings are not admitted through the predecessor baseline model."
48883
+ description: "No admitted baseline suppresses this observed finding."
48641
48884
  })
48642
48885
  }, {
48643
48886
  additionalProperties: false,
@@ -48651,80 +48894,83 @@ var CheckApplicationStatusSchema = exports_typebox.Union([
48651
48894
  ], {
48652
48895
  description: "Semantic terminal status for one resolved application."
48653
48896
  });
48654
- var GritCheckApplicationDispositionSchema = exports_typebox.Union([
48655
- exports_typebox.Object({
48656
- kind: exports_typebox.Literal("evaluated", {
48657
- description: "The application completed mechanical evaluation."
48658
- })
48659
- }, {
48660
- additionalProperties: false,
48661
- description: "Completed mechanical evaluation disposition."
48662
- }),
48663
- exports_typebox.Object({
48664
- kind: exports_typebox.Literal("failed", {
48665
- description: "The application could not produce trusted findings."
48666
- }),
48667
- reason: exports_typebox.Union([
48668
- RuleEvaluationFailureReasonSchema,
48669
- exports_typebox.Literal("PatternReadFailed"),
48670
- exports_typebox.Literal("PatternInvalid"),
48671
- exports_typebox.Literal("FindingPathInvalid")
48672
- ], {
48673
- description: "Stable operational failure reason."
48674
- }),
48675
- detail: exports_typebox.String({
48676
- minLength: 1,
48677
- maxLength: 4096,
48678
- description: "Bounded operational failure detail."
48679
- })
48680
- }, {
48681
- additionalProperties: false,
48682
- description: "Failed application evaluation disposition."
48897
+ var GritEvaluatedDispositionSchema = exports_typebox.Object({
48898
+ kind: exports_typebox.Literal("evaluated", {
48899
+ description: "The application completed mechanical evaluation."
48683
48900
  })
48684
- ], {
48685
- description: "Mechanical disposition underlying one semantic application status."
48901
+ }, {
48902
+ additionalProperties: false,
48903
+ description: "Completed mechanical evaluation disposition."
48686
48904
  });
48687
- var GritCheckApplicationReportSchema = exports_typebox.Object({
48688
- ownerProject: exports_typebox.String({
48689
- minLength: 1,
48690
- maxLength: 250,
48691
- description: "Repository project that owns the resolved application."
48905
+ var GritFailedDispositionSchema = exports_typebox.Object({
48906
+ kind: exports_typebox.Literal("failed", {
48907
+ description: "The application could not produce trusted findings."
48692
48908
  }),
48693
- instanceId: exports_typebox.String({
48694
- minLength: 1,
48695
- maxLength: 250,
48696
- description: "Repository-unique instance identity."
48909
+ reason: exports_typebox.Union([
48910
+ RuleEvaluationFailureReasonSchema,
48911
+ exports_typebox.Literal("PatternReadFailed"),
48912
+ exports_typebox.Literal("PatternInvalid"),
48913
+ exports_typebox.Literal("FindingPathInvalid")
48914
+ ], {
48915
+ description: "Stable operational failure reason."
48697
48916
  }),
48698
- ruleId: exports_typebox.String({
48917
+ detail: exports_typebox.String({
48699
48918
  minLength: 1,
48700
- maxLength: 200,
48701
- description: "Resolved rule identity."
48702
- }),
48703
- runner: exports_typebox.Literal("grit", {
48704
- description: "Mechanical runner used by this check operation."
48705
- }),
48706
- lane: exports_typebox.Union([exports_typebox.Literal("enforced"), exports_typebox.Literal("advisory")], {
48707
- description: "Application policy lane."
48708
- }),
48709
- locked: exports_typebox.Literal(false, {
48710
- description: "Version-three applications do not inherit predecessor baseline locking."
48919
+ maxLength: 4096,
48920
+ description: "Bounded operational failure detail."
48921
+ })
48922
+ }, {
48923
+ additionalProperties: false,
48924
+ description: "Failed application evaluation disposition."
48925
+ });
48926
+ var GritNotApplicableDispositionSchema = exports_typebox.Object({
48927
+ kind: exports_typebox.Literal("not-applicable", {
48928
+ description: "The compatibility rule had no live exact-coverage subjects."
48711
48929
  }),
48930
+ reason: exports_typebox.Literal("no-matched-acquisition-roots", {
48931
+ description: "No regular file matched both exact coverage and declared authority."
48932
+ })
48933
+ }, {
48934
+ additionalProperties: false,
48935
+ description: "Compatibility rule with no current subject files."
48936
+ });
48937
+ var GritCheckApplicationDispositionSchema = exports_typebox.Union([GritEvaluatedDispositionSchema, GritFailedDispositionSchema], { description: "Version-three Grit evaluation disposition." });
48938
+ var CompatibilityGritCheckApplicationDispositionSchema = exports_typebox.Union([GritEvaluatedDispositionSchema, GritNotApplicableDispositionSchema, GritFailedDispositionSchema], { description: "Compatibility Grit evaluation disposition." });
48939
+ var GritInstanceCheckApplicationReportSchema = exports_typebox.Object({
48940
+ ownerProject: ReportOwnerProjectSchema,
48941
+ instanceId: ReportInstanceIdSchema,
48942
+ ruleId: ReportRuleIdSchema,
48943
+ runner: GritRunnerSchema,
48944
+ lane: ReportLaneSchema,
48945
+ locked: InstanceReportLockSchema,
48712
48946
  status: CheckApplicationStatusSchema,
48713
- message: exports_typebox.String({
48714
- minLength: 1,
48715
- maxLength: 8192,
48716
- description: "Rule-authored finding message."
48717
- }),
48718
- remediate: exports_typebox.Union([exports_typebox.String({ maxLength: 16384 }), exports_typebox.Null()], {
48719
- description: "Rule-authored remediation when supplied."
48720
- }),
48947
+ message: ReportMessageSchema,
48948
+ remediate: ReportRemediationSchema,
48721
48949
  disposition: GritCheckApplicationDispositionSchema,
48722
48950
  findings: exports_typebox.Array(GritCheckFindingSchema, {
48723
48951
  description: "Deterministically ordered findings for this application."
48724
48952
  })
48725
48953
  }, {
48726
48954
  additionalProperties: false,
48727
- description: "One resolved application check report."
48955
+ description: "One version-three Grit application report."
48956
+ });
48957
+ var CompatibilityGritCheckApplicationReportSchema = exports_typebox.Object({
48958
+ ownerProject: ReportOwnerProjectSchema,
48959
+ instanceId: exports_typebox.Null({ description: "Compatibility rules have no version-three instance." }),
48960
+ ruleId: ReportRuleIdSchema,
48961
+ runner: GritRunnerSchema,
48962
+ lane: ReportLaneSchema,
48963
+ locked: CompatibilityReportLockSchema,
48964
+ status: CheckApplicationStatusSchema,
48965
+ message: ReportMessageSchema,
48966
+ remediate: ReportRemediationSchema,
48967
+ disposition: CompatibilityGritCheckApplicationDispositionSchema,
48968
+ findings: exports_typebox.Array(GritCheckFindingSchema, {
48969
+ description: "Deterministically ordered findings for this compatibility rule."
48970
+ })
48971
+ }, {
48972
+ additionalProperties: false,
48973
+ description: "One version-two compatibility Grit report."
48728
48974
  });
48729
48975
  var StructureFindingCodeSchema = exports_typebox.Union([
48730
48976
  exports_typebox.Literal("root-missing"),
@@ -48749,7 +48995,7 @@ var StructureCheckFindingSchema = exports_typebox.Object({
48749
48995
  description: "Service-owned severity derived from the application lane."
48750
48996
  }),
48751
48997
  baselined: exports_typebox.Literal(false, {
48752
- description: "Version-three findings do not inherit predecessor baselines."
48998
+ description: "No admitted baseline suppresses this observed finding."
48753
48999
  })
48754
49000
  }, { additionalProperties: false, description: "One path-only native structure finding." });
48755
49001
  var StructureCheckApplicationDispositionSchema = exports_typebox.Union([
@@ -48775,46 +49021,42 @@ var StructureCheckApplicationDispositionSchema = exports_typebox.Union([
48775
49021
  })
48776
49022
  }, { additionalProperties: false, description: "Failed native structure evaluation." })
48777
49023
  ], { description: "Native structure evaluation disposition." });
48778
- var StructureCheckApplicationReportSchema = exports_typebox.Object({
48779
- ownerProject: exports_typebox.String({
48780
- minLength: 1,
48781
- maxLength: 250,
48782
- description: "Repository project that owns this structure application."
48783
- }),
48784
- instanceId: exports_typebox.String({
48785
- minLength: 1,
48786
- maxLength: 250,
48787
- description: "Resolved instance evaluated by this structure application."
48788
- }),
48789
- ruleId: exports_typebox.String({
48790
- minLength: 1,
48791
- maxLength: 200,
48792
- description: "Native structure rule evaluated for this instance."
48793
- }),
48794
- runner: exports_typebox.Literal("habitat", {
48795
- description: "Native Habitat runner used by this application."
48796
- }),
48797
- lane: exports_typebox.Union([exports_typebox.Literal("enforced"), exports_typebox.Literal("advisory")], {
48798
- description: "Policy lane that determines finding severity and completion status."
48799
- }),
48800
- locked: exports_typebox.Literal(false, {
48801
- description: "Native structure reports do not expose Grit lock semantics."
48802
- }),
49024
+ var StructureInstanceCheckApplicationReportSchema = exports_typebox.Object({
49025
+ ownerProject: ReportOwnerProjectSchema,
49026
+ instanceId: ReportInstanceIdSchema,
49027
+ ruleId: ReportRuleIdSchema,
49028
+ runner: StructureRunnerSchema,
49029
+ lane: ReportLaneSchema,
49030
+ locked: InstanceReportLockSchema,
48803
49031
  status: CheckApplicationStatusSchema,
48804
- message: exports_typebox.String({
48805
- minLength: 1,
48806
- maxLength: 8192,
48807
- description: "Catalog-authored human guidance for this structure rule."
48808
- }),
48809
- remediate: exports_typebox.Union([exports_typebox.String({ maxLength: 16384 }), exports_typebox.Null()], {
48810
- description: "Optional catalog-authored remediation guidance."
48811
- }),
49032
+ message: ReportMessageSchema,
49033
+ remediate: ReportRemediationSchema,
48812
49034
  disposition: StructureCheckApplicationDispositionSchema,
48813
49035
  findings: exports_typebox.Array(StructureCheckFindingSchema, {
48814
49036
  description: "Deterministically ordered path-only structure findings."
48815
49037
  })
48816
- }, { additionalProperties: false, description: "One native Habitat structure report." });
48817
- var CheckApplicationReportSchema = exports_typebox.Union([GritCheckApplicationReportSchema, StructureCheckApplicationReportSchema], { description: "Runner-discriminated application check report." });
49038
+ }, { additionalProperties: false, description: "One version-three native structure report." });
49039
+ var CompatibilityStructureCheckApplicationReportSchema = exports_typebox.Object({
49040
+ ownerProject: ReportOwnerProjectSchema,
49041
+ instanceId: exports_typebox.Null({ description: "Compatibility rules have no version-three instance." }),
49042
+ ruleId: ReportRuleIdSchema,
49043
+ runner: StructureRunnerSchema,
49044
+ lane: ReportLaneSchema,
49045
+ locked: CompatibilityReportLockSchema,
49046
+ status: CheckApplicationStatusSchema,
49047
+ message: ReportMessageSchema,
49048
+ remediate: ReportRemediationSchema,
49049
+ disposition: StructureCheckApplicationDispositionSchema,
49050
+ findings: exports_typebox.Array(StructureCheckFindingSchema, {
49051
+ description: "Deterministically ordered path-only compatibility findings."
49052
+ })
49053
+ }, { additionalProperties: false, description: "One version-two compatibility structure report." });
49054
+ var CheckApplicationReportSchema = exports_typebox.Union([
49055
+ GritInstanceCheckApplicationReportSchema,
49056
+ CompatibilityGritCheckApplicationReportSchema,
49057
+ StructureInstanceCheckApplicationReportSchema,
49058
+ CompatibilityStructureCheckApplicationReportSchema
49059
+ ], { description: "Runner- and authority-discriminated application check report." });
48818
49060
  var CheckCatalogResultSchema = exports_typebox.Union([
48819
49061
  exports_typebox.Object({
48820
49062
  _tag: exports_typebox.Literal("CatalogRejected", {
@@ -49849,6 +50091,7 @@ var policyPackPackageJsonValidator = new Validator({}, PolicyPackPackageJsonSche
49849
50091
  var instanceValidator = new Validator({}, HabitatInstanceManifestSchema);
49850
50092
  var compatibilityIndexValidator = new Validator({}, CompatibilityIndexSchema);
49851
50093
  var compatibilityRuleValidator = new Validator({}, CompatibilityRuleSourceSchema);
50094
+ var compatibilityBaselineValidator = new Validator({}, CompatibilityBaselineSchema);
49852
50095
  function admitPolicyPackSelection(selection, path) {
49853
50096
  const issues = [];
49854
50097
  if (!path.isAbsolute(selection.packageJsonPath)) {
@@ -49899,8 +50142,29 @@ function admitCompatibilityRule(value4, relativePath) {
49899
50142
  const admitted = admit(compatibilityRuleValidator, value4, relativePath);
49900
50143
  return admitted.ok ? { ok: true, source: { rule: admitted.value, relativePath } } : admitted;
49901
50144
  }
50145
+ function admitCompatibilityBaseline(value4, relativePath) {
50146
+ return admit(compatibilityBaselineValidator, value4, relativePath);
50147
+ }
49902
50148
  function referencedRepositoryPaths(documents, path) {
49903
50149
  const references = new Set;
50150
+ for (const root of Object.values(documents.compatibilityIndex?.ownerRoots ?? {})) {
50151
+ if (relativePathIssues(root, ".habitat/index.json", path).length === 0) {
50152
+ references.add(toRepositoryPath(root, path));
50153
+ }
50154
+ }
50155
+ for (const source of documents.compatibilityRules) {
50156
+ const rule = source.rule;
50157
+ const paths = [
50158
+ rule.supportFiles.baseline,
50159
+ rule.runner.name === "grit" ? rule.runner.files.pattern : rule.runner.files.structure,
50160
+ ...rule.runner.name === "grit" ? rule.runner.acquisition.roots : []
50161
+ ];
50162
+ for (const referencedPath of paths) {
50163
+ if (relativePathIssues(referencedPath, source.relativePath, path).length === 0) {
50164
+ references.add(toRepositoryPath(referencedPath, path));
50165
+ }
50166
+ }
50167
+ }
49904
50168
  for (const source of documents.blueprints) {
49905
50169
  const directory = path.dirname(source.relativePath);
49906
50170
  for (const rule of source.definition.rules) {
@@ -49949,10 +50213,10 @@ function resolveCatalog(documents, pathFacts, workspaceRoot, workspaceRealRoot,
49949
50213
  for (const source of blueprints) {
49950
50214
  issues.push(...validateBlueprint(source, path));
49951
50215
  }
49952
- const compatibility = resolveCompatibility(documents, issues, path);
50216
+ const compatibility = resolveCompatibility(documents, issues, pathFacts, workspaceRoot, workspaceRealRoot, path);
49953
50217
  const ruleSources = [
49954
50218
  ...blueprints.flatMap((source) => source.definition.rules.map((rule) => ({ identity: rule.id, path: source.relativePath }))),
49955
- ...compatibility.rules.map((rule) => ({ identity: rule.id, path: rule.manifestPath }))
50219
+ ...compatibility.rules.map((rule) => ({ identity: rule.ruleId, path: rule.manifestPath }))
49956
50220
  ];
49957
50221
  issues.push(...duplicateIssues(ruleSources, "authority-duplicate-rule", "rule"));
49958
50222
  const definitions = new Map(blueprints.map((source) => [blueprintIdentity(source.definition), source]));
@@ -50090,22 +50354,72 @@ function rejected(issues) {
50090
50354
  issues: stable.length > 0 ? stable : [issue("authority-resolution-failed", "", "Catalog resolution failed.")]
50091
50355
  };
50092
50356
  }
50093
- function resolveCompatibility(documents, issues, path) {
50357
+ function resolveCompatibility(documents, issues, pathFacts, workspaceRoot, workspaceRealRoot, path) {
50094
50358
  if (!documents.compatibilityIndex) {
50095
50359
  return { schemaVersion: 2, ownerRoots: {}, rules: [] };
50096
50360
  }
50097
50361
  const ownerRoots = Object.fromEntries(Object.entries(documents.compatibilityIndex.ownerRoots).sort(([left], [right]) => textOrder(left, right)));
50098
50362
  for (const [owner, root] of Object.entries(ownerRoots)) {
50099
50363
  issues.push(...relativePathIssues(root, `.habitat/index.json#ownerRoots:${owner}`, path));
50364
+ issues.push(...pathFactIssues(root, "directory", `.habitat/index.json#ownerRoots:${owner}`, pathFacts, workspaceRoot, workspaceRealRoot, path));
50100
50365
  }
50101
50366
  const rules = [...documents.compatibilityRules].sort((left, right) => textOrder(left.rule.id, right.rule.id) || textOrder(left.relativePath, right.relativePath)).map((source) => {
50102
- if (!Object.hasOwn(ownerRoots, source.rule.ownerProject)) {
50103
- issues.push(issue("authority-compatibility-invalid", source.relativePath, `Legacy rule ownerProject "${source.rule.ownerProject}" has no owner root.`));
50367
+ const rule = source.rule;
50368
+ if (!Object.hasOwn(ownerRoots, rule.ownerProject)) {
50369
+ issues.push(issue("authority-compatibility-invalid", source.relativePath, `Legacy rule ownerProject "${rule.ownerProject}" has no owner root.`));
50370
+ }
50371
+ for (const pattern4 of rule.pathCoverage[0].patterns) {
50372
+ issues.push(...repositoryPatternIssues(pattern4, source.relativePath, path));
50373
+ }
50374
+ const baselinePath = rule.supportFiles.baseline;
50375
+ const runnerAssetPath = rule.runner.name === "grit" ? rule.runner.files.pattern : rule.runner.files.structure;
50376
+ issues.push(...pathFactIssues(baselinePath, "file", source.relativePath, pathFacts, workspaceRoot, workspaceRealRoot, path), ...pathFactIssues(runnerAssetPath, "file", source.relativePath, pathFacts, workspaceRoot, workspaceRealRoot, path));
50377
+ const provenance = {
50378
+ kind: "local",
50379
+ authorityRoot: workspaceRoot,
50380
+ relativePath: source.relativePath
50381
+ };
50382
+ const asset = (relativePath) => ({
50383
+ provenance,
50384
+ relativePath,
50385
+ absolutePath: path.resolve(workspaceRoot, relativePath)
50386
+ });
50387
+ const common = {
50388
+ ruleId: rule.id,
50389
+ ownerProject: rule.ownerProject,
50390
+ manifestPath: source.relativePath,
50391
+ lane: rule.lane,
50392
+ message: rule.message,
50393
+ remediate: rule.remediate,
50394
+ provenance,
50395
+ coveragePatterns: [...rule.pathCoverage[0].patterns],
50396
+ baseline: asset(baselinePath)
50397
+ };
50398
+ if (rule.runner.name === "habitat") {
50399
+ return {
50400
+ ...common,
50401
+ runner: {
50402
+ name: "habitat",
50403
+ mode: "structure",
50404
+ structure: asset(runnerAssetPath)
50405
+ }
50406
+ };
50407
+ }
50408
+ const entries3 = [];
50409
+ for (const root of rule.runner.acquisition.roots) {
50410
+ const admission = pathFactAnyIssues(root, source.relativePath, pathFacts, workspaceRoot, workspaceRealRoot, path);
50411
+ issues.push(...admission.issues);
50412
+ if (admission.kind !== undefined)
50413
+ entries3.push({ kind: admission.kind, path: root });
50104
50414
  }
50105
50415
  return {
50106
- id: source.rule.id,
50107
- ownerProject: source.rule.ownerProject,
50108
- manifestPath: source.relativePath
50416
+ ...common,
50417
+ runner: {
50418
+ name: "grit",
50419
+ pattern: asset(runnerAssetPath),
50420
+ patternName: rule.runner.patternName,
50421
+ acquisition: { kind: "check", entries: entries3 }
50422
+ }
50109
50423
  };
50110
50424
  });
50111
50425
  return { schemaVersion: 2, ownerRoots, rules };
@@ -50309,6 +50623,15 @@ function pathFactIssues(relativePath, expectedKind, sourcePath, facts, workspace
50309
50623
  }
50310
50624
  return [];
50311
50625
  }
50626
+ function pathFactAnyIssues(relativePath, sourcePath, facts, workspaceRoot, workspaceRealRoot, path) {
50627
+ const normalized = toRepositoryPath(relativePath, path);
50628
+ const fact = facts.get(normalized);
50629
+ const kind = fact?.kind === "directory" || fact?.kind === "file" ? fact.kind : undefined;
50630
+ return {
50631
+ kind,
50632
+ issues: pathFactIssues(normalized, kind ?? "directory", sourcePath, facts, workspaceRoot, workspaceRealRoot, path)
50633
+ };
50634
+ }
50312
50635
  function ruleAssetPath(source, rule, path) {
50313
50636
  const asset = rule.runner.name === "habitat" ? rule.runner.structure : rule.runner.pattern;
50314
50637
  return toRepositoryPath(path.join(path.dirname(source.relativePath), asset), path);
@@ -50319,6 +50642,12 @@ function relativePathIssues(candidate, sourcePath, path) {
50319
50642
  issue("authority-path-invalid", sourcePath, `Path must be normalized, repository-relative, traversal-free, and non-glob: "${candidate}".`)
50320
50643
  ] : [];
50321
50644
  }
50645
+ function repositoryPatternIssues(candidate, sourcePath, path) {
50646
+ const invalid2 = candidate.includes("\\") || path.isAbsolute(candidate) || candidate.includes("//") || candidate.endsWith("/") || candidate.split("/").some((segment) => segment === "" || segment === "..") || /[\u0000-\u001f\u007f]/u.test(candidate);
50647
+ return invalid2 ? [
50648
+ issue("authority-path-invalid", sourcePath, `Coverage pattern must be repository-relative and traversal-free: "${candidate}".`)
50649
+ ] : [];
50650
+ }
50322
50651
  function pathTemplateIssues(template2, sourcePath, path) {
50323
50652
  const placeholderCount = template2.split(MEMBER_PLACEHOLDER).length - 1;
50324
50653
  const substituted = template2.replaceAll(MEMBER_PLACEHOLDER, "member");
@@ -50425,7 +50754,11 @@ function selectCheckApplications(catalog2, input) {
50425
50754
  }
50426
50755
  if (issues.length > 0)
50427
50756
  return refused(issues);
50428
- const selected = catalog2.applications.filter((application) => (selectors?.owner === undefined || application.ownerProject === selectors.owner) && (selectors?.instance === undefined || application.instanceId === selectors.instance) && (requestedRules.length === 0 || requestedRules.includes(application.ruleId)) && (selectors?.runner === undefined || application.runner.name === selectors.runner));
50757
+ const applications = [
50758
+ ...catalog2.applications,
50759
+ ...catalog2.compatibility.rules
50760
+ ];
50761
+ const selected = applications.filter((application) => (selectors?.owner === undefined || application.ownerProject === selectors.owner) && (selectors?.instance === undefined || isInstanceApplication(application) && application.instanceId === selectors.instance) && (requestedRules.length === 0 || requestedRules.includes(application.ruleId)) && (selectors?.runner === undefined || application.runner.name === selectors.runner));
50429
50762
  if (hasExplicitSelectors && selected.length === 0 && !isKnownEmptyRunnerSelection(selectors)) {
50430
50763
  return refused([
50431
50764
  issue2("selector-empty", "selectors", "The requested selector intersection contains no resolved applications.")
@@ -50433,7 +50766,7 @@ function selectCheckApplications(catalog2, input) {
50433
50766
  }
50434
50767
  const unsupported = selected.filter(isUnsupportedGritApplication);
50435
50768
  if (unsupported.length > 0) {
50436
- return refused(unsupported.map((application) => issue2("runner-unsupported", `${application.instanceId}:${application.ruleId}`, `Rule "${application.ruleId}" requires Grit ${application.runner.acquisition.kind}, which catalog.check does not execute.`)));
50769
+ return refused(unsupported.map((application) => issue2("runner-unsupported", applicationIdentityText(application), `Rule "${application.ruleId}" requires Grit ${application.runner.acquisition.kind}, which catalog.check does not execute.`)));
50437
50770
  }
50438
50771
  return {
50439
50772
  ok: true,
@@ -50479,6 +50812,21 @@ function failedApplication(application, reason, detail) {
50479
50812
  findings: []
50480
50813
  };
50481
50814
  }
50815
+ function notApplicableApplication(application) {
50816
+ return {
50817
+ ownerProject: application.ownerProject,
50818
+ instanceId: null,
50819
+ ruleId: application.ruleId,
50820
+ runner: "grit",
50821
+ lane: application.lane,
50822
+ locked: true,
50823
+ message: application.message,
50824
+ remediate: application.remediate,
50825
+ status: "pass",
50826
+ disposition: { kind: "not-applicable", reason: "no-matched-acquisition-roots" },
50827
+ findings: []
50828
+ };
50829
+ }
50482
50830
  function evaluatedStructureApplication(application, diagnostics) {
50483
50831
  const severity = application.lane === "enforced" ? "error" : "advisory";
50484
50832
  return {
@@ -50508,6 +50856,18 @@ function completedCheck(applications) {
50508
50856
  };
50509
50857
  }
50510
50858
  function applicationIdentity(application) {
50859
+ if (isCompatibilityRule(application)) {
50860
+ return {
50861
+ ownerProject: application.ownerProject,
50862
+ instanceId: null,
50863
+ ruleId: application.ruleId,
50864
+ runner: "grit",
50865
+ lane: application.lane,
50866
+ locked: true,
50867
+ message: application.message,
50868
+ remediate: application.remediate
50869
+ };
50870
+ }
50511
50871
  return {
50512
50872
  ownerProject: application.ownerProject,
50513
50873
  instanceId: application.instanceId,
@@ -50520,6 +50880,18 @@ function applicationIdentity(application) {
50520
50880
  };
50521
50881
  }
50522
50882
  function structureApplicationIdentity(application) {
50883
+ if (isCompatibilityRule(application)) {
50884
+ return {
50885
+ ownerProject: application.ownerProject,
50886
+ instanceId: null,
50887
+ ruleId: application.ruleId,
50888
+ runner: "habitat",
50889
+ lane: application.lane,
50890
+ locked: true,
50891
+ message: application.message,
50892
+ remediate: application.remediate
50893
+ };
50894
+ }
50523
50895
  return {
50524
50896
  ownerProject: application.ownerProject,
50525
50897
  instanceId: application.instanceId,
@@ -50541,7 +50913,7 @@ function isExecutableCheckApplication(application) {
50541
50913
  return application.runner.name === "habitat" || isGritCheckApplication(application);
50542
50914
  }
50543
50915
  function compareApplications(left, right) {
50544
- return compareText5(left.ruleId, right.ruleId) || compareText5(left.instanceId, right.instanceId) || compareText5(left.ownerProject, right.ownerProject);
50916
+ return compareText5(left.ruleId, right.ruleId) || compareText5(instanceId(left) ?? "", instanceId(right) ?? "") || compareText5(left.ownerProject, right.ownerProject);
50545
50917
  }
50546
50918
  function compareText5(left, right) {
50547
50919
  return left < right ? -1 : left > right ? 1 : 0;
@@ -50553,17 +50925,34 @@ function issue2(code, selector, message) {
50553
50925
  return { code, selector, message };
50554
50926
  }
50555
50927
  function selectionIssue(catalog2, kind, value4) {
50928
+ const applications = [
50929
+ ...catalog2.applications,
50930
+ ...catalog2.compatibility.rules
50931
+ ];
50556
50932
  const matches = {
50557
- owner: catalog2.applications.some((application) => application.ownerProject === value4),
50933
+ owner: applications.some((application) => application.ownerProject === value4),
50558
50934
  instance: catalog2.applications.some((application) => application.instanceId === value4),
50559
- rule: catalog2.applications.some((application) => application.ruleId === value4),
50560
- runner: catalog2.applications.some((application) => application.runner.name === value4)
50935
+ rule: applications.some((application) => application.ruleId === value4),
50936
+ runner: applications.some((application) => application.runner.name === value4)
50561
50937
  };
50562
50938
  if (matches[kind] || kind === "runner" && knownRunnerSelectors.has(value4))
50563
50939
  return;
50564
50940
  const actualKind = ["owner", "instance", "rule", "runner"].find((candidate) => candidate !== kind && matches[candidate]);
50565
50941
  return actualKind === undefined ? issue2("selector-unknown", `${kind}:${value4}`, `No resolved application uses ${kind} "${value4}".`) : issue2("selector-wrong-namespace", `${kind}:${value4}`, `"${value4}" is a known ${actualKind}, not a ${kind}.`);
50566
50942
  }
50943
+ function isCompatibilityRule(application) {
50944
+ return "baseline" in application;
50945
+ }
50946
+ function isInstanceApplication(application) {
50947
+ return "instanceId" in application;
50948
+ }
50949
+ function instanceId(application) {
50950
+ return isInstanceApplication(application) ? application.instanceId : null;
50951
+ }
50952
+ function applicationIdentityText(application) {
50953
+ const instance = instanceId(application);
50954
+ return instance === null ? application.ruleId : `${instance}:${application.ruleId}`;
50955
+ }
50567
50956
  function isKnownEmptyRunnerSelection(selectors) {
50568
50957
  return selectors?.owner === undefined && selectors?.instance === undefined && selectors?.rule === undefined && selectors?.rules === undefined && selectors?.runner !== undefined && knownRunnerSelectors.has(selectors.runner);
50569
50958
  }
@@ -50626,6 +51015,33 @@ var StructureScopeSchema = exports_typebox.Object({
50626
51015
  description: "Unique direct-child globs rejected in every scope mode."
50627
51016
  }))
50628
51017
  }, { additionalProperties: false, description: "One closed Habitat structure scope." });
51018
+ var CompatibilityStructureScopeSchema = exports_typebox.Object({
51019
+ name: exports_typebox.String({
51020
+ minLength: 1,
51021
+ maxLength: 200,
51022
+ description: "Stable identity for one compatibility structure scope."
51023
+ }),
51024
+ root: RootRelativePatternSchema,
51025
+ kind: exports_typebox.Union([exports_typebox.Literal("directory"), exports_typebox.Literal("file")], {
51026
+ description: "Expected kind for every matched scope root."
51027
+ }),
51028
+ mode: exports_typebox.Union([exports_typebox.Literal("open"), exports_typebox.Literal("closed")], {
51029
+ description: "Whether unmatched direct children are admitted."
51030
+ }),
51031
+ allowEmpty: exports_typebox.Optional(exports_typebox.Boolean({ description: "Whether a scope may match no visible roots." })),
51032
+ required: exports_typebox.Optional(exports_typebox.Array(DirectChildPatternSchema, {
51033
+ uniqueItems: true,
51034
+ description: "Unique direct-child globs that must each match at least one child."
51035
+ })),
51036
+ allowed: exports_typebox.Optional(exports_typebox.Array(DirectChildPatternSchema, {
51037
+ uniqueItems: true,
51038
+ description: "Unique direct-child globs admitted by a closed scope."
51039
+ })),
51040
+ forbidden: exports_typebox.Optional(exports_typebox.Array(DirectChildPatternSchema, {
51041
+ uniqueItems: true,
51042
+ description: "Unique direct-child globs rejected in every scope mode."
51043
+ }))
51044
+ }, { additionalProperties: false, description: "One closed compatibility structure scope." });
50629
51045
  var StructureDocumentShapeSchema = exports_typebox.Object({
50630
51046
  schemaVersion: exports_typebox.Literal(2, { description: "Structure document schema version." }),
50631
51047
  scopes: exports_typebox.Array(StructureScopeSchema, {
@@ -50634,9 +51050,20 @@ var StructureDocumentShapeSchema = exports_typebox.Object({
50634
51050
  })
50635
51051
  }, { additionalProperties: false, description: "Closed Habitat structure document." });
50636
51052
  var StructureDocumentSchema = exports_typebox.Refine(StructureDocumentShapeSchema, hasUniqueScopeNames, () => "Expected unique structure scope names");
51053
+ var CompatibilityStructureDocumentShapeSchema = exports_typebox.Object({
51054
+ schemaVersion: exports_typebox.Literal(1, { description: "Compatibility structure schema version." }),
51055
+ scopes: exports_typebox.Array(CompatibilityStructureScopeSchema, {
51056
+ minItems: 1,
51057
+ description: "Compatibility structure scopes evaluated in declared order."
51058
+ })
51059
+ }, { additionalProperties: false, description: "Closed compatibility structure document." });
51060
+ var CompatibilityStructureDocumentSchema = exports_typebox.Refine(CompatibilityStructureDocumentShapeSchema, hasUniqueCompatibilityScopeNames, () => "Expected unique compatibility structure scope names");
50637
51061
  function hasUniqueScopeNames(document) {
50638
51062
  return new Set(document.scopes.map((scope3) => scope3.name)).size === document.scopes.length;
50639
51063
  }
51064
+ function hasUniqueCompatibilityScopeNames(document) {
51065
+ return new Set(document.scopes.map((scope3) => scope3.name)).size === document.scopes.length;
51066
+ }
50640
51067
  function isSafeRootRelativePattern(value4) {
50641
51068
  if (!isValidGlob(value4))
50642
51069
  return false;
@@ -50661,7 +51088,34 @@ function isHabitatStructureApplication(application) {
50661
51088
  return application.runner.name === "habitat";
50662
51089
  }
50663
51090
  var structureValidator = new Validator({}, StructureDocumentSchema);
51091
+ var compatibilityStructureValidator = new Validator({}, CompatibilityStructureDocumentSchema);
50664
51092
  function admitStructureDocument(value4, application) {
51093
+ if (isCompatibilityStructureApplication(application)) {
51094
+ if (!compatibilityStructureValidator.Check(value4)) {
51095
+ const [, errors4] = compatibilityStructureValidator.Errors(value4);
51096
+ return {
51097
+ ok: false,
51098
+ detail: errors4.slice(0, 20).map((error2) => error2.message).join("; ") || "Structure document does not satisfy compatibility schema version 1."
51099
+ };
51100
+ }
51101
+ return {
51102
+ ok: true,
51103
+ admitted: {
51104
+ application,
51105
+ scopes: value4.scopes.map((scope3) => ({
51106
+ name: scope3.name,
51107
+ relativePath: scope3.root,
51108
+ kind: scope3.kind,
51109
+ mode: scope3.mode,
51110
+ allowEmpty: scope3.allowEmpty ?? false,
51111
+ ...scope3.required === undefined ? {} : { required: scope3.required },
51112
+ ...scope3.allowed === undefined ? {} : { allowed: scope3.allowed },
51113
+ ...scope3.forbidden === undefined ? {} : { forbidden: scope3.forbidden },
51114
+ bindingPath: "."
51115
+ }))
51116
+ }
51117
+ };
51118
+ }
50665
51119
  if (!structureValidator.Check(value4)) {
50666
51120
  const [, errors4] = structureValidator.Errors(value4);
50667
51121
  return {
@@ -50691,10 +51145,23 @@ function admitStructureDocument(value4, application) {
50691
51145
  detail: `Structure scope "${scope3.name}" resolves beyond the maximum repository path length.`
50692
51146
  };
50693
51147
  }
50694
- scopes.push({ ...scope3, allowEmpty: scope3.allowEmpty ?? false, bindingPath: binding.path });
51148
+ scopes.push({
51149
+ name: scope3.name,
51150
+ relativePath: scope3.relativePath,
51151
+ kind: scope3.kind,
51152
+ mode: scope3.mode,
51153
+ allowEmpty: scope3.allowEmpty ?? false,
51154
+ ...scope3.required === undefined ? {} : { required: scope3.required },
51155
+ ...scope3.allowed === undefined ? {} : { allowed: scope3.allowed },
51156
+ ...scope3.forbidden === undefined ? {} : { forbidden: scope3.forbidden },
51157
+ bindingPath: binding.path
51158
+ });
50695
51159
  }
50696
51160
  return { ok: true, admitted: { application, scopes } };
50697
51161
  }
51162
+ function isCompatibilityStructureApplication(application) {
51163
+ return "baseline" in application;
51164
+ }
50698
51165
  function makeStructureUniverse(inventory) {
50699
51166
  const trackedNonFilePaths = new Set(inventory.trackedNonFilePaths);
50700
51167
  const visiblePaths = inventory.paths.filter((candidate) => !ancestors(candidate).some((ancestor) => trackedNonFilePaths.has(ancestor)));
@@ -50921,6 +51388,13 @@ var excludedDirectorySegments = new Set([
50921
51388
  "vendor"
50922
51389
  ]);
50923
51390
  var excludedRepositoryGlobs = [...excludedDirectorySegments].map((segment) => `**/${segment}/**`);
51391
+ var compatibilityProtectedRoots = [
51392
+ ".git",
51393
+ ".habitat/cache/patterns",
51394
+ "dist",
51395
+ "node_modules",
51396
+ "tools/habitat/dist"
51397
+ ];
50924
51398
  var MAX_MANIFEST_DIRECTORIES = 50000;
50925
51399
  function resolveCurrentCatalog(context4) {
50926
51400
  return exports_Effect.gen(function* () {
@@ -51229,10 +51703,69 @@ function resolveCurrentCatalog(context4) {
51229
51703
  continue;
51230
51704
  }
51231
51705
  const admitted = admitCompatibilityRule(parsed.success, relativePath);
51232
- if (admitted.ok)
51233
- compatibilityRules.push(admitted.source);
51234
- else
51706
+ if (!admitted.ok) {
51235
51707
  issues.push(...admitted.issues);
51708
+ continue;
51709
+ }
51710
+ const baselinePath = admitted.source.rule.supportFiles.baseline;
51711
+ const absoluteBaselinePath = path.resolve(workspaceRoot, baselinePath);
51712
+ if (!isContained2(workspaceRoot, absoluteBaselinePath, path)) {
51713
+ issues.push({
51714
+ code: "authority-path-escape",
51715
+ path: baselinePath,
51716
+ message: "Compatibility baseline escapes workspaceRoot."
51717
+ });
51718
+ continue;
51719
+ }
51720
+ const baselineRealPath = yield* exports_Effect.result(fileSystem.realPath(absoluteBaselinePath));
51721
+ if (baselineRealPath._tag === "Failure") {
51722
+ issues.push(filesystemIssue(baselineRealPath.failure, baselinePath, "resolve compatibility baseline", "Compatibility baseline does not exist."));
51723
+ continue;
51724
+ }
51725
+ if (!isContained2(workspaceRealRoot, baselineRealPath.success, path)) {
51726
+ issues.push({
51727
+ code: "authority-path-escape",
51728
+ path: baselinePath,
51729
+ message: "Compatibility baseline escapes workspaceRoot through a symbolic link."
51730
+ });
51731
+ continue;
51732
+ }
51733
+ const baselineStat = yield* exports_Effect.result(fileSystem.stat(baselineRealPath.success));
51734
+ if (baselineStat._tag === "Failure") {
51735
+ issues.push(filesystemIssue(baselineStat.failure, baselinePath, "inspect compatibility baseline", "Compatibility baseline does not exist."));
51736
+ continue;
51737
+ }
51738
+ if (baselineStat.success.type !== "File") {
51739
+ issues.push({
51740
+ code: "authority-path-kind-mismatch",
51741
+ path: baselinePath,
51742
+ message: "Compatibility baseline must be a regular file."
51743
+ });
51744
+ continue;
51745
+ }
51746
+ const baselineRead = yield* exports_Effect.result(fileSystem.readFileString(baselineRealPath.success));
51747
+ if (baselineRead._tag === "Failure") {
51748
+ issues.push(filesystemIssue(baselineRead.failure, baselinePath, "read compatibility baseline", "Compatibility baseline does not exist."));
51749
+ continue;
51750
+ }
51751
+ const baselineParsed = yield* exports_Effect.result(exports_Effect.try({
51752
+ try: () => JSON.parse(baselineRead.success),
51753
+ catch: (cause) => cause
51754
+ }));
51755
+ if (baselineParsed._tag === "Failure") {
51756
+ issues.push({
51757
+ code: "authority-json-invalid",
51758
+ path: baselinePath,
51759
+ message: "Compatibility baseline is not valid JSON."
51760
+ });
51761
+ continue;
51762
+ }
51763
+ const baseline = admitCompatibilityBaseline(baselineParsed.success, baselinePath);
51764
+ if (!baseline.ok) {
51765
+ issues.push(...baseline.issues);
51766
+ continue;
51767
+ }
51768
+ compatibilityRules.push({ ...admitted.source, baseline: baseline.value });
51236
51769
  }
51237
51770
  if (issues.length > 0)
51238
51771
  return rejected(issues);
@@ -51447,7 +51980,19 @@ var check7 = module3.check.effect(function* ({ context: context4, input }) {
51447
51980
  reports.push(failedApplication(application, "PatternInvalid", program.detail));
51448
51981
  continue;
51449
51982
  }
51450
- const subjects = resolvedSubjects(application, context4.workspaceRoot, context4.path);
51983
+ const subjectPreparation = yield* prepareGritSubjects(application, context4.workspaceRoot, context4.fileSystem, context4.path);
51984
+ if (subjectPreparation.kind === "failed") {
51985
+ reports.push(failedApplication(application, "SetupFailed", subjectPreparation.detail));
51986
+ continue;
51987
+ }
51988
+ if (subjectPreparation.kind === "not-applicable") {
51989
+ if (!isCompatibilityRule(application)) {
51990
+ return yield* exports_Effect.die(new Error("Version-three Grit applications cannot be not applicable."));
51991
+ }
51992
+ reports.push(notApplicableApplication(application));
51993
+ continue;
51994
+ }
51995
+ const subjects = subjectPreparation.subjects;
51451
51996
  const evaluation = yield* exports_Effect.result(context4.ruleEvaluation.evaluate({
51452
51997
  program: program.program,
51453
51998
  subjectPaths: subjects.map((subject) => subject.absolutePath)
@@ -51492,6 +52037,100 @@ function hasExactCauseCode(error2, code) {
51492
52037
  const cause = "cause" in error2.reason ? error2.reason.cause : undefined;
51493
52038
  return typeof cause === "object" && cause !== null && "code" in cause && cause.code === code;
51494
52039
  }
52040
+ function prepareGritSubjects(application, workspaceRoot, fileSystem, path) {
52041
+ if (!isCompatibilityRule(application)) {
52042
+ return exports_Effect.succeed({
52043
+ kind: "ready",
52044
+ subjects: resolvedSubjects(application, workspaceRoot, path)
52045
+ });
52046
+ }
52047
+ return exports_Effect.gen(function* () {
52048
+ const workspaceRealPath = yield* exports_Effect.result(fileSystem.realPath(workspaceRoot));
52049
+ if (workspaceRealPath._tag === "Failure") {
52050
+ return {
52051
+ kind: "failed",
52052
+ detail: "Unable to canonicalize the compatibility workspace root."
52053
+ };
52054
+ }
52055
+ const authority = resolvedSubjects(application, workspaceRoot, path);
52056
+ for (const root of authority) {
52057
+ const canonical = yield* exports_Effect.result(fileSystem.realPath(root.absolutePath));
52058
+ if (canonical._tag === "Failure") {
52059
+ return {
52060
+ kind: "failed",
52061
+ detail: `Unable to canonicalize compatibility acquisition root "${toRepositoryPath2(path.relative(workspaceRoot, root.absolutePath), path.sep)}".`
52062
+ };
52063
+ }
52064
+ const expectedCanonical = path.resolve(workspaceRealPath.success, path.relative(workspaceRoot, root.absolutePath));
52065
+ if (canonical.success !== expectedCanonical || !isContained2(workspaceRealPath.success, canonical.success, path)) {
52066
+ return {
52067
+ kind: "failed",
52068
+ detail: `Compatibility acquisition root "${toRepositoryPath2(path.relative(workspaceRoot, root.absolutePath), path.sep)}" is a symbolic link; compatibility checks accept direct workspace roots only.`
52069
+ };
52070
+ }
52071
+ }
52072
+ const resolvedCoveragePatterns = application.coveragePatterns.map((pattern4) => path.resolve(workspaceRoot, pattern4));
52073
+ const compatibilityExcludes = [path.resolve(workspaceRoot, "**/node_modules/**")];
52074
+ const globAttempts = yield* exports_Effect.all(resolvedCoveragePatterns.map((pattern4) => exports_Effect.result(fileSystem.glob(pattern4, { exclude: compatibilityExcludes }))));
52075
+ const failedGlob = globAttempts.find((attempt) => attempt._tag === "Failure");
52076
+ if (failedGlob?._tag === "Failure") {
52077
+ return {
52078
+ kind: "failed",
52079
+ detail: "Unable to enumerate compatibility exact-path coverage."
52080
+ };
52081
+ }
52082
+ const directAttempts = yield* exports_Effect.all(resolvedCoveragePatterns.map((pattern4) => exports_Effect.result(fileSystem.stat(pattern4))));
52083
+ const failedDirect = directAttempts.find((attempt) => attempt._tag === "Failure" && !isNotFound(attempt.failure));
52084
+ if (failedDirect?._tag === "Failure") {
52085
+ return {
52086
+ kind: "failed",
52087
+ detail: "Unable to inspect compatibility exact-path coverage."
52088
+ };
52089
+ }
52090
+ const candidates2 = stablePaths([
52091
+ ...globAttempts.flatMap((attempt) => attempt._tag === "Success" ? attempt.success.map((candidate) => path.isAbsolute(candidate) ? path.resolve(candidate) : path.resolve(workspaceRoot, candidate)) : []),
52092
+ ...directAttempts.flatMap((attempt, index4) => attempt._tag === "Success" && attempt.success.type === "File" ? [resolvedCoveragePatterns[index4]] : [])
52093
+ ].filter((candidate) => candidate !== undefined)).filter((candidate) => !isCompatibilityProtectedSubject(candidate, workspaceRoot, path) && authority.some((root) => root.kind === "file" ? candidate === root.absolutePath : isContained2(root.absolutePath, candidate, path)));
52094
+ const subjects = [];
52095
+ for (const candidate of candidates2) {
52096
+ const canonical = yield* exports_Effect.result(fileSystem.realPath(candidate));
52097
+ if (canonical._tag === "Failure") {
52098
+ if (isNotFound(canonical.failure))
52099
+ continue;
52100
+ return {
52101
+ kind: "failed",
52102
+ detail: `Unable to canonicalize compatibility subject "${toRepositoryPath2(path.relative(workspaceRoot, candidate), path.sep)}".`
52103
+ };
52104
+ }
52105
+ const expectedCanonical = path.resolve(workspaceRealPath.success, path.relative(workspaceRoot, candidate));
52106
+ if (canonical.success !== expectedCanonical || !isContained2(workspaceRealPath.success, canonical.success, path)) {
52107
+ return {
52108
+ kind: "failed",
52109
+ detail: `Exact coverage selected symbolic link "${toRepositoryPath2(path.relative(workspaceRoot, candidate), path.sep)}"; compatibility checks accept regular files only.`
52110
+ };
52111
+ }
52112
+ const stat3 = yield* exports_Effect.result(fileSystem.stat(canonical.success));
52113
+ if (stat3._tag === "Failure") {
52114
+ if (isNotFound(stat3.failure))
52115
+ continue;
52116
+ return {
52117
+ kind: "failed",
52118
+ detail: `Unable to inspect compatibility subject "${toRepositoryPath2(path.relative(workspaceRoot, candidate), path.sep)}".`
52119
+ };
52120
+ }
52121
+ if (stat3.success.type === "File") {
52122
+ subjects.push({ absolutePath: candidate, kind: "file" });
52123
+ }
52124
+ }
52125
+ return subjects.length === 0 ? { kind: "not-applicable" } : { kind: "ready", subjects };
52126
+ });
52127
+ }
52128
+ function isCompatibilityProtectedSubject(candidate, workspaceRoot, path) {
52129
+ const relative = toRepositoryPath2(path.relative(workspaceRoot, candidate), path.sep);
52130
+ if (relative.split("/").includes("node_modules"))
52131
+ return true;
52132
+ return compatibilityProtectedRoots.some((root) => relative === root || relative.startsWith(`${root}/`));
52133
+ }
51495
52134
  function resolvedSubjects(application, workspaceRoot, path) {
51496
52135
  const subjects = new Map;
51497
52136
  for (const entry of application.runner.acquisition.entries) {
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "commands": {},
3
- "version": "0.2.0"
3
+ "version": "0.2.1"
4
4
  }
package/package.json CHANGED
@@ -1,7 +1,12 @@
1
1
  {
2
2
  "name": "@habitat-ai/cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "private": false,
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/rawr-ai/rawr-hq-template.git",
8
+ "directory": "apps/habitat"
9
+ },
5
10
  "description": "Habitat structural authority CLI and Nx projection",
6
11
  "license": "MIT",
7
12
  "type": "module",
@@ -43,10 +48,10 @@
43
48
  "dependencies": {
44
49
  "@effect/platform-node": "4.0.0-beta.101",
45
50
  "@getgrit/cli": "0.1.0-alpha.1743007075",
46
- "@habitat-ai/plugin-cli": "0.2.0",
47
- "@habitat-ai/resource-rule-evaluation": "0.2.0",
48
- "@habitat-ai/resource-source-inventory": "0.2.0",
49
- "@habitat-ai/service": "0.2.0",
51
+ "@habitat-ai/plugin-cli": "0.2.1",
52
+ "@habitat-ai/resource-rule-evaluation": "0.2.1",
53
+ "@habitat-ai/resource-source-inventory": "0.2.1",
54
+ "@habitat-ai/service": "0.2.1",
50
55
  "@nx/devkit": "23.1.0",
51
56
  "@oclif/core": "^4.11.4",
52
57
  "@oclif/plugin-help": "^6.2.27",
@@ -61,7 +66,7 @@
61
66
  "vitest": "^4.0.18"
62
67
  },
63
68
  "peerDependencies": {
64
- "@habitat-ai/blueprints": "0.2.0"
69
+ "@habitat-ai/blueprints": "0.2.1"
65
70
  },
66
71
  "oclif": {
67
72
  "bin": "habitat",