@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 +795 -156
- package/oclif.manifest.json +1 -1
- package/package.json +11 -6
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
|
|
1745
|
+
return projectCatalogTargets(matchedFiles, result.catalog, binding.runtimeInputs);
|
|
1746
1746
|
}
|
|
1747
1747
|
];
|
|
1748
1748
|
return Object.freeze({ createNodes });
|
|
1749
1749
|
}
|
|
1750
|
-
function
|
|
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 =
|
|
1760
|
-
|
|
1761
|
-
|
|
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
|
-
|
|
1779
|
-
|
|
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
|
-
|
|
1782
|
-
projects
|
|
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
|
|
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
|
|
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: {
|
|
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
|
|
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
|
-
|
|
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.
|
|
48501
|
-
|
|
48502
|
-
|
|
48503
|
-
|
|
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: "
|
|
48716
|
+
description: "Resolved executable compatibility rules in stable identity order."
|
|
48512
48717
|
})
|
|
48513
|
-
}, { additionalProperties: false, description: "
|
|
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: "
|
|
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
|
|
48655
|
-
exports_typebox.
|
|
48656
|
-
|
|
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
|
-
|
|
48901
|
+
}, {
|
|
48902
|
+
additionalProperties: false,
|
|
48903
|
+
description: "Completed mechanical evaluation disposition."
|
|
48686
48904
|
});
|
|
48687
|
-
var
|
|
48688
|
-
|
|
48689
|
-
|
|
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
|
-
|
|
48694
|
-
|
|
48695
|
-
|
|
48696
|
-
|
|
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
|
-
|
|
48917
|
+
detail: exports_typebox.String({
|
|
48699
48918
|
minLength: 1,
|
|
48700
|
-
maxLength:
|
|
48701
|
-
description: "
|
|
48702
|
-
})
|
|
48703
|
-
|
|
48704
|
-
|
|
48705
|
-
|
|
48706
|
-
|
|
48707
|
-
|
|
48708
|
-
|
|
48709
|
-
|
|
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:
|
|
48714
|
-
|
|
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
|
|
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: "
|
|
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
|
|
48779
|
-
ownerProject:
|
|
48780
|
-
|
|
48781
|
-
|
|
48782
|
-
|
|
48783
|
-
|
|
48784
|
-
|
|
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:
|
|
48805
|
-
|
|
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
|
|
48817
|
-
var
|
|
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.
|
|
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
|
-
|
|
50103
|
-
|
|
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
|
-
|
|
50107
|
-
|
|
50108
|
-
|
|
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
|
|
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",
|
|
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
|
|
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:
|
|
50933
|
+
owner: applications.some((application) => application.ownerProject === value4),
|
|
50558
50934
|
instance: catalog2.applications.some((application) => application.instanceId === value4),
|
|
50559
|
-
rule:
|
|
50560
|
-
runner:
|
|
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({
|
|
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
|
|
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) {
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@habitat-ai/cli",
|
|
3
|
-
"version": "0.2.
|
|
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.
|
|
47
|
-
"@habitat-ai/resource-rule-evaluation": "0.2.
|
|
48
|
-
"@habitat-ai/resource-source-inventory": "0.2.
|
|
49
|
-
"@habitat-ai/service": "0.2.
|
|
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.
|
|
69
|
+
"@habitat-ai/blueprints": "0.2.1"
|
|
65
70
|
},
|
|
66
71
|
"oclif": {
|
|
67
72
|
"bin": "habitat",
|