@codyswann/lisa 3.4.0 → 3.4.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 (84) hide show
  1. package/all/copy-overwrite/scripts/lisa-hooks/block-no-verify.sh +31 -0
  2. package/all/copy-overwrite/scripts/lisa-work-item.mjs +24 -2
  3. package/dist/codex/scripts/block-no-verify.sh +53 -4
  4. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  5. package/dist/core/upstream-evidence-manifest.js +9 -8
  6. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  7. package/package.json +1 -1
  8. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  9. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  10. package/plugins/lisa/.codex-plugin/skills/lisa-implement/SKILL.md +1 -1
  11. package/plugins/lisa/.codex-plugin/skills/lisa-track/SKILL.md +1 -1
  12. package/plugins/lisa/hooks/block-no-verify.agy.sh +53 -4
  13. package/plugins/lisa/hooks/block-no-verify.sh +31 -0
  14. package/plugins/lisa/rules/eager/tracked-work.md +1 -1
  15. package/plugins/lisa/rules/reference/tracked-work.md +4 -2
  16. package/plugins/lisa/skills/lisa-implement/SKILL.md +1 -1
  17. package/plugins/lisa/skills/lisa-track/SKILL.md +1 -1
  18. package/plugins/lisa-agy/hooks/block-no-verify.agy.sh +53 -4
  19. package/plugins/lisa-agy/plugin.json +1 -1
  20. package/plugins/lisa-agy/skills/lisa-implement/SKILL.md +1 -1
  21. package/plugins/lisa-agy/skills/lisa-track/SKILL.md +1 -1
  22. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  23. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  24. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  25. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  27. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  28. package/plugins/lisa-copilot/hooks/block-no-verify.sh +31 -0
  29. package/plugins/lisa-copilot/rules/eager/tracked-work.md +1 -1
  30. package/plugins/lisa-copilot/rules/reference/tracked-work.md +4 -2
  31. package/plugins/lisa-copilot/skills/lisa-implement/SKILL.md +1 -1
  32. package/plugins/lisa-copilot/skills/lisa-track/SKILL.md +1 -1
  33. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  34. package/plugins/lisa-cursor/hooks/block-no-verify.sh +31 -0
  35. package/plugins/lisa-cursor/rules/tracked-work-reference.mdc +4 -2
  36. package/plugins/lisa-cursor/rules/tracked-work.mdc +1 -1
  37. package/plugins/lisa-cursor/skills/lisa-implement/SKILL.md +1 -1
  38. package/plugins/lisa-cursor/skills/lisa-track/SKILL.md +1 -1
  39. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  41. package/plugins/lisa-expo-agy/plugin.json +1 -1
  42. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  44. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  45. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  46. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  47. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  51. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  52. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  54. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  55. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  56. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  57. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  59. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  60. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  61. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  62. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  63. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  64. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  65. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  66. package/plugins/lisa-rails-agy/plugin.json +1 -1
  67. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  68. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  69. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  70. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  71. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  72. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  73. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  74. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  75. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  76. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  77. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  78. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  79. package/plugins/src/base/hooks/block-no-verify.agy.sh +53 -4
  80. package/plugins/src/base/hooks/block-no-verify.sh +31 -0
  81. package/plugins/src/base/rules/eager/tracked-work.md +1 -1
  82. package/plugins/src/base/rules/reference/tracked-work.md +4 -2
  83. package/plugins/src/base/skills/lisa-implement/SKILL.md +1 -1
  84. package/plugins/src/base/skills/lisa-track/SKILL.md +1 -1
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "3.4.0",
3
+ "version": "3.4.1",
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": "3.4.0",
3
+ "version": "3.4.1",
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": "3.4.0",
3
+ "version": "3.4.1",
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": "3.4.0",
3
+ "version": "3.4.1",
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": "3.4.0",
3
+ "version": "3.4.1",
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": "3.4.0",
3
+ "version": "3.4.1",
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": "3.4.0",
3
+ "version": "3.4.1",
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": "3.4.0",
3
+ "version": "3.4.1",
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": "3.4.0",
3
+ "version": "3.4.1",
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": "3.4.0",
3
+ "version": "3.4.1",
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": "3.4.0",
3
+ "version": "3.4.1",
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": "3.4.0",
3
+ "version": "3.4.1",
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": "3.4.0",
3
+ "version": "3.4.1",
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": "3.4.0",
3
+ "version": "3.4.1",
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": "3.4.0",
3
+ "version": "3.4.1",
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": "3.4.0",
3
+ "version": "3.4.1",
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": "3.4.0",
3
+ "version": "3.4.1",
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": "3.4.0",
3
+ "version": "3.4.1",
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": "3.4.0",
3
+ "version": "3.4.1",
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": "3.4.0",
3
+ "version": "3.4.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": "3.4.0",
3
+ "version": "3.4.1",
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": "3.4.0",
3
+ "version": "3.4.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": "3.4.0",
3
+ "version": "3.4.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": "3.4.0",
3
+ "version": "3.4.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": "3.4.0",
3
+ "version": "3.4.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": "3.4.0",
3
+ "version": "3.4.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": "3.4.0",
3
+ "version": "3.4.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": "3.4.0",
3
+ "version": "3.4.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": "3.4.0",
3
+ "version": "3.4.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": "3.4.0",
3
+ "version": "3.4.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": "3.4.0",
3
+ "version": "3.4.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": "3.4.0",
3
+ "version": "3.4.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": "3.4.0",
3
+ "version": "3.4.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": "3.4.0",
3
+ "version": "3.4.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"
@@ -102,16 +102,65 @@ def disables_verification(token):
102
102
  and NO_VERIFY.startswith(token)
103
103
  )
104
104
 
105
+ # The only relocations that keep a repo's own hooks in play. Anything else —
106
+ # including "" and /dev/null, which are simply the two most obvious members of
107
+ # the blocked set rather than special cases — is refused.
108
+ PERMITTED_HOOKS_PATHS = {".husky", ".githooks"}
109
+
110
+
111
+ def is_permitted_hooks_path(value):
112
+ """Whether a core.hooksPath value relocates hooks rather than disabling them.
113
+
114
+ Args:
115
+ value: The raw core.hooksPath value as it appeared on the command line.
116
+
117
+ Returns:
118
+ True if the path is an established in-repo hooks directory.
119
+ """
120
+ cleaned = value.strip().strip("'\"")
121
+ if cleaned.startswith("./"):
122
+ cleaned = cleaned[2:]
123
+ return cleaned.rstrip("/") in PERMITTED_HOOKS_PATHS
124
+
125
+
105
126
  for i, token in enumerate(normalized_tokens):
106
127
  if disables_verification(token):
107
128
  sys.exit(1)
108
129
  if token == "HUSKY=0" or token.startswith("HUSKY_SKIP_HOOKS="):
109
130
  sys.exit(1)
110
- if token.startswith("core.hooksPath="):
111
- value = token.split("=", 1)[1]
112
- if value in ("", "/dev/null"):
131
+ # Allowlist the destinations, do not denylist the disabling ones: hooks are
132
+ # disabled just as completely by any directory that happens to contain none
133
+ # (`-c core.hooksPath=/tmp/empty`), so the set that DISABLES hooks is
134
+ # unbounded while the set that legitimately relocates them is tiny. Matched
135
+ # case-insensitively because git config names are.
136
+ lowered = token.lower()
137
+ if lowered.startswith("core.hookspath="):
138
+ if not is_permitted_hooks_path(token.split("=", 1)[1]):
139
+ sys.exit(1)
140
+ if lowered == "core.hookspath" and i + 1 < len(normalized_tokens):
141
+ if not is_permitted_hooks_path(normalized_tokens[i + 1]):
142
+ sys.exit(1)
143
+ # `--config-env=core.hooksPath=SOMEVAR` reads the path out of the named env
144
+ # var, so it is not in the command at all and cannot be allowlisted.
145
+ if lowered.startswith("--config-env="):
146
+ spec = token.split("=", 1)[1]
147
+ if spec.split("=", 1)[0].strip().lower() == "core.hookspath":
148
+ sys.exit(1)
149
+ # git also accepts `--config-env <name>=<envvar>` as two tokens. Guarding
150
+ # only the `=` spelling let the trailing `core.hooksPath=.husky` fall
151
+ # through to the allowlist above, which reads `.husky` as a path — but here
152
+ # it names an ENVIRONMENT VARIABLE, which can hold /dev/null. Checked at the
153
+ # `--config-env` token, which the loop reaches first.
154
+ if lowered == "--config-env" and i + 1 < len(normalized_tokens):
155
+ spec = normalized_tokens[i + 1]
156
+ if spec.split("=", 1)[0].strip().strip("'\"").lower() == "core.hookspath":
113
157
  sys.exit(1)
114
- if token == "core.hooksPath" and i + 1 < len(normalized_tokens) and normalized_tokens[i + 1] in ("", "/dev/null"):
158
+ # `GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=core.hooksPath
159
+ # GIT_CONFIG_VALUE_0=/dev/null git ...` sets the same command-scope config
160
+ # via env-var-style assignments. The index is arbitrary below
161
+ # GIT_CONFIG_COUNT, so it is matched as `\d+` rather than pinned to 0.
162
+ key_match = re.match(r"git_config_key_\d+=(.*)$", lowered, re.DOTALL)
163
+ if key_match and key_match.group(1).strip().strip("'\"") == "core.hookspath":
115
164
  sys.exit(1)
116
165
 
117
166
  sys.exit(0)
@@ -186,6 +186,37 @@ for i, token in enumerate(normalized_tokens):
186
186
  spec = token.split("=", 1)[1]
187
187
  if spec.split("=", 1)[0].strip().lower() == "core.hookspath":
188
188
  sys.exit(1)
189
+ # git accepts `--config-env <name>=<envvar>` as TWO tokens as well as one,
190
+ # and guarding only the `=` spelling was worse than missing the separate
191
+ # form outright: the trailing `core.hooksPath=.husky` then fell through to
192
+ # the allowlist above, which reads `.husky` as a PATH and permits it. But
193
+ # here it is an ENVIRONMENT VARIABLE NAME, and `env '.husky=/dev/null' git
194
+ # --config-env core.hooksPath=.husky` really does resolve hooksPath to
195
+ # /dev/null. The allowlist was being used as the bypass.
196
+ #
197
+ # Checked at the `--config-env` token, which the loop reaches first, so the
198
+ # refusal happens before the value token can be mistaken for a path.
199
+ if lowered == "--config-env" and i + 1 < len(normalized_tokens):
200
+ spec = normalized_tokens[i + 1]
201
+ if spec.split("=", 1)[0].strip().strip("'\"").lower() == "core.hookspath":
202
+ sys.exit(1)
203
+ # `GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=core.hooksPath
204
+ # GIT_CONFIG_VALUE_0=/dev/null git commit` sets command-scope config the
205
+ # same way `-c core.hooksPath=...` does — env-var-style assignments ahead of
206
+ # the invocation instead of a flag — so it disables every hook just as
207
+ # completely while matching none of the token shapes above. Upstream missed
208
+ # this until a downstream fork hardened its own copy against it, which is
209
+ # the one direction a guard must never be caught in.
210
+ #
211
+ # The index is matched as `\d+` rather than pinned to 0: git accepts any
212
+ # index below GIT_CONFIG_COUNT, so a single-index check is evaded by typing
213
+ # a 1. Refused outright, like --config-env=, because the path lives in a
214
+ # separate GIT_CONFIG_VALUE_<n> token that can be exported earlier,
215
+ # reordered, or left out entirely — there is nothing here to allowlist
216
+ # against.
217
+ key_match = re.match(r"git_config_key_\d+=(.*)$", lowered, re.DOTALL)
218
+ if key_match and key_match.group(1).strip().strip("'\"") == "core.hookspath":
219
+ sys.exit(1)
189
220
 
190
221
  sys.exit(0)
191
222
  PY
@@ -2,6 +2,6 @@
2
2
 
3
3
  Before the first durable project mutation (code, tests, config, docs, committed research/plans/findings, commits, or PRs), establish exactly one live tracker leaf through `lisa-track`. Read-only discussion and orientation are exempt only while they produce no durable artifact.
4
4
 
5
- The mandatory order is: live-validate an explicit ref, or conservatively search and create exactly one valid leaf through `lisa-tracker-write` when no unique match exists; idempotently claim it through `lisa-tracker-claim`; then persist and verify the worktree-local binding with `node scripts/lisa-work-item.mjs bind <ref>`. A tracker that answers no, and any claim or binding failure, blocks durable work; a tracker that cannot be reached does not block a commit — the offline checks still run, the skip is loud on stderr, and the required `Work-Item Traceability` check re-runs the live checks with credentials before anything merges.
5
+ The mandatory order is: live-validate an explicit ref, or conservatively search and create exactly one valid leaf through `lisa-tracker-write` when no unique match exists; idempotently claim it through `lisa-tracker-claim`; then persist and verify the worktree-local binding with `node scripts/lisa-work-item.mjs link <ref>`. A tracker that answers no, and any claim or binding failure, blocks durable work; a tracker that cannot be reached does not block a commit — the offline checks still run, the skip is loud on stderr, and the required `Work-Item Traceability` check re-runs the live checks with credentials before anything merges.
6
6
 
7
7
  Carry that canonical ref through the branch, every ordinary commit's `Work-Item:` trailer, the PR, usage/evidence, and `lisa-tracker-sync`. Hooks and CI never create tickets. Keep the binding through interruptions or blocked outcomes; run `node scripts/lisa-work-item.mjs clear` only after merge/deploy/verification, two-way linkage/evidence, and the tracker item have all reached true terminal completion.
@@ -9,9 +9,11 @@ Use `lisa-track` as the single entry point:
9
9
  1. An explicit ticket is live-read through `lisa-tracker-read` and rejected if it is missing, inaccessible, terminal, a container, outside the configured project, or outside the current repository.
10
10
  2. A plain-text request or specification file is searched conservatively within the configured project. Reuse only one uniquely high-confidence matching live leaf. If no unique match exists, create exactly one complete single-repository leaf through `lisa-tracker-write`; never create a thin placeholder or a container.
11
11
  3. Idempotently claim the resolved leaf through `lisa-tracker-claim`, which reuses the vendor build-intake claim semantics and post-read verifies the claimed-or-later state.
12
- 4. Before any durable repository work, persist the canonical reference with `node scripts/lisa-work-item.mjs bind <ref>` and verify the worktree-local binding.
12
+ 4. Before any durable repository work, persist the canonical reference with `node scripts/lisa-work-item.mjs link <ref>` and verify the worktree-local binding.
13
13
 
14
- The sequence is strict: **live validate/create -> claim -> bind -> durable work**. A tracker answer of no, and any claim or binding failure, blocks the work. A tracker that cannot be reached `gh` absent, or its credential refused does not block a commit: the offline checks still run, the skip is loud on stderr, and the required `Work-Item Traceability` check re-runs the live checks with credentials before anything merges. Any other tracker failure still blocks. Tool presence or stale session text is not access.
14
+ `link` is the spelling to use. `bind` is accepted as a permanent alias for the identical operation, but some agent harnesses Claude Code's worktree isolation among them refuse any command line containing the bare token `bind`, because it names a shell builtin that evaluates a string. Inside an isolated worktree that refusal makes the `bind` spelling unrunnable, so reach for `link` and never work around a blocked binding by hand-writing `Work-Item:` trailers.
15
+
16
+ The sequence is strict: **live validate/create -> claim -> link -> durable work**. A tracker answer of no, and any claim or binding failure, blocks the work. A tracker that cannot be reached — `gh` absent, or its credential refused — does not block a commit: the offline checks still run, the skip is loud on stderr, and the required `Work-Item Traceability` check re-runs the live checks with credentials before anything merges. Any other tracker failure still blocks. Tool presence or stale session text is not access.
15
17
 
16
18
  ## One canonical identity
17
19
 
@@ -64,7 +64,7 @@ The input-resolver invokes `lisa-track $ARGUMENTS` and owns its complete resolve
64
64
  - **Bind before durable work:** only after the verified claim, run:
65
65
 
66
66
  ```bash
67
- node scripts/lisa-work-item.mjs bind <canonical-ref>
67
+ node scripts/lisa-work-item.mjs link <canonical-ref>
68
68
  ```
69
69
 
70
70
  Require a successful readback of that worktree-local binding. On detached HEAD, `branch: null` is the expected pending binding; after branch creation the mandatory `attach-branch` step below must replace it before any commit. Tracker or binding failure stops the flow; never continue untracked.
@@ -47,7 +47,7 @@ This is intentionally conservative: ambiguity creates one explicit work item ins
47
47
  2. Persist only the canonical reference in worktree-local machine state:
48
48
 
49
49
  ```bash
50
- node scripts/lisa-work-item.mjs bind <canonical-ref>
50
+ node scripts/lisa-work-item.mjs link <canonical-ref>
51
51
  ```
52
52
 
53
53
  3. Read the binding back through `node scripts/lisa-work-item.mjs current` and require it to equal the canonical reference. If binding fails, stop before durable project work.