@codyswann/lisa 4.24.2 → 4.25.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.
Files changed (79) hide show
  1. package/all/copy-overwrite/scripts/lisa-hooks/block-no-verify.sh +218 -82
  2. package/all/copy-overwrite/scripts/lisa-reconcile-policy.mjs +85 -12
  3. package/all/copy-overwrite/scripts/lisa-work-item.mjs +74 -15
  4. package/dist/cli/ui-config-write-persistence.d.ts +12 -2
  5. package/dist/cli/ui-config-write-persistence.d.ts.map +1 -1
  6. package/dist/cli/ui-config-write-persistence.js +7 -3
  7. package/dist/cli/ui-config-write-persistence.js.map +1 -1
  8. package/dist/cli/ui-config-write.d.ts +1 -1
  9. package/dist/cli/ui-config-write.d.ts.map +1 -1
  10. package/dist/cli/ui-config-write.js +62 -6
  11. package/dist/cli/ui-config-write.js.map +1 -1
  12. package/dist/codex/scripts/block-no-verify.sh +134 -37
  13. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  14. package/dist/core/lisa-owned-hash-ledger.js +8 -0
  15. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  16. package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
  17. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  18. package/dist/core/upstream-evidence-manifest.js +7 -6
  19. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  20. package/dist/opencode/plugin-templates/block-no-verify.sh +218 -82
  21. package/package.json +3 -3
  22. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  23. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  24. package/plugins/lisa/hooks/block-no-verify.agy.sh +134 -37
  25. package/plugins/lisa/hooks/block-no-verify.sh +218 -82
  26. package/plugins/lisa-agy/hooks/block-no-verify.agy.sh +134 -37
  27. package/plugins/lisa-agy/plugin.json +1 -1
  28. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  29. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  30. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  31. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  32. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  33. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  34. package/plugins/lisa-copilot/hooks/block-no-verify.sh +218 -82
  35. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-cursor/hooks/block-no-verify.sh +218 -82
  37. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  38. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  39. package/plugins/lisa-expo-agy/plugin.json +1 -1
  40. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  44. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  45. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  47. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  49. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  50. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  52. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  54. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  55. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  59. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  60. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  63. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  64. package/plugins/lisa-rails-agy/plugin.json +1 -1
  65. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  66. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  68. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  69. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  70. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  71. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  72. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  73. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  74. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  75. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  76. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  77. package/plugins/src/base/hooks/block-no-verify.agy.sh +134 -37
  78. package/plugins/src/base/hooks/block-no-verify.sh +218 -82
  79. package/ui/README.md +30 -2
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "4.24.2",
3
+ "version": "4.25.1",
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": "4.24.2",
3
+ "version": "4.25.1",
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": "4.24.2",
3
+ "version": "4.25.1",
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": "4.24.2",
3
+ "version": "4.25.1",
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": "4.24.2",
3
+ "version": "4.25.1",
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": "4.24.2",
3
+ "version": "4.25.1",
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": "4.24.2",
3
+ "version": "4.25.1",
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": "4.24.2",
3
+ "version": "4.25.1",
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": "4.24.2",
3
+ "version": "4.25.1",
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": "4.24.2",
3
+ "version": "4.25.1",
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": "4.24.2",
3
+ "version": "4.25.1",
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": "4.24.2",
3
+ "version": "4.25.1",
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"
@@ -161,13 +161,26 @@ COMMAND_SEPARATORS = {
161
161
  ";", "|", "||", "&", "&&", "(", ")", "<", ">", ">>", "<<", "&|",
162
162
  }
163
163
 
164
- ENV_OPTIONS_NO_VALUE = {
165
- "-i", "--ignore-environment", "-0", "--null", "-v", "--debug",
164
+ # GNU env's long options in FULL, so an ABBREVIATION can be resolved against
165
+ # them: getopt_long accepts any prefix naming exactly one option, and nothing
166
+ # but --split-string starts with `s`, so `env --s` splits a string just as
167
+ # completely as `env --split-string` does.
168
+ ENV_LONG_OPTIONS = {
169
+ "--argv0", "--block-signals", "--chdir", "--debug", "--default-signal",
170
+ "--help", "--ignore-environment", "--ignore-signal",
171
+ "--list-signal-handling", "--null", "--split-string", "--unset",
172
+ "--version",
166
173
  }
167
- ENV_OPTIONS_SEPARATE_VALUE = {
168
- "-u", "--unset", "-C", "--chdir", "-a", "--argv0",
169
- }
170
- ENV_OPTIONS_INLINE_VALUE = ("--unset=", "--chdir=", "--argv0=")
174
+ # Of those, the ones whose value is a SEPARATE token. The signal options take
175
+ # an OPTIONAL value, which GNU reads only when attached with `=`.
176
+ ENV_LONG_SEPARATE_VALUE = {"--argv0", "--chdir", "--split-string", "--unset"}
177
+ ENV_SHORT_NO_VALUE = frozenset("i0v")
178
+ ENV_SHORT_TAKES_VALUE = frozenset("uCaS")
179
+
180
+ # Builtins and wrappers that run whatever FOLLOWS them without changing what it
181
+ # is, so `command env -S ...` runs exactly the `env` that `env -S ...` runs.
182
+ COMMAND_PREFIX_WRAPPERS = {"command", "exec", "builtin", "nohup", "setsid"}
183
+ COMMAND_PREFIX_SEPARATE_VALUE = {"-a"}
171
184
 
172
185
  # git's own options taking a SEPARATE value token, skipped when looking for the
173
186
  # subcommand so `git -c core.hooksPath=x commit` still reaches `commit`.
@@ -310,19 +323,110 @@ def subcommand_after_git(tokens, start):
310
323
  return None
311
324
 
312
325
 
313
- def env_short_option_uses_split_string(token):
314
- """Whether one GNU env short-option cluster enables split-string."""
315
- if not token.startswith("-") or token.startswith("--") or token == "-":
316
- return False
317
- for letter in token[1:]:
326
+ def resolve_env_long_option(name):
327
+ """Resolve one env long option, abbreviations included.
328
+
329
+ Returns the full spelling, "" when the abbreviation names several options
330
+ (real env refuses those), or None when nothing matches.
331
+ """
332
+ if not name.startswith("--") or name == "--":
333
+ return None
334
+ if name in ENV_LONG_OPTIONS:
335
+ return name
336
+ matches = [option for option in ENV_LONG_OPTIONS if option.startswith(name)]
337
+ if len(matches) == 1:
338
+ return matches[0]
339
+ return "" if matches else None
340
+
341
+
342
+ def env_option_kind(token):
343
+ """Classify one token in an `env` option position.
344
+
345
+ Returns "split-string", "separate-value", "no-value", "ambiguous" when env
346
+ accepts the token but this parser cannot name it, or None when the token is
347
+ not an option at all.
348
+ """
349
+ if not token.startswith("-") or token in {"-", "--"}:
350
+ return None
351
+ if token.startswith("--"):
352
+ resolved = resolve_env_long_option(token.split("=", 1)[0])
353
+ if not resolved:
354
+ return "ambiguous"
355
+ if resolved == "--split-string":
356
+ return "split-string"
357
+ if "=" in token:
358
+ return "no-value"
359
+ return (
360
+ "separate-value" if resolved in ENV_LONG_SEPARATE_VALUE else "no-value"
361
+ )
362
+ for position, letter in enumerate(token[1:], start=2):
318
363
  if letter == "S":
319
- return True
320
- if letter in {"u", "C", "a"}:
321
- # The rest of this token is the option's value, not more options.
322
- return False
323
- if letter not in {"i", "0", "v"}:
324
- return False
325
- return False
364
+ return "split-string"
365
+ if letter in ENV_SHORT_TAKES_VALUE:
366
+ # The rest of the cluster is the option's value when there is one;
367
+ # otherwise the value is the following token.
368
+ return "no-value" if position <= len(token) - 1 else "separate-value"
369
+ if letter not in ENV_SHORT_NO_VALUE:
370
+ return "ambiguous"
371
+ return "no-value"
372
+
373
+
374
+ def strip_command_prefix(prefix):
375
+ """Drop tokens that precede a command without changing what it is.
376
+
377
+ Assignments, the `command`/`exec`/`builtin` builtins, and nested `env`
378
+ wrappers all leave the following word in command position. Reading any of
379
+ them as the command is what let `command env -S ...` and `env -- env -S
380
+ ...` past the split-string check: the prefix failed the assignments-only
381
+ test, so the wrapped `env` was never classified.
382
+
383
+ Returns a pair (status, remainder): "ok" with whatever still stands before
384
+ the candidate, "operand" when the candidate is a wrapper option's value,
385
+ or "ambiguous" when an option could not be classified.
386
+ """
387
+ cursor = 0
388
+ while cursor < len(prefix):
389
+ token = prefix[cursor]
390
+ if "=" in token and not token.startswith(("=", "-")):
391
+ cursor += 1
392
+ continue
393
+ program = token.rsplit("/", 1)[-1]
394
+ if program in COMMAND_PREFIX_WRAPPERS:
395
+ cursor += 1
396
+ while cursor < len(prefix) and prefix[cursor].startswith("-"):
397
+ if prefix[cursor] == "--":
398
+ cursor += 1
399
+ break
400
+ if prefix[cursor] in COMMAND_PREFIX_SEPARATE_VALUE:
401
+ if cursor + 1 >= len(prefix):
402
+ return ("operand", [])
403
+ cursor += 2
404
+ continue
405
+ cursor += 1
406
+ continue
407
+ if program == "env":
408
+ cursor += 1
409
+ while cursor < len(prefix):
410
+ option = prefix[cursor]
411
+ if option == "--":
412
+ cursor += 1
413
+ break
414
+ kind = env_option_kind(option)
415
+ if kind is None:
416
+ break
417
+ if kind == "ambiguous":
418
+ return ("ambiguous", [])
419
+ if kind == "split-string":
420
+ return ("operand", [])
421
+ if kind == "separate-value":
422
+ if cursor + 1 >= len(prefix):
423
+ return ("operand", [])
424
+ cursor += 2
425
+ continue
426
+ cursor += 1
427
+ continue
428
+ break
429
+ return ("ok", prefix[cursor:])
326
430
 
327
431
 
328
432
  def env_uses_split_string(tokens, index):
@@ -330,8 +434,8 @@ def env_uses_split_string(tokens, index):
330
434
  start = index - 1
331
435
  while start >= 0 and tokens[start] not in COMMAND_SEPARATORS:
332
436
  start -= 1
333
- prefix = tokens[start + 1:index]
334
- if not all("=" in token and not token.startswith("=") for token in prefix):
437
+ status, remainder = strip_command_prefix(tokens[start + 1:index])
438
+ if status != "ok" or remainder:
335
439
  return False
336
440
 
337
441
  cursor = index + 1
@@ -339,24 +443,17 @@ def env_uses_split_string(tokens, index):
339
443
  token = tokens[cursor]
340
444
  if token in COMMAND_SEPARATORS or token == "--":
341
445
  return False
342
- if (
343
- token in {"-S", "--split-string"}
344
- or token.startswith("--split-string=")
345
- or env_short_option_uses_split_string(token)
346
- ):
446
+ kind = env_option_kind(token)
447
+ if kind in {"split-string", "ambiguous"}:
448
+ # An option this parser cannot name makes the rest of the
449
+ # invocation unreadable; refuse instead of reading past it.
347
450
  return True
348
- if "=" in token and not token.startswith(("=", "-")):
349
- cursor += 1
350
- continue
351
- if token in ENV_OPTIONS_NO_VALUE or token.startswith(
352
- ENV_OPTIONS_INLINE_VALUE
353
- ):
354
- cursor += 1
355
- continue
356
- if token in ENV_OPTIONS_SEPARATE_VALUE:
357
- cursor += 2
358
- continue
359
- return False
451
+ if kind is None:
452
+ if "=" in token and not token.startswith(("=", "-")):
453
+ cursor += 1
454
+ continue
455
+ return False
456
+ cursor += 2 if kind == "separate-value" else 1
360
457
  return False
361
458
 
362
459