@codyswann/lisa 4.35.0 → 4.35.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/all/copy-overwrite/scripts/check-npm-publish-landed.mjs +49 -26
- package/all/copy-overwrite/scripts/lib/kill-marks.mjs +1 -0
- package/all/copy-overwrite/scripts/lisa-hooks/block-direct-issue-create.sh +49 -10
- package/all/copy-overwrite/scripts/lisa-hooks/block-managed-file-edits.sh +42 -4
- package/all/copy-overwrite/scripts/lisa-hooks/parity-safety-net.sh +33 -12
- package/all/copy-overwrite/scripts/lisa-run-gates.mjs +9 -4
- package/all/copy-overwrite/scripts/lisa-work-item.mjs +9 -6
- package/dist/cli/apply.js +8 -8
- package/dist/cli/apply.js.map +1 -1
- package/dist/codex/scripts/_extract-edit-paths.sh +4 -0
- package/dist/core/apply-receipt.d.ts +17 -12
- package/dist/core/apply-receipt.d.ts.map +1 -1
- package/dist/core/apply-receipt.js +3 -3
- package/dist/core/apply-receipt.js.map +1 -1
- package/dist/core/config.d.ts +10 -6
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +20 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
- package/dist/core/lisa.d.ts +34 -24
- package/dist/core/lisa.d.ts.map +1 -1
- package/dist/core/lisa.js +49 -41
- package/dist/core/lisa.js.map +1 -1
- package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
- package/dist/core/upstream-evidence-manifest.js +10 -10
- package/dist/migrations/ensure-lisa-postinstall.d.ts +6 -37
- package/dist/migrations/ensure-lisa-postinstall.d.ts.map +1 -1
- package/dist/migrations/ensure-lisa-postinstall.js +20 -67
- package/dist/migrations/ensure-lisa-postinstall.js.map +1 -1
- package/dist/opencode/plugin-templates/parity-safety-net.sh +33 -12
- package/package.json +4 -4
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/hooks/block-direct-issue-create.sh +49 -10
- package/plugins/lisa/hooks/block-managed-file-edits.sh +42 -4
- package/plugins/lisa/hooks/parity-safety-net.sh +33 -12
- package/plugins/lisa-agy/hooks/block-direct-issue-create.sh +49 -10
- package/plugins/lisa-agy/hooks/parity-safety-net.sh +33 -12
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/hooks/block-direct-issue-create.sh +49 -10
- package/plugins/lisa-copilot/hooks/block-managed-file-edits.sh +42 -4
- package/plugins/lisa-copilot/hooks/parity-safety-net.sh +33 -12
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/hooks/block-direct-issue-create.sh +49 -10
- package/plugins/lisa-cursor/hooks/block-managed-file-edits.sh +42 -4
- package/plugins/lisa-cursor/hooks/parity-safety-net.sh +33 -12
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/src/base/hooks/block-direct-issue-create.sh +49 -10
- package/plugins/src/base/hooks/block-managed-file-edits.sh +42 -4
- package/plugins/src/base/hooks/parity-safety-net.sh +33 -12
|
@@ -60,6 +60,9 @@ const DEFAULT_ATTEMPTS = 5;
|
|
|
60
60
|
/** Pause between attempts, in milliseconds. */
|
|
61
61
|
const DEFAULT_DELAY_MS = 3000;
|
|
62
62
|
|
|
63
|
+
/** Maximum wall time for one registry attempt, including body parsing. */
|
|
64
|
+
const DEFAULT_ATTEMPT_TIMEOUT_MS = 10_000;
|
|
65
|
+
|
|
63
66
|
/** The line a caller greps for. Never printed without a real verdict behind it. */
|
|
64
67
|
const VERDICT_PREFIX = "npm-publish-landed:";
|
|
65
68
|
|
|
@@ -90,42 +93,52 @@ export function exactVersionUrl(registry, name, version) {
|
|
|
90
93
|
* @param {string} url - The exact-version manifest URL.
|
|
91
94
|
* @param {typeof fetch} fetchImpl - Injected for tests.
|
|
92
95
|
* @param {string} version - The version the answer must name.
|
|
96
|
+
* @param {object} timeout - Per-attempt deadline dependencies.
|
|
97
|
+
* @param {number} timeout.attemptTimeoutMs - Deadline in milliseconds.
|
|
98
|
+
* @param {() => AbortController} timeout.createAbortController - Controller factory.
|
|
99
|
+
* @param {typeof setTimeout} timeout.setAttemptTimer - Timer scheduler.
|
|
100
|
+
* @param {typeof clearTimeout} timeout.clearAttemptTimer - Timer clearer.
|
|
93
101
|
* @returns {Promise<{verdict: string, detail: string}>} One attempt's outcome.
|
|
94
102
|
*/
|
|
95
|
-
async function askOnce(url, fetchImpl, version) {
|
|
96
|
-
|
|
103
|
+
async function askOnce(url, fetchImpl, version, timeout) {
|
|
104
|
+
const controller = timeout.createAbortController();
|
|
105
|
+
const timer = timeout.setAttemptTimer(
|
|
106
|
+
() => controller.abort(),
|
|
107
|
+
timeout.attemptTimeoutMs
|
|
108
|
+
);
|
|
97
109
|
try {
|
|
98
|
-
response = await fetchImpl(url, {
|
|
110
|
+
const response = await fetchImpl(url, {
|
|
99
111
|
headers: { accept: "application/json" },
|
|
112
|
+
signal: controller.signal,
|
|
100
113
|
});
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
+
if (response.status === 404) {
|
|
115
|
+
return { verdict: "missing", detail: "registry returned 404" };
|
|
116
|
+
}
|
|
117
|
+
if (!response.ok) {
|
|
118
|
+
return { verdict: "unprovable", detail: `HTTP ${response.status}` };
|
|
119
|
+
}
|
|
120
|
+
const manifest = await response.json();
|
|
121
|
+
// A 200 that names a different version is not this version being present.
|
|
122
|
+
if (manifest?.version !== version) {
|
|
123
|
+
return {
|
|
124
|
+
verdict: "unprovable",
|
|
125
|
+
detail: `HTTP 200 but the body names version ${String(manifest?.version)}`,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
114
128
|
return {
|
|
115
|
-
verdict: "
|
|
116
|
-
detail:
|
|
129
|
+
verdict: "published",
|
|
130
|
+
detail: "registry served this exact version",
|
|
117
131
|
};
|
|
118
|
-
}
|
|
119
|
-
// A 200 that names a different version is not this version being present. The
|
|
120
|
-
// registry is not expected to do this; treating it as proof anyway is how a
|
|
121
|
-
// surprise becomes a silent pass.
|
|
122
|
-
if (manifest?.version !== version) {
|
|
132
|
+
} catch (error) {
|
|
123
133
|
return {
|
|
124
134
|
verdict: "unprovable",
|
|
125
|
-
detail:
|
|
135
|
+
detail: controller.signal.aborted
|
|
136
|
+
? `attempt exceeded ${String(timeout.attemptTimeoutMs)}ms deadline`
|
|
137
|
+
: `network or body: ${error.message}`,
|
|
126
138
|
};
|
|
139
|
+
} finally {
|
|
140
|
+
timeout.clearAttemptTimer(timer);
|
|
127
141
|
}
|
|
128
|
-
return { verdict: "published", detail: "registry served this exact version" };
|
|
129
142
|
}
|
|
130
143
|
|
|
131
144
|
/**
|
|
@@ -149,6 +162,7 @@ const worthRetrying = verdict => verdict !== "published";
|
|
|
149
162
|
* @param {string} [options.registry] - Registry origin.
|
|
150
163
|
* @param {number} [options.attempts] - How many times to ask.
|
|
151
164
|
* @param {number} [options.delayMs] - Pause between attempts.
|
|
165
|
+
* @param {number} [options.attemptTimeoutMs] - Deadline for each attempt.
|
|
152
166
|
* @param {typeof fetch} [options.fetchImpl] - Injected for tests.
|
|
153
167
|
* @param {(ms: number) => Promise<void>} [options.sleep] - Injected for tests.
|
|
154
168
|
* @returns {Promise<{verdict: string, detail: string, urls: string[]}>} Outcome.
|
|
@@ -159,15 +173,24 @@ export async function verifyPublish({
|
|
|
159
173
|
registry = DEFAULT_REGISTRY,
|
|
160
174
|
attempts = DEFAULT_ATTEMPTS,
|
|
161
175
|
delayMs = DEFAULT_DELAY_MS,
|
|
176
|
+
attemptTimeoutMs = DEFAULT_ATTEMPT_TIMEOUT_MS,
|
|
162
177
|
fetchImpl = fetch,
|
|
163
178
|
sleep = ms => new Promise(resolve => setTimeout(resolve, ms)),
|
|
179
|
+
createAbortController = () => new AbortController(),
|
|
180
|
+
setAttemptTimer = setTimeout,
|
|
181
|
+
clearAttemptTimer = clearTimeout,
|
|
164
182
|
}) {
|
|
165
183
|
const url = exactVersionUrl(registry, packageName, version);
|
|
166
184
|
const urls = [];
|
|
167
185
|
let outcome = { verdict: "unprovable", detail: "no attempt was made" };
|
|
168
186
|
for (let attempt = 1; attempt <= attempts; attempt += 1) {
|
|
169
187
|
urls.push(url);
|
|
170
|
-
outcome = await askOnce(url, fetchImpl, version
|
|
188
|
+
outcome = await askOnce(url, fetchImpl, version, {
|
|
189
|
+
attemptTimeoutMs,
|
|
190
|
+
createAbortController,
|
|
191
|
+
setAttemptTimer,
|
|
192
|
+
clearAttemptTimer,
|
|
193
|
+
});
|
|
171
194
|
if (!worthRetrying(outcome.verdict)) break;
|
|
172
195
|
if (attempt < attempts) await sleep(delayMs);
|
|
173
196
|
}
|
|
@@ -164,6 +164,7 @@ export function recentKillMarks(deps = {}) {
|
|
|
164
164
|
})
|
|
165
165
|
.filter(mark => mark !== null && mark.schema === 1)
|
|
166
166
|
.filter(mark => Number.isFinite(mark.at))
|
|
167
|
+
.filter(mark => mark.at <= now)
|
|
167
168
|
.filter(mark => now - mark.at <= KILL_MARK_RETENTION_MS)
|
|
168
169
|
.sort((left, right) => right.at - left.at);
|
|
169
170
|
} catch {
|
|
@@ -1429,7 +1429,11 @@ EXEC_WRAPPERS = {
|
|
|
1429
1429
|
"nohup": (frozenset(), 0),
|
|
1430
1430
|
"setsid": (frozenset(), 0),
|
|
1431
1431
|
"stdbuf": (frozenset({"-i", "-o", "-e"}), 0),
|
|
1432
|
-
"sudo": (frozenset({
|
|
1432
|
+
"sudo": (frozenset({
|
|
1433
|
+
"-u", "--user", "-g", "--group", "-C", "--close-from",
|
|
1434
|
+
"-p", "--prompt", "-h", "--host", "-r", "--role",
|
|
1435
|
+
"-t", "--type", "-U", "--other-user",
|
|
1436
|
+
}), 0),
|
|
1433
1437
|
"time": (frozenset(), 0),
|
|
1434
1438
|
"timeout": (frozenset({"-k", "--kill-after", "-s", "--signal"}), 1),
|
|
1435
1439
|
}
|
|
@@ -1450,6 +1454,31 @@ NO_SCRIPT_OPTIONS = {
|
|
|
1450
1454
|
"ruby": {"-e"},
|
|
1451
1455
|
}
|
|
1452
1456
|
|
|
1457
|
+
# Interpreter switches whose value is a separate token, followed by the real
|
|
1458
|
+
# script operand. Treating the value as the script makes the guard inspect a
|
|
1459
|
+
# preload or option value and never reach what the interpreter executes.
|
|
1460
|
+
INTERPRETER_VALUE_OPTIONS = {
|
|
1461
|
+
"bash": {"-o", "--option"},
|
|
1462
|
+
"dash": {"-o"},
|
|
1463
|
+
"deno": {"-c", "--config"},
|
|
1464
|
+
"ksh": {"-o"},
|
|
1465
|
+
"node": {"-r", "--require"},
|
|
1466
|
+
"nodejs": {"-r", "--require"},
|
|
1467
|
+
"sh": {"-o"},
|
|
1468
|
+
"zsh": {"-o"},
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
# Runtime subcommands that introduce the script path rather than name it.
|
|
1472
|
+
INTERPRETER_SUBCOMMANDS = {
|
|
1473
|
+
"bun": {"run"},
|
|
1474
|
+
"deno": {"run"},
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
|
|
1478
|
+
def is_assignment_word(token):
|
|
1479
|
+
"""Whether token is a POSIX shell assignment in command-prefix position."""
|
|
1480
|
+
return re.match(r"^[A-Za-z_][A-Za-z0-9_]*\+?=", token) is not None
|
|
1481
|
+
|
|
1453
1482
|
# Programs that READ their operands and never execute them as programs.
|
|
1454
1483
|
#
|
|
1455
1484
|
# This is an allowlist of readers rather than the inverse, and the asymmetry is
|
|
@@ -1504,7 +1533,7 @@ def executing_command(argv):
|
|
|
1504
1533
|
index = 0
|
|
1505
1534
|
while index < len(argv):
|
|
1506
1535
|
token = argv[index]
|
|
1507
|
-
if
|
|
1536
|
+
if is_assignment_word(token):
|
|
1508
1537
|
index += 1
|
|
1509
1538
|
continue
|
|
1510
1539
|
program = basename(token)
|
|
@@ -1571,16 +1600,20 @@ def executed_operand(argv):
|
|
|
1571
1600
|
# shebang — `./create.sh` names no interpreter and runs all the same.
|
|
1572
1601
|
if program not in EXECUTING_INTERPRETERS and resolve_operand(token) is not None:
|
|
1573
1602
|
return token
|
|
1574
|
-
# `bash < create.sh` runs that file as surely as `bash create.sh` does, and
|
|
1575
|
-
# `<` is not a segment boundary, so the pair survives in one argv.
|
|
1576
|
-
for index, argument in enumerate(args):
|
|
1577
|
-
if argument == "<" and index + 1 < len(args):
|
|
1578
|
-
return args[index + 1]
|
|
1579
1603
|
# Reached by a known interpreter AND by a program this parser cannot name.
|
|
1580
1604
|
# The unknown case is followed on purpose — see READ_ONLY_PROGRAMS.
|
|
1581
|
-
|
|
1582
|
-
|
|
1605
|
+
redirected = None
|
|
1606
|
+
index = 0
|
|
1607
|
+
while index < len(args):
|
|
1608
|
+
argument = args[index]
|
|
1609
|
+
if argument == "<":
|
|
1610
|
+
if index + 1 < len(args):
|
|
1611
|
+
redirected = args[index + 1]
|
|
1612
|
+
index += 2
|
|
1583
1613
|
continue
|
|
1614
|
+
if argument == "--":
|
|
1615
|
+
index += 1
|
|
1616
|
+
return args[index] if index < len(args) else redirected
|
|
1584
1617
|
if argument.startswith("-"):
|
|
1585
1618
|
# A command string or a module name; no script file follows.
|
|
1586
1619
|
head = argument.split("=", 1)[0]
|
|
@@ -1591,9 +1624,15 @@ def executed_operand(argv):
|
|
|
1591
1624
|
return None
|
|
1592
1625
|
elif head in NO_SCRIPT_OPTIONS.get(program, set()):
|
|
1593
1626
|
return None
|
|
1627
|
+
takes_value = head in INTERPRETER_VALUE_OPTIONS.get(program, set())
|
|
1628
|
+
index += 2 if takes_value and "=" not in argument else 1
|
|
1629
|
+
continue
|
|
1630
|
+
if argument in INTERPRETER_SUBCOMMANDS.get(program, set()):
|
|
1631
|
+
index += 1
|
|
1594
1632
|
continue
|
|
1595
1633
|
return argument
|
|
1596
|
-
|
|
1634
|
+
# `bash < create.sh` runs stdin only when no explicit script was named.
|
|
1635
|
+
return redirected
|
|
1597
1636
|
|
|
1598
1637
|
|
|
1599
1638
|
def file_operands(argv):
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
# from mine", and guessing "behind" is how a fork's stronger guard gets silently
|
|
94
94
|
# replaced by a weaker upstream one. Add a name here in the same commit that
|
|
95
95
|
# closes a vector.
|
|
96
|
-
# lisa-guard-capabilities: managed-path-resolution, lisaignore-precedence, generated-path-rebuild, redirect-target, tee-target, sed-in-place-all-spellings, executed-script-reach, source-builtin-reach, stdin-redirect-reach, wrapper-positional-operand, direct-script-command-reach, analyzer-failure-visible
|
|
96
|
+
# lisa-guard-capabilities: managed-path-resolution, lisaignore-precedence, generated-path-rebuild, redirect-target, tee-target, sed-in-place-all-spellings, executed-script-reach, source-builtin-reach, stdin-redirect-reach, wrapper-positional-operand, direct-script-command-reach, analyzer-failure-visible, apply-patch-parse-failure-visible, apply-patch-move-target, shell-command-string-reach
|
|
97
97
|
set -euo pipefail
|
|
98
98
|
|
|
99
99
|
input="$(cat)"
|
|
@@ -402,6 +402,7 @@ case "$tool_name" in
|
|
|
402
402
|
# *** Add File: <path>
|
|
403
403
|
# *** Update File: <path>
|
|
404
404
|
# *** Delete File: <path>
|
|
405
|
+
# *** Move to: <path>
|
|
405
406
|
#
|
|
406
407
|
# So every header is walked and each target classified; one managed
|
|
407
408
|
# target anywhere in a multi-file patch refuses the whole call, because
|
|
@@ -418,14 +419,25 @@ case "$tool_name" in
|
|
|
418
419
|
# legitimately cannot be one file. What is NOT restated is the
|
|
419
420
|
# classification: `managed_source` and `refuse` are the single copy here,
|
|
420
421
|
# exactly as for every other arm.
|
|
421
|
-
patch_text="$(printf '%s' "$input" | jq -
|
|
422
|
+
if ! patch_text="$(printf '%s' "$input" | jq -er '
|
|
423
|
+
if ((.tool_input.command? // "") | type) == "string"
|
|
424
|
+
then (.tool_input.command? // "")
|
|
425
|
+
else error("tool_input.command must be a string")
|
|
426
|
+
end')"; then
|
|
427
|
+
printf 'block-managed-file-edits: could not parse the apply_patch command; managed-file protection refused the edit\n' >&2
|
|
428
|
+
exit 2
|
|
429
|
+
fi
|
|
422
430
|
[ -n "$patch_text" ] || exit 0
|
|
423
431
|
while IFS= read -r patch_line; do
|
|
424
432
|
case "$patch_line" in
|
|
425
|
-
"*** Add File: "* | "*** Update File: "* | "*** Delete File: "*)
|
|
433
|
+
"*** Add File: "* | "*** Update File: "* | "*** Delete File: "*)
|
|
434
|
+
candidate="${patch_line#*File: }"
|
|
435
|
+
;;
|
|
436
|
+
"*** Move to: "*)
|
|
437
|
+
candidate="${patch_line#*** Move to: }"
|
|
438
|
+
;;
|
|
426
439
|
*) continue ;;
|
|
427
440
|
esac
|
|
428
|
-
candidate="${patch_line#*File: }"
|
|
429
441
|
[ -n "$candidate" ] || continue
|
|
430
442
|
if source_path="$(managed_source "$candidate")"; then
|
|
431
443
|
refuse "$candidate" "$source_path" "$(relative_path "$candidate")"
|
|
@@ -715,6 +727,29 @@ def shell_script_operand(args):
|
|
|
715
727
|
return None
|
|
716
728
|
|
|
717
729
|
|
|
730
|
+
def shell_command_string(statement):
|
|
731
|
+
"""The inline command a shell executes with `-c`, or None.
|
|
732
|
+
|
|
733
|
+
Args:
|
|
734
|
+
statement: One statement's tokens.
|
|
735
|
+
|
|
736
|
+
Returns:
|
|
737
|
+
The command string operand, or None when this is not a shell `-c` call.
|
|
738
|
+
"""
|
|
739
|
+
_token, program, args = command_word(statement)
|
|
740
|
+
if program not in SHELL_PROGRAMS:
|
|
741
|
+
return None
|
|
742
|
+
for index, token in enumerate(args):
|
|
743
|
+
if token == "--":
|
|
744
|
+
return None
|
|
745
|
+
if token.startswith("-") and not token.startswith("--") and "c" in token[1:]:
|
|
746
|
+
command_index = index + 1
|
|
747
|
+
if command_index < len(args) and args[command_index] == "--":
|
|
748
|
+
command_index += 1
|
|
749
|
+
return args[command_index] if command_index < len(args) else None
|
|
750
|
+
return None
|
|
751
|
+
|
|
752
|
+
|
|
718
753
|
def write_targets(statement):
|
|
719
754
|
"""Paths this statement WRITES.
|
|
720
755
|
|
|
@@ -837,6 +872,9 @@ def collect(text, depth, seen, out):
|
|
|
837
872
|
if not statement:
|
|
838
873
|
continue
|
|
839
874
|
out.extend(write_targets(statement))
|
|
875
|
+
nested = shell_command_string(statement)
|
|
876
|
+
if nested is not None and depth < FOLLOW_MAX_DEPTH:
|
|
877
|
+
collect(nested, depth + 1, seen, out)
|
|
840
878
|
operand = executed_script(statement)
|
|
841
879
|
if operand is None:
|
|
842
880
|
continue
|
|
@@ -182,12 +182,14 @@ EOF
|
|
|
182
182
|
# The patch file is per-worktree: `mktemp` names it, so nothing has to invent a
|
|
183
183
|
# filename, and it lives in this agent's own TMPDIR where no sibling can reach
|
|
184
184
|
# it. Untracked files are unaffected by both refused operations, so `git diff`
|
|
185
|
-
# captures everything at risk.
|
|
185
|
+
# captures everything at risk. `HEAD` includes staged and unstaged changes, and
|
|
186
|
+
# `--binary` keeps binary edits recoverable rather than emitting a text-only
|
|
187
|
+
# placeholder that cannot be applied.
|
|
186
188
|
PRESERVE_GUIDANCE="$(
|
|
187
189
|
cat <<'EOF'
|
|
188
190
|
Preserve the work first, per-worktree:
|
|
189
191
|
|
|
190
|
-
git diff [-- <path>] > "$(mktemp "${TMPDIR:-/tmp}/lisa-preserve-XXXXXX.patch")"
|
|
192
|
+
git diff --binary HEAD [-- <path>] > "$(mktemp "${TMPDIR:-/tmp}/lisa-preserve-XXXXXX.patch")"
|
|
191
193
|
|
|
192
194
|
and restore it later with `git apply <that file>`.
|
|
193
195
|
|
|
@@ -447,6 +449,7 @@ follow_refuse() {
|
|
|
447
449
|
# so peak process count never rises. The latency was the whole problem.
|
|
448
450
|
follow_unwrapped=""
|
|
449
451
|
follow_operand_index=0
|
|
452
|
+
follow_located=""
|
|
450
453
|
|
|
451
454
|
# Strip substitution, quote and alias wrappers off one token. A sibling of
|
|
452
455
|
# strip_subst_wrappers() below rather than a call to it: that one is defined
|
|
@@ -571,6 +574,7 @@ follow_add_base() {
|
|
|
571
574
|
# this hook cannot evaluate.
|
|
572
575
|
follow_locate() {
|
|
573
576
|
local token="$1" home="${HOME:-}" tmp="${TMPDIR:-/tmp}" proj="${CLAUDE_PROJECT_DIR:-$PWD}" base
|
|
577
|
+
follow_located=""
|
|
574
578
|
tmp="${tmp%/}"
|
|
575
579
|
[ -n "$tmp" ] || tmp="/tmp"
|
|
576
580
|
# The tilde arms below are LITERAL text: this is the unexpanded spelling the
|
|
@@ -592,14 +596,14 @@ follow_locate() {
|
|
|
592
596
|
"" | *'$'* | *'*'* | *'?'* | *'`'* | *'{'* | *'['*) return 1 ;;
|
|
593
597
|
/*)
|
|
594
598
|
[ -f "$token" ] && [ -r "$token" ] || return 1
|
|
595
|
-
|
|
599
|
+
follow_located="$token"
|
|
596
600
|
return 0
|
|
597
601
|
;;
|
|
598
602
|
esac
|
|
599
603
|
while IFS= read -r base; do
|
|
600
604
|
[ -n "$base" ] || continue
|
|
601
605
|
if [ -f "$base/$token" ] && [ -r "$base/$token" ]; then
|
|
602
|
-
|
|
606
|
+
follow_located="$base/$token"
|
|
603
607
|
return 0
|
|
604
608
|
fi
|
|
605
609
|
done <<<"$PWD"$'\n'"$proj$follow_bases"
|
|
@@ -644,12 +648,13 @@ follow_take() {
|
|
|
644
648
|
follow_target() {
|
|
645
649
|
local token="$1" depth="$2" path=""
|
|
646
650
|
[ -n "$token" ] || return 0
|
|
647
|
-
if !
|
|
651
|
+
if ! follow_locate "$token"; then
|
|
648
652
|
if [ "$depth" -eq 0 ]; then
|
|
649
653
|
follow_refuse "$token" "no readable file could be resolved for it"
|
|
650
654
|
fi
|
|
651
655
|
return 0
|
|
652
656
|
fi
|
|
657
|
+
path="$follow_located"
|
|
653
658
|
follow_take "$path" "$depth"
|
|
654
659
|
}
|
|
655
660
|
|
|
@@ -670,11 +675,18 @@ follow_target() {
|
|
|
670
675
|
# Accepted residual: a shebang script whose relative path resolves only from a
|
|
671
676
|
# working directory this hook does not share is not followed.
|
|
672
677
|
follow_direct() {
|
|
673
|
-
local token="$1" depth="$2" path="" first=""
|
|
674
|
-
|
|
678
|
+
local token="$1" depth="$2" path="" first="" raw="" char="" k=0
|
|
679
|
+
local LC_ALL=C
|
|
680
|
+
if ! follow_locate "$token"; then
|
|
675
681
|
return 0
|
|
676
682
|
fi
|
|
677
|
-
|
|
683
|
+
path="$follow_located"
|
|
684
|
+
IFS= read -r -n 256 raw <"$path" 2>/dev/null || true
|
|
685
|
+
while [ "$k" -lt "${#raw}" ]; do
|
|
686
|
+
char="${raw:k:1}"
|
|
687
|
+
case "$char" in [[:print:]]) first="$first$char" ;; esac
|
|
688
|
+
k=$((k + 1))
|
|
689
|
+
done
|
|
678
690
|
case "$first" in
|
|
679
691
|
'#!'*[/[:space:]]bash* | '#!'*[/[:space:]]sh* | '#!'*[/[:space:]]zsh* \
|
|
680
692
|
| '#!'*[/[:space:]]ksh* | '#!'*[/[:space:]]dash* | '#!'*[/[:space:]]ash*) ;;
|
|
@@ -704,7 +716,7 @@ follow_next_operand() {
|
|
|
704
716
|
follow_scan() {
|
|
705
717
|
local text="$1" depth="$2"
|
|
706
718
|
local split_out line sep stmt t tj i j n cmd_pos eval_mode inline arg_exec
|
|
707
|
-
local heredoc redirected pipe_cat prev_cat pending_operand
|
|
719
|
+
local heredoc redirected pipe_cat prev_cat pending_operand stdin_mode
|
|
708
720
|
local find_mode dispatch_pending
|
|
709
721
|
local -a toks=()
|
|
710
722
|
split_out="$(follow_split "$text")"
|
|
@@ -891,6 +903,7 @@ follow_scan() {
|
|
|
891
903
|
inline=0
|
|
892
904
|
redirected=""
|
|
893
905
|
heredoc=0
|
|
906
|
+
stdin_mode=0
|
|
894
907
|
j=$((i + 1))
|
|
895
908
|
while [ "$j" -lt "$n" ]; do
|
|
896
909
|
follow_unwrap "${toks[j]}"
|
|
@@ -923,6 +936,7 @@ follow_scan() {
|
|
|
923
936
|
;;
|
|
924
937
|
--*) j=$((j + 1)) ;;
|
|
925
938
|
-*c*) inline=1; j=$((j + 1)) ;;
|
|
939
|
+
-s | -[a-zA-Z]*s[a-zA-Z]*) stdin_mode=1; j=$((j + 1)) ;;
|
|
926
940
|
-*) j=$((j + 1)) ;;
|
|
927
941
|
*) break ;;
|
|
928
942
|
esac
|
|
@@ -947,6 +961,14 @@ follow_scan() {
|
|
|
947
961
|
i="$j"
|
|
948
962
|
continue
|
|
949
963
|
fi
|
|
964
|
+
if [ "$stdin_mode" -eq 1 ]; then
|
|
965
|
+
# `sh -s -- -y` reads its program from stdin; tokens after `--` are
|
|
966
|
+
# positional arguments to that program, never a script path.
|
|
967
|
+
[ -z "$pipe_cat" ] || follow_target "$pipe_cat" "$depth"
|
|
968
|
+
cmd_pos=0
|
|
969
|
+
i="$n"
|
|
970
|
+
continue
|
|
971
|
+
fi
|
|
950
972
|
if [ "$j" -ge "$n" ]; then
|
|
951
973
|
# A dispatcher supplies the script from ANOTHER command's output, so
|
|
952
974
|
# the operand exists but is unreadable here. That is the fail-closed
|
|
@@ -1809,15 +1831,14 @@ readonly SQL_TRUNCATE_EVIDENCE='\btruncate[[:space:]]+(table[[:space:]]+[[:alnum
|
|
|
1809
1831
|
# the same command must also invoke a command-line database client. Prose in a
|
|
1810
1832
|
# tracker filing or a commit message invokes none, which is exactly the
|
|
1811
1833
|
# difference the text scan could not see on its own.
|
|
1812
|
-
readonly
|
|
1813
|
-
readonly SQL_TRUNCATE_BARE='\btruncate[[:space:]]+(only[[:space:]]+)?[[:alnum:]_."`]'
|
|
1834
|
+
readonly SQL_CLIENT_TRUNCATE='(^|[;&|()][[:space:]]*)([[:alnum:]_./-]*/)?(psql|pgcli|mysql|mysqladmin|mysqlsh|mariadb|mycli|sqlite3|sqlcmd|cqlsh|clickhouse-client|cockroach|mongosh|duckdb|usql)([[:space:]]+[^;&|()]*)?[[:space:]]+(-e|-c|--command|--eval)(=|[[:space:]]+)[^;&|()]*\btruncate[[:space:]]+(only[[:space:]]+)?[[:alnum:]_."`]'
|
|
1814
1835
|
# Residual, accepted and stated: a bare `TRUNCATE <name>` with no terminator,
|
|
1815
1836
|
# no qualification and no recognized client in the same command goes unmatched
|
|
1816
1837
|
# — the same trade the `drop` arm has always made for `drop the ball`. No DROP
|
|
1817
1838
|
# shape is weakened, and the guard still fails in the safe direction.
|
|
1818
1839
|
if matches "$SQL_DROP" \
|
|
1819
1840
|
|| matches "$SQL_TRUNCATE_EVIDENCE" \
|
|
1820
|
-
||
|
|
1841
|
+
|| matches "$SQL_CLIENT_TRUNCATE"; then
|
|
1821
1842
|
block "destructive SQL (DROP/TRUNCATE) detected"
|
|
1822
1843
|
fi
|
|
1823
1844
|
|
|
@@ -1322,9 +1322,10 @@ function inputsDigest() {
|
|
|
1322
1322
|
* @param {object|null} options.gates The gates block that was executed.
|
|
1323
1323
|
* @param {string} [options.runner] The task-runner prefix.
|
|
1324
1324
|
* @param {Record<string,string>|null} [options.scripts] Project scripts.
|
|
1325
|
+
* @param {object} options.identity Lisa artifact identity captured at run start.
|
|
1325
1326
|
* @returns {object} The contract binding.
|
|
1326
1327
|
*/
|
|
1327
|
-
function evidenceContract({ moment, gates, runner, scripts = null }) {
|
|
1328
|
+
function evidenceContract({ moment, gates, runner, scripts = null, identity }) {
|
|
1328
1329
|
return {
|
|
1329
1330
|
moment,
|
|
1330
1331
|
runner: runner ?? null,
|
|
@@ -1337,7 +1338,7 @@ function evidenceContract({ moment, gates, runner, scripts = null }) {
|
|
|
1337
1338
|
// produced the verdict — a fact a workflow ref cannot carry, because the
|
|
1338
1339
|
// wrapper's identity and the enforcement's identity are independent when
|
|
1339
1340
|
// the enforcement is a file living in the consuming repository.
|
|
1340
|
-
...
|
|
1341
|
+
...identity,
|
|
1341
1342
|
inputs_digest: inputsDigest(),
|
|
1342
1343
|
};
|
|
1343
1344
|
}
|
|
@@ -1484,6 +1485,7 @@ function gateEvidence(outcome, observedAt) {
|
|
|
1484
1485
|
* @param {string} [options.runner] The task-runner prefix.
|
|
1485
1486
|
* @param {Record<string,string>|null} [options.scripts] Project scripts.
|
|
1486
1487
|
* @param {string} options.observedAt When the run began, ISO-8601.
|
|
1488
|
+
* @param {object} [options.identity] Lisa identity captured for this run.
|
|
1487
1489
|
* @returns {object} The evidence envelope.
|
|
1488
1490
|
*/
|
|
1489
1491
|
export function evidenceDocument({
|
|
@@ -1494,6 +1496,7 @@ export function evidenceDocument({
|
|
|
1494
1496
|
runner = undefined,
|
|
1495
1497
|
scripts = null,
|
|
1496
1498
|
observedAt,
|
|
1499
|
+
identity = lisaIdentity(),
|
|
1497
1500
|
}) {
|
|
1498
1501
|
const observations = (result?.results ?? []).map(outcome =>
|
|
1499
1502
|
gateEvidence(outcome, observedAt)
|
|
@@ -1502,7 +1505,7 @@ export function evidenceDocument({
|
|
|
1502
1505
|
schema: EVIDENCE_SCHEMA,
|
|
1503
1506
|
verdict,
|
|
1504
1507
|
subject: evidenceSubject(),
|
|
1505
|
-
contract: evidenceContract({ gates, moment, runner, scripts }),
|
|
1508
|
+
contract: evidenceContract({ gates, moment, runner, scripts, identity }),
|
|
1506
1509
|
producer: evidenceProducer(),
|
|
1507
1510
|
observed_at: observedAt,
|
|
1508
1511
|
gates: observations,
|
|
@@ -1644,7 +1647,8 @@ function main() {
|
|
|
1644
1647
|
// defect this line exists to close: the local hook runs the version this
|
|
1645
1648
|
// project PINNED, while CI runs a floating ref, so two reports about "the
|
|
1646
1649
|
// gate" are routinely claims about different code.
|
|
1647
|
-
|
|
1650
|
+
const identity = lisaIdentity();
|
|
1651
|
+
console.log(formatIdentityLine(identity));
|
|
1648
1652
|
|
|
1649
1653
|
/**
|
|
1650
1654
|
* Record this run, and refuse to report a verdict we could not record.
|
|
@@ -1677,6 +1681,7 @@ function main() {
|
|
|
1677
1681
|
runner: parts.runner,
|
|
1678
1682
|
scripts: parts.scripts ?? null,
|
|
1679
1683
|
verdict,
|
|
1684
|
+
identity,
|
|
1680
1685
|
})
|
|
1681
1686
|
);
|
|
1682
1687
|
if (written) return code;
|
|
@@ -414,6 +414,9 @@ function statePath() {
|
|
|
414
414
|
return resolve(git(["rev-parse", "--git-path", "lisa/work-item.json"]));
|
|
415
415
|
}
|
|
416
416
|
|
|
417
|
+
/** Canonical prefix on a fully qualified local branch ref. */
|
|
418
|
+
const HEADS_PREFIX = "refs/heads/";
|
|
419
|
+
|
|
417
420
|
function currentBranch() {
|
|
418
421
|
return git(["branch", "--show-current"]);
|
|
419
422
|
}
|
|
@@ -431,8 +434,8 @@ function rebaseBranch() {
|
|
|
431
434
|
);
|
|
432
435
|
if (!existsSync(file)) continue;
|
|
433
436
|
const headName = readFileSync(file, "utf8").trim();
|
|
434
|
-
if (headName.startsWith(
|
|
435
|
-
return headName.slice(
|
|
437
|
+
if (headName.startsWith(HEADS_PREFIX)) {
|
|
438
|
+
return headName.slice(HEADS_PREFIX.length);
|
|
436
439
|
}
|
|
437
440
|
}
|
|
438
441
|
return "";
|
|
@@ -799,7 +802,10 @@ export function deployBranchEnvironments(config) {
|
|
|
799
802
|
: [];
|
|
800
803
|
const mapped = new Map();
|
|
801
804
|
for (const [environment, branch] of entries) {
|
|
802
|
-
const
|
|
805
|
+
const trimmed = typeof branch === "string" ? branch.trim() : "";
|
|
806
|
+
const name = trimmed.startsWith(HEADS_PREFIX)
|
|
807
|
+
? trimmed.slice(HEADS_PREFIX.length)
|
|
808
|
+
: trimmed;
|
|
803
809
|
if (name !== "") mapped.set(name, String(environment).trim().toLowerCase());
|
|
804
810
|
}
|
|
805
811
|
if (mapped.size > 0) return mapped;
|
|
@@ -2434,9 +2440,6 @@ function parsePushGroups(input, remote) {
|
|
|
2434
2440
|
return groups;
|
|
2435
2441
|
}
|
|
2436
2442
|
|
|
2437
|
-
/** The `refs/heads/` prefix, spelled once because three parsers below strip it. */
|
|
2438
|
-
const HEADS_PREFIX = "refs/heads/";
|
|
2439
|
-
|
|
2440
2443
|
/**
|
|
2441
2444
|
* Deploy branches this push must never reach by inheritance.
|
|
2442
2445
|
*
|
package/dist/cli/apply.js
CHANGED
|
@@ -129,10 +129,10 @@ function buildApplyConfig(parts) {
|
|
|
129
129
|
* @param parts.harness - Resolved harness for this invocation
|
|
130
130
|
* @param parts.persistence - Inputs deciding whether config must be written
|
|
131
131
|
* @param parts.stalePaths - Managed files this apply left out of date
|
|
132
|
-
* @param parts.
|
|
132
|
+
* @param parts.deletedPaths - Files this apply removed
|
|
133
133
|
*/
|
|
134
134
|
async function finalizeSuccessfulApply(parts) {
|
|
135
|
-
const { destDir, logger, config, harness, persistence, stalePaths,
|
|
135
|
+
const { destDir, logger, config, harness, persistence, stalePaths, deletedPaths, } = parts;
|
|
136
136
|
// Ensure every applied project carries a .lisa.config.json. A missing file is
|
|
137
137
|
// always backfilled with the resolved harness (the default when no --harness
|
|
138
138
|
// was passed) so no project is left config-less; an existing file is only
|
|
@@ -162,11 +162,11 @@ async function finalizeSuccessfulApply(parts) {
|
|
|
162
162
|
// upstream fixes. Doctor reads the receipt, so the finding outlives the
|
|
163
163
|
// install (CodySwannGT/lisa#3033).
|
|
164
164
|
stalePaths,
|
|
165
|
-
// Same argument as stalePaths, one degree worse. A
|
|
166
|
-
//
|
|
167
|
-
// the receipt is the only place the removal is still
|
|
168
|
-
// install output is gone (CodySwannGT/lisa#3656).
|
|
169
|
-
|
|
165
|
+
// Same argument as stalePaths, one degree worse. A file Lisa removed leaves
|
|
166
|
+
// nothing on disk to notice, and a removed workflow cannot fail a check
|
|
167
|
+
// afterwards either, so the receipt is the only place the removal is still
|
|
168
|
+
// recorded once the install output is gone (CodySwannGT/lisa#3656).
|
|
169
|
+
deletedPaths,
|
|
170
170
|
});
|
|
171
171
|
}
|
|
172
172
|
/**
|
|
@@ -290,7 +290,7 @@ export async function runApply(destination, options) {
|
|
|
290
290
|
resolvedHarness: harness,
|
|
291
291
|
},
|
|
292
292
|
stalePaths: result.stalePaths,
|
|
293
|
-
|
|
293
|
+
deletedPaths: result.deletedPaths,
|
|
294
294
|
});
|
|
295
295
|
}
|
|
296
296
|
// After a real apply, surface (read-only) whether any locally-authored
|
package/dist/cli/apply.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply.js","sourceRoot":"","sources":["../../src/cli/apply.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"apply.js","sourceRoot":"","sources":["../../src/cli/apply.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
# *** Add File: <path>
|
|
17
17
|
# *** Update File: <path>
|
|
18
18
|
# *** Delete File: <path>
|
|
19
|
+
# *** Move to: <path>
|
|
19
20
|
# A single patch may carry MANY files, so callers must loop over the output.
|
|
20
21
|
|
|
21
22
|
# Print, one per line, every file path the tool envelope intends to write.
|
|
@@ -41,6 +42,9 @@ lisa_extract_edit_paths() {
|
|
|
41
42
|
"*** Add File: "* | "*** Update File: "* | "*** Delete File: "*)
|
|
42
43
|
printf '%s\n' "${line#*File: }"
|
|
43
44
|
;;
|
|
45
|
+
"*** Move to: "*)
|
|
46
|
+
printf '%s\n' "${line#*** Move to: }"
|
|
47
|
+
;;
|
|
44
48
|
esac
|
|
45
49
|
done <<<"$patch_text"
|
|
46
50
|
else
|