@codyswann/lisa 4.4.16 → 4.4.18

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 (73) hide show
  1. package/all/copy-overwrite/scripts/lisa-hooks/block-direct-issue-create.sh +53 -13
  2. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  3. package/dist/core/lisa-owned-hash-ledger.js +3 -0
  4. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  5. package/dist/core/upstream-evidence-manifest.js +8 -8
  6. package/package.json +1 -1
  7. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  8. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  9. package/plugins/lisa/hooks/block-direct-issue-create.sh +53 -13
  10. package/plugins/lisa/hooks/threshold-ratchet-compare.mjs +7 -0
  11. package/plugins/lisa/hooks/threshold-ratchet-families.mjs +53 -0
  12. package/plugins/lisa-agy/hooks/block-direct-issue-create.sh +53 -13
  13. package/plugins/lisa-agy/plugin.json +1 -1
  14. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  15. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  16. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  17. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  18. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  19. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  20. package/plugins/lisa-copilot/hooks/block-direct-issue-create.sh +53 -13
  21. package/plugins/lisa-copilot/hooks/threshold-ratchet-compare.mjs +7 -0
  22. package/plugins/lisa-copilot/hooks/threshold-ratchet-families.mjs +53 -0
  23. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  24. package/plugins/lisa-cursor/hooks/block-direct-issue-create.sh +53 -13
  25. package/plugins/lisa-cursor/hooks/threshold-ratchet-compare.mjs +7 -0
  26. package/plugins/lisa-cursor/hooks/threshold-ratchet-families.mjs +53 -0
  27. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  28. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  29. package/plugins/lisa-expo-agy/plugin.json +1 -1
  30. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  31. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  32. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  33. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  34. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  35. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  37. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  38. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  39. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  40. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  44. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  45. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  47. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  49. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  50. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  52. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  54. package/plugins/lisa-rails-agy/plugin.json +1 -1
  55. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  59. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  60. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  63. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  64. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  65. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  66. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  67. package/plugins/src/base/hooks/block-direct-issue-create.sh +53 -13
  68. package/plugins/src/base/hooks/threshold-ratchet-compare.mjs +7 -0
  69. package/plugins/src/base/hooks/threshold-ratchet-families.mjs +53 -0
  70. package/rails/copy-overwrite/scripts/threshold-ratchet-compare.mjs +7 -0
  71. package/rails/copy-overwrite/scripts/threshold-ratchet-families.mjs +53 -0
  72. package/typescript/copy-overwrite/scripts/threshold-ratchet-compare.mjs +7 -0
  73. package/typescript/copy-overwrite/scripts/threshold-ratchet-families.mjs +53 -0
@@ -392,13 +392,21 @@ POST_PAYLOAD_FLAGS = {
392
392
  # read as an endpoint: it is data being sent, not the address being posted to.
393
393
  PAYLOAD_VALUE_FLAGS = {"-f", "-F", "--raw-field", "--field"}
394
394
 
395
- GITHUB_ISSUES_PATH = re.compile(r"repos/[^/\s]+/[^/\s]+/issues/?$")
395
+ # Matched against a token's PATH COMPONENT, never the raw argument — see
396
+ # `endpoint_path`. The `$` anchor is load-bearing and stays: without it
397
+ # `repos/o/r/issues/123/comments` reads as a creation, which is a different
398
+ # operation this guard must not refuse. The segment classes exclude `?` and
399
+ # `#` so the anchor cannot be reached past a decoration even if some future
400
+ # caller forgets to parse first.
401
+ GITHUB_ISSUES_PATH = re.compile(r"repos/[^/\s?#]+/[^/\s?#]+/issues/?$")
396
402
  GITHUB_ISSUES_URL = re.compile(r"api\.github\.com/repos/[^/\s]+/[^/\s]+/issues")
397
403
  # The repository a creation is ADDRESSED at, which decides whose ready role
398
404
  # answers for it. `gh` accepts the flag before or after the subcommand and in
399
405
  # either spelling, and the REST paths carry the same pair positionally.
400
406
  REPO_FLAGS = {"--repo", "-R"}
401
- GITHUB_ISSUES_PATH_REPO = re.compile(r"repos/([^/\s]+)/([^/\s]+)/issues/?$")
407
+ GITHUB_ISSUES_PATH_REPO = re.compile(
408
+ r"repos/([^/\s?#]+)/([^/\s?#]+)/issues/?$"
409
+ )
402
410
  GITHUB_ISSUES_URL_REPO = re.compile(
403
411
  r"api\.github\.com/repos/([^/\s]+)/([^/\s]+)/issues"
404
412
  )
@@ -666,8 +674,33 @@ def is_write_request(args):
666
674
  return False
667
675
 
668
676
 
669
- def endpoint_tokens(args, pattern):
670
- """Tokens naming an API endpoint, excluding payload values.
677
+ def endpoint_path(token):
678
+ """The path component of an endpoint-shaped argument.
679
+
680
+ An endpoint is a URL, and a URL is not its path: `?query` and `#fragment`
681
+ are separate components that address the SAME resource. Comparing the raw
682
+ argument against a path pattern therefore recognised a URL SHAPE rather
683
+ than an endpoint, and `repos/o/r/issues?foo=1` — the identical request —
684
+ was classified as a non-creation and allowed (#2939).
685
+
686
+ Trailing whitespace is stripped for the same reason: `"repos/o/r/issues "`
687
+ survives shlex as one token and addresses the same endpoint, but defeats an
688
+ end-anchored comparison just as a query string does.
689
+
690
+ Args:
691
+ token: One argument, possibly a decorated endpoint.
692
+
693
+ Returns:
694
+ The token with any fragment, query, and surrounding whitespace removed.
695
+ """
696
+ # Fragment first: it is the LAST component of a URL, so `path?q#f` yields
697
+ # `path?q` here and `path` after the query split, while a malformed
698
+ # `path#a?b` still collapses to `path` rather than keeping `a?b`.
699
+ return token.split("#", 1)[0].split("?", 1)[0].strip()
700
+
701
+
702
+ def endpoint_paths(args, pattern):
703
+ """Endpoint path components matching a pattern, excluding payload values.
671
704
 
672
705
  Scans every token rather than a filtered positional list, because a BOOLEAN
673
706
  flag has no value to skip and filtering swallowed the endpoint behind one:
@@ -675,21 +708,28 @@ def endpoint_tokens(args, pattern):
675
708
  behind `--silent`. Payload values are excluded the other way, so
676
709
  `-f path=repos/o/r/issues` is not mistaken for the address being posted to.
677
710
 
711
+ That payload exclusion is tested on the PATH, not the raw token, and the
712
+ order matters: a query string carries `=`, so testing the raw token skipped
713
+ `repos/o/r/issues?foo=1` before the pattern ever ran. Two independent
714
+ mechanisms — this filter and the pattern's end anchor — hid the same
715
+ creation, which is why fixing only the anchor would not have closed it.
716
+
678
717
  Args:
679
718
  args: A command's arguments.
680
- pattern: The endpoint regex.
719
+ pattern: The endpoint regex, written against a path component.
681
720
 
682
721
  Returns:
683
- Matching endpoint tokens.
722
+ The matching path components, decoration removed.
684
723
  """
685
724
  found = []
686
725
  for index, token in enumerate(args):
687
- if "=" in token:
726
+ path = endpoint_path(token)
727
+ if "=" in path:
688
728
  continue
689
729
  if index > 0 and args[index - 1] in PAYLOAD_VALUE_FLAGS:
690
730
  continue
691
- if pattern.search(token):
692
- found.append(token)
731
+ if pattern.search(path):
732
+ found.append(path)
693
733
  return found
694
734
 
695
735
 
@@ -715,7 +755,7 @@ def creation_signature(name, args):
715
755
  if "api" in args:
716
756
  if GRAPHQL_CREATE.search(joined):
717
757
  return "gh api graphql issue creation"
718
- if endpoint_tokens(args, GITHUB_ISSUES_PATH) and is_write_request(args):
758
+ if endpoint_paths(args, GITHUB_ISSUES_PATH) and is_write_request(args):
719
759
  return "gh api POST .../issues"
720
760
  return None
721
761
 
@@ -823,7 +863,7 @@ def target_repository(args):
823
863
  Read only from positions that actually reach the created item: a flag
824
864
  before the end-of-options marker, or the endpoint the write is posted to.
825
865
  A `-f repo=o/r` payload field is data being SENT, not the address being
826
- posted to, and `endpoint_tokens` already excludes it.
866
+ posted to, and `endpoint_paths` already excludes it.
827
867
 
828
868
  Args:
829
869
  args: A creating command's arguments.
@@ -840,8 +880,8 @@ def target_repository(args):
840
880
  head, value = token.split("=", 1)
841
881
  if head in REPO_FLAGS:
842
882
  return normalise_repo(value)
843
- for token in endpoint_tokens(scoped, GITHUB_ISSUES_PATH):
844
- match = GITHUB_ISSUES_PATH_REPO.search(token)
883
+ for path in endpoint_paths(scoped, GITHUB_ISSUES_PATH):
884
+ match = GITHUB_ISSUES_PATH_REPO.search(path)
845
885
  if match:
846
886
  return normalise_repo("%s/%s" % (match.group(1), match.group(2)))
847
887
  for token in scoped:
@@ -1 +1 @@
1
- {"version":3,"file":"lisa-owned-hash-ledger.d.ts","sourceRoot":"","sources":["../../src/core/lisa-owned-hash-ledger.ts"],"names":[],"mappings":"AACA,6EAA6E;AAE7E;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,EAAE,QAAQ,CAC3C,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CA+lBjC,CAAC"}
1
+ {"version":3,"file":"lisa-owned-hash-ledger.d.ts","sourceRoot":"","sources":["../../src/core/lisa-owned-hash-ledger.ts"],"names":[],"mappings":"AACA,6EAA6E;AAE7E;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,EAAE,QAAQ,CAC3C,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAkmBjC,CAAC"}
@@ -391,6 +391,7 @@ export const LISA_OWNED_HASH_LEDGER = Object.freeze({
391
391
  "014510942610f36b17f006dee4b96c7737abad3e3acc4f5b416ab6d52403c793",
392
392
  "17c442bf60259d8183c7359bc54f992e8b7f305798704af1ed33f3e22e1a6006",
393
393
  "22184f1dd1b96e818741bd4ae659446299535d7ce594817155edebac4172a7ba",
394
+ "2e030d5a394d3edb48c391db49661fb3d45545c85f88ea03d1ab07ad3787c089",
394
395
  "60a4f94ec671b2372f7492680ab327d97aff686588ce85791f54e0fbd098b0ca",
395
396
  "63c2f9b54ea30997905bc6e17709dd1300436204ac82ad16717d7cc215af262b",
396
397
  "698131242f9ea27ea00e864d4b302f4ccc4a24d1383cb8ca9f0b17b565796197",
@@ -601,6 +602,7 @@ export const LISA_OWNED_HASH_LEDGER = Object.freeze({
601
602
  "scripts/threshold-ratchet-compare.mjs": Object.freeze([
602
603
  "4535a145c5c5cbee13bdf970bc91d390a264043604e607288cdd6bf28de56192",
603
604
  "67b5769dde341d06799c7a49c1fbcd46d92df1268177cc575e704e5a8a2d3096",
605
+ "874f0792beab000939d480c1a0547ce4dd351421b4e5f0fbb495aae246ab85c2",
604
606
  "8bc4b379d7057b2fecf9cb35820c39efad0a65df7df49073786f996cc2a74810",
605
607
  "90affbeaed0d65c032dccfc0bd4a4b26eda291f6b61aa8b12599f41842452e0a",
606
608
  "b5e064971bc29a052ee3757c24696c2fd8c2cd83cd3200a2420dba52351c395c",
@@ -608,6 +610,7 @@ export const LISA_OWNED_HASH_LEDGER = Object.freeze({
608
610
  "cf99167b05d210afad01fb41fc4aed548c66ee0e9a7c4decb8afa1f180eb5640",
609
611
  ]),
610
612
  "scripts/threshold-ratchet-families.mjs": Object.freeze([
613
+ "47d44b2bca383ae395b4e415e06c97a127327ab13762ee95b8c43d0198639bbb",
611
614
  "8fa58cc7276add0b2edf1de92bdcc32d81d840811ef0614ddc724010b59a888c",
612
615
  "93190f926689725418c1ec9eae15c55910b128cff6e3cb10185e466c7b90cc4f",
613
616
  "db14245ed89b483912af287bdee917a7a921dc21bb29b49be37fc799c05c413f",
@@ -1 +1 @@
1
- {"version":3,"file":"lisa-owned-hash-ledger.js","sourceRoot":"","sources":["../../src/core/lisa-owned-hash-ledger.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lisa-owned-hash-ledger.js","sourceRoot":"","sources":["../../src/core/lisa-owned-hash-ledger.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,6EAA6E;AAE7E;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAE/B,MAAM,CAAC,MAAM,CAAC;IAChB,wBAAwB,EAAE,MAAM,CAAC,MAAM,CAAC;QACtC,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,0BAA0B,EAAE,MAAM,CAAC,MAAM,CAAC;QACxC,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,0BAA0B,EAAE,MAAM,CAAC,MAAM,CAAC;QACxC,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,0BAA0B,EAAE,MAAM,CAAC,MAAM,CAAC;QACxC,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,0BAA0B,EAAE,MAAM,CAAC,MAAM,CAAC;QACxC,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,+BAA+B,EAAE,MAAM,CAAC,MAAM,CAAC;QAC7C,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,uBAAuB,EAAE,MAAM,CAAC,MAAM,CAAC;QACrC,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,wBAAwB,EAAE,MAAM,CAAC,MAAM,CAAC;QACtC,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,wBAAwB,EAAE,MAAM,CAAC,MAAM,CAAC;QACtC,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,0BAA0B,EAAE,MAAM,CAAC,MAAM,CAAC;QACxC,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,yBAAyB,EAAE,MAAM,CAAC,MAAM,CAAC;QACvC,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,gCAAgC,EAAE,MAAM,CAAC,MAAM,CAAC;QAC9C,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,oCAAoC,EAAE,MAAM,CAAC,MAAM,CAAC;QAClD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,gCAAgC,EAAE,MAAM,CAAC,MAAM,CAAC;QAC9C,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,sCAAsC,EAAE,MAAM,CAAC,MAAM,CAAC;QACpD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,2CAA2C,EAAE,MAAM,CAAC,MAAM,CAAC;QACzD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,wCAAwC,EAAE,MAAM,CAAC,MAAM,CAAC;QACtD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,qCAAqC,EAAE,MAAM,CAAC,MAAM,CAAC;QACnD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,yCAAyC,EAAE,MAAM,CAAC,MAAM,CAAC;QACvD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,uCAAuC,EAAE,MAAM,CAAC,MAAM,CAAC;QACrD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,+BAA+B,EAAE,MAAM,CAAC,MAAM,CAAC;QAC7C,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,wCAAwC,EAAE,MAAM,CAAC,MAAM,CAAC;QACtD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,mCAAmC,EAAE,MAAM,CAAC,MAAM,CAAC;QACjD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,oCAAoC,EAAE,MAAM,CAAC,MAAM,CAAC;QAClD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,+BAA+B,EAAE,MAAM,CAAC,MAAM,CAAC;QAC7C,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,mCAAmC,EAAE,MAAM,CAAC,MAAM,CAAC;QACjD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,mCAAmC,EAAE,MAAM,CAAC,MAAM,CAAC;QACjD,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,oCAAoC,EAAE,MAAM,CAAC,MAAM,CAAC;QAClD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,sCAAsC,EAAE,MAAM,CAAC,MAAM,CAAC;QACpD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,sCAAsC,EAAE,MAAM,CAAC,MAAM,CAAC;QACpD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,mCAAmC,EAAE,MAAM,CAAC,MAAM,CAAC;QACjD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,wBAAwB,EAAE,MAAM,CAAC,MAAM,CAAC;QACtC,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,iDAAiD,EAAE,MAAM,CAAC,MAAM,CAAC;QAC/D,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,oDAAoD,EAAE,MAAM,CAAC,MAAM,CAAC;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,gDAAgD,EAAE,MAAM,CAAC,MAAM,CAAC;QAC9D,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,uCAAuC,EAAE,MAAM,CAAC,MAAM,CAAC;QACrD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,gDAAgD,EAAE,MAAM,CAAC,MAAM,CAAC;QAC9D,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,yCAAyC,EAAE,MAAM,CAAC,MAAM,CAAC;QACvD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,qCAAqC,EAAE,MAAM,CAAC,MAAM,CAAC;QACnD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,wCAAwC,EAAE,MAAM,CAAC,MAAM,CAAC;QACtD,kEAAkE;KACnE,CAAC;IACF,2BAA2B,EAAE,MAAM,CAAC,MAAM,CAAC;QACzC,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,8BAA8B,EAAE,MAAM,CAAC,MAAM,CAAC;QAC5C,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,mCAAmC,EAAE,MAAM,CAAC,MAAM,CAAC;QACjD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,4BAA4B,EAAE,MAAM,CAAC,MAAM,CAAC;QAC1C,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,kCAAkC,EAAE,MAAM,CAAC,MAAM,CAAC;QAChD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,4BAA4B,EAAE,MAAM,CAAC,MAAM,CAAC;QAC1C,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,4BAA4B,EAAE,MAAM,CAAC,MAAM,CAAC;QAC1C,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,wCAAwC,EAAE,MAAM,CAAC,MAAM,CAAC;QACtD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,sDAAsD,EAAE,MAAM,CAAC,MAAM,CAAC;QACpE,kEAAkE;KACnE,CAAC;IACF,oDAAoD,EAAE,MAAM,CAAC,MAAM,CAAC;QAClE,kEAAkE;KACnE,CAAC;IACF,uCAAuC,EAAE,MAAM,CAAC,MAAM,CAAC;QACrD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,wCAAwC,EAAE,MAAM,CAAC,MAAM,CAAC;QACtD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;CACH,CAAC,CAAC;AACH,sEAAsE"}
@@ -16,7 +16,7 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
16
16
  "all/copy-overwrite/scripts/lisa-environment-prepare.mjs": "63879152ebb67f289e900167daf035f2d03d7773c6e110ed5ab708c95417c55c",
17
17
  "all/copy-overwrite/scripts/lisa-floor-collisions.mjs": "41060648b4394d417528f4f560a52f296b4df5b6ec8a5633e08afe4588b6a088",
18
18
  "all/copy-overwrite/scripts/lisa-gates.mjs": "bff724776d5818f5dba71078ef964e9436fa44eeb1c3f8d55974ce11f8e80a13",
19
- "all/copy-overwrite/scripts/lisa-hooks/block-direct-issue-create.sh": "17c442bf60259d8183c7359bc54f992e8b7f305798704af1ed33f3e22e1a6006",
19
+ "all/copy-overwrite/scripts/lisa-hooks/block-direct-issue-create.sh": "2e030d5a394d3edb48c391db49661fb3d45545c85f88ea03d1ab07ad3787c089",
20
20
  "all/copy-overwrite/scripts/lisa-hooks/block-instruction-file-edits.sh": "3e709e1ec8a5843c00684bc477ad32ddab2c5fdb11f71d5aeec0c49609eaf025",
21
21
  "all/copy-overwrite/scripts/lisa-hooks/block-managed-file-edits.sh": "d3ef2562b718156912f0877f8a0668026f5966fcca43eb9e064aa57a4e9a4976",
22
22
  "all/copy-overwrite/scripts/lisa-hooks/block-no-verify.sh": "d18448d642f40d46f690a7c868ed39627cb10b0fdcbd5a9505c26d05163a95d7",
@@ -346,7 +346,7 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
346
346
  "plugins/src/base/commands/verify.md": "ffbc553ec86e77845da72b5b0eb0dbb2b5a93b781ac8a7dbb2ef0f31f38f7b96",
347
347
  "plugins/src/base/commands/wiki/install.md": "51392cf053c17edd549bfbaba5d19ce669dc79021aafa7cfa100324ad38de11f",
348
348
  "plugins/src/base/hooks/block-direct-issue-create.agy.sh": "2adaf15910b6d00e69c202d263d407a21b31c0afce0039c6c042e51c278d2325",
349
- "plugins/src/base/hooks/block-direct-issue-create.sh": "ccf9594392c6450afac82052f26803d405c939c9044e34f7248ca253a42570e7",
349
+ "plugins/src/base/hooks/block-direct-issue-create.sh": "9a62b9648a4ac0f5812429546b56802efd86594d79c4a726884a73c16eed2593",
350
350
  "plugins/src/base/hooks/block-instruction-file-edits.agy.sh": "aa249cae53caeb3e0fb6d6af114e2756084f45a2896332fb063a9f20e4902125",
351
351
  "plugins/src/base/hooks/block-instruction-file-edits.sh": "d47314b66d6ce85f77d6e058f861eede4462b2b0a33d54e82ff1c931167ec3f7",
352
352
  "plugins/src/base/hooks/block-managed-file-edits.sh": "9b566bd1ff465147955300ce66b75c866db461a04dc67866c22bb928c757a616",
@@ -368,8 +368,8 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
368
368
  "plugins/src/base/hooks/setup-jira-cli.sh": "b55988c2a9a74c4dda08f85c269d34527555cac8f023f6ffea6fd20e2498b7c6",
369
369
  "plugins/src/base/hooks/shell-write-nudge.sh": "69839af423f8792b1e52c71097316c3264425553031627c0a2f9409a9d5becd0",
370
370
  "plugins/src/base/hooks/sonar-secrets.sh": "e37c8db517dff5cce357bacdd1316643bfb823c8ef5df44bbc983d3107619356",
371
- "plugins/src/base/hooks/threshold-ratchet-compare.mjs": "13808dd202fbd7539ee1ea198b7998d9912e93389d3faf6920c428eb6a857e5e",
372
- "plugins/src/base/hooks/threshold-ratchet-families.mjs": "8fa58cc7276add0b2edf1de92bdcc32d81d840811ef0614ddc724010b59a888c",
371
+ "plugins/src/base/hooks/threshold-ratchet-compare.mjs": "2ae57ea1eb0a0199559a17ee69186953f41115986a276e641ff8b3070e2f9fa6",
372
+ "plugins/src/base/hooks/threshold-ratchet-families.mjs": "d9c8086113d5e549476a1e6b6921c2a3b2f331e5ef5ccead0e8a3111f69b957a",
373
373
  "plugins/src/base/hooks/threshold-ratchet.mjs": "8e8f5e3a11a786926ea9b26e0503c9d9479d7e68695147bfdd23de732f581a3d",
374
374
  "plugins/src/base/hooks/threshold-ratchet.sh": "b86f4d0b554e44fd119ad8a8920cd0ba6c9dbe779f7ee219d381cf0629453990",
375
375
  "plugins/src/base/hooks/ticket-sync-reminder.sh": "212f80bcdfd9e3ec2254987c5a7186d1d2d38065b330ddcdc631f76df7c4a6c0",
@@ -1050,8 +1050,8 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
1050
1050
  "rails/copy-overwrite/lefthook.yml": "3ae82d0a6ad86708d8ceaa1f9a3bbe12ef64e8fa12a0248bed5e3180bb431c68",
1051
1051
  "rails/copy-overwrite/scripts/check-threshold-ratchet.mjs": "47bc8b91e38535e694f43d9d3b76c4589ae2796e4ce9e875ab6b09a273e0c93a",
1052
1052
  "rails/copy-overwrite/scripts/lisa-clean-git-env.sh": "d15af6f13eedbca41046070972380e69fc0af8f7d903aac12b8644389b9a0c91",
1053
- "rails/copy-overwrite/scripts/threshold-ratchet-compare.mjs": "b5e064971bc29a052ee3757c24696c2fd8c2cd83cd3200a2420dba52351c395c",
1054
- "rails/copy-overwrite/scripts/threshold-ratchet-families.mjs": "f50e35d11295a836bd5b6d818aed6daea68ff70bdffbbdf9f67b09984a2628da",
1053
+ "rails/copy-overwrite/scripts/threshold-ratchet-compare.mjs": "874f0792beab000939d480c1a0547ce4dd351421b4e5f0fbb495aae246ab85c2",
1054
+ "rails/copy-overwrite/scripts/threshold-ratchet-families.mjs": "47d44b2bca383ae395b4e415e06c97a127327ab13762ee95b8c43d0198639bbb",
1055
1055
  "rails/copy-overwrite/sgconfig.yml": "ff5b62de42eb969a851fdc53ee6932a32ffe010b567ed2c62460ed454ad2a24f",
1056
1056
  "rails/create-only/.github/workflows/ci.yml": "924375bcfcb8c13f546a7e323cf5ad99cee1427d3ba90386680db16b981e5ab4",
1057
1057
  "rails/create-only/.github/workflows/deploy.yml": "11dc8b52947f6b1476a277d1fe5f532b398ae9cd4b8d0dc8cc09df3e4e4f77eb",
@@ -1192,8 +1192,8 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
1192
1192
  "typescript/copy-overwrite/scripts/lib/invoked-as-script.mjs": "fbb9b88fc85a3e22f21af39e1c17acf67ff83fc6b5a6cdc8081bde333c48faa7",
1193
1193
  "typescript/copy-overwrite/scripts/lisa-mutation.mjs": "20bc2e58a54d7ef3c99b91393b85aa2f59d42984cbcbdb0a710b2c8d12d46b39",
1194
1194
  "typescript/copy-overwrite/scripts/nightly-e2e-suites.schema.json": "bce579fc87a3ca892dc96f0366ef8afdc650a20015f4623f2561662ec7a1f6c8",
1195
- "typescript/copy-overwrite/scripts/threshold-ratchet-compare.mjs": "b5e064971bc29a052ee3757c24696c2fd8c2cd83cd3200a2420dba52351c395c",
1196
- "typescript/copy-overwrite/scripts/threshold-ratchet-families.mjs": "f50e35d11295a836bd5b6d818aed6daea68ff70bdffbbdf9f67b09984a2628da",
1195
+ "typescript/copy-overwrite/scripts/threshold-ratchet-compare.mjs": "874f0792beab000939d480c1a0547ce4dd351421b4e5f0fbb495aae246ab85c2",
1196
+ "typescript/copy-overwrite/scripts/threshold-ratchet-families.mjs": "47d44b2bca383ae395b4e415e06c97a127327ab13762ee95b8c43d0198639bbb",
1197
1197
  "typescript/copy-overwrite/sgconfig.yml": "ff5b62de42eb969a851fdc53ee6932a32ffe010b567ed2c62460ed454ad2a24f",
1198
1198
  "typescript/copy-overwrite/tsconfig.eslint.json": "8a8ae5e201b18887b8eeda5eb569747221695524d4193ea03b4338b97b7fa642",
1199
1199
  "typescript/copy-overwrite/tsconfig.json": "8f4257fcd2cfd4b23e83e0fdd4908d41ee8f1ae75bb95d632e653a0ac13d58e4",
package/package.json CHANGED
@@ -146,7 +146,7 @@
146
146
  "zod-validation-error": "^4.0.0"
147
147
  },
148
148
  "name": "@codyswann/lisa",
149
- "version": "4.4.16",
149
+ "version": "4.4.18",
150
150
  "description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
151
151
  "main": "dist/index.js",
152
152
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "4.4.16",
3
+ "version": "4.4.18",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "4.4.16",
3
+ "version": "4.4.18",
4
4
  "description": "Universal governance: agents, skills, commands, hooks, and rules for all projects.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -389,13 +389,21 @@ POST_PAYLOAD_FLAGS = {
389
389
  # read as an endpoint: it is data being sent, not the address being posted to.
390
390
  PAYLOAD_VALUE_FLAGS = {"-f", "-F", "--raw-field", "--field"}
391
391
 
392
- GITHUB_ISSUES_PATH = re.compile(r"repos/[^/\s]+/[^/\s]+/issues/?$")
392
+ # Matched against a token's PATH COMPONENT, never the raw argument — see
393
+ # `endpoint_path`. The `$` anchor is load-bearing and stays: without it
394
+ # `repos/o/r/issues/123/comments` reads as a creation, which is a different
395
+ # operation this guard must not refuse. The segment classes exclude `?` and
396
+ # `#` so the anchor cannot be reached past a decoration even if some future
397
+ # caller forgets to parse first.
398
+ GITHUB_ISSUES_PATH = re.compile(r"repos/[^/\s?#]+/[^/\s?#]+/issues/?$")
393
399
  GITHUB_ISSUES_URL = re.compile(r"api\.github\.com/repos/[^/\s]+/[^/\s]+/issues")
394
400
  # The repository a creation is ADDRESSED at, which decides whose ready role
395
401
  # answers for it. `gh` accepts the flag before or after the subcommand and in
396
402
  # either spelling, and the REST paths carry the same pair positionally.
397
403
  REPO_FLAGS = {"--repo", "-R"}
398
- GITHUB_ISSUES_PATH_REPO = re.compile(r"repos/([^/\s]+)/([^/\s]+)/issues/?$")
404
+ GITHUB_ISSUES_PATH_REPO = re.compile(
405
+ r"repos/([^/\s?#]+)/([^/\s?#]+)/issues/?$"
406
+ )
399
407
  GITHUB_ISSUES_URL_REPO = re.compile(
400
408
  r"api\.github\.com/repos/([^/\s]+)/([^/\s]+)/issues"
401
409
  )
@@ -663,8 +671,33 @@ def is_write_request(args):
663
671
  return False
664
672
 
665
673
 
666
- def endpoint_tokens(args, pattern):
667
- """Tokens naming an API endpoint, excluding payload values.
674
+ def endpoint_path(token):
675
+ """The path component of an endpoint-shaped argument.
676
+
677
+ An endpoint is a URL, and a URL is not its path: `?query` and `#fragment`
678
+ are separate components that address the SAME resource. Comparing the raw
679
+ argument against a path pattern therefore recognised a URL SHAPE rather
680
+ than an endpoint, and `repos/o/r/issues?foo=1` — the identical request —
681
+ was classified as a non-creation and allowed (#2939).
682
+
683
+ Trailing whitespace is stripped for the same reason: `"repos/o/r/issues "`
684
+ survives shlex as one token and addresses the same endpoint, but defeats an
685
+ end-anchored comparison just as a query string does.
686
+
687
+ Args:
688
+ token: One argument, possibly a decorated endpoint.
689
+
690
+ Returns:
691
+ The token with any fragment, query, and surrounding whitespace removed.
692
+ """
693
+ # Fragment first: it is the LAST component of a URL, so `path?q#f` yields
694
+ # `path?q` here and `path` after the query split, while a malformed
695
+ # `path#a?b` still collapses to `path` rather than keeping `a?b`.
696
+ return token.split("#", 1)[0].split("?", 1)[0].strip()
697
+
698
+
699
+ def endpoint_paths(args, pattern):
700
+ """Endpoint path components matching a pattern, excluding payload values.
668
701
 
669
702
  Scans every token rather than a filtered positional list, because a BOOLEAN
670
703
  flag has no value to skip and filtering swallowed the endpoint behind one:
@@ -672,21 +705,28 @@ def endpoint_tokens(args, pattern):
672
705
  behind `--silent`. Payload values are excluded the other way, so
673
706
  `-f path=repos/o/r/issues` is not mistaken for the address being posted to.
674
707
 
708
+ That payload exclusion is tested on the PATH, not the raw token, and the
709
+ order matters: a query string carries `=`, so testing the raw token skipped
710
+ `repos/o/r/issues?foo=1` before the pattern ever ran. Two independent
711
+ mechanisms — this filter and the pattern's end anchor — hid the same
712
+ creation, which is why fixing only the anchor would not have closed it.
713
+
675
714
  Args:
676
715
  args: A command's arguments.
677
- pattern: The endpoint regex.
716
+ pattern: The endpoint regex, written against a path component.
678
717
 
679
718
  Returns:
680
- Matching endpoint tokens.
719
+ The matching path components, decoration removed.
681
720
  """
682
721
  found = []
683
722
  for index, token in enumerate(args):
684
- if "=" in token:
723
+ path = endpoint_path(token)
724
+ if "=" in path:
685
725
  continue
686
726
  if index > 0 and args[index - 1] in PAYLOAD_VALUE_FLAGS:
687
727
  continue
688
- if pattern.search(token):
689
- found.append(token)
728
+ if pattern.search(path):
729
+ found.append(path)
690
730
  return found
691
731
 
692
732
 
@@ -712,7 +752,7 @@ def creation_signature(name, args):
712
752
  if "api" in args:
713
753
  if GRAPHQL_CREATE.search(joined):
714
754
  return "gh api graphql issue creation"
715
- if endpoint_tokens(args, GITHUB_ISSUES_PATH) and is_write_request(args):
755
+ if endpoint_paths(args, GITHUB_ISSUES_PATH) and is_write_request(args):
716
756
  return "gh api POST .../issues"
717
757
  return None
718
758
 
@@ -820,7 +860,7 @@ def target_repository(args):
820
860
  Read only from positions that actually reach the created item: a flag
821
861
  before the end-of-options marker, or the endpoint the write is posted to.
822
862
  A `-f repo=o/r` payload field is data being SENT, not the address being
823
- posted to, and `endpoint_tokens` already excludes it.
863
+ posted to, and `endpoint_paths` already excludes it.
824
864
 
825
865
  Args:
826
866
  args: A creating command's arguments.
@@ -837,8 +877,8 @@ def target_repository(args):
837
877
  head, value = token.split("=", 1)
838
878
  if head in REPO_FLAGS:
839
879
  return normalise_repo(value)
840
- for token in endpoint_tokens(scoped, GITHUB_ISSUES_PATH):
841
- match = GITHUB_ISSUES_PATH_REPO.search(token)
880
+ for path in endpoint_paths(scoped, GITHUB_ISSUES_PATH):
881
+ match = GITHUB_ISSUES_PATH_REPO.search(path)
842
882
  if match:
843
883
  return normalise_repo("%s/%s" % (match.group(1), match.group(2)))
844
884
  for token in scoped:
@@ -9,6 +9,7 @@
9
9
  import {
10
10
  extractAllowEntries,
11
11
  extractK6Constraints,
12
+ extractLighthouseAssertions,
12
13
  extractNumericLeaves,
13
14
  extractRubocopThresholds,
14
15
  extractStrykerConstraints,
@@ -296,6 +297,12 @@ export function compareFile(relPath, baselineText, currentText) {
296
297
  return compareStryker(relPath, base, current);
297
298
  case "k6":
298
299
  return compareK6(relPath, base, current);
300
+ case "lighthouse":
301
+ return compareConstraints(
302
+ relPath,
303
+ extractLighthouseAssertions(base),
304
+ extractLighthouseAssertions(current)
305
+ );
299
306
  case KIND_ALLOW_LIST:
300
307
  return compareAllowList(relPath, base, current);
301
308
  default:
@@ -77,8 +77,61 @@ export const FAMILIES = [
77
77
  match: /(^|\/)\.lisa\.config\.json$/,
78
78
  kind: "allow-list",
79
79
  },
80
+ {
81
+ id: "lighthouse",
82
+ match: /(^|\/)lighthouserc-config\.json$/,
83
+ kind: "lighthouse",
84
+ },
80
85
  ];
81
86
 
87
+ /**
88
+ * Which way each Lighthouse assertion key ratchets.
89
+ *
90
+ * Lighthouse mixes floors and ceilings in one file, so assigning one direction
91
+ * to the whole family would silently approve half of the possible weakenings.
92
+ * Unknown keys stay unwatched until their direction is explicit here.
93
+ * @type {Readonly<Record<string, "min"|"max">>}
94
+ */
95
+ export const LIGHTHOUSE_ASSERTION_DIRECTIONS = {
96
+ minScore: "min",
97
+ maxNumericValue: "max",
98
+ maxLength: "max",
99
+ };
100
+
101
+ /**
102
+ * Extract numeric Lighthouse assertions with a direction chosen per key.
103
+ *
104
+ * A malformed array is deliberately ignored instead of being walked as an
105
+ * object whose numeric indices look like audit names.
106
+ * @param {unknown} conf Parsed lighthouserc-config.json
107
+ * @returns {Map<string, { value: number, direction: "min"|"max" }>} Dotted
108
+ * `assertion.key` path to numeric constraint
109
+ */
110
+ export function extractLighthouseAssertions(conf) {
111
+ const out = new Map();
112
+ const assertions =
113
+ conf && typeof conf === "object" && !Array.isArray(conf)
114
+ ? /** @type {Record<string, unknown>} */ (conf).assertions
115
+ : undefined;
116
+ if (
117
+ !assertions ||
118
+ typeof assertions !== "object" ||
119
+ Array.isArray(assertions)
120
+ ) {
121
+ return out;
122
+ }
123
+ for (const [audit, spec] of Object.entries(assertions)) {
124
+ if (!spec || typeof spec !== "object" || Array.isArray(spec)) continue;
125
+ for (const [key, value] of Object.entries(spec)) {
126
+ const direction = LIGHTHOUSE_ASSERTION_DIRECTIONS[key];
127
+ if (direction && typeof value === "number" && Number.isFinite(value)) {
128
+ out.set(`${audit}.${key}`, { value, direction });
129
+ }
130
+ }
131
+ }
132
+ return out;
133
+ }
134
+
82
135
  /**
83
136
  * Find the family a repo-relative path belongs to.
84
137
  * @param {string} relPath Repo-relative path (forward slashes)
@@ -389,13 +389,21 @@ POST_PAYLOAD_FLAGS = {
389
389
  # read as an endpoint: it is data being sent, not the address being posted to.
390
390
  PAYLOAD_VALUE_FLAGS = {"-f", "-F", "--raw-field", "--field"}
391
391
 
392
- GITHUB_ISSUES_PATH = re.compile(r"repos/[^/\s]+/[^/\s]+/issues/?$")
392
+ # Matched against a token's PATH COMPONENT, never the raw argument — see
393
+ # `endpoint_path`. The `$` anchor is load-bearing and stays: without it
394
+ # `repos/o/r/issues/123/comments` reads as a creation, which is a different
395
+ # operation this guard must not refuse. The segment classes exclude `?` and
396
+ # `#` so the anchor cannot be reached past a decoration even if some future
397
+ # caller forgets to parse first.
398
+ GITHUB_ISSUES_PATH = re.compile(r"repos/[^/\s?#]+/[^/\s?#]+/issues/?$")
393
399
  GITHUB_ISSUES_URL = re.compile(r"api\.github\.com/repos/[^/\s]+/[^/\s]+/issues")
394
400
  # The repository a creation is ADDRESSED at, which decides whose ready role
395
401
  # answers for it. `gh` accepts the flag before or after the subcommand and in
396
402
  # either spelling, and the REST paths carry the same pair positionally.
397
403
  REPO_FLAGS = {"--repo", "-R"}
398
- GITHUB_ISSUES_PATH_REPO = re.compile(r"repos/([^/\s]+)/([^/\s]+)/issues/?$")
404
+ GITHUB_ISSUES_PATH_REPO = re.compile(
405
+ r"repos/([^/\s?#]+)/([^/\s?#]+)/issues/?$"
406
+ )
399
407
  GITHUB_ISSUES_URL_REPO = re.compile(
400
408
  r"api\.github\.com/repos/([^/\s]+)/([^/\s]+)/issues"
401
409
  )
@@ -663,8 +671,33 @@ def is_write_request(args):
663
671
  return False
664
672
 
665
673
 
666
- def endpoint_tokens(args, pattern):
667
- """Tokens naming an API endpoint, excluding payload values.
674
+ def endpoint_path(token):
675
+ """The path component of an endpoint-shaped argument.
676
+
677
+ An endpoint is a URL, and a URL is not its path: `?query` and `#fragment`
678
+ are separate components that address the SAME resource. Comparing the raw
679
+ argument against a path pattern therefore recognised a URL SHAPE rather
680
+ than an endpoint, and `repos/o/r/issues?foo=1` — the identical request —
681
+ was classified as a non-creation and allowed (#2939).
682
+
683
+ Trailing whitespace is stripped for the same reason: `"repos/o/r/issues "`
684
+ survives shlex as one token and addresses the same endpoint, but defeats an
685
+ end-anchored comparison just as a query string does.
686
+
687
+ Args:
688
+ token: One argument, possibly a decorated endpoint.
689
+
690
+ Returns:
691
+ The token with any fragment, query, and surrounding whitespace removed.
692
+ """
693
+ # Fragment first: it is the LAST component of a URL, so `path?q#f` yields
694
+ # `path?q` here and `path` after the query split, while a malformed
695
+ # `path#a?b` still collapses to `path` rather than keeping `a?b`.
696
+ return token.split("#", 1)[0].split("?", 1)[0].strip()
697
+
698
+
699
+ def endpoint_paths(args, pattern):
700
+ """Endpoint path components matching a pattern, excluding payload values.
668
701
 
669
702
  Scans every token rather than a filtered positional list, because a BOOLEAN
670
703
  flag has no value to skip and filtering swallowed the endpoint behind one:
@@ -672,21 +705,28 @@ def endpoint_tokens(args, pattern):
672
705
  behind `--silent`. Payload values are excluded the other way, so
673
706
  `-f path=repos/o/r/issues` is not mistaken for the address being posted to.
674
707
 
708
+ That payload exclusion is tested on the PATH, not the raw token, and the
709
+ order matters: a query string carries `=`, so testing the raw token skipped
710
+ `repos/o/r/issues?foo=1` before the pattern ever ran. Two independent
711
+ mechanisms — this filter and the pattern's end anchor — hid the same
712
+ creation, which is why fixing only the anchor would not have closed it.
713
+
675
714
  Args:
676
715
  args: A command's arguments.
677
- pattern: The endpoint regex.
716
+ pattern: The endpoint regex, written against a path component.
678
717
 
679
718
  Returns:
680
- Matching endpoint tokens.
719
+ The matching path components, decoration removed.
681
720
  """
682
721
  found = []
683
722
  for index, token in enumerate(args):
684
- if "=" in token:
723
+ path = endpoint_path(token)
724
+ if "=" in path:
685
725
  continue
686
726
  if index > 0 and args[index - 1] in PAYLOAD_VALUE_FLAGS:
687
727
  continue
688
- if pattern.search(token):
689
- found.append(token)
728
+ if pattern.search(path):
729
+ found.append(path)
690
730
  return found
691
731
 
692
732
 
@@ -712,7 +752,7 @@ def creation_signature(name, args):
712
752
  if "api" in args:
713
753
  if GRAPHQL_CREATE.search(joined):
714
754
  return "gh api graphql issue creation"
715
- if endpoint_tokens(args, GITHUB_ISSUES_PATH) and is_write_request(args):
755
+ if endpoint_paths(args, GITHUB_ISSUES_PATH) and is_write_request(args):
716
756
  return "gh api POST .../issues"
717
757
  return None
718
758
 
@@ -820,7 +860,7 @@ def target_repository(args):
820
860
  Read only from positions that actually reach the created item: a flag
821
861
  before the end-of-options marker, or the endpoint the write is posted to.
822
862
  A `-f repo=o/r` payload field is data being SENT, not the address being
823
- posted to, and `endpoint_tokens` already excludes it.
863
+ posted to, and `endpoint_paths` already excludes it.
824
864
 
825
865
  Args:
826
866
  args: A creating command's arguments.
@@ -837,8 +877,8 @@ def target_repository(args):
837
877
  head, value = token.split("=", 1)
838
878
  if head in REPO_FLAGS:
839
879
  return normalise_repo(value)
840
- for token in endpoint_tokens(scoped, GITHUB_ISSUES_PATH):
841
- match = GITHUB_ISSUES_PATH_REPO.search(token)
880
+ for path in endpoint_paths(scoped, GITHUB_ISSUES_PATH):
881
+ match = GITHUB_ISSUES_PATH_REPO.search(path)
842
882
  if match:
843
883
  return normalise_repo("%s/%s" % (match.group(1), match.group(2)))
844
884
  for token in scoped:
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "4.4.16",
3
+ "version": "4.4.18",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "4.4.16",
3
+ "version": "4.4.18",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "4.4.16",
3
+ "version": "4.4.18",
4
4
  "description": "AWS CDK-specific Lisa plugin.",
5
5
  "author": {
6
6
  "name": "Cody Swann"