jules-orchestrator-kit 0.41.1 → 0.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agent/prompts/A11y.md +23 -0
- package/.agent/prompts/Alchemist.md +23 -0
- package/.agent/prompts/Scribe.md +23 -0
- package/.agent/prompts/Spectator.md +24 -0
- package/JULES_RULES_TEMPLATE.md +10 -8
- package/README.md +10 -4
- package/bin/agentctl.mjs +356 -0
- package/index.mjs +26 -1
- package/package.json +1 -1
- package/scripts/asset-integrity-check.mjs +1 -1
- package/scripts/rules-lint.mjs +1 -1
- package/src/assertions.mjs +244 -0
- package/src/config.mjs +25 -0
- package/src/coverage.mjs +328 -0
- package/src/engine.mjs +20 -4
- package/src/git.mjs +131 -9
- package/src/mutation.mjs +739 -0
- package/src/ops/checkpoint.mjs +31 -3
- package/src/perf.mjs +92 -0
- package/src/provider.mjs +10 -1
- package/src/remediation.mjs +154 -1
- package/src/rules-budget.mjs +8 -2
- package/src/scaffold.mjs +139 -2
- package/src/security.mjs +286 -28
- package/src/stability.mjs +86 -0
- package/src/web-templates.mjs +172 -0
- package/src/asset_integrity.mjs +0 -1
- package/src/execution_envelope.mjs +0 -1
- package/src/rules_budget.mjs +0 -1
package/src/git.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { execFileSync, execSync } from "node:child_process";
|
|
2
2
|
import { readFileSync, existsSync } from "node:fs";
|
|
3
|
-
import { join } from "node:path";
|
|
3
|
+
import { join, delimiter } from "node:path";
|
|
4
4
|
import { normalizePath } from "./config.mjs";
|
|
5
5
|
|
|
6
6
|
|
|
@@ -18,6 +18,118 @@ export class GateError extends Error {
|
|
|
18
18
|
const DEFAULT_TIMEOUT = 10 * 60 * 1000; // 10 minutes
|
|
19
19
|
const DEFAULT_MAX_BUFFER = 10 * 1024 * 1024; // 10 MB
|
|
20
20
|
|
|
21
|
+
// Windows cmd.exe quoting. `.cmd`/`.bat` shims (npm.cmd, claude.cmd, …) cannot
|
|
22
|
+
// be spawned by CreateProcess, so they must run through cmd.exe, and the
|
|
23
|
+
// command line cmd.exe sees must round-trip every argv element exactly. The
|
|
24
|
+
// rules below follow the C runtime's argument parser and cmd.exe's meta-char
|
|
25
|
+
// escaping — the same algorithm cross-spawn uses — reimplemented here so the
|
|
26
|
+
// kit stays dependency-free.
|
|
27
|
+
|
|
28
|
+
// Characters cmd.exe treats specially outside double quotes.
|
|
29
|
+
const WINDOWS_META_CHARS = /([()\][%!^"`<>&|;, *?])/g;
|
|
30
|
+
// A real Windows executable, which CreateProcess can start without a shell.
|
|
31
|
+
const WINDOWS_NATIVE_EXE = /\.(?:com|exe)$/i;
|
|
32
|
+
// An npm-style cmd shim, which re-parses its own arguments and therefore needs
|
|
33
|
+
// its meta chars double-escaped.
|
|
34
|
+
const WINDOWS_CMD_SHIM = /node_modules[\\/]\.bin[\\/][^\\/]+\.cmd$/i;
|
|
35
|
+
|
|
36
|
+
/** Escapes cmd.exe meta characters in a command *name*. */
|
|
37
|
+
export function windowsEscapeCommand(command) {
|
|
38
|
+
return String(command).replace(WINDOWS_META_CHARS, "^$1");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Quotes a single argv element for cmd.exe.
|
|
43
|
+
*
|
|
44
|
+
* @param {string} arg
|
|
45
|
+
* @param {boolean} [doubleEscapeMetaChars] true when the command is a cmd-shim
|
|
46
|
+
* that will re-parse its own arguments (node_modules/.bin/*.cmd).
|
|
47
|
+
* @returns {string}
|
|
48
|
+
*/
|
|
49
|
+
export function windowsEscapeArgument(arg, doubleEscapeMetaChars = false) {
|
|
50
|
+
let ret = String(arg);
|
|
51
|
+
// Backslash runs immediately before a double quote: double the backslashes
|
|
52
|
+
// and escape the quote.
|
|
53
|
+
ret = ret.replace(/(?=(\\+?)?)\1"/g, '$1$1\\"');
|
|
54
|
+
// A backslash run at the very end will sit in front of the closing quote we
|
|
55
|
+
// add next: double it so it stays literal.
|
|
56
|
+
ret = ret.replace(/(?=(\\+?)?)\1$/, "$1$1");
|
|
57
|
+
ret = `"${ret}"`;
|
|
58
|
+
ret = ret.replace(WINDOWS_META_CHARS, "^$1");
|
|
59
|
+
if (doubleEscapeMetaChars) ret = ret.replace(WINDOWS_META_CHARS, "^$1");
|
|
60
|
+
return ret;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Resolves `binary` against PATH + PATHEXT on Windows.
|
|
65
|
+
*
|
|
66
|
+
* @param {string} binary
|
|
67
|
+
* @param {NodeJS.ProcessEnv} env
|
|
68
|
+
* @returns {string | null}
|
|
69
|
+
*/
|
|
70
|
+
function resolveWindowsCommand(binary, env) {
|
|
71
|
+
const pathExt = (env.PATHEXT || ".COM;.EXE;.BAT;.CMD").split(";").map((e) => e.trim()).filter(Boolean);
|
|
72
|
+
const hasSeparator = /[\\/]/.test(binary) || /^[A-Za-z]:/.test(binary);
|
|
73
|
+
|
|
74
|
+
const candidates = [];
|
|
75
|
+
if (hasSeparator) {
|
|
76
|
+
candidates.push(binary);
|
|
77
|
+
for (const ext of pathExt) candidates.push(binary + ext);
|
|
78
|
+
} else {
|
|
79
|
+
const dirs = (env.PATH || "").split(delimiter).filter(Boolean);
|
|
80
|
+
for (const dir of dirs) {
|
|
81
|
+
for (const ext of pathExt) candidates.push(join(dir, binary + ext));
|
|
82
|
+
candidates.push(join(dir, binary));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
for (const candidate of candidates) {
|
|
87
|
+
try {
|
|
88
|
+
if (existsSync(candidate)) return candidate;
|
|
89
|
+
} catch (_) {}
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Builds the spawn arguments that correctly execute `binary` with `args` on
|
|
96
|
+
* Windows, handling the `.cmd`/`.bat` shims package managers and CLI providers
|
|
97
|
+
* install. Returns null on non-Windows so callers keep spawning the binary
|
|
98
|
+
* directly (`P-07`).
|
|
99
|
+
*
|
|
100
|
+
* @param {string} binary
|
|
101
|
+
* @param {string[]} args
|
|
102
|
+
* @param {NodeJS.ProcessEnv} [env]
|
|
103
|
+
* @param {NodeJS.Platform} [platform]
|
|
104
|
+
* @returns {{ file: string, args: string[], verbatim: boolean } | null}
|
|
105
|
+
*/
|
|
106
|
+
export function resolveWindowsSpawn(binary, args, env = process.env, platform = process.platform) {
|
|
107
|
+
if (platform !== "win32") return null;
|
|
108
|
+
|
|
109
|
+
const argArray = (args || []).map((a) => String(a));
|
|
110
|
+
const resolved = resolveWindowsCommand(binary, env);
|
|
111
|
+
|
|
112
|
+
// A native executable is spawned directly — its argv needs no quoting.
|
|
113
|
+
if (resolved && WINDOWS_NATIVE_EXE.test(resolved)) {
|
|
114
|
+
return { file: resolved, args: argArray, verbatim: false };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Everything else (`.cmd`, `.bat`, or an unresolved name) goes through
|
|
118
|
+
// cmd.exe. The `/s /c` invocation plus one outer quote pair is the shape
|
|
119
|
+
// cmd.exe expects so the pre-quoted argv parses back into the same elements.
|
|
120
|
+
const commandName = resolved || binary;
|
|
121
|
+
const doubleEscape = WINDOWS_CMD_SHIM.test(resolved || commandName);
|
|
122
|
+
const shellCommand = [windowsEscapeCommand(commandName)]
|
|
123
|
+
.concat(argArray.map((a) => windowsEscapeArgument(a, doubleEscape)))
|
|
124
|
+
.join(" ");
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
file: (env && env.ComSpec) || "cmd.exe",
|
|
128
|
+
args: ["/d", "/s", "/c", `"${shellCommand}"`],
|
|
129
|
+
verbatim: true,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
21
133
|
export function runCmd(command, opts = {}) {
|
|
22
134
|
const cwd = opts.cwd || process.cwd();
|
|
23
135
|
const timeout = opts.timeout || DEFAULT_TIMEOUT;
|
|
@@ -53,14 +165,23 @@ export function runCmd(command, opts = {}) {
|
|
|
53
165
|
// Windows install, and the gate reported it as a plain non-zero verification
|
|
54
166
|
// rather than as an environment problem.
|
|
55
167
|
//
|
|
56
|
-
//
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
// metacharacter
|
|
62
|
-
//
|
|
168
|
+
// A whitespace-split string command is re-run under `shell: true`: Node
|
|
169
|
+
// rebuilds the command line as `[file, ...args].join(" ")` and passes it to
|
|
170
|
+
// cmd.exe verbatim. That reconstruction is normally lossy — it does not quote
|
|
171
|
+
// an argument containing a space — but it is exact here, because these tokens
|
|
172
|
+
// were produced by splitting on whitespace in the first place, and none of
|
|
173
|
+
// them can contain a shell metacharacter (those took the execSync branch).
|
|
174
|
+
//
|
|
175
|
+
// An *array* command cannot use that trick: its elements may legitimately
|
|
176
|
+
// contain spaces, so the same join would corrupt argv. Arrays are therefore
|
|
177
|
+
// wrapped in cmd.exe with every element quoted per the C-runtime + cmd.exe
|
|
178
|
+
// rules, which preserves argv exactly while still letting the shell resolve
|
|
179
|
+
// the `.cmd` shim (P-07).
|
|
63
180
|
const winShim = tokenized && process.platform === "win32";
|
|
181
|
+
const winSpawn =
|
|
182
|
+
!useShell && !winShim && process.platform === "win32"
|
|
183
|
+
? resolveWindowsSpawn(binary, args, opts.env || process.env)
|
|
184
|
+
: null;
|
|
64
185
|
|
|
65
186
|
if (!binary && !useShell) {
|
|
66
187
|
if (opts.ignoreError) return { status: 0, stdout: "", stderr: "" };
|
|
@@ -77,10 +198,11 @@ export function runCmd(command, opts = {}) {
|
|
|
77
198
|
timeout,
|
|
78
199
|
maxBuffer,
|
|
79
200
|
})
|
|
80
|
-
: execFileSync(binary, args, {
|
|
201
|
+
: execFileSync(winSpawn ? winSpawn.file : binary, winSpawn ? winSpawn.args : args, {
|
|
81
202
|
cwd,
|
|
82
203
|
encoding: "utf-8",
|
|
83
204
|
shell: winShim,
|
|
205
|
+
windowsVerbatimArguments: Boolean(winSpawn && winSpawn.verbatim),
|
|
84
206
|
stdio: ["ignore", "pipe", "pipe"],
|
|
85
207
|
env: opts.env || process.env,
|
|
86
208
|
timeout,
|