@codyswann/lisa 2.332.4 → 2.332.5

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.
Files changed (65) hide show
  1. package/all/copy-overwrite/scripts/lisa-hooks/block-no-verify.sh +27 -4
  2. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  3. package/dist/core/upstream-evidence-manifest.js +4 -3
  4. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  5. package/package.json +1 -1
  6. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  7. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  8. package/plugins/lisa/.codex-plugin/skills/lisa-drive-pr-to-merge/SKILL.md +53 -18
  9. package/plugins/lisa/hooks/block-no-verify.sh +27 -4
  10. package/plugins/lisa/skills/lisa-drive-pr-to-merge/SKILL.md +53 -18
  11. package/plugins/lisa-agy/plugin.json +1 -1
  12. package/plugins/lisa-agy/skills/lisa-drive-pr-to-merge/SKILL.md +53 -18
  13. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  14. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  15. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  16. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  17. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  18. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  19. package/plugins/lisa-copilot/hooks/block-no-verify.sh +27 -4
  20. package/plugins/lisa-copilot/skills/lisa-drive-pr-to-merge/SKILL.md +53 -18
  21. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  22. package/plugins/lisa-cursor/hooks/block-no-verify.sh +27 -4
  23. package/plugins/lisa-cursor/skills/lisa-drive-pr-to-merge/SKILL.md +53 -18
  24. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  25. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  26. package/plugins/lisa-expo-agy/plugin.json +1 -1
  27. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  28. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  29. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  30. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  31. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  32. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  33. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  34. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  35. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  36. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  37. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  38. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  39. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  41. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  42. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  44. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  45. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  46. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  47. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  51. package/plugins/lisa-rails-agy/plugin.json +1 -1
  52. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  54. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  55. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  56. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  57. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  59. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  60. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  61. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  62. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  63. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  64. package/plugins/src/base/hooks/block-no-verify.sh +27 -4
  65. package/plugins/src/base/skills/lisa-drive-pr-to-merge/SKILL.md +53 -18
@@ -20,18 +20,41 @@ set -euo pipefail
20
20
 
21
21
  input="$(cat)"
22
22
 
23
- tool_name="$(printf '%s' "$input" | jq -r '.tool_name // empty')"
23
+ # Both interpreters must be probed BEFORE they are used, and a missing one must
24
+ # be announced rather than swallowed.
25
+ #
26
+ # `jq` used to be called unguarded here while `python3` two lines below was
27
+ # guarded. Under `set -e` an absent jq aborted the script with 127, and Claude
28
+ # Code treats any non-2 exit as a NON-BLOCKING hook error — so the hook that
29
+ # enforces "never --no-verify" silently permitted the very thing it exists to
30
+ # stop. It was not hypothetical: agent containers routinely ship no jq (that is
31
+ # why jq is now a pinned toolchain entry). The Codex variant of this script has
32
+ # always had the guard, so this was a parity gap rather than a design choice.
33
+ #
34
+ # Degrading to "allow" is still the right behaviour — a hook that cannot parse
35
+ # its input cannot tell a bypass from an ordinary command, and failing closed
36
+ # would block every Bash call on a machine missing an interpreter. What is NOT
37
+ # right is doing it quietly, so the operator gets one line on stderr saying the
38
+ # protection is off. A guard that is silently absent reads exactly like a guard
39
+ # that is passing.
40
+ for required in jq python3; do
41
+ if ! command -v "$required" >/dev/null 2>&1; then
42
+ printf 'block-no-verify: %s not found; --no-verify protection is NOT active\n' \
43
+ "$required" >&2
44
+ exit 0
45
+ fi
46
+ done
47
+
48
+ tool_name="$(printf '%s' "$input" | jq -r '.tool_name // empty' 2>/dev/null || true)"
24
49
  if [ "$tool_name" != "Bash" ]; then
25
50
  exit 0
26
51
  fi
27
52
 
28
- command_str="$(printf '%s' "$input" | jq -r '.tool_input.command // empty')"
53
+ command_str="$(printf '%s' "$input" | jq -r '.tool_input.command // empty' 2>/dev/null || true)"
29
54
  if [ -z "$command_str" ]; then
30
55
  exit 0
31
56
  fi
32
57
 
33
- command -v python3 >/dev/null 2>&1 || exit 0
34
-
35
58
  if ! BLOCK_NO_VERIFY_COMMAND="$command_str" python3 - <<'PY'
36
59
  import os
37
60
  import re
@@ -126,13 +126,50 @@ auto-merge against a stale head you have not verified.
126
126
  `gh pr merge <pr> --auto --<merge_method>`. Enabling auto-merge is **not terminal**
127
127
  — continue the loop below until the PR is actually `MERGED` or `CLOSED`.
128
128
 
129
- If any later step will push commits, temporarily remove the auto-merge latch
130
- before the push when GitHub exposes that mutation (`disablePullRequestAutoMerge`),
131
- or otherwise treat the push as a merge race: immediately re-read `headRefOid`,
132
- reset `verify_commit` to the pushed head, wait until that head's checks have
133
- started, then re-enable auto-merge. Do not leave auto-merge armed while a
134
- required fix, CodeRabbit follow-up, generated artifact update, or CI auto-fix is
135
- still in flight.
129
+ **With `auto_merge=true`, leave the latch ARMED never disable auto-merge.**
130
+ (Under `auto_merge=false` the deliberate disarm above still applies: that mode
131
+ must leave the PR open for a human, so a pre-existing latch is removed on
132
+ purpose. Everything below is the `auto_merge=true` path.)
133
+
134
+ Once a fix is PUSHED the latch is safe: GitHub evaluates required checks against
135
+ the PR's current head, so a new commit whose checks have not reported leaves the
136
+ PR blocked. Auto-merge cannot ship a commit nothing has verified.
137
+
138
+ The only window a disarm ever protected is the gap between deciding to fix
139
+ something and that fix landing — during which the PR is genuinely green and
140
+ genuinely mergeable, and auto-merge firing is GitHub behaving correctly. Two
141
+ merges in this repo's history are attributed to that window (#1392, and the
142
+ release that shipped the `./hooks/` Cursor bug). Both were fixed forward within
143
+ minutes; one was a one-line docs inconsistency.
144
+
145
+ That evidence is also weaker than it looks: **auto-merge attributes the merge to
146
+ whoever enabled it**, so an auto-merge and a human pressing Merge are
147
+ indistinguishable in the timeline. The record cannot tell us those PRs were not
148
+ simply merged by hand while the latch happened to be armed.
149
+
150
+ Against that, disarming costs something certain. Disabling is a durable state
151
+ change on GitHub; re-enabling is one more step the run has to reach. When a run
152
+ ends in between — turns exhausted, job timeout, or you concluding the work while
153
+ checks are still pending — the latch stays off and nothing restores it. The PR is
154
+ left WORSE OFF THAN IF THIS SKILL HAD NEVER RUN: it has lost the mechanism that
155
+ merges it while no agent is watching, and the run reports success. Measured on
156
+ `gunnertech/frontend#282`, the latch went off 14s before the fix commit and the
157
+ PR sat 26 minutes after going green, against ~3 minutes for PRs this skill never
158
+ touched.
159
+
160
+ So the trade is a rare, unproven miss that costs a fix-forward PR, against a
161
+ frequent, silent stall on every PR this skill repairs. Take the rare one.
162
+
163
+ What still applies on a push: immediately re-read `headRefOid` and reset
164
+ `verify_commit` to the pushed head, so the shipped-verification in step 3 checks
165
+ what you actually pushed rather than the commit you replaced. That ancestry check
166
+ is what CATCHES a raced merge — it fails loudly when the fix SHA is not an
167
+ ancestor of the base branch — so the rare miss is detected rather than silent.
168
+
169
+ **Invariant:** never terminate having left auto-merge OFF on an open PR when
170
+ `auto_merge=true`. If some future path does disable it, restoring it is a
171
+ terminal obligation on EVERY exit — including give-up, budget-exhausted and error
172
+ paths — not a later step in a sequence.
136
173
 
137
174
  - **Capability fallback** (`auto_merge=true` only): if the repo disallows
138
175
  auto-merge, do not fail. Keep watching; once checks are green, the review gate
@@ -215,10 +252,9 @@ registered you will instead see real conflict markers — run
215
252
  ### c. Failing CI / deploy checks (`statusCheckRollup` has FAILURE)
216
253
  Inspect the failing check's logs (`gh pr checks <pr>`, `gh run view <run> --log-failed`).
217
254
  Fix the underlying code inline — **never lower thresholds, skip tests, or disable
218
- checks** to force green. Before pushing the fix, disarm auto-merge or classify the
219
- run as race-prone, then after the push re-read the PR head, update `verify_commit`
220
- to that exact SHA, wait for checks on that head to start, and only then resume
221
- auto-merge. When the root cause is an upstream Lisa template/postinstall bug
255
+ checks** to force green. Leave auto-merge armed across the push (section 1);
256
+ after it, re-read the PR head and update `verify_commit` to that exact SHA so the
257
+ shipped-verification checks what you pushed. When the root cause is an upstream Lisa template/postinstall bug
222
258
  rather than this project's code, fix it upstream and propagate down rather than
223
259
  patching only here.
224
260
 
@@ -227,10 +263,9 @@ Delegate to the `pull-request-review` skill with the PR number. It owns the whol
227
263
  comment cycle: fetch every unresolved human + bot thread (with resolution state via
228
264
  GraphQL), implement valid feedback (commit + push), reply to invalid feedback, and
229
265
  resolve every thread via `resolveReviewThread` so the branch-protection
230
- thread-resolution gate clears. If that skill needs to push a commit, auto-merge
231
- must be disabled first when possible; when it returns, re-read `headRefOid`, reset
232
- `verify_commit` to the returned/pushed head, wait for that head's checks to start,
233
- then re-enable auto-merge and continue. Do not re-implement review handling here
266
+ thread-resolution gate clears. If that skill needs to push a commit, leave
267
+ auto-merge armed (section 1); when it returns, re-read `headRefOid` and reset
268
+ `verify_commit` to the returned/pushed head, then continue. Do not re-implement review handling here
234
269
  — it is the single source of truth for review-thread handling.
235
270
 
236
271
  ### e. Review gate stall (`reviewDecision == CHANGES_REQUESTED`)
@@ -252,9 +287,9 @@ branch (the CI auto-fix workflow engaged before this session took the lease),
252
287
  adjudicate it: merge it into the head branch if the fix is correct and still
253
288
  needed, otherwise close it and delete the side branch. Never leave it dangling
254
289
  — it represents a competing writer's pending work. Merging it mutates the
255
- driven branch, so treat it like any other push: disarm auto-merge first,
256
- re-read `headRefOid`, reset `verify_commit` to the merged head, wait for that
257
- head's checks to start, then re-enable auto-merge (section 1). In
290
+ driven branch, so treat it like any other push: leave auto-merge armed
291
+ (section 1), then re-read `headRefOid` and reset `verify_commit` to the merged
292
+ head. In
258
293
  `on_blocker=report` mode this whole step is off-limits (diagnose-only): do not
259
294
  merge, close, or delete anything — return `blocked:pending-auto-fix`.
260
295
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Expo and React Native-specific skills, agents, rules, and MCP servers.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Harper/Fabric-specific Lisa rules for TypeScript component apps.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "NestJS-specific skills and migration write-protection hooks.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Ruby on Rails-specific skills and hooks for RuboCop and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "TypeScript-specific hooks for formatting, linting, and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "Distributable LLM Wiki kernel — ingest, query, lint, and maintain a git-native markdown knowledge base across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.332.4",
3
+ "version": "2.332.5",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -20,18 +20,41 @@ set -euo pipefail
20
20
 
21
21
  input="$(cat)"
22
22
 
23
- tool_name="$(printf '%s' "$input" | jq -r '.tool_name // empty')"
23
+ # Both interpreters must be probed BEFORE they are used, and a missing one must
24
+ # be announced rather than swallowed.
25
+ #
26
+ # `jq` used to be called unguarded here while `python3` two lines below was
27
+ # guarded. Under `set -e` an absent jq aborted the script with 127, and Claude
28
+ # Code treats any non-2 exit as a NON-BLOCKING hook error — so the hook that
29
+ # enforces "never --no-verify" silently permitted the very thing it exists to
30
+ # stop. It was not hypothetical: agent containers routinely ship no jq (that is
31
+ # why jq is now a pinned toolchain entry). The Codex variant of this script has
32
+ # always had the guard, so this was a parity gap rather than a design choice.
33
+ #
34
+ # Degrading to "allow" is still the right behaviour — a hook that cannot parse
35
+ # its input cannot tell a bypass from an ordinary command, and failing closed
36
+ # would block every Bash call on a machine missing an interpreter. What is NOT
37
+ # right is doing it quietly, so the operator gets one line on stderr saying the
38
+ # protection is off. A guard that is silently absent reads exactly like a guard
39
+ # that is passing.
40
+ for required in jq python3; do
41
+ if ! command -v "$required" >/dev/null 2>&1; then
42
+ printf 'block-no-verify: %s not found; --no-verify protection is NOT active\n' \
43
+ "$required" >&2
44
+ exit 0
45
+ fi
46
+ done
47
+
48
+ tool_name="$(printf '%s' "$input" | jq -r '.tool_name // empty' 2>/dev/null || true)"
24
49
  if [ "$tool_name" != "Bash" ]; then
25
50
  exit 0
26
51
  fi
27
52
 
28
- command_str="$(printf '%s' "$input" | jq -r '.tool_input.command // empty')"
53
+ command_str="$(printf '%s' "$input" | jq -r '.tool_input.command // empty' 2>/dev/null || true)"
29
54
  if [ -z "$command_str" ]; then
30
55
  exit 0
31
56
  fi
32
57
 
33
- command -v python3 >/dev/null 2>&1 || exit 0
34
-
35
58
  if ! BLOCK_NO_VERIFY_COMMAND="$command_str" python3 - <<'PY'
36
59
  import os
37
60
  import re