@codyswann/lisa 4.37.3 → 4.38.1
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-contents/.gitattributes +9 -0
- package/all/copy-overwrite/scripts/lisa-work-item.mjs +209 -8
- package/dist/core/learnings-merge-driver.d.ts +8 -0
- package/dist/core/learnings-merge-driver.d.ts.map +1 -1
- package/dist/core/learnings-merge-driver.js +17 -0
- package/dist/core/learnings-merge-driver.js.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +6 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
- package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +37 -5
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/package.json +5 -4
- package/plugins/lisa/.claude-plugin/plugin.json +37 -1
- package/plugins/lisa/.codex-plugin/hooks.json +36 -0
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-git-submit-pr/SKILL.md +8 -3
- package/plugins/lisa/hooks/discharge-work-item-gates.sh +54 -0
- package/plugins/lisa/hooks/withdrawn-rulings.mjs +525 -0
- package/plugins/lisa/hooks/withdrawn-rulings.sh +24 -0
- package/plugins/lisa/rules/eager/withdrawn-rulings.md +69 -0
- package/plugins/lisa/rules/reference/withdrawn-rulings.md +114 -0
- package/plugins/lisa/skills/lisa-git-submit-pr/SKILL.md +8 -3
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/lisa-git-submit-pr/SKILL.md +8 -3
- 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 +28 -1
- package/plugins/lisa-copilot/hooks/discharge-work-item-gates.sh +54 -0
- package/plugins/lisa-copilot/hooks/withdrawn-rulings.mjs +525 -0
- package/plugins/lisa-copilot/hooks/withdrawn-rulings.sh +24 -0
- package/plugins/lisa-copilot/rules/eager/withdrawn-rulings.md +69 -0
- package/plugins/lisa-copilot/rules/reference/withdrawn-rulings.md +114 -0
- package/plugins/lisa-copilot/skills/lisa-git-submit-pr/SKILL.md +8 -3
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/hooks/discharge-work-item-gates.sh +54 -0
- package/plugins/lisa-cursor/hooks/hooks.json +14 -0
- package/plugins/lisa-cursor/hooks/withdrawn-rulings.mjs +525 -0
- package/plugins/lisa-cursor/hooks/withdrawn-rulings.sh +24 -0
- package/plugins/lisa-cursor/rules/withdrawn-rulings-reference.mdc +119 -0
- package/plugins/lisa-cursor/rules/withdrawn-rulings.mdc +74 -0
- package/plugins/lisa-cursor/skills/lisa-git-submit-pr/SKILL.md +8 -3
- 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/.claude-plugin/plugin.json +36 -0
- package/plugins/src/base/hooks/discharge-work-item-gates.sh +54 -0
- package/plugins/src/base/hooks/withdrawn-rulings.mjs +525 -0
- package/plugins/src/base/hooks/withdrawn-rulings.sh +24 -0
- package/plugins/src/base/rules/eager/withdrawn-rulings.md +69 -0
- package/plugins/src/base/rules/reference/withdrawn-rulings.md +114 -0
- package/plugins/src/base/skills/lisa-git-submit-pr/SKILL.md +8 -3
- package/scripts/lib/hook-registration-audit.mjs +612 -0
- package/scripts/lib/per-agent-hook-filter.mjs +19 -0
- package/typescript/copy-contents/.husky/pre-push +98 -26
|
@@ -584,41 +584,113 @@ else
|
|
|
584
584
|
echo " Check that TMPDIR (${TMPDIR:-/tmp}) exists and is writable." >&2
|
|
585
585
|
exit 1
|
|
586
586
|
fi
|
|
587
|
-
#
|
|
588
|
-
#
|
|
589
|
-
#
|
|
590
|
-
|
|
591
|
-
|
|
587
|
+
# The audit is a NETWORK call, and the network is the one input to this gate
|
|
588
|
+
# that answers differently to the same question. Measured 2026-09-04, three
|
|
589
|
+
# consecutive `bun audit --production --json` invocations in one directory
|
|
590
|
+
# seconds apart: run 1 returned 0 bytes with `Timeout: audit request failed`,
|
|
591
|
+
# runs 2 and 3 returned 6036 bytes of valid JSON. Read as a single attempt
|
|
592
|
+
# that is a blocked `git push` — and the push has already paid for the whole
|
|
593
|
+
# gate chain (tests, typecheck, dead-code, traceability, mutation) because
|
|
594
|
+
# the audit sits near the end of it. One flaky call, one full cycle.
|
|
595
|
+
#
|
|
596
|
+
# So the call is retried, and ONLY the indeterminate outcome is retried:
|
|
597
|
+
#
|
|
598
|
+
# determinate — the payload parsed. Break immediately, whether it is
|
|
599
|
+
# clean or names a critical advisory. A real vulnerability
|
|
600
|
+
# fails on the FIRST call and is never retried into a pass;
|
|
601
|
+
# a clean audit pays nothing for a knob it did not need.
|
|
602
|
+
# indeterminate — nothing parsed: zero bytes, or bytes that are neither
|
|
603
|
+
# JSON nor gzipped JSON. The audit did not happen. That is
|
|
604
|
+
# what a retry can change, and the only thing it may.
|
|
605
|
+
#
|
|
606
|
+
# The direction matters more than the retry does. Retrying a determinate
|
|
607
|
+
# answer is how a gate talks itself out of a finding; this loop cannot,
|
|
608
|
+
# because a parsed payload leaves the loop before any backoff is reached.
|
|
609
|
+
#
|
|
610
|
+
# Three outcomes, three sentences. "The audit did not run" is never collapsed
|
|
611
|
+
# into "the audit found nothing" (that is the fail-open this block exists to
|
|
612
|
+
# remove) nor into "the audit found something" (that sends the reader hunting
|
|
613
|
+
# a vulnerability that was never measured). When every attempt is
|
|
614
|
+
# indeterminate the block still refuses, with the same two distinguishable
|
|
615
|
+
# messages it printed before — a retry that muted either would trade a noisy
|
|
616
|
+
# flake for a silent hole.
|
|
617
|
+
AUDIT_ATTEMPTS="${LISA_AUDIT_ATTEMPTS:-3}"
|
|
618
|
+
AUDIT_RETRY_DELAY="${LISA_AUDIT_RETRY_DELAY:-2}"
|
|
619
|
+
# A non-numeric knob is a typo, not an instruction. This hook does not run
|
|
620
|
+
# under `set -e`, so `[ abc -le 3 ]` would print an error and the loop would
|
|
621
|
+
# behave in a way nobody chose; falling back to the default keeps a
|
|
622
|
+
# fat-fingered env var from quietly disarming the retry.
|
|
623
|
+
case "$AUDIT_ATTEMPTS" in ''|*[!0-9]*) AUDIT_ATTEMPTS=3 ;; esac
|
|
624
|
+
case "$AUDIT_RETRY_DELAY" in ''|*[!0-9]*) AUDIT_RETRY_DELAY=2 ;; esac
|
|
625
|
+
[ "$AUDIT_ATTEMPTS" -ge 1 ] || AUDIT_ATTEMPTS=1
|
|
626
|
+
|
|
627
|
+
AUDIT_JSON=""
|
|
628
|
+
# "" once a payload parsed; otherwise which refusal the last attempt earned.
|
|
629
|
+
AUDIT_INDETERMINATE=""
|
|
630
|
+
AUDIT_ATTEMPT=1
|
|
631
|
+
while [ "$AUDIT_ATTEMPT" -le "$AUDIT_ATTEMPTS" ]; do
|
|
632
|
+
# bun's own diagnostics are kept rather than discarded. "Lockfile not
|
|
633
|
+
# found" is the difference between a broken audit and a clean one, and
|
|
634
|
+
# throwing it away is how a failed command comes to read as a measured
|
|
635
|
+
# zero. "Timeout: audit request failed" is the line that names this bug,
|
|
636
|
+
# and an agent grepping the push output for its own expected failure
|
|
637
|
+
# shapes has already thrown it away once.
|
|
638
|
+
bun audit --production --json > "$AUDIT_OUTPUT" 2>"$AUDIT_STDERR" || true
|
|
639
|
+
if [ ! -s "$AUDIT_OUTPUT" ]; then
|
|
640
|
+
AUDIT_INDETERMINATE="empty"
|
|
641
|
+
elif jq empty "$AUDIT_OUTPUT" >/dev/null 2>&1; then
|
|
642
|
+
AUDIT_JSON=$(cat "$AUDIT_OUTPUT")
|
|
643
|
+
AUDIT_INDETERMINATE=""
|
|
644
|
+
break
|
|
645
|
+
else
|
|
646
|
+
# Bun can return gzip-compressed JSON on stdout while still reporting a
|
|
647
|
+
# parse error on stderr. Normalize that transport shape before applying
|
|
648
|
+
# Lisa's advisory allowlist.
|
|
649
|
+
DECOMPRESSED_AUDIT_OUTPUT="$(mktemp "${TMPDIR:-/tmp}/bun-audit-gz.XXXXXXXX")"
|
|
650
|
+
if [ -n "$DECOMPRESSED_AUDIT_OUTPUT" ]; then
|
|
651
|
+
gzip -dc "$AUDIT_OUTPUT" > "$DECOMPRESSED_AUDIT_OUTPUT" 2>/dev/null || true
|
|
652
|
+
fi
|
|
653
|
+
# `-s` before `jq empty`: an EMPTY file passes `jq empty` (no input is
|
|
654
|
+
# not invalid input), so a gunzip that failed and wrote nothing would be
|
|
655
|
+
# accepted as valid JSON and set AUDIT_JSON to the empty string.
|
|
656
|
+
if [ -s "$DECOMPRESSED_AUDIT_OUTPUT" ] && jq empty "$DECOMPRESSED_AUDIT_OUTPUT" >/dev/null 2>&1; then
|
|
657
|
+
AUDIT_JSON=$(cat "$DECOMPRESSED_AUDIT_OUTPUT")
|
|
658
|
+
rm -f "$DECOMPRESSED_AUDIT_OUTPUT"
|
|
659
|
+
AUDIT_INDETERMINATE=""
|
|
660
|
+
break
|
|
661
|
+
fi
|
|
662
|
+
rm -f "$DECOMPRESSED_AUDIT_OUTPUT"
|
|
663
|
+
AUDIT_INDETERMINATE="unparseable"
|
|
664
|
+
fi
|
|
665
|
+
if [ "$AUDIT_ATTEMPT" -lt "$AUDIT_ATTEMPTS" ]; then
|
|
666
|
+
echo "⏳ Security audit attempt $AUDIT_ATTEMPT of $AUDIT_ATTEMPTS parsed no advisory data (the audit did not run — this is not a finding); retrying in ${AUDIT_RETRY_DELAY}s..." >&2
|
|
667
|
+
if [ "$AUDIT_RETRY_DELAY" -gt 0 ]; then
|
|
668
|
+
sleep "$AUDIT_RETRY_DELAY"
|
|
669
|
+
fi
|
|
670
|
+
AUDIT_RETRY_DELAY=$((AUDIT_RETRY_DELAY * 2))
|
|
671
|
+
fi
|
|
672
|
+
AUDIT_ATTEMPT=$((AUDIT_ATTEMPT + 1))
|
|
673
|
+
done
|
|
674
|
+
|
|
675
|
+
if [ "$AUDIT_INDETERMINATE" = "empty" ]; then
|
|
592
676
|
echo "❌ Push blocked: bun audit produced no output, so nothing was audited." >&2
|
|
593
677
|
echo " This is NOT a clean result — a clean audit prints JSON ({} when" >&2
|
|
594
678
|
echo " there are no advisories). Empty output means the audit did not run." >&2
|
|
679
|
+
echo " Tried $AUDIT_ATTEMPTS attempt(s) with backoff; every one came back" >&2
|
|
680
|
+
echo " empty, so this is not the transient registry timeout a retry clears." >&2
|
|
595
681
|
if [ -s "$AUDIT_STDERR" ]; then
|
|
596
682
|
echo " bun said:" >&2
|
|
597
683
|
sed 's/^/ /' "$AUDIT_STDERR" >&2
|
|
598
684
|
fi
|
|
599
685
|
rm -f "$AUDIT_OUTPUT" "$AUDIT_STDERR"
|
|
600
686
|
exit 1
|
|
601
|
-
elif
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
# `-s` before `jq empty`: an EMPTY file passes `jq empty` (no input is
|
|
609
|
-
# not invalid input), so a gunzip that failed and wrote nothing would be
|
|
610
|
-
# accepted as valid JSON and set AUDIT_JSON to the empty string.
|
|
611
|
-
if [ -s "$DECOMPRESSED_AUDIT_OUTPUT" ] && jq empty "$DECOMPRESSED_AUDIT_OUTPUT" >/dev/null 2>&1; then
|
|
612
|
-
AUDIT_JSON=$(cat "$DECOMPRESSED_AUDIT_OUTPUT")
|
|
613
|
-
rm -f "$DECOMPRESSED_AUDIT_OUTPUT"
|
|
614
|
-
else
|
|
615
|
-
rm -f "$DECOMPRESSED_AUDIT_OUTPUT" "$AUDIT_OUTPUT" "$AUDIT_STDERR"
|
|
616
|
-
echo "❌ Push blocked: bun audit output is neither JSON nor gzipped JSON," >&2
|
|
617
|
-
echo " so no advisory data was parsed and nothing was audited." >&2
|
|
618
|
-
echo " This is NOT a clean result. Re-run 'bun audit --production --json'" >&2
|
|
619
|
-
echo " to see what it emitted." >&2
|
|
620
|
-
exit 1
|
|
621
|
-
fi
|
|
687
|
+
elif [ "$AUDIT_INDETERMINATE" = "unparseable" ]; then
|
|
688
|
+
rm -f "$AUDIT_OUTPUT" "$AUDIT_STDERR"
|
|
689
|
+
echo "❌ Push blocked: bun audit output is neither JSON nor gzipped JSON," >&2
|
|
690
|
+
echo " so no advisory data was parsed and nothing was audited." >&2
|
|
691
|
+
echo " This is NOT a clean result. Re-run 'bun audit --production --json'" >&2
|
|
692
|
+
echo " to see what it emitted. Tried $AUDIT_ATTEMPTS attempt(s)." >&2
|
|
693
|
+
exit 1
|
|
622
694
|
fi
|
|
623
695
|
rm -f "$AUDIT_OUTPUT" "$AUDIT_STDERR"
|
|
624
696
|
UNFIXED_HIGH=$(echo "$AUDIT_JSON" | jq -r --arg ids "$AUDIT_EXCLUSIONS" '
|