@codyswann/lisa 4.4.14 → 4.4.16
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/lib/placeholder-expiry.mjs +79 -7
- package/all/copy-overwrite/scripts/lisa-floor-collisions.mjs +46 -9
- package/all/copy-overwrite/scripts/lisa-postinstall.mjs +10 -1
- package/all/copy-overwrite/scripts/lisa-reconcile-policy.mjs +260 -41
- package/all/copy-overwrite/scripts/lisa-schema-validate.mjs +12 -1
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +17 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +19 -14
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/package.json +2 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-improve-test-coverage/SKILL.md +4 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-improve-tests/SKILL.md +4 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-nightly-lower-code-complexity/SKILL.md +10 -2
- package/plugins/lisa/rules/eager/falsifiable-checks.md +16 -1
- package/plugins/lisa/rules/reference/falsifiable-checks.md +74 -1
- package/plugins/lisa/skills/lisa-improve-test-coverage/SKILL.md +4 -1
- package/plugins/lisa/skills/lisa-improve-tests/SKILL.md +4 -1
- package/plugins/lisa/skills/lisa-nightly-lower-code-complexity/SKILL.md +10 -2
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/lisa-improve-test-coverage/SKILL.md +4 -1
- package/plugins/lisa-agy/skills/lisa-improve-tests/SKILL.md +4 -1
- package/plugins/lisa-agy/skills/lisa-nightly-lower-code-complexity/SKILL.md +10 -2
- 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/rules/eager/falsifiable-checks.md +16 -1
- package/plugins/lisa-copilot/rules/reference/falsifiable-checks.md +74 -1
- package/plugins/lisa-copilot/skills/lisa-improve-test-coverage/SKILL.md +4 -1
- package/plugins/lisa-copilot/skills/lisa-improve-tests/SKILL.md +4 -1
- package/plugins/lisa-copilot/skills/lisa-nightly-lower-code-complexity/SKILL.md +10 -2
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/rules/falsifiable-checks-reference.mdc +74 -1
- package/plugins/lisa-cursor/rules/falsifiable-checks.mdc +16 -1
- package/plugins/lisa-cursor/skills/lisa-improve-test-coverage/SKILL.md +4 -1
- package/plugins/lisa-cursor/skills/lisa-improve-tests/SKILL.md +4 -1
- package/plugins/lisa-cursor/skills/lisa-nightly-lower-code-complexity/SKILL.md +10 -2
- 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/.codex-plugin/skills/improve-code-complexity/SKILL.md +4 -1
- package/plugins/lisa-rails/.codex-plugin/skills/improve-test-coverage/SKILL.md +4 -1
- package/plugins/lisa-rails/.codex-plugin/skills/ops-verify-telemetry/SKILL.md +30 -1
- package/plugins/lisa-rails/skills/improve-code-complexity/SKILL.md +4 -1
- package/plugins/lisa-rails/skills/improve-test-coverage/SKILL.md +4 -1
- package/plugins/lisa-rails/skills/ops-verify-telemetry/SKILL.md +30 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-agy/skills/improve-code-complexity/SKILL.md +4 -1
- package/plugins/lisa-rails-agy/skills/improve-test-coverage/SKILL.md +4 -1
- package/plugins/lisa-rails-agy/skills/ops-verify-telemetry/SKILL.md +30 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/skills/improve-code-complexity/SKILL.md +4 -1
- package/plugins/lisa-rails-copilot/skills/improve-test-coverage/SKILL.md +4 -1
- package/plugins/lisa-rails-copilot/skills/ops-verify-telemetry/SKILL.md +30 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/skills/improve-code-complexity/SKILL.md +4 -1
- package/plugins/lisa-rails-cursor/skills/improve-test-coverage/SKILL.md +4 -1
- package/plugins/lisa-rails-cursor/skills/ops-verify-telemetry/SKILL.md +30 -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/rules/eager/falsifiable-checks.md +16 -1
- package/plugins/src/base/rules/reference/falsifiable-checks.md +74 -1
- package/plugins/src/base/skills/lisa-improve-test-coverage/SKILL.md +4 -1
- package/plugins/src/base/skills/lisa-improve-tests/SKILL.md +4 -1
- package/plugins/src/base/skills/lisa-nightly-lower-code-complexity/SKILL.md +10 -2
- package/plugins/src/rails/skills/improve-code-complexity/SKILL.md +4 -1
- package/plugins/src/rails/skills/improve-test-coverage/SKILL.md +4 -1
- package/plugins/src/rails/skills/ops-verify-telemetry/SKILL.md +30 -1
- package/scripts/check-pipeline-status-reads.mjs +684 -0
- package/typescript/copy-overwrite/scripts/lisa-mutation.mjs +75 -25
|
@@ -147,6 +147,7 @@ export const OUTCOMES = Object.freeze({
|
|
|
147
147
|
nothingToMutate: "mutation-gate: nothing-to-mutate",
|
|
148
148
|
inertConfig: "mutation-gate: inert-mutate-config",
|
|
149
149
|
unrepresentablePath: "mutation-gate: unrepresentable-path",
|
|
150
|
+
diffFailed: "mutation-gate: diff-failed",
|
|
150
151
|
scoped: "mutation-gate: scoped-run",
|
|
151
152
|
wholeList: "mutation-gate: whole-list-run",
|
|
152
153
|
dryRunTimeout: "mutation-gate: dry-run-timeout",
|
|
@@ -1467,31 +1468,45 @@ kill -9 "$1" 2>/dev/null || true
|
|
|
1467
1468
|
* holds `tee` open for the WHOLE deadline after Stryker has finished, turning
|
|
1468
1469
|
* every successful run into a two-hour hang. Measured the hard way.
|
|
1469
1470
|
*
|
|
1470
|
-
* The program and every path argument
|
|
1471
|
+
* The program and every path argument travel as argv through `"$0" "$@"`.
|
|
1471
1472
|
* Interpolating them would put a filename through the shell's word splitting,
|
|
1472
1473
|
* which is how a path with a space becomes two paths that do not exist.
|
|
1473
|
-
*
|
|
1474
|
-
*
|
|
1475
|
-
*
|
|
1474
|
+
*
|
|
1475
|
+
* That was a promise this function did not keep (CodySwannGT/lisa#3029). The
|
|
1476
|
+
* three scratch paths were single-quoted straight into the script text, and all
|
|
1477
|
+
* three derive from `mkdtempSync(path.join(os.tmpdir(), …))`, so all three carry
|
|
1478
|
+
* `TMPDIR`. A `TMPDIR` containing a single quote closed the quote and handed the
|
|
1479
|
+
* remainder of the path to the shell as syntax. They now arrive as `$1`, `$2`
|
|
1480
|
+
* and `$3` and are shifted off before `"$@"` is expanded, so the paragraph above
|
|
1481
|
+
* describes the code.
|
|
1482
|
+
*
|
|
1483
|
+
* The deadline is still interpolated, and that is not an exception to the rule:
|
|
1484
|
+
* `seconds` is the output of `Math.max(1, Math.ceil(…))`, so it is a number by
|
|
1485
|
+
* construction and carries nothing to word-split. The rule is about PATHS,
|
|
1486
|
+
* which is where the untrusted bytes are.
|
|
1476
1487
|
* @param {number} deadlineMs - How long Stryker may run.
|
|
1477
|
-
* @returns {string} The script.
|
|
1488
|
+
* @returns {string} The script, which reads its three paths from argv.
|
|
1478
1489
|
*/
|
|
1479
|
-
export const watchdogScript =
|
|
1490
|
+
export const watchdogScript = deadlineMs => {
|
|
1480
1491
|
const seconds = Math.max(1, Math.ceil(deadlineMs / 1000));
|
|
1481
|
-
return `${REAP_FUNCTION}
|
|
1492
|
+
return `${REAP_FUNCTION}lisa_gate_status="$1"
|
|
1493
|
+
lisa_gate_log="$2"
|
|
1494
|
+
lisa_gate_killed="$3"
|
|
1495
|
+
shift 3
|
|
1496
|
+
{ set -m 2>/dev/null || true
|
|
1482
1497
|
"$0" "$@" &
|
|
1483
1498
|
lisa_gate_child=$!
|
|
1484
1499
|
( sleep ${seconds}
|
|
1485
|
-
: >
|
|
1500
|
+
: > "$lisa_gate_killed"
|
|
1486
1501
|
kill -9 -"$lisa_gate_child" 2>/dev/null
|
|
1487
1502
|
lisa_gate_reap "$lisa_gate_child"
|
|
1488
1503
|
) >/dev/null 2>&1 </dev/null &
|
|
1489
1504
|
lisa_gate_watchdog=$!
|
|
1490
1505
|
set +m 2>/dev/null || true
|
|
1491
1506
|
wait "$lisa_gate_child"
|
|
1492
|
-
echo $? >
|
|
1507
|
+
echo $? > "$lisa_gate_status"
|
|
1493
1508
|
kill -9 "$lisa_gate_watchdog" 2>/dev/null || true
|
|
1494
|
-
} 2>&1 | tee
|
|
1509
|
+
} 2>&1 | tee "$lisa_gate_log"
|
|
1495
1510
|
`;
|
|
1496
1511
|
};
|
|
1497
1512
|
|
|
@@ -1533,6 +1548,14 @@ const runStrykerPlain = (cwd, entry, env, deadlineMs) => {
|
|
|
1533
1548
|
* space becomes two paths that do not exist — and Stryker would then mutate
|
|
1534
1549
|
* neither, find nothing, and exit 0.
|
|
1535
1550
|
*
|
|
1551
|
+
* That promise used to cover only Stryker's own arguments. The two scratch
|
|
1552
|
+
* paths were single-quoted straight into the script text, and both derive from
|
|
1553
|
+
* `mkdtempSync(path.join(os.tmpdir(), …))`, so both carry `TMPDIR` — attacker-
|
|
1554
|
+
* adjacent on a shared machine and merely hostile on a normal one. A `TMPDIR`
|
|
1555
|
+
* containing a single quote closed the quote and handed the rest of the path to
|
|
1556
|
+
* the shell as syntax. They now arrive as `$1` and `$2` and are shifted off
|
|
1557
|
+
* before `"$@"` is expanded, so the doc comment above describes the code.
|
|
1558
|
+
*
|
|
1536
1559
|
* The exit code comes from a status file written INSIDE the pipeline, never
|
|
1537
1560
|
* from the pipeline itself: a pipeline reports `tee`'s status, which is
|
|
1538
1561
|
* essentially always zero, and reading it would report every failing gate as
|
|
@@ -1555,20 +1578,32 @@ const runStrykerCaptured = (cwd, entry, env, deadlineMs) => {
|
|
|
1555
1578
|
const logPath = path.join(dir, "stryker.log");
|
|
1556
1579
|
const statusPath = path.join(dir, "status");
|
|
1557
1580
|
const killedPath = path.join(dir, "killed");
|
|
1558
|
-
const script = watchdogScript(
|
|
1581
|
+
const script = watchdogScript(deadlineMs);
|
|
1559
1582
|
try {
|
|
1560
|
-
const child = spawnSync(
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1583
|
+
const child = spawnSync(
|
|
1584
|
+
"sh",
|
|
1585
|
+
[
|
|
1586
|
+
"-c",
|
|
1587
|
+
script,
|
|
1588
|
+
entry.file,
|
|
1589
|
+
statusPath,
|
|
1590
|
+
logPath,
|
|
1591
|
+
killedPath,
|
|
1592
|
+
...entry.args,
|
|
1593
|
+
],
|
|
1594
|
+
{
|
|
1595
|
+
cwd,
|
|
1596
|
+
stdio: "inherit",
|
|
1597
|
+
env,
|
|
1598
|
+
killSignal: "SIGKILL",
|
|
1599
|
+
// A backstop under the wrapper's own watchdog, not the bound. The
|
|
1600
|
+
// wrapper kills STRYKER; this kills the shell, which leaves Stryker
|
|
1601
|
+
// running until its next write hits a broken pipe — and a hung run has
|
|
1602
|
+
// no next write. The grace is what keeps the two from racing, so the
|
|
1603
|
+
// failure that gets reported is the one that names the real child.
|
|
1604
|
+
timeout: deadlineMs + WATCHDOG_GRACE_MS,
|
|
1605
|
+
}
|
|
1606
|
+
);
|
|
1572
1607
|
if (fs.existsSync(killedPath) || child.error?.code === "ETIMEDOUT") {
|
|
1573
1608
|
return {
|
|
1574
1609
|
code: 1,
|
|
@@ -1773,8 +1808,23 @@ export const runGate = (cwd = process.cwd(), argv = []) => {
|
|
|
1773
1808
|
try {
|
|
1774
1809
|
scope = selectChangedTargets(cwd, base, patterns);
|
|
1775
1810
|
} catch (error) {
|
|
1776
|
-
|
|
1777
|
-
|
|
1811
|
+
// Was a warning and an exit 0, with no outcome marker — the only exit in
|
|
1812
|
+
// this module shaped that way. Both halves were wrong in the same
|
|
1813
|
+
// direction. A git prerequisite that failed AFTER a merge-base resolved is
|
|
1814
|
+
// an anomaly, not a clean tree, and reporting it as a pass is the silent
|
|
1815
|
+
// green this whole file exists to refuse. The marker matters just as much:
|
|
1816
|
+
// a test asserting the gate did not no-op could not observe this path at
|
|
1817
|
+
// all, so the one exit that lied was also the one exit nothing could see.
|
|
1818
|
+
//
|
|
1819
|
+
// The genuinely-cannot-measure cases are already handled above and keep
|
|
1820
|
+
// their exit 0: a disabled gate, and a merge-base that does not resolve.
|
|
1821
|
+
console.error(
|
|
1822
|
+
`❌ ${OUTCOMES.diffFailed}\n` +
|
|
1823
|
+
` Could not compute the files changed vs ${since}: ${error.message}\n` +
|
|
1824
|
+
" NO mutant was generated and NO score was computed. Nothing was measured,\n" +
|
|
1825
|
+
" so nothing passed."
|
|
1826
|
+
);
|
|
1827
|
+
return 1;
|
|
1778
1828
|
}
|
|
1779
1829
|
|
|
1780
1830
|
if (scope.selected.length === 0) {
|