@codyswann/lisa 3.17.2 → 3.17.3
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/lisa-destructive-guard.mjs +30 -1
- package/all/copy-overwrite/scripts/lisa-work-item.mjs +41 -2
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +3 -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 +9 -6
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/package.json +2 -2
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/hooks/threshold-ratchet.mjs +44 -4
- 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/threshold-ratchet.mjs +44 -4
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/hooks/threshold-ratchet.mjs +44 -4
- 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/threshold-ratchet.mjs +44 -4
- package/rails/copy-overwrite/scripts/check-threshold-ratchet.mjs +44 -4
- package/typescript/copy-contents/.husky/commit-msg +10 -3
- package/typescript/copy-overwrite/scripts/check-threshold-ratchet.mjs +44 -4
|
@@ -430,9 +430,49 @@ function main() {
|
|
|
430
430
|
return 0;
|
|
431
431
|
}
|
|
432
432
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
433
|
+
/**
|
|
434
|
+
* True when `moduleUrl` names the module node was asked to run.
|
|
435
|
+
*
|
|
436
|
+
* The one implementation of this lives at `scripts/lib/invoked-as-script.mjs`,
|
|
437
|
+
* and every other shipped entry point imports it. This file cannot: it is
|
|
438
|
+
* materialized from `plugins/src/base/hooks/`, where it also runs as an
|
|
439
|
+
* agent-time hook, and a plugin payload has no `./lib/` to import from. So the
|
|
440
|
+
* rule is written out here rather than pointed at — the same accommodation
|
|
441
|
+
* `preflight-secrets.mjs` makes, for the same reason.
|
|
442
|
+
*
|
|
443
|
+
* Both sides are realpath'd. The previous spelling compared
|
|
444
|
+
* `fileURLToPath(import.meta.url)` against `path.resolve(process.argv[1])`, and
|
|
445
|
+
* `resolve` makes a path absolute without following symlinks. `import.meta.url`
|
|
446
|
+
* is the REAL path — node resolves ESM through realpath unless
|
|
447
|
+
* `--preserve-symlinks` or `--preserve-symlinks-main` is set — while `argv[1]`
|
|
448
|
+
* is whatever the caller typed. Reached through a symlinked checkout, a git
|
|
449
|
+
* worktree, or a `/tmp` path on macOS (`/tmp` being a symlink to `/private/tmp`),
|
|
450
|
+
* the two disagreed, `main()` never ran, and the process exited 0.
|
|
451
|
+
*
|
|
452
|
+
* For a CHECK that is a fail-OPEN, not a mild degradation: no output, exit 0,
|
|
453
|
+
* the npm script "succeeds", and the ratchet silently stops having an opinion.
|
|
454
|
+
* It was measured, not theorised — every control in the #2531 promotion tests
|
|
455
|
+
* no-opped until the fixture directory was realpath'd.
|
|
456
|
+
*
|
|
457
|
+
* Realpathing BOTH sides rather than only `argv[1]` matters under
|
|
458
|
+
* `--preserve-symlinks-main`, which tells node not to resolve the main entry:
|
|
459
|
+
* normalizing one side then compares a real path against a symlinked one and
|
|
460
|
+
* answers `false` for an entry point that WAS invoked directly. Any resolution
|
|
461
|
+
* error returns `false` — node loaded the entry from that path moments ago, so
|
|
462
|
+
* a path that will not resolve now is not the path this module came through.
|
|
463
|
+
* @param {string} moduleUrl - The caller's own `import.meta.url`.
|
|
464
|
+
* @param {string | undefined} [argv1] - Entry path; defaults to `process.argv[1]`.
|
|
465
|
+
* @returns {boolean} Whether the caller should run its CLI body.
|
|
466
|
+
*/
|
|
467
|
+
export function invokedAsScript(moduleUrl, argv1 = process.argv[1]) {
|
|
468
|
+
if (!argv1) return false;
|
|
469
|
+
try {
|
|
470
|
+
return fs.realpathSync(argv1) === fs.realpathSync(fileURLToPath(moduleUrl));
|
|
471
|
+
} catch {
|
|
472
|
+
return false;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
if (invokedAsScript(import.meta.url)) {
|
|
437
477
|
process.exit(main());
|
|
438
478
|
}
|
|
@@ -433,9 +433,49 @@ function main() {
|
|
|
433
433
|
return 0;
|
|
434
434
|
}
|
|
435
435
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
436
|
+
/**
|
|
437
|
+
* True when `moduleUrl` names the module node was asked to run.
|
|
438
|
+
*
|
|
439
|
+
* The one implementation of this lives at `scripts/lib/invoked-as-script.mjs`,
|
|
440
|
+
* and every other shipped entry point imports it. This file cannot: it is
|
|
441
|
+
* materialized from `plugins/src/base/hooks/`, where it also runs as an
|
|
442
|
+
* agent-time hook, and a plugin payload has no `./lib/` to import from. So the
|
|
443
|
+
* rule is written out here rather than pointed at — the same accommodation
|
|
444
|
+
* `preflight-secrets.mjs` makes, for the same reason.
|
|
445
|
+
*
|
|
446
|
+
* Both sides are realpath'd. The previous spelling compared
|
|
447
|
+
* `fileURLToPath(import.meta.url)` against `path.resolve(process.argv[1])`, and
|
|
448
|
+
* `resolve` makes a path absolute without following symlinks. `import.meta.url`
|
|
449
|
+
* is the REAL path — node resolves ESM through realpath unless
|
|
450
|
+
* `--preserve-symlinks` or `--preserve-symlinks-main` is set — while `argv[1]`
|
|
451
|
+
* is whatever the caller typed. Reached through a symlinked checkout, a git
|
|
452
|
+
* worktree, or a `/tmp` path on macOS (`/tmp` being a symlink to `/private/tmp`),
|
|
453
|
+
* the two disagreed, `main()` never ran, and the process exited 0.
|
|
454
|
+
*
|
|
455
|
+
* For a CHECK that is a fail-OPEN, not a mild degradation: no output, exit 0,
|
|
456
|
+
* the npm script "succeeds", and the ratchet silently stops having an opinion.
|
|
457
|
+
* It was measured, not theorised — every control in the #2531 promotion tests
|
|
458
|
+
* no-opped until the fixture directory was realpath'd.
|
|
459
|
+
*
|
|
460
|
+
* Realpathing BOTH sides rather than only `argv[1]` matters under
|
|
461
|
+
* `--preserve-symlinks-main`, which tells node not to resolve the main entry:
|
|
462
|
+
* normalizing one side then compares a real path against a symlinked one and
|
|
463
|
+
* answers `false` for an entry point that WAS invoked directly. Any resolution
|
|
464
|
+
* error returns `false` — node loaded the entry from that path moments ago, so
|
|
465
|
+
* a path that will not resolve now is not the path this module came through.
|
|
466
|
+
* @param {string} moduleUrl - The caller's own `import.meta.url`.
|
|
467
|
+
* @param {string | undefined} [argv1] - Entry path; defaults to `process.argv[1]`.
|
|
468
|
+
* @returns {boolean} Whether the caller should run its CLI body.
|
|
469
|
+
*/
|
|
470
|
+
export function invokedAsScript(moduleUrl, argv1 = process.argv[1]) {
|
|
471
|
+
if (!argv1) return false;
|
|
472
|
+
try {
|
|
473
|
+
return fs.realpathSync(argv1) === fs.realpathSync(fileURLToPath(moduleUrl));
|
|
474
|
+
} catch {
|
|
475
|
+
return false;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
if (invokedAsScript(import.meta.url)) {
|
|
440
480
|
process.exit(main());
|
|
441
481
|
}
|
|
@@ -54,15 +54,22 @@ fi
|
|
|
54
54
|
|
|
55
55
|
# Check for Co-Authored-By line (skip for merge commits)
|
|
56
56
|
COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")
|
|
57
|
+
# `printf '%s\n'`, never `echo "$COMMIT_MSG"`. Under a POSIX/XSI `echo` the
|
|
58
|
+
# backslash escapes are interpreted, and `\c` means "stop output here" — so a
|
|
59
|
+
# message containing `\copy`, `\cite`, or a Windows path like `C:\config` is
|
|
60
|
+
# silently truncated at that point before grep ever sees it. The
|
|
61
|
+
# `Co-Authored-By:` trailer is always the last line, so it is always the part
|
|
62
|
+
# lost, and the hook then rejects a commit whose trailer is present and
|
|
63
|
+
# correctly formatted while pointing the author at the trailer.
|
|
57
64
|
|
|
58
65
|
# Skip AI co-authorship check for merge commits (e.g., from git pull)
|
|
59
|
-
if
|
|
66
|
+
if printf '%s\n' "$COMMIT_MSG" | grep -qE "^Merge (branch|pull request|remote-tracking)"; then
|
|
60
67
|
echo "🔀 Merge commit detected, skipping AI co-authorship check"
|
|
61
68
|
exit 0
|
|
62
69
|
fi
|
|
63
70
|
|
|
64
71
|
# Skip AI co-authorship check for automated release commits (e.g., from standard-version in CI)
|
|
65
|
-
if
|
|
72
|
+
if printf '%s\n' "$COMMIT_MSG" | grep -qE "^chore\(release\):"; then
|
|
66
73
|
echo "🚀 Release commit detected, skipping AI co-authorship check"
|
|
67
74
|
exit 0
|
|
68
75
|
fi
|
|
@@ -72,7 +79,7 @@ echo "🤖 Checking for AI co-authorship..."
|
|
|
72
79
|
# Accept attribution from any supported coding agent (Claude or Codex),
|
|
73
80
|
# case-insensitively. Claude Code emits "Co-Authored-By: Claude"; the Codex CLI
|
|
74
81
|
# emits "Co-authored-by: Codex <noreply@openai.com>".
|
|
75
|
-
if !
|
|
82
|
+
if ! printf '%s\n' "$COMMIT_MSG" | grep -Eiq "Co-authored-by:.*(Claude|Codex)"; then
|
|
76
83
|
echo ""
|
|
77
84
|
echo "❌ Commit message must include AI co-authorship!"
|
|
78
85
|
echo ""
|
|
@@ -433,9 +433,49 @@ function main() {
|
|
|
433
433
|
return 0;
|
|
434
434
|
}
|
|
435
435
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
436
|
+
/**
|
|
437
|
+
* True when `moduleUrl` names the module node was asked to run.
|
|
438
|
+
*
|
|
439
|
+
* The one implementation of this lives at `scripts/lib/invoked-as-script.mjs`,
|
|
440
|
+
* and every other shipped entry point imports it. This file cannot: it is
|
|
441
|
+
* materialized from `plugins/src/base/hooks/`, where it also runs as an
|
|
442
|
+
* agent-time hook, and a plugin payload has no `./lib/` to import from. So the
|
|
443
|
+
* rule is written out here rather than pointed at — the same accommodation
|
|
444
|
+
* `preflight-secrets.mjs` makes, for the same reason.
|
|
445
|
+
*
|
|
446
|
+
* Both sides are realpath'd. The previous spelling compared
|
|
447
|
+
* `fileURLToPath(import.meta.url)` against `path.resolve(process.argv[1])`, and
|
|
448
|
+
* `resolve` makes a path absolute without following symlinks. `import.meta.url`
|
|
449
|
+
* is the REAL path — node resolves ESM through realpath unless
|
|
450
|
+
* `--preserve-symlinks` or `--preserve-symlinks-main` is set — while `argv[1]`
|
|
451
|
+
* is whatever the caller typed. Reached through a symlinked checkout, a git
|
|
452
|
+
* worktree, or a `/tmp` path on macOS (`/tmp` being a symlink to `/private/tmp`),
|
|
453
|
+
* the two disagreed, `main()` never ran, and the process exited 0.
|
|
454
|
+
*
|
|
455
|
+
* For a CHECK that is a fail-OPEN, not a mild degradation: no output, exit 0,
|
|
456
|
+
* the npm script "succeeds", and the ratchet silently stops having an opinion.
|
|
457
|
+
* It was measured, not theorised — every control in the #2531 promotion tests
|
|
458
|
+
* no-opped until the fixture directory was realpath'd.
|
|
459
|
+
*
|
|
460
|
+
* Realpathing BOTH sides rather than only `argv[1]` matters under
|
|
461
|
+
* `--preserve-symlinks-main`, which tells node not to resolve the main entry:
|
|
462
|
+
* normalizing one side then compares a real path against a symlinked one and
|
|
463
|
+
* answers `false` for an entry point that WAS invoked directly. Any resolution
|
|
464
|
+
* error returns `false` — node loaded the entry from that path moments ago, so
|
|
465
|
+
* a path that will not resolve now is not the path this module came through.
|
|
466
|
+
* @param {string} moduleUrl - The caller's own `import.meta.url`.
|
|
467
|
+
* @param {string | undefined} [argv1] - Entry path; defaults to `process.argv[1]`.
|
|
468
|
+
* @returns {boolean} Whether the caller should run its CLI body.
|
|
469
|
+
*/
|
|
470
|
+
export function invokedAsScript(moduleUrl, argv1 = process.argv[1]) {
|
|
471
|
+
if (!argv1) return false;
|
|
472
|
+
try {
|
|
473
|
+
return fs.realpathSync(argv1) === fs.realpathSync(fileURLToPath(moduleUrl));
|
|
474
|
+
} catch {
|
|
475
|
+
return false;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
if (invokedAsScript(import.meta.url)) {
|
|
440
480
|
process.exit(main());
|
|
441
481
|
}
|