@guilz-dev/belay 0.9.1 → 0.9.2
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/adapters/cursor/hooks.d.ts +4 -3
- package/dist/adapters/cursor/hooks.js +10 -22
- package/dist/bundle/claude-runtime.mjs +439 -18
- package/dist/bundle/codex-runtime.mjs +439 -18
- package/dist/bundle/cursor-runtime.mjs +439 -18
- package/dist/commands/doctor.js +14 -8
- package/dist/core/audit-legacy-archive.d.ts +1 -0
- package/dist/core/audit-legacy-archive.js +5 -0
- package/dist/core/effect-ir/shell-lower.js +205 -2
- package/dist/core/verdict/launcher-resolve.js +51 -10
- package/dist/core/verdict/makefile-expand.d.ts +4 -0
- package/dist/core/verdict/makefile-expand.js +151 -0
- package/dist/core/verdict/parser.d.ts +1 -0
- package/dist/core/verdict/parser.js +24 -12
- package/dist/corpus/benign-probe-cores.d.ts +1 -1
- package/dist/corpus/benign-probe-cores.js +2 -0
- package/dist/defaults.js +9 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { HookEntry, HooksFile } from '../../types.js';
|
|
2
|
-
/**
|
|
3
|
-
export declare function
|
|
4
|
-
|
|
2
|
+
/** Managed Shell preToolUse gate for Cursor Agent Shell tool invocations. */
|
|
3
|
+
export declare function managedShellPreToolUseEntry(platform: NodeJS.Platform, hooksDir: string, repoRoot: string): HookEntry;
|
|
4
|
+
/** @deprecated Use {@link managedShellPreToolUseEntry}. */
|
|
5
|
+
export declare const legacyManagedShellPreToolUseEntry: typeof managedShellPreToolUseEntry;
|
|
5
6
|
export declare function mergeCursorHooksFile(current: HooksFile, platform: NodeJS.Platform, hooksDir: string, repoRoot: string): HooksFile;
|
|
6
7
|
export declare function hasDuplicateCursorShellGates(hooks: HooksFile, platform: NodeJS.Platform, hooksDir: string, repoRoot: string): boolean;
|
|
@@ -10,37 +10,24 @@ function mergeHookEntry(current, expected, placement) {
|
|
|
10
10
|
}
|
|
11
11
|
return [...filtered, expected];
|
|
12
12
|
}
|
|
13
|
-
/**
|
|
14
|
-
export function
|
|
13
|
+
/** Managed Shell preToolUse gate for Cursor Agent Shell tool invocations. */
|
|
14
|
+
export function managedShellPreToolUseEntry(platform, hooksDir, repoRoot) {
|
|
15
15
|
const managed = getManagedHookEntries(platform, hooksDir, repoRoot);
|
|
16
16
|
const referencePreToolUse = managed.find((entry) => entry.event === 'preToolUse' && entry.definition.matcher === 'Write')?.definition;
|
|
17
17
|
if (!referencePreToolUse) {
|
|
18
|
-
throw new Error('managed hook definitions missing for
|
|
18
|
+
throw new Error('managed hook definitions missing for Shell preToolUse gate');
|
|
19
19
|
}
|
|
20
20
|
return {
|
|
21
21
|
command: referencePreToolUse.command,
|
|
22
22
|
matcher: 'Shell',
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const preToolUse = hooks.hooks.preToolUse;
|
|
28
|
-
if (!Array.isArray(preToolUse)) {
|
|
29
|
-
return hooks;
|
|
30
|
-
}
|
|
31
|
-
return {
|
|
32
|
-
...hooks,
|
|
33
|
-
hooks: {
|
|
34
|
-
...hooks.hooks,
|
|
35
|
-
preToolUse: preToolUse.filter((entry) => !entryMatches(entry, legacy)),
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
}
|
|
25
|
+
/** @deprecated Use {@link managedShellPreToolUseEntry}. */
|
|
26
|
+
export const legacyManagedShellPreToolUseEntry = managedShellPreToolUseEntry;
|
|
39
27
|
export function mergeCursorHooksFile(current, platform, hooksDir, repoRoot) {
|
|
40
|
-
const withoutLegacyShell = removeLegacyManagedShellPreToolUse(current, platform, hooksDir, repoRoot);
|
|
41
28
|
const next = {
|
|
42
|
-
version:
|
|
43
|
-
hooks: { ...
|
|
29
|
+
version: current.version || 1,
|
|
30
|
+
hooks: { ...current.hooks },
|
|
44
31
|
};
|
|
45
32
|
const managedEntries = getManagedHookEntries(platform, hooksDir, repoRoot);
|
|
46
33
|
for (const { event, definition } of managedEntries) {
|
|
@@ -52,10 +39,11 @@ export function mergeCursorHooksFile(current, platform, hooksDir, repoRoot) {
|
|
|
52
39
|
return next;
|
|
53
40
|
}
|
|
54
41
|
export function hasDuplicateCursorShellGates(hooks, platform, hooksDir, repoRoot) {
|
|
55
|
-
const
|
|
42
|
+
const shellEntry = managedShellPreToolUseEntry(platform, hooksDir, repoRoot);
|
|
56
43
|
const preToolUse = hooks.hooks.preToolUse;
|
|
57
44
|
if (!Array.isArray(preToolUse)) {
|
|
58
45
|
return false;
|
|
59
46
|
}
|
|
60
|
-
|
|
47
|
+
const shellMatches = preToolUse.filter((entry) => entryMatches(entry, shellEntry));
|
|
48
|
+
return shellMatches.length > 1;
|
|
61
49
|
}
|
|
@@ -11125,6 +11125,7 @@ function worstEffectDecision(decisions) {
|
|
|
11125
11125
|
|
|
11126
11126
|
// src/core/effect-ir/shell-lower.ts
|
|
11127
11127
|
init_git_resource_identity();
|
|
11128
|
+
init_path_utils();
|
|
11128
11129
|
init_shell_tokenizer();
|
|
11129
11130
|
import { lstatSync as lstatSync2, realpathSync as realpathSync4 } from "node:fs";
|
|
11130
11131
|
import path39 from "node:path";
|
|
@@ -12855,6 +12856,159 @@ function gitRequirement(tag, action, resource, segment, signals) {
|
|
|
12855
12856
|
// src/core/verdict/launcher-resolve.ts
|
|
12856
12857
|
import { existsSync as existsSync11, readFileSync as readFileSync5 } from "node:fs";
|
|
12857
12858
|
import path37 from "node:path";
|
|
12859
|
+
|
|
12860
|
+
// src/core/verdict/makefile-expand.ts
|
|
12861
|
+
var MAX_EXPAND_DEPTH = 16;
|
|
12862
|
+
function parseMakefileVariables(content) {
|
|
12863
|
+
const variables = /* @__PURE__ */ new Map();
|
|
12864
|
+
for (const line of content.split("\n")) {
|
|
12865
|
+
const trimmed = line.trim();
|
|
12866
|
+
if (!trimmed || trimmed.startsWith("#")) {
|
|
12867
|
+
continue;
|
|
12868
|
+
}
|
|
12869
|
+
const match = /^([A-Za-z_][A-Za-z0-9_]*)\s*[:?]?=\s*(.+)$/.exec(trimmed);
|
|
12870
|
+
if (!match) {
|
|
12871
|
+
continue;
|
|
12872
|
+
}
|
|
12873
|
+
variables.set(match[1] ?? "", (match[2] ?? "").trim());
|
|
12874
|
+
}
|
|
12875
|
+
return variables;
|
|
12876
|
+
}
|
|
12877
|
+
function parsePhonyTargets(content) {
|
|
12878
|
+
const phony = /* @__PURE__ */ new Set();
|
|
12879
|
+
for (const line of content.split("\n")) {
|
|
12880
|
+
const trimmed = line.trim();
|
|
12881
|
+
const match = /^\.PHONY:\s*(.+)$/.exec(trimmed);
|
|
12882
|
+
if (!match) {
|
|
12883
|
+
continue;
|
|
12884
|
+
}
|
|
12885
|
+
for (const token of (match[1] ?? "").split(/\s+/)) {
|
|
12886
|
+
if (token) {
|
|
12887
|
+
phony.add(token);
|
|
12888
|
+
}
|
|
12889
|
+
}
|
|
12890
|
+
}
|
|
12891
|
+
return phony;
|
|
12892
|
+
}
|
|
12893
|
+
function normalizeMakeRecipeLine(line) {
|
|
12894
|
+
let normalized = line.trim();
|
|
12895
|
+
while (normalized.startsWith("@") || normalized.startsWith("-") || normalized.startsWith("+")) {
|
|
12896
|
+
normalized = normalized.slice(1).trimStart();
|
|
12897
|
+
}
|
|
12898
|
+
return normalized;
|
|
12899
|
+
}
|
|
12900
|
+
function expandMakeExpression(expression, cliVars, makefileVars) {
|
|
12901
|
+
if (/\$\(\s*shell\b/i.test(expression) || expression.includes("$$")) {
|
|
12902
|
+
return null;
|
|
12903
|
+
}
|
|
12904
|
+
try {
|
|
12905
|
+
const expanded = expandMakeValue(expression, cliVars, makefileVars, 0);
|
|
12906
|
+
if (expanded === null || /\$\(/.test(expanded) || /\$\{/.test(expanded)) {
|
|
12907
|
+
return null;
|
|
12908
|
+
}
|
|
12909
|
+
return expanded;
|
|
12910
|
+
} catch {
|
|
12911
|
+
return null;
|
|
12912
|
+
}
|
|
12913
|
+
}
|
|
12914
|
+
function expandMakeValue(expression, cliVars, makefileVars, depth) {
|
|
12915
|
+
if (depth > MAX_EXPAND_DEPTH) {
|
|
12916
|
+
return null;
|
|
12917
|
+
}
|
|
12918
|
+
let value = expression.trim();
|
|
12919
|
+
let changed = true;
|
|
12920
|
+
let iterations = 0;
|
|
12921
|
+
while (changed && iterations < MAX_EXPAND_DEPTH) {
|
|
12922
|
+
changed = false;
|
|
12923
|
+
iterations += 1;
|
|
12924
|
+
const orMatch = value.match(/\$\(\s*or\s+([^()]*(?:\([^)]*\)[^()]*)*)\)/);
|
|
12925
|
+
if (orMatch) {
|
|
12926
|
+
const [fullMatch, inner] = orMatch;
|
|
12927
|
+
const parts = splitMakeFunctionArgs(inner ?? "");
|
|
12928
|
+
let selected = null;
|
|
12929
|
+
for (const part of parts) {
|
|
12930
|
+
const expanded = expandMakeValue(part.trim(), cliVars, makefileVars, depth + 1);
|
|
12931
|
+
if (expanded !== null && expanded.trim() !== "") {
|
|
12932
|
+
selected = expanded;
|
|
12933
|
+
break;
|
|
12934
|
+
}
|
|
12935
|
+
}
|
|
12936
|
+
if (selected === null) {
|
|
12937
|
+
const fallback = parts.at(-1)?.trim();
|
|
12938
|
+
selected = fallback === void 0 ? "" : expandMakeValue(fallback, cliVars, makefileVars, depth + 1);
|
|
12939
|
+
}
|
|
12940
|
+
if (selected === null) {
|
|
12941
|
+
return null;
|
|
12942
|
+
}
|
|
12943
|
+
value = value.replace(fullMatch, selected);
|
|
12944
|
+
changed = true;
|
|
12945
|
+
continue;
|
|
12946
|
+
}
|
|
12947
|
+
const varMatch = value.match(/\$\(([A-Za-z_][A-Za-z0-9_]*)\)/);
|
|
12948
|
+
if (varMatch) {
|
|
12949
|
+
const [fullMatch, name] = varMatch;
|
|
12950
|
+
const resolved = resolveMakeVariable(name ?? "", cliVars, makefileVars, depth + 1);
|
|
12951
|
+
if (resolved === null) {
|
|
12952
|
+
return null;
|
|
12953
|
+
}
|
|
12954
|
+
value = value.replace(fullMatch, resolved);
|
|
12955
|
+
changed = true;
|
|
12956
|
+
continue;
|
|
12957
|
+
}
|
|
12958
|
+
const bracedMatch = value.match(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/);
|
|
12959
|
+
if (bracedMatch) {
|
|
12960
|
+
const [fullMatch, name] = bracedMatch;
|
|
12961
|
+
const resolved = name === "PWD" ? "." : resolveMakeVariable(name ?? "", cliVars, makefileVars, depth + 1);
|
|
12962
|
+
if (resolved === null) {
|
|
12963
|
+
return null;
|
|
12964
|
+
}
|
|
12965
|
+
value = value.replace(fullMatch, resolved);
|
|
12966
|
+
changed = true;
|
|
12967
|
+
continue;
|
|
12968
|
+
}
|
|
12969
|
+
break;
|
|
12970
|
+
}
|
|
12971
|
+
return value;
|
|
12972
|
+
}
|
|
12973
|
+
function resolveMakeVariable(name, cliVars, makefileVars, depth) {
|
|
12974
|
+
if (Object.hasOwn(cliVars, name)) {
|
|
12975
|
+
return cliVars[name] ?? "";
|
|
12976
|
+
}
|
|
12977
|
+
const definition = makefileVars.get(name);
|
|
12978
|
+
if (definition === void 0) {
|
|
12979
|
+
return null;
|
|
12980
|
+
}
|
|
12981
|
+
return expandMakeValue(definition, cliVars, makefileVars, depth);
|
|
12982
|
+
}
|
|
12983
|
+
function splitMakeFunctionArgs(input) {
|
|
12984
|
+
const parts = [];
|
|
12985
|
+
let current = "";
|
|
12986
|
+
let depth = 0;
|
|
12987
|
+
for (const char of input) {
|
|
12988
|
+
if (char === "(") {
|
|
12989
|
+
depth += 1;
|
|
12990
|
+
current += char;
|
|
12991
|
+
continue;
|
|
12992
|
+
}
|
|
12993
|
+
if (char === ")") {
|
|
12994
|
+
depth -= 1;
|
|
12995
|
+
current += char;
|
|
12996
|
+
continue;
|
|
12997
|
+
}
|
|
12998
|
+
if (char === "," && depth === 0) {
|
|
12999
|
+
parts.push(current.trim());
|
|
13000
|
+
current = "";
|
|
13001
|
+
continue;
|
|
13002
|
+
}
|
|
13003
|
+
current += char;
|
|
13004
|
+
}
|
|
13005
|
+
if (current.trim()) {
|
|
13006
|
+
parts.push(current.trim());
|
|
13007
|
+
}
|
|
13008
|
+
return parts;
|
|
13009
|
+
}
|
|
13010
|
+
|
|
13011
|
+
// src/core/verdict/launcher-resolve.ts
|
|
12858
13012
|
var MAX_RESOLVE_DEPTH = 8;
|
|
12859
13013
|
var PNPM_BUILTIN_COMMANDS = /* @__PURE__ */ new Set([
|
|
12860
13014
|
"add",
|
|
@@ -12995,10 +13149,9 @@ function resolveNpmRecipe(cwd, repoRoot, scriptName, extraArgs) {
|
|
|
12995
13149
|
reason: "npm_script_resolved"
|
|
12996
13150
|
};
|
|
12997
13151
|
}
|
|
12998
|
-
function
|
|
13152
|
+
function parseMakefileRecipeContent(content) {
|
|
12999
13153
|
const targets = /* @__PURE__ */ new Map();
|
|
13000
13154
|
try {
|
|
13001
|
-
const content = readFileSync5(makefilePath, "utf8");
|
|
13002
13155
|
const lines = content.split("\n");
|
|
13003
13156
|
let currentTarget = null;
|
|
13004
13157
|
let recipeLines = [];
|
|
@@ -13057,7 +13210,7 @@ function parseMakefileRecipes(makefilePath) {
|
|
|
13057
13210
|
}
|
|
13058
13211
|
return targets;
|
|
13059
13212
|
}
|
|
13060
|
-
function resolveMakeRecipe(cwd, repoRoot, target) {
|
|
13213
|
+
function resolveMakeRecipe(cwd, repoRoot, target, cliVars = {}) {
|
|
13061
13214
|
const candidates = ["Makefile", "makefile", "GNUmakefile"];
|
|
13062
13215
|
let makefilePath = null;
|
|
13063
13216
|
let searchDir = path37.resolve(cwd);
|
|
@@ -13078,7 +13231,10 @@ function resolveMakeRecipe(cwd, repoRoot, target) {
|
|
|
13078
13231
|
if (!makefilePath) {
|
|
13079
13232
|
return { recipes: [], opaque: true, reason: "unknown_local_effect" };
|
|
13080
13233
|
}
|
|
13081
|
-
const
|
|
13234
|
+
const makefileContent = readFileSync5(makefilePath, "utf8");
|
|
13235
|
+
const makefileVars = parseMakefileVariables(makefileContent);
|
|
13236
|
+
const phonyTargets = parsePhonyTargets(makefileContent);
|
|
13237
|
+
const targets = parseMakefileRecipeContent(makefileContent);
|
|
13082
13238
|
if (!targets.has(target)) {
|
|
13083
13239
|
return { recipes: [], opaque: true, reason: "make_target_undefined" };
|
|
13084
13240
|
}
|
|
@@ -13104,7 +13260,10 @@ function resolveMakeRecipe(cwd, repoRoot, target) {
|
|
|
13104
13260
|
return false;
|
|
13105
13261
|
}
|
|
13106
13262
|
}
|
|
13107
|
-
|
|
13263
|
+
const skipPhonyPrerequisiteRecipes = name !== target && (phonyTargets.has(name) || name.startsWith("_")) && (targets.get(target)?.recipes.length ?? 0) > 0;
|
|
13264
|
+
if (!skipPhonyPrerequisiteRecipes) {
|
|
13265
|
+
recipeLines.push(...entry.recipes);
|
|
13266
|
+
}
|
|
13108
13267
|
visiting.delete(name);
|
|
13109
13268
|
visited.add(name);
|
|
13110
13269
|
return true;
|
|
@@ -13112,15 +13271,24 @@ function resolveMakeRecipe(cwd, repoRoot, target) {
|
|
|
13112
13271
|
if (!collect(target)) {
|
|
13113
13272
|
return { recipes: recipeLines, opaque: true, reason: "make_dependency_cycle" };
|
|
13114
13273
|
}
|
|
13274
|
+
const expandedRecipes = [];
|
|
13115
13275
|
for (const line of recipeLines) {
|
|
13116
|
-
|
|
13276
|
+
const normalized = normalizeMakeRecipeLine(line);
|
|
13277
|
+
const expanded = expandMakeExpression(normalized, cliVars, makefileVars);
|
|
13278
|
+
if (expanded === null) {
|
|
13117
13279
|
return { recipes: recipeLines, opaque: true, reason: "make_recipe_dynamic" };
|
|
13118
13280
|
}
|
|
13281
|
+
expandedRecipes.push(expanded);
|
|
13282
|
+
}
|
|
13283
|
+
for (const line of expandedRecipes) {
|
|
13284
|
+
if (/\$\(/.test(line) || /\$\{/.test(line)) {
|
|
13285
|
+
return { recipes: expandedRecipes, opaque: true, reason: "make_recipe_dynamic" };
|
|
13286
|
+
}
|
|
13119
13287
|
}
|
|
13120
13288
|
if (opaquePrerequisites) {
|
|
13121
|
-
return { recipes:
|
|
13289
|
+
return { recipes: expandedRecipes, opaque: true, reason: "make_prerequisite_dynamic" };
|
|
13122
13290
|
}
|
|
13123
|
-
return { recipes:
|
|
13291
|
+
return { recipes: expandedRecipes, opaque: false, reason: "make_recipe_resolved" };
|
|
13124
13292
|
}
|
|
13125
13293
|
function resolveLauncherRecipe(params) {
|
|
13126
13294
|
if (params.depth >= MAX_RESOLVE_DEPTH) {
|
|
@@ -13144,8 +13312,28 @@ function resolveLauncherRecipe(params) {
|
|
|
13144
13312
|
}
|
|
13145
13313
|
return resolution;
|
|
13146
13314
|
}
|
|
13147
|
-
if (tokens[0] === "make"
|
|
13148
|
-
|
|
13315
|
+
if (tokens[0] === "make") {
|
|
13316
|
+
if (tokens.includes("-n") || tokens.includes("--dry-run")) {
|
|
13317
|
+
return null;
|
|
13318
|
+
}
|
|
13319
|
+
let target = null;
|
|
13320
|
+
const cliVars = {};
|
|
13321
|
+
for (const token of tokens.slice(1)) {
|
|
13322
|
+
if (token.startsWith("-")) {
|
|
13323
|
+
continue;
|
|
13324
|
+
}
|
|
13325
|
+
const assignment = /^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/.exec(token);
|
|
13326
|
+
if (assignment) {
|
|
13327
|
+
cliVars[assignment[1] ?? ""] = assignment[2] ?? "";
|
|
13328
|
+
continue;
|
|
13329
|
+
}
|
|
13330
|
+
if (!target) {
|
|
13331
|
+
target = token;
|
|
13332
|
+
}
|
|
13333
|
+
}
|
|
13334
|
+
if (target) {
|
|
13335
|
+
return resolveMakeRecipe(params.cwd, params.repoRoot, target, cliVars);
|
|
13336
|
+
}
|
|
13149
13337
|
}
|
|
13150
13338
|
if (tokens[0] === "pnpm" && tokens[1] === "exec" && tokens[2]) {
|
|
13151
13339
|
return {
|
|
@@ -13662,7 +13850,6 @@ function extractRecursiveScript(tokens) {
|
|
|
13662
13850
|
return null;
|
|
13663
13851
|
}
|
|
13664
13852
|
const head = normalizeHead(filtered[0] ?? "");
|
|
13665
|
-
const second = filtered[1] ?? "";
|
|
13666
13853
|
if (head === "eval") {
|
|
13667
13854
|
const body = filtered.slice(1).join(" ").trim();
|
|
13668
13855
|
return body || null;
|
|
@@ -13670,12 +13857,33 @@ function extractRecursiveScript(tokens) {
|
|
|
13670
13857
|
if (SHELL_INTERPRETERS.has(head) || CODE_INTERPRETERS.has(head)) {
|
|
13671
13858
|
const flagIndex = filtered.findIndex((token) => SCRIPT_FLAGS.has(token));
|
|
13672
13859
|
if (flagIndex !== -1) {
|
|
13673
|
-
const body = filtered
|
|
13860
|
+
const body = filtered[flagIndex + 1] ?? "";
|
|
13674
13861
|
return body || null;
|
|
13675
13862
|
}
|
|
13676
13863
|
}
|
|
13677
|
-
|
|
13678
|
-
|
|
13864
|
+
return null;
|
|
13865
|
+
}
|
|
13866
|
+
function extractDockerComposeRunScript(tokens) {
|
|
13867
|
+
const head = normalizeHead(tokens[0] ?? "");
|
|
13868
|
+
const usesCompose = head === "docker-compose" || head === "docker" && (tokens[1] ?? "") === "compose";
|
|
13869
|
+
if (!usesCompose) {
|
|
13870
|
+
return null;
|
|
13871
|
+
}
|
|
13872
|
+
if (!tokens.includes("run")) {
|
|
13873
|
+
return null;
|
|
13874
|
+
}
|
|
13875
|
+
const runIndex = tokens.indexOf("run");
|
|
13876
|
+
const tail = tokens.slice(runIndex + 1);
|
|
13877
|
+
for (let index = 0; index < tail.length; index += 1) {
|
|
13878
|
+
const shellHead = normalizeHead(tail[index] ?? "");
|
|
13879
|
+
if (!SHELL_INTERPRETERS.has(shellHead)) {
|
|
13880
|
+
continue;
|
|
13881
|
+
}
|
|
13882
|
+
const flag = tail[index + 1] ?? "";
|
|
13883
|
+
if (flag !== "-lc" && flag !== "-c") {
|
|
13884
|
+
continue;
|
|
13885
|
+
}
|
|
13886
|
+
const body = tail[index + 2] ?? "";
|
|
13679
13887
|
return body || null;
|
|
13680
13888
|
}
|
|
13681
13889
|
return null;
|
|
@@ -14039,9 +14247,10 @@ function lowerSegment(command, context) {
|
|
|
14039
14247
|
const environment = extractEnvironment(rawTokens, context.env);
|
|
14040
14248
|
const env = environment.env;
|
|
14041
14249
|
const parsed = parseSegment(command);
|
|
14042
|
-
const
|
|
14043
|
-
|
|
14044
|
-
|
|
14250
|
+
const parsedTokens = environment.commandTokens ?? parsed.tokens;
|
|
14251
|
+
const tokens = stripRedirects(
|
|
14252
|
+
parsedTokens.length === 0 && rawTokens.length > 0 && rawTokens.every((token) => ENV_PREFIX_PATTERN2.test(token)) ? rawTokens : parsedTokens
|
|
14253
|
+
).map((token) => expandKnownVariables(token, env));
|
|
14045
14254
|
const head = path39.basename(tokens[0] ?? parsed.head);
|
|
14046
14255
|
let opacity = segmentOpacity(command);
|
|
14047
14256
|
const signals = /* @__PURE__ */ new Set();
|
|
@@ -14143,6 +14352,31 @@ function lowerSegment(command, context) {
|
|
|
14143
14352
|
}
|
|
14144
14353
|
return shellSegment(commandRedacted, head, requirements, "recursive", signals);
|
|
14145
14354
|
}
|
|
14355
|
+
const dockerComposeScript = extractDockerComposeRunScript(tokens);
|
|
14356
|
+
if (dockerComposeScript && opacity !== "opaque" && opacity !== "unparseable") {
|
|
14357
|
+
requirements.push(
|
|
14358
|
+
processRequirement(head, "spawn", commandRedacted, ["process.docker_compose_run"])
|
|
14359
|
+
);
|
|
14360
|
+
const nested = lowerTopLevelSegments(dockerComposeScript, {
|
|
14361
|
+
...context,
|
|
14362
|
+
command: dockerComposeScript,
|
|
14363
|
+
env,
|
|
14364
|
+
depth: context.depth + 1
|
|
14365
|
+
});
|
|
14366
|
+
for (const nestedSegment of nested) {
|
|
14367
|
+
requirements.push(
|
|
14368
|
+
...nestedSegment.requirements.map(
|
|
14369
|
+
(entry) => withInnerProvenance(entry, dockerComposeScript, head, commandRedacted)
|
|
14370
|
+
)
|
|
14371
|
+
);
|
|
14372
|
+
for (const signal of nestedSegment.signals) {
|
|
14373
|
+
signals.add(signal);
|
|
14374
|
+
}
|
|
14375
|
+
opacity = joinNestedOpacity(opacity, nestedSegment);
|
|
14376
|
+
}
|
|
14377
|
+
signals.add("process.docker_compose_run");
|
|
14378
|
+
return shellSegment(commandRedacted, head, requirements, "recursive", signals);
|
|
14379
|
+
}
|
|
14146
14380
|
const launcher = resolveLauncherRecipe({
|
|
14147
14381
|
tokens,
|
|
14148
14382
|
cwd: context.cwd,
|
|
@@ -14364,6 +14598,111 @@ function railsReadOnlySubcommand(args) {
|
|
|
14364
14598
|
}
|
|
14365
14599
|
return RAILS_READ_ONLY_SUBCOMMANDS.has(subcommand);
|
|
14366
14600
|
}
|
|
14601
|
+
function isRubyTestScript(scriptPath) {
|
|
14602
|
+
const base = path39.basename(scriptPath);
|
|
14603
|
+
return base.endsWith("_test.rb") || base.endsWith("_spec.rb");
|
|
14604
|
+
}
|
|
14605
|
+
function parseRubyTestInvocation(args) {
|
|
14606
|
+
const includePaths = [];
|
|
14607
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
14608
|
+
const arg = args[index] ?? "";
|
|
14609
|
+
if (arg === "-e" || arg === "-r") {
|
|
14610
|
+
return null;
|
|
14611
|
+
}
|
|
14612
|
+
if (arg === "-I") {
|
|
14613
|
+
const includePath = args[index + 1];
|
|
14614
|
+
if (!includePath) {
|
|
14615
|
+
return null;
|
|
14616
|
+
}
|
|
14617
|
+
includePaths.push(includePath);
|
|
14618
|
+
index += 1;
|
|
14619
|
+
continue;
|
|
14620
|
+
}
|
|
14621
|
+
if (arg.startsWith("-I") && arg.length > 2) {
|
|
14622
|
+
includePaths.push(arg.slice(2));
|
|
14623
|
+
continue;
|
|
14624
|
+
}
|
|
14625
|
+
if (arg.startsWith("-")) {
|
|
14626
|
+
if (arg === "-n") {
|
|
14627
|
+
if (!args[index + 1]) {
|
|
14628
|
+
return null;
|
|
14629
|
+
}
|
|
14630
|
+
index += 1;
|
|
14631
|
+
continue;
|
|
14632
|
+
}
|
|
14633
|
+
if (arg.startsWith("-n")) {
|
|
14634
|
+
continue;
|
|
14635
|
+
}
|
|
14636
|
+
return null;
|
|
14637
|
+
}
|
|
14638
|
+
if (isRubyTestScript(arg)) {
|
|
14639
|
+
return { includePaths, scriptPath: arg };
|
|
14640
|
+
}
|
|
14641
|
+
return null;
|
|
14642
|
+
}
|
|
14643
|
+
return null;
|
|
14644
|
+
}
|
|
14645
|
+
function isRubocopMutating(args) {
|
|
14646
|
+
return args.some(
|
|
14647
|
+
(arg) => arg === "-A" || arg === "-a" || arg === "--auto-correct" || arg === "--autocorrect" || arg.startsWith("--auto-correct-all") || arg.startsWith("--autocorrect-all")
|
|
14648
|
+
);
|
|
14649
|
+
}
|
|
14650
|
+
function decodeBundleExecInner(innerHead, innerArgs, segment) {
|
|
14651
|
+
const innerBase = executableBaseName(innerHead);
|
|
14652
|
+
if (innerBase === "rubocop") {
|
|
14653
|
+
const mutating = isRubocopMutating(innerArgs);
|
|
14654
|
+
return [
|
|
14655
|
+
processRequirement(
|
|
14656
|
+
innerHead,
|
|
14657
|
+
mutating ? "spawn" : "inspect",
|
|
14658
|
+
segment,
|
|
14659
|
+
mutating ? ["process.linter.mutating"] : ["process.inspect.linter"]
|
|
14660
|
+
)
|
|
14661
|
+
];
|
|
14662
|
+
}
|
|
14663
|
+
if (innerBase === "rspec") {
|
|
14664
|
+
const targetArgs = innerArgs.filter((arg) => !arg.startsWith("-"));
|
|
14665
|
+
if (targetArgs.length === 0) {
|
|
14666
|
+
return null;
|
|
14667
|
+
}
|
|
14668
|
+
return [processRequirement(innerHead, "spawn", segment, ["process.test_runner.rspec"])];
|
|
14669
|
+
}
|
|
14670
|
+
return null;
|
|
14671
|
+
}
|
|
14672
|
+
function decodeRuby(args, cwd, repoRoot, segment) {
|
|
14673
|
+
const parsed = parseRubyTestInvocation(args);
|
|
14674
|
+
if (!parsed) {
|
|
14675
|
+
return unsupportedProcess("ruby", segment, "process.ruby_grammar_incomplete");
|
|
14676
|
+
}
|
|
14677
|
+
const scriptPath = resolvePathOperand(parsed.scriptPath, cwd);
|
|
14678
|
+
if (!pathWithinRoot(canonicalPath(repoRoot), canonicalPath(scriptPath))) {
|
|
14679
|
+
return unsupportedProcess("ruby", segment, "process.ruby_outside_repo");
|
|
14680
|
+
}
|
|
14681
|
+
for (const includePath of parsed.includePaths) {
|
|
14682
|
+
const resolvedInclude = resolvePathOperand(includePath, cwd);
|
|
14683
|
+
if (!pathWithinRoot(canonicalPath(repoRoot), canonicalPath(resolvedInclude))) {
|
|
14684
|
+
return unsupportedProcess("ruby", segment, "process.ruby_outside_repo");
|
|
14685
|
+
}
|
|
14686
|
+
}
|
|
14687
|
+
const lowered = [
|
|
14688
|
+
processRequirement("ruby", "spawn", segment, ["process.test_runner.minitest"]),
|
|
14689
|
+
requirement2("fs.read", "fs.read", { kind: "path", path: scriptPath }, segment, [
|
|
14690
|
+
"ruby.minitest_script_read"
|
|
14691
|
+
])
|
|
14692
|
+
];
|
|
14693
|
+
for (const includePath of parsed.includePaths) {
|
|
14694
|
+
lowered.push(
|
|
14695
|
+
requirement2(
|
|
14696
|
+
"fs.read",
|
|
14697
|
+
"fs.read",
|
|
14698
|
+
{ kind: "path", path: resolvePathOperand(includePath, cwd) },
|
|
14699
|
+
segment,
|
|
14700
|
+
["ruby.minitest_load_path_read"]
|
|
14701
|
+
)
|
|
14702
|
+
);
|
|
14703
|
+
}
|
|
14704
|
+
return lowered;
|
|
14705
|
+
}
|
|
14367
14706
|
function decodeRuntimeMetadataProcess(head, args, segment) {
|
|
14368
14707
|
if (head === "bundle") {
|
|
14369
14708
|
if (args.length === 1 && isMetadataOnlyArgv(args)) {
|
|
@@ -14385,6 +14724,10 @@ function decodeRuntimeMetadataProcess(head, args, segment) {
|
|
|
14385
14724
|
])
|
|
14386
14725
|
];
|
|
14387
14726
|
}
|
|
14727
|
+
const bundleExecInner = decodeBundleExecInner(innerHead, innerArgs, segment);
|
|
14728
|
+
if (bundleExecInner) {
|
|
14729
|
+
return bundleExecInner;
|
|
14730
|
+
}
|
|
14388
14731
|
}
|
|
14389
14732
|
return null;
|
|
14390
14733
|
}
|
|
@@ -14400,9 +14743,74 @@ function decodeRuntimeMetadataProcess(head, args, segment) {
|
|
|
14400
14743
|
}
|
|
14401
14744
|
return null;
|
|
14402
14745
|
}
|
|
14746
|
+
function decodeSetBuiltin(args) {
|
|
14747
|
+
let index = 0;
|
|
14748
|
+
while (index < args.length) {
|
|
14749
|
+
const arg = args[index] ?? "";
|
|
14750
|
+
if (arg === "--") {
|
|
14751
|
+
index += 1;
|
|
14752
|
+
continue;
|
|
14753
|
+
}
|
|
14754
|
+
if (arg === "-o" || arg === "+o") {
|
|
14755
|
+
if (!args[index + 1]) {
|
|
14756
|
+
return false;
|
|
14757
|
+
}
|
|
14758
|
+
index += 2;
|
|
14759
|
+
continue;
|
|
14760
|
+
}
|
|
14761
|
+
if (/^[-+][A-Za-z0-9]+$/.test(arg)) {
|
|
14762
|
+
index += 1;
|
|
14763
|
+
continue;
|
|
14764
|
+
}
|
|
14765
|
+
return false;
|
|
14766
|
+
}
|
|
14767
|
+
return true;
|
|
14768
|
+
}
|
|
14769
|
+
function decodeShellControlBuiltin(head, args) {
|
|
14770
|
+
if (head === "set") {
|
|
14771
|
+
return decodeSetBuiltin(args) ? [] : null;
|
|
14772
|
+
}
|
|
14773
|
+
if (head === "wait") {
|
|
14774
|
+
if (args.length === 0 || args.every((arg) => /^\d+$/.test(arg))) {
|
|
14775
|
+
return [];
|
|
14776
|
+
}
|
|
14777
|
+
return null;
|
|
14778
|
+
}
|
|
14779
|
+
if (head === "exit") {
|
|
14780
|
+
if (args.length === 0 || args.length === 1 && /^-?\d+$/.test(args[0] ?? "")) {
|
|
14781
|
+
return [];
|
|
14782
|
+
}
|
|
14783
|
+
return null;
|
|
14784
|
+
}
|
|
14785
|
+
return null;
|
|
14786
|
+
}
|
|
14787
|
+
function decodeDockerComposeRun(head, args, segment) {
|
|
14788
|
+
let composeArgs = null;
|
|
14789
|
+
let command = head;
|
|
14790
|
+
if (head === "docker-compose") {
|
|
14791
|
+
composeArgs = args;
|
|
14792
|
+
} else if (head === "docker" && args[0] === "compose") {
|
|
14793
|
+
composeArgs = args.slice(1);
|
|
14794
|
+
command = "docker";
|
|
14795
|
+
}
|
|
14796
|
+
if (!composeArgs) {
|
|
14797
|
+
return null;
|
|
14798
|
+
}
|
|
14799
|
+
if (composeArgs.includes("run")) {
|
|
14800
|
+
return [processRequirement(command, "spawn", segment, ["process.docker_compose_run"])];
|
|
14801
|
+
}
|
|
14802
|
+
return unsupportedProcess(command, segment, "process.docker_compose_grammar_incomplete");
|
|
14803
|
+
}
|
|
14403
14804
|
function decodeProcessOrFilesystem(params) {
|
|
14404
14805
|
const { tokens, head, env, cwd, repoRoot, segment } = params;
|
|
14405
14806
|
const args = tokens.slice(1);
|
|
14807
|
+
if (tokens.length > 0 && tokens.every((token) => ENV_PREFIX_PATTERN2.test(token))) {
|
|
14808
|
+
return [];
|
|
14809
|
+
}
|
|
14810
|
+
const shellControl = decodeShellControlBuiltin(head, args);
|
|
14811
|
+
if (shellControl) {
|
|
14812
|
+
return shellControl;
|
|
14813
|
+
}
|
|
14406
14814
|
if (isCommandInspection(tokens)) {
|
|
14407
14815
|
return [processRequirement(head, "inspect", segment, ["process.inspect.command_lookup"])];
|
|
14408
14816
|
}
|
|
@@ -14485,6 +14893,19 @@ function decodeProcessOrFilesystem(params) {
|
|
|
14485
14893
|
if (runtimeMetadata) {
|
|
14486
14894
|
return runtimeMetadata;
|
|
14487
14895
|
}
|
|
14896
|
+
if (head === "ruby") {
|
|
14897
|
+
return decodeRuby(args, cwd, repoRoot, segment);
|
|
14898
|
+
}
|
|
14899
|
+
if (head === "rubocop" || head === "rspec") {
|
|
14900
|
+
const decoded = decodeBundleExecInner(head, args, segment);
|
|
14901
|
+
if (decoded) {
|
|
14902
|
+
return decoded;
|
|
14903
|
+
}
|
|
14904
|
+
}
|
|
14905
|
+
const dockerCompose = decodeDockerComposeRun(head, args, segment);
|
|
14906
|
+
if (dockerCompose) {
|
|
14907
|
+
return dockerCompose;
|
|
14908
|
+
}
|
|
14488
14909
|
if ((head === "npm" || head === "pnpm") && args.length === 1 && isMetadataOnlyArgv(args)) {
|
|
14489
14910
|
return [processRequirement(head, "inspect", segment, ["process.inspect.package_manager"])];
|
|
14490
14911
|
}
|
|
@@ -16723,7 +17144,7 @@ function hashDecisionConfig(config) {
|
|
|
16723
17144
|
init_fingerprint2();
|
|
16724
17145
|
|
|
16725
17146
|
// src/version.ts
|
|
16726
|
-
var PACKAGE_VERSION = "0.9.
|
|
17147
|
+
var PACKAGE_VERSION = "0.9.2";
|
|
16727
17148
|
|
|
16728
17149
|
// src/runtime-provenance.ts
|
|
16729
17150
|
function resolveRuntimeArtifactHash(artifactHash) {
|