@habitat-ai/cli 0.2.4 → 0.3.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 +221 -73
- package/oclif.manifest.json +1 -1
- package/package.json +5 -5
package/dist/nx-plugin.js
CHANGED
|
@@ -1733,6 +1733,7 @@ var HABITAT_CATALOG_PATHS = [
|
|
|
1733
1733
|
var HABITAT_AUTHORITY_GLOB = `{${HABITAT_CATALOG_PATHS.join(",")}}`;
|
|
1734
1734
|
var DEFAULT_CHECK_TARGET = "check:policy";
|
|
1735
1735
|
var HABITAT_EXECUTABLE = "habitat";
|
|
1736
|
+
var PORTABLE_OWNER_PROJECT = /^[A-Za-z0-9@][A-Za-z0-9@._/+:-]*$/u;
|
|
1736
1737
|
function createHabitatNxPlugin(binding) {
|
|
1737
1738
|
const createNodes = [
|
|
1738
1739
|
HABITAT_AUTHORITY_GLOB,
|
|
@@ -1778,8 +1779,7 @@ function projectCatalogTargets(matchedFiles, catalog, runtimeInputs) {
|
|
|
1778
1779
|
addLeafTarget(project, compatibilityTargetName(rule), compatibilityTarget(rule, runtimeInputs));
|
|
1779
1780
|
}
|
|
1780
1781
|
return [...projects.entries()].sort(([left], [right]) => compareText(left, right)).map(([root, project]) => {
|
|
1781
|
-
|
|
1782
|
-
project.targets[DEFAULT_CHECK_TARGET] = ownerTarget(project.ownerProject, leafTargets, project.compatibilityManifests.size > 0);
|
|
1782
|
+
project.targets[DEFAULT_CHECK_TARGET] = ownerTarget(project.ownerProject, ownerInputs(project.targets, runtimeInputs), project.compatibilityManifests.size > 0);
|
|
1783
1783
|
return [
|
|
1784
1784
|
projectionSource(project),
|
|
1785
1785
|
{
|
|
@@ -1900,17 +1900,32 @@ function compatibilityTarget(rule, runtimeInputs) {
|
|
|
1900
1900
|
metadata: { description: `Check Habitat compatibility rule ${rule.ruleId}` }
|
|
1901
1901
|
};
|
|
1902
1902
|
}
|
|
1903
|
-
function ownerTarget(ownerProject,
|
|
1903
|
+
function ownerTarget(ownerProject, inputs, hasCompatibility) {
|
|
1904
|
+
if (!PORTABLE_OWNER_PROJECT.test(ownerProject)) {
|
|
1905
|
+
throw new Error(`Habitat Nx projection rejected owner '${ownerProject}': identity is not portable as an Nx command argument.`);
|
|
1906
|
+
}
|
|
1904
1907
|
return {
|
|
1905
|
-
|
|
1906
|
-
cache:
|
|
1908
|
+
command: `${HABITAT_EXECUTABLE} check --owner ${ownerProject}`,
|
|
1909
|
+
cache: true,
|
|
1910
|
+
inputs,
|
|
1907
1911
|
outputs: [],
|
|
1908
|
-
|
|
1912
|
+
options: { cwd: "{workspaceRoot}" },
|
|
1909
1913
|
metadata: {
|
|
1910
1914
|
description: hasCompatibility ? `Check resolved Habitat policy owned by ${ownerProject}` : `Check resolved Habitat applications owned by ${ownerProject}`
|
|
1911
1915
|
}
|
|
1912
1916
|
};
|
|
1913
1917
|
}
|
|
1918
|
+
function ownerInputs(targets, runtimeInputs) {
|
|
1919
|
+
const runtimeStrings = new Set(runtimeInputs.filter((input) => typeof input === "string"));
|
|
1920
|
+
const corpusInputs = new Set;
|
|
1921
|
+
for (const target of Object.values(targets)) {
|
|
1922
|
+
for (const input of target.inputs ?? []) {
|
|
1923
|
+
if (typeof input === "string" && !runtimeStrings.has(input))
|
|
1924
|
+
corpusInputs.add(input);
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1927
|
+
return [...runtimeInputs, ...[...corpusInputs].sort(compareText)];
|
|
1928
|
+
}
|
|
1914
1929
|
function applicationInputs(application, runtimeInputs) {
|
|
1915
1930
|
const files = new Set(HABITAT_CATALOG_PATHS.map(workspaceInput));
|
|
1916
1931
|
if (application.runner.name === "grit") {
|
|
@@ -1934,15 +1949,25 @@ function compatibilityInputs(rule, runtimeInputs) {
|
|
|
1934
1949
|
files.add(workspaceInput(rule.baseline.relativePath));
|
|
1935
1950
|
for (const pattern of rule.coveragePatterns)
|
|
1936
1951
|
files.add(workspaceInput(pattern));
|
|
1937
|
-
|
|
1952
|
+
if (rule.runner.name === "grit") {
|
|
1953
|
+
files.add(workspaceInput(rule.runner.pattern.relativePath));
|
|
1954
|
+
for (const entry of rule.runner.acquisition.entries) {
|
|
1955
|
+
addSubjectInputs(files, entry.path, entry.kind);
|
|
1956
|
+
}
|
|
1957
|
+
} else {
|
|
1958
|
+
files.add(workspaceInput(rule.runner.structure.relativePath));
|
|
1959
|
+
}
|
|
1938
1960
|
return [...runtimeInputs, ...[...files].sort(compareText)];
|
|
1939
1961
|
}
|
|
1940
1962
|
function addSubjectInputs(target, path, kind) {
|
|
1941
1963
|
const exact = workspaceInput(path);
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1964
|
+
if (kind === "directory" && path === ".") {
|
|
1965
|
+
target.add("{workspaceRoot}/**/*");
|
|
1966
|
+
return;
|
|
1945
1967
|
}
|
|
1968
|
+
target.add(exact);
|
|
1969
|
+
if (kind === "directory")
|
|
1970
|
+
target.add(`${exact}/**/*`);
|
|
1946
1971
|
}
|
|
1947
1972
|
function workspaceInput(path) {
|
|
1948
1973
|
const normalized = normalizeWorkspacePath(path);
|
|
@@ -44644,6 +44669,17 @@ var MAX_RULE_EVALUATION_FAILURE_DETAIL = 4096;
|
|
|
44644
44669
|
var NonEmptyStringSchema = exports_typebox.String({
|
|
44645
44670
|
minLength: 1
|
|
44646
44671
|
});
|
|
44672
|
+
var RuleEvaluationProgramSchema = ReadonlyObject(exports_typebox.Object({
|
|
44673
|
+
id: exports_typebox.String({
|
|
44674
|
+
minLength: 1,
|
|
44675
|
+
maxLength: 1024,
|
|
44676
|
+
description: "Invocation-local program identity used to attribute findings"
|
|
44677
|
+
}),
|
|
44678
|
+
program: exports_typebox.String({
|
|
44679
|
+
minLength: 1,
|
|
44680
|
+
description: "Already-resolved evaluator program"
|
|
44681
|
+
})
|
|
44682
|
+
}), { additionalProperties: false });
|
|
44647
44683
|
var RuleEvaluationPositionSchema = ReadonlyObject(exports_typebox.Object({
|
|
44648
44684
|
line: exports_typebox.Integer({
|
|
44649
44685
|
minimum: 1,
|
|
@@ -44670,20 +44706,31 @@ var RuleEvaluationFindingSchema = ReadonlyObject(exports_typebox.Object({
|
|
|
44670
44706
|
})
|
|
44671
44707
|
}), { additionalProperties: false });
|
|
44672
44708
|
var RuleEvaluationRequestSchema = ReadonlyObject(exports_typebox.Object({
|
|
44673
|
-
|
|
44674
|
-
|
|
44675
|
-
description: "
|
|
44709
|
+
programs: ReadonlyObject(exports_typebox.Array(RuleEvaluationProgramSchema), {
|
|
44710
|
+
minItems: 1,
|
|
44711
|
+
description: "Non-empty ordered programs evaluated against the same subjects"
|
|
44676
44712
|
}),
|
|
44677
44713
|
subjectPaths: ReadonlyObject(exports_typebox.Array(NonEmptyStringSchema), {
|
|
44678
44714
|
minItems: 1,
|
|
44679
44715
|
description: "Non-empty caller-resolved absolute subject paths"
|
|
44680
44716
|
})
|
|
44681
44717
|
}), { additionalProperties: false });
|
|
44682
|
-
var
|
|
44718
|
+
var RuleEvaluationProgramResultSchema = ReadonlyObject(exports_typebox.Object({
|
|
44719
|
+
programId: exports_typebox.String({
|
|
44720
|
+
minLength: 1,
|
|
44721
|
+
maxLength: 1024,
|
|
44722
|
+
description: "Invocation-local identity of the evaluated program"
|
|
44723
|
+
}),
|
|
44683
44724
|
findings: ReadonlyObject(exports_typebox.Array(RuleEvaluationFindingSchema), {
|
|
44684
44725
|
description: "Findings reported by the evaluator in provider-defined stable order"
|
|
44685
44726
|
})
|
|
44686
44727
|
}), { additionalProperties: false });
|
|
44728
|
+
var RuleEvaluationResultSchema = ReadonlyObject(exports_typebox.Object({
|
|
44729
|
+
results: ReadonlyObject(exports_typebox.Array(RuleEvaluationProgramResultSchema), {
|
|
44730
|
+
minItems: 1,
|
|
44731
|
+
description: "Per-program results in request order"
|
|
44732
|
+
})
|
|
44733
|
+
}), { additionalProperties: false });
|
|
44687
44734
|
var RuleEvaluationFailureReasonSchema = exports_typebox.Union([
|
|
44688
44735
|
exports_typebox.Literal("InvalidInput"),
|
|
44689
44736
|
exports_typebox.Literal("SetupFailed"),
|
|
@@ -46194,8 +46241,9 @@ __export(exports_value, {
|
|
|
46194
46241
|
});
|
|
46195
46242
|
// ../../resources/rule-evaluation/dist/providers/grit-effect-platform-node/index.js
|
|
46196
46243
|
var TEMP_CATALOG_PREFIX = "habitat-rule-evaluation-";
|
|
46197
|
-
var
|
|
46198
|
-
var
|
|
46244
|
+
var GRIT_PATTERN_PREFIX = "habitat_rule_evaluation_";
|
|
46245
|
+
var MAX_GRIT_OUTPUT_BYTES_PER_PROGRAM = 256 * 1024;
|
|
46246
|
+
var MAX_GRIT_BATCH_OUTPUT_BYTES = 16 * 1024 * 1024;
|
|
46199
46247
|
var GritRuleEvaluationProviderConfigSchema = ReadonlyObject(exports_typebox.Object({
|
|
46200
46248
|
executable: exports_typebox.String({
|
|
46201
46249
|
minLength: 1,
|
|
@@ -46213,11 +46261,12 @@ var GritPositionSchema = exports_typebox.Object({
|
|
|
46213
46261
|
}, { additionalProperties: false, description: "Grit-reported source position" });
|
|
46214
46262
|
var GritResultSchema = exports_typebox.Object({
|
|
46215
46263
|
check_id: exports_typebox.String({
|
|
46216
|
-
|
|
46217
|
-
description: "
|
|
46264
|
+
minLength: 1,
|
|
46265
|
+
description: "Grit check identity with evaluator suffix"
|
|
46218
46266
|
}),
|
|
46219
|
-
local_name: exports_typebox.
|
|
46220
|
-
|
|
46267
|
+
local_name: exports_typebox.String({
|
|
46268
|
+
minLength: 1,
|
|
46269
|
+
description: "Local Grit catalog pattern name"
|
|
46221
46270
|
}),
|
|
46222
46271
|
path: exports_typebox.String({ minLength: 1, description: "Grit-reported subject path" }),
|
|
46223
46272
|
start: GritPositionSchema,
|
|
@@ -46247,13 +46296,27 @@ function makeGritRuleEvaluationResource(config) {
|
|
|
46247
46296
|
return yield* fail11("InvalidInput", "Grit provider configuration does not match its structural contract");
|
|
46248
46297
|
}
|
|
46249
46298
|
if (!requestValidator.Check(input)) {
|
|
46250
|
-
return yield* fail11("InvalidInput", "Rule-evaluation request requires
|
|
46299
|
+
return yield* fail11("InvalidInput", "Rule-evaluation request requires resolved programs and non-empty subject paths");
|
|
46251
46300
|
}
|
|
46252
46301
|
const path = yield* exports_Path.Path;
|
|
46253
46302
|
if (input.subjectPaths.some((subjectPath) => !path.isAbsolute(subjectPath))) {
|
|
46254
46303
|
return yield* fail11("InvalidInput", "Rule-evaluation subject paths must be caller-resolved absolute paths");
|
|
46255
46304
|
}
|
|
46256
|
-
|
|
46305
|
+
const [firstProgram, ...remainingPrograms] = input.programs;
|
|
46306
|
+
if (firstProgram === undefined) {
|
|
46307
|
+
return yield* fail11("InvalidInput", "Rule-evaluation request requires at least one program");
|
|
46308
|
+
}
|
|
46309
|
+
if (new Set(input.programs.map(({ id: id3 }) => id3)).size !== input.programs.length) {
|
|
46310
|
+
return yield* fail11("InvalidInput", "Rule-evaluation program identities must be unique");
|
|
46311
|
+
}
|
|
46312
|
+
const programs = [
|
|
46313
|
+
materializeProgram(firstProgram, 0),
|
|
46314
|
+
...remainingPrograms.map((program) => materializeProgram(program, 0))
|
|
46315
|
+
];
|
|
46316
|
+
const evaluations = yield* exports_Effect.forEach(programs, (program) => exports_Effect.scoped(withScopedGritCatalog([program], (catalog) => runGritCheck(config, catalog, [program], input.subjectPaths))), { concurrency: 1 });
|
|
46317
|
+
return Object.freeze({
|
|
46318
|
+
results: Object.freeze(evaluations.flatMap(({ results }) => results))
|
|
46319
|
+
});
|
|
46257
46320
|
});
|
|
46258
46321
|
return Object.freeze({ evaluate: evaluate6 });
|
|
46259
46322
|
}
|
|
@@ -46263,7 +46326,7 @@ function makeNodeGritRuleEvaluationResource(config) {
|
|
|
46263
46326
|
evaluate: (input) => resource.evaluate(input).pipe(exports_Effect.provide(exports_NodeServices.layer))
|
|
46264
46327
|
});
|
|
46265
46328
|
}
|
|
46266
|
-
function withScopedGritCatalog(
|
|
46329
|
+
function withScopedGritCatalog(programs, use) {
|
|
46267
46330
|
return exports_Effect.gen(function* () {
|
|
46268
46331
|
const fs = yield* exports_FileSystem.FileSystem;
|
|
46269
46332
|
const path = yield* exports_Path.Path;
|
|
@@ -46277,11 +46340,12 @@ function withScopedGritCatalog(program, use) {
|
|
|
46277
46340
|
yield* fs.makeDirectory(catalog.gritDirectory).pipe(mapPlatform("SetupFailed", "Failed to create Grit catalog directory"));
|
|
46278
46341
|
yield* fs.makeDirectory(catalog.userConfigDirectory).pipe(mapPlatform("SetupFailed", "Failed to create Grit user-config directory"));
|
|
46279
46342
|
yield* fs.makeDirectory(catalog.cacheDirectory).pipe(mapPlatform("SetupFailed", "Failed to create Grit cache directory"));
|
|
46280
|
-
yield* fs.writeFileString(path.join(catalog.gritDirectory, "grit.yaml"), renderGritCatalog(
|
|
46343
|
+
yield* fs.writeFileString(path.join(catalog.gritDirectory, "grit.yaml"), renderGritCatalog(programs)).pipe(mapPlatform("SetupFailed", "Failed to write temporary Grit catalog"));
|
|
46281
46344
|
return yield* use(catalog);
|
|
46282
46345
|
});
|
|
46283
46346
|
}
|
|
46284
|
-
function runGritCheck(config, catalog, subjectPaths) {
|
|
46347
|
+
function runGritCheck(config, catalog, programs, subjectPaths) {
|
|
46348
|
+
const outputLimit = gritOutputLimit(programs.length);
|
|
46285
46349
|
const observe = exports_Effect.gen(function* () {
|
|
46286
46350
|
const command = exports_ChildProcess.make(config.executable, ["--json", "check", "--no-cache", "--grit-dir", catalog.gritDirectory, ...subjectPaths], {
|
|
46287
46351
|
cwd: catalog.root,
|
|
@@ -46290,7 +46354,8 @@ function runGritCheck(config, catalog, subjectPaths) {
|
|
|
46290
46354
|
GRIT_CACHE_DIR: catalog.cacheDirectory,
|
|
46291
46355
|
GRIT_USER_CONFIG: catalog.userConfigDirectory,
|
|
46292
46356
|
GRIT_TELEMETRY_DISABLED: "true",
|
|
46293
|
-
NO_COLOR: undefined
|
|
46357
|
+
NO_COLOR: undefined,
|
|
46358
|
+
RAYON_NUM_THREADS: "2"
|
|
46294
46359
|
},
|
|
46295
46360
|
extendEnv: true,
|
|
46296
46361
|
stdin: "ignore",
|
|
@@ -46299,8 +46364,8 @@ function runGritCheck(config, catalog, subjectPaths) {
|
|
|
46299
46364
|
});
|
|
46300
46365
|
const process2 = yield* command.pipe(mapPlatform("ExecutionFailed", "Failed to start Grit"));
|
|
46301
46366
|
const output = yield* exports_Effect.all({
|
|
46302
|
-
stdout: collectBoundedOutput(process2.stdout, "stdout"),
|
|
46303
|
-
stderr: collectBoundedOutput(process2.stderr, "stderr"),
|
|
46367
|
+
stdout: collectBoundedOutput(process2.stdout, "stdout", outputLimit),
|
|
46368
|
+
stderr: collectBoundedOutput(process2.stderr, "stderr", outputLimit),
|
|
46304
46369
|
exitCode: process2.exitCode.pipe(exports_Effect.map(Number), mapPlatform("ExecutionFailed", "Failed to observe Grit exit"))
|
|
46305
46370
|
}, { concurrency: "unbounded" });
|
|
46306
46371
|
return Object.freeze(output);
|
|
@@ -46316,7 +46381,7 @@ function runGritCheck(config, catalog, subjectPaths) {
|
|
|
46316
46381
|
if (observation.stdout.trim().length > 0) {
|
|
46317
46382
|
return fail11("InvalidOutput", "Grit check emitted unexpected stdout alongside its stderr JSON report");
|
|
46318
46383
|
}
|
|
46319
|
-
return decodeGritReport(observation.stderr).pipe(exports_Effect.
|
|
46384
|
+
return decodeGritReport(observation.stderr).pipe(exports_Effect.flatMap((report) => resultFromGritReport(report, programs)));
|
|
46320
46385
|
}));
|
|
46321
46386
|
}
|
|
46322
46387
|
function decodeGritReport(stderr) {
|
|
@@ -46328,45 +46393,61 @@ function decodeGritReport(stderr) {
|
|
|
46328
46393
|
catch: (error2) => failure("InvalidOutput", `Grit check emitted an invalid report: ${errorMessage(error2)}`)
|
|
46329
46394
|
})));
|
|
46330
46395
|
}
|
|
46331
|
-
function resultFromGritReport(report) {
|
|
46332
|
-
const
|
|
46333
|
-
|
|
46334
|
-
|
|
46335
|
-
|
|
46336
|
-
|
|
46337
|
-
|
|
46338
|
-
}
|
|
46339
|
-
|
|
46340
|
-
|
|
46341
|
-
|
|
46342
|
-
|
|
46343
|
-
|
|
46344
|
-
|
|
46345
|
-
|
|
46396
|
+
function resultFromGritReport(report, programs) {
|
|
46397
|
+
const programsByPattern = new Map(programs.map((program) => [program.patternName, program]));
|
|
46398
|
+
const findingsByProgram = new Map(programs.map(({ id: id3 }) => [id3, []]));
|
|
46399
|
+
for (const result4 of report.results) {
|
|
46400
|
+
const program = programsByPattern.get(result4.local_name);
|
|
46401
|
+
if (program === undefined || !result4.check_id.startsWith(`#${result4.local_name}/`)) {
|
|
46402
|
+
return fail11("InvalidOutput", `Grit check reported unexpected pattern identity '${result4.local_name}'`);
|
|
46403
|
+
}
|
|
46404
|
+
findingsByProgram.get(program.id)?.push(Object.freeze({
|
|
46405
|
+
path: result4.path,
|
|
46406
|
+
start: Object.freeze({
|
|
46407
|
+
line: result4.start.line,
|
|
46408
|
+
column: result4.start.col,
|
|
46409
|
+
offset: result4.start.offset
|
|
46410
|
+
}),
|
|
46411
|
+
end: Object.freeze({
|
|
46412
|
+
line: result4.end.line,
|
|
46413
|
+
column: result4.end.col,
|
|
46414
|
+
offset: result4.end.offset
|
|
46415
|
+
}),
|
|
46416
|
+
message: result4.extra.message
|
|
46417
|
+
}));
|
|
46418
|
+
}
|
|
46419
|
+
return exports_Effect.succeed(Object.freeze({
|
|
46420
|
+
results: Object.freeze(programs.map(({ id: id3 }) => Object.freeze({
|
|
46421
|
+
programId: id3,
|
|
46422
|
+
findings: Object.freeze((findingsByProgram.get(id3) ?? []).sort(compareFindings))
|
|
46423
|
+
})))
|
|
46424
|
+
}));
|
|
46425
|
+
}
|
|
46426
|
+
function materializeProgram(program, index4) {
|
|
46346
46427
|
return Object.freeze({
|
|
46347
|
-
|
|
46428
|
+
id: program.id,
|
|
46429
|
+
patternName: `${GRIT_PATTERN_PREFIX}${index4}`,
|
|
46430
|
+
program: program.program
|
|
46348
46431
|
});
|
|
46349
46432
|
}
|
|
46350
|
-
function renderGritCatalog(
|
|
46433
|
+
function renderGritCatalog(programs) {
|
|
46351
46434
|
return `${JSON.stringify({
|
|
46352
46435
|
version: "0.0.2",
|
|
46353
|
-
patterns:
|
|
46354
|
-
|
|
46355
|
-
|
|
46356
|
-
|
|
46357
|
-
|
|
46358
|
-
|
|
46359
|
-
}
|
|
46360
|
-
]
|
|
46436
|
+
patterns: programs.map(({ id: id3, patternName, program }) => Object.freeze({
|
|
46437
|
+
name: patternName,
|
|
46438
|
+
title: id3,
|
|
46439
|
+
level: "error",
|
|
46440
|
+
body: program
|
|
46441
|
+
}))
|
|
46361
46442
|
}, undefined, 2)}
|
|
46362
46443
|
`;
|
|
46363
46444
|
}
|
|
46364
|
-
function collectBoundedOutput(stream2, channel) {
|
|
46365
|
-
return exports_Stream.runFoldEffect(stream2.pipe(exports_Stream.mapError((error2) => failure("ExecutionFailed", `Failed to drain Grit ${channel}: ${error2.message}`))), () => Object.freeze({ buffer: new Uint8Array(
|
|
46445
|
+
function collectBoundedOutput(stream2, channel, outputLimit) {
|
|
46446
|
+
return exports_Stream.runFoldEffect(stream2.pipe(exports_Stream.mapError((error2) => failure("ExecutionFailed", `Failed to drain Grit ${channel}: ${error2.message}`))), () => Object.freeze({ buffer: new Uint8Array(outputLimit), bytes: 0 }), (state2, chunk) => {
|
|
46366
46447
|
if (chunk.byteLength === 0)
|
|
46367
46448
|
return exports_Effect.succeed(state2);
|
|
46368
46449
|
const bytes = state2.bytes + chunk.byteLength;
|
|
46369
|
-
return bytes >
|
|
46450
|
+
return bytes > outputLimit ? fail11("InvalidOutput", `Grit ${channel} exceeded its ${outputLimit}-byte output limit`) : exports_Effect.sync(() => {
|
|
46370
46451
|
state2.buffer.set(chunk, state2.bytes);
|
|
46371
46452
|
return Object.freeze({ buffer: state2.buffer, bytes });
|
|
46372
46453
|
});
|
|
@@ -46375,6 +46456,9 @@ function collectBoundedOutput(stream2, channel) {
|
|
|
46375
46456
|
catch: (error2) => failure("InvalidOutput", `Grit ${channel} was not valid UTF-8: ${errorMessage(error2)}`)
|
|
46376
46457
|
})));
|
|
46377
46458
|
}
|
|
46459
|
+
function gritOutputLimit(programCount) {
|
|
46460
|
+
return Math.min(MAX_GRIT_BATCH_OUTPUT_BYTES, MAX_GRIT_OUTPUT_BYTES_PER_PROGRAM * programCount);
|
|
46461
|
+
}
|
|
46378
46462
|
function mapPlatform(reason, context4) {
|
|
46379
46463
|
return (effect2) => effect2.pipe(exports_Effect.mapError((error2) => failure(reason, `${context4}: ${error2.message}`)));
|
|
46380
46464
|
}
|
|
@@ -51941,21 +52025,22 @@ var check7 = module3.check.effect(function* ({ context: context4, input }) {
|
|
|
51941
52025
|
};
|
|
51942
52026
|
}
|
|
51943
52027
|
}
|
|
51944
|
-
const reports =
|
|
51945
|
-
|
|
52028
|
+
const reports = new Array(preparations.length);
|
|
52029
|
+
const readyGritEvaluations = [];
|
|
52030
|
+
for (const [applicationIndex, prepared] of preparations.entries()) {
|
|
51946
52031
|
if (prepared.kind === "structure") {
|
|
51947
52032
|
if (prepared.preparation.kind === "failed") {
|
|
51948
|
-
reports
|
|
52033
|
+
reports[applicationIndex] = prepared.preparation.report;
|
|
51949
52034
|
continue;
|
|
51950
52035
|
}
|
|
51951
52036
|
const admitted = prepared.preparation.value;
|
|
51952
52037
|
const application2 = admitted.application;
|
|
51953
52038
|
if (admitted.scopes.length === 0) {
|
|
51954
|
-
reports
|
|
52039
|
+
reports[applicationIndex] = evaluatedStructureApplication(application2, []);
|
|
51955
52040
|
continue;
|
|
51956
52041
|
}
|
|
51957
52042
|
if (inventoryPreparation.kind === "failed") {
|
|
51958
|
-
reports
|
|
52043
|
+
reports[applicationIndex] = failedStructureApplication(application2, "InventoryFailed", inventoryPreparation.detail);
|
|
51959
52044
|
continue;
|
|
51960
52045
|
}
|
|
51961
52046
|
if (inventoryPreparation.kind === "not-required") {
|
|
@@ -51969,48 +52054,85 @@ var check7 = module3.check.effect(function* ({ context: context4, input }) {
|
|
|
51969
52054
|
return yield* prepareStructureObservations(structureChildObservationPaths(plan, roots.kinds), roots.kinds);
|
|
51970
52055
|
});
|
|
51971
52056
|
if (observations.kind === "failed") {
|
|
51972
|
-
reports
|
|
52057
|
+
reports[applicationIndex] = failedStructureApplication(application2, "StructureObservationFailed", observations.detail);
|
|
51973
52058
|
continue;
|
|
51974
52059
|
}
|
|
51975
|
-
reports
|
|
52060
|
+
reports[applicationIndex] = evaluatedStructureApplication(application2, evaluateStructurePlan(plan, observations.kinds));
|
|
51976
52061
|
continue;
|
|
51977
52062
|
}
|
|
51978
52063
|
const application = prepared.application;
|
|
51979
52064
|
const patternAttempt = yield* exports_Effect.result(context4.fileSystem.readFileString(application.runner.pattern.absolutePath));
|
|
51980
52065
|
if (patternAttempt._tag === "Failure") {
|
|
51981
|
-
reports
|
|
52066
|
+
reports[applicationIndex] = failedApplication(application, "PatternReadFailed", `Unable to read pattern asset "${application.runner.pattern.relativePath}".`);
|
|
51982
52067
|
continue;
|
|
51983
52068
|
}
|
|
51984
52069
|
const program = extractGritProgram(patternAttempt.success);
|
|
51985
52070
|
if (!program.ok) {
|
|
51986
|
-
reports
|
|
52071
|
+
reports[applicationIndex] = failedApplication(application, "PatternInvalid", program.detail);
|
|
51987
52072
|
continue;
|
|
51988
52073
|
}
|
|
51989
52074
|
const subjectPreparation = yield* prepareGritSubjects(application, context4.workspaceRoot, context4.fileSystem, context4.path);
|
|
51990
52075
|
if (subjectPreparation.kind === "failed") {
|
|
51991
|
-
reports
|
|
52076
|
+
reports[applicationIndex] = failedApplication(application, "SetupFailed", subjectPreparation.detail);
|
|
51992
52077
|
continue;
|
|
51993
52078
|
}
|
|
51994
52079
|
if (subjectPreparation.kind === "not-applicable") {
|
|
51995
52080
|
if (!isCompatibilityRule(application)) {
|
|
51996
52081
|
return yield* exports_Effect.die(new Error("Version-three Grit applications cannot be not applicable."));
|
|
51997
52082
|
}
|
|
51998
|
-
reports
|
|
52083
|
+
reports[applicationIndex] = notApplicableApplication(application);
|
|
51999
52084
|
continue;
|
|
52000
52085
|
}
|
|
52001
52086
|
const subjects = subjectPreparation.subjects;
|
|
52002
|
-
|
|
52087
|
+
readyGritEvaluations.push({
|
|
52088
|
+
applicationIndex,
|
|
52089
|
+
application,
|
|
52090
|
+
programId: `application-${applicationIndex}`,
|
|
52003
52091
|
program: program.program,
|
|
52092
|
+
subjects,
|
|
52004
52093
|
subjectPaths: subjects.map((subject) => subject.absolutePath)
|
|
52094
|
+
});
|
|
52095
|
+
}
|
|
52096
|
+
for (const evaluations of groupGritEvaluations(readyGritEvaluations)) {
|
|
52097
|
+
const first = evaluations[0];
|
|
52098
|
+
if (first === undefined) {
|
|
52099
|
+
return yield* exports_Effect.die(new Error("A Grit evaluation group must not be empty."));
|
|
52100
|
+
}
|
|
52101
|
+
const evaluation = yield* exports_Effect.result(context4.ruleEvaluation.evaluate({
|
|
52102
|
+
programs: evaluations.map(({ programId, program }) => ({ id: programId, program })),
|
|
52103
|
+
subjectPaths: first.subjectPaths
|
|
52005
52104
|
}));
|
|
52006
52105
|
if (evaluation._tag === "Failure") {
|
|
52007
|
-
|
|
52106
|
+
for (const prepared of evaluations) {
|
|
52107
|
+
reports[prepared.applicationIndex] = failedApplication(prepared.application, evaluation.failure.reason, evaluation.failure.detail);
|
|
52108
|
+
}
|
|
52008
52109
|
continue;
|
|
52009
52110
|
}
|
|
52010
|
-
const
|
|
52011
|
-
|
|
52111
|
+
const resultMismatch = evaluationResultMismatch(evaluations, evaluation.success.results);
|
|
52112
|
+
if (resultMismatch !== undefined) {
|
|
52113
|
+
for (const prepared of evaluations) {
|
|
52114
|
+
reports[prepared.applicationIndex] = failedApplication(prepared.application, "InvalidOutput", resultMismatch);
|
|
52115
|
+
}
|
|
52116
|
+
continue;
|
|
52117
|
+
}
|
|
52118
|
+
const results = indexEvaluationResults(evaluation.success.results);
|
|
52119
|
+
for (const prepared of evaluations) {
|
|
52120
|
+
const result4 = results.get(prepared.programId);
|
|
52121
|
+
if (result4 === undefined) {
|
|
52122
|
+
return yield* exports_Effect.die(new Error(`Validated evaluation result '${prepared.programId}' is absent.`));
|
|
52123
|
+
}
|
|
52124
|
+
const normalized = normalizeFindings(result4.findings, prepared.subjects, context4.workspaceRoot, context4.path);
|
|
52125
|
+
reports[prepared.applicationIndex] = normalized.ok ? evaluatedApplication(prepared.application, normalized.findings) : failedApplication(prepared.application, "FindingPathInvalid", normalized.detail);
|
|
52126
|
+
}
|
|
52012
52127
|
}
|
|
52013
|
-
|
|
52128
|
+
const completedReports = [];
|
|
52129
|
+
for (const [applicationIndex, report] of reports.entries()) {
|
|
52130
|
+
if (report === undefined) {
|
|
52131
|
+
return yield* exports_Effect.die(new Error(`Habitat check produced no report for application ${applicationIndex}.`));
|
|
52132
|
+
}
|
|
52133
|
+
completedReports.push(report);
|
|
52134
|
+
}
|
|
52135
|
+
return completedCheck(completedReports);
|
|
52014
52136
|
});
|
|
52015
52137
|
var catalog2 = { resolve: resolve5, check: check7 };
|
|
52016
52138
|
function catalogRejected(issues) {
|
|
@@ -52043,6 +52165,32 @@ function hasExactCauseCode(error2, code) {
|
|
|
52043
52165
|
const cause = "cause" in error2.reason ? error2.reason.cause : undefined;
|
|
52044
52166
|
return typeof cause === "object" && cause !== null && "code" in cause && cause.code === code;
|
|
52045
52167
|
}
|
|
52168
|
+
function groupGritEvaluations(evaluations) {
|
|
52169
|
+
const groups = new Map;
|
|
52170
|
+
for (const evaluation of evaluations) {
|
|
52171
|
+
const key = JSON.stringify(evaluation.subjectPaths);
|
|
52172
|
+
const group = groups.get(key);
|
|
52173
|
+
if (group === undefined)
|
|
52174
|
+
groups.set(key, [evaluation]);
|
|
52175
|
+
else
|
|
52176
|
+
group.push(evaluation);
|
|
52177
|
+
}
|
|
52178
|
+
return [...groups.values()];
|
|
52179
|
+
}
|
|
52180
|
+
function evaluationResultMismatch(evaluations, results) {
|
|
52181
|
+
if (results.length !== evaluations.length) {
|
|
52182
|
+
return `Rule evaluator returned ${results.length} program results for ${evaluations.length} requested programs.`;
|
|
52183
|
+
}
|
|
52184
|
+
const uniqueIds = new Set(results.map(({ programId }) => programId));
|
|
52185
|
+
if (uniqueIds.size !== results.length) {
|
|
52186
|
+
return "Rule evaluator returned duplicate program result identities.";
|
|
52187
|
+
}
|
|
52188
|
+
const unexpected = results.find((result4, index4) => result4.programId !== evaluations[index4]?.programId);
|
|
52189
|
+
return unexpected === undefined ? undefined : "Rule evaluator did not preserve requested program result order and identity.";
|
|
52190
|
+
}
|
|
52191
|
+
function indexEvaluationResults(results) {
|
|
52192
|
+
return new Map(results.map((result4) => [result4.programId, result4]));
|
|
52193
|
+
}
|
|
52046
52194
|
function prepareGritSubjects(application, workspaceRoot, fileSystem, path) {
|
|
52047
52195
|
if (!isCompatibilityRule(application)) {
|
|
52048
52196
|
return exports_Effect.succeed({
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@habitat-ai/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -48,10 +48,10 @@
|
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@effect/platform-node": "4.0.0-beta.101",
|
|
50
50
|
"@getgrit/cli": "0.1.0-alpha.1743007075",
|
|
51
|
-
"@habitat-ai/plugin-cli": "0.
|
|
52
|
-
"@habitat-ai/resource-rule-evaluation": "0.
|
|
53
|
-
"@habitat-ai/resource-source-inventory": "0.
|
|
54
|
-
"@habitat-ai/service": "0.
|
|
51
|
+
"@habitat-ai/plugin-cli": "0.3.1",
|
|
52
|
+
"@habitat-ai/resource-rule-evaluation": "0.3.1",
|
|
53
|
+
"@habitat-ai/resource-source-inventory": "0.3.1",
|
|
54
|
+
"@habitat-ai/service": "0.3.1",
|
|
55
55
|
"@nx/devkit": "23.1.0",
|
|
56
56
|
"@oclif/core": "^4.11.4",
|
|
57
57
|
"@oclif/plugin-help": "^6.2.27",
|