@codyswann/lisa 2.290.0 → 2.292.0

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 (98) hide show
  1. package/all/merge/.claude/settings.json +1 -1
  2. package/cdk/merge/.claude/settings.json +1 -1
  3. package/dist/core/config-field-validation.d.ts +19 -0
  4. package/dist/core/config-field-validation.d.ts.map +1 -0
  5. package/dist/core/config-field-validation.js +69 -0
  6. package/dist/core/config-field-validation.js.map +1 -0
  7. package/dist/core/deploy-status-sync.d.ts +88 -0
  8. package/dist/core/deploy-status-sync.d.ts.map +1 -0
  9. package/dist/core/deploy-status-sync.js +301 -0
  10. package/dist/core/deploy-status-sync.js.map +1 -0
  11. package/dist/core/project-config.d.ts +3 -0
  12. package/dist/core/project-config.d.ts.map +1 -1
  13. package/dist/core/project-config.js +4 -40
  14. package/dist/core/project-config.js.map +1 -1
  15. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  16. package/dist/core/upstream-evidence-manifest.js +21 -13
  17. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  18. package/dist/opencode/plugin-templates/parity-safety-net.sh +299 -35
  19. package/dist/sync/registry.d.ts.map +1 -1
  20. package/dist/sync/registry.js +3 -6
  21. package/dist/sync/registry.js.map +1 -1
  22. package/expo/merge/.claude/settings.json +1 -1
  23. package/harper-fabric/merge/.claude/settings.json +1 -1
  24. package/nestjs/merge/.claude/settings.json +1 -1
  25. package/package.json +1 -1
  26. package/phaser/merge/.claude/settings.json +1 -1
  27. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  28. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  29. package/plugins/lisa/.codex-plugin/skills/lisa-parity-safety-net-rules/SKILL.md +41 -5
  30. package/plugins/lisa/hooks/parity-safety-net.sh +299 -35
  31. package/plugins/lisa/rules/eager/config-resolution.md +8 -0
  32. package/plugins/lisa/rules/reference/config-resolution.md +47 -0
  33. package/plugins/lisa/skills/lisa-parity-safety-net-rules/SKILL.md +41 -5
  34. package/plugins/lisa-agy/hooks/parity-safety-net.sh +299 -35
  35. package/plugins/lisa-agy/plugin.json +1 -1
  36. package/plugins/lisa-agy/skills/lisa-parity-safety-net-rules/SKILL.md +41 -5
  37. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  38. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  39. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  40. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-copilot/hooks/parity-safety-net.sh +299 -35
  44. package/plugins/lisa-copilot/rules/eager/config-resolution.md +8 -0
  45. package/plugins/lisa-copilot/rules/reference/config-resolution.md +47 -0
  46. package/plugins/lisa-copilot/skills/lisa-parity-safety-net-rules/SKILL.md +41 -5
  47. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-cursor/hooks/parity-safety-net.sh +299 -35
  49. package/plugins/lisa-cursor/rules/config-resolution-reference.mdc +47 -0
  50. package/plugins/lisa-cursor/rules/config-resolution.mdc +8 -0
  51. package/plugins/lisa-cursor/skills/lisa-parity-safety-net-rules/SKILL.md +41 -5
  52. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  54. package/plugins/lisa-expo-agy/plugin.json +1 -1
  55. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  59. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  60. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  63. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  64. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  65. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  66. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  68. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  69. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  70. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  71. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  72. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  73. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  74. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  75. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  76. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  77. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  78. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  79. package/plugins/lisa-rails-agy/plugin.json +1 -1
  80. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  81. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  82. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  83. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  84. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  85. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  86. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  87. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  88. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  89. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  90. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  91. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  92. package/plugins/src/base/hooks/parity-safety-net.sh +299 -35
  93. package/plugins/src/base/rules/eager/config-resolution.md +8 -0
  94. package/plugins/src/base/rules/reference/config-resolution.md +47 -0
  95. package/plugins/src/base/skills/lisa-parity-safety-net-rules/SKILL.md +41 -5
  96. package/rails/merge/.claude/settings.json +1 -1
  97. package/scripts/install-claude-plugins.sh +9 -6
  98. package/typescript/merge/.claude/settings.json +1 -1
@@ -1,17 +1,50 @@
1
1
  #!/usr/bin/env bash
2
2
  # PreToolUse hook for Bash: a safety net that blocks destructive shell commands
3
3
  # before they run. Lisa-native reimplementation of the upstream
4
- # `safety-net@cc-marketplace` plugin's PreToolUse Bash-guard (parity work, issue
5
- # #1059). It does NOT port upstream code — it re-expresses the behavior in Lisa's
6
- # hook conventions, modeled on block-no-verify.sh.
4
+ # `safety-net@cc-marketplace` plugin's PreToolUse Bash-guard (parity work,
5
+ # issues #1059 and #1960). It does NOT port upstream code — it re-expresses the
6
+ # behavior in Lisa's hook conventions, modeled on block-no-verify.sh.
7
7
  #
8
8
  # It reads the hook stdin JSON, inspects the proposed Bash command, and EXITS
9
9
  # NON-ZERO (2) to BLOCK when a known-destructive pattern matches:
10
- # - `rm -rf /` (recursive forced delete of a root / home / wildcard path)
11
- # - force-pushing a protected branch (main/master/production/release)
12
- # - `git reset --hard` while the working tree is dirty (would discard work)
13
- # - dropping or truncating a database/schema/table
14
- # Otherwise it exits 0 and the command proceeds.
10
+ # - `rm -rf` of a root / home / wildcard path (quote-aware boundaries, so
11
+ # `bash -c "rm -rf /"` and interpreter one-liners are caught too; the rm
12
+ # guards also match path-prefixed invocations like `/bin/rm` and `./rm`)
13
+ # - `rm -rf` of the cwd (`.`), a `..`-traversal path, a `~/`-anchored path,
14
+ # an absolute path outside the project (with a /tmp, /var/tmp, $TMPDIR
15
+ # allowance), a `$VAR` target other than $TMPDIR, or ANY recursive forced
16
+ # delete while cwd is $HOME
17
+ # - force-pushing a protected branch (main/master/production/prod/release) —
18
+ # feature-branch force-push stays allowed (sanctioned rebase workflow;
19
+ # deliberate divergence from upstream's any-branch block). Every git guard
20
+ # sees through leading git GLOBAL options (`-C <path>`, `-c <k>=<v>`,
21
+ # `--git-dir[=…]`, `--no-pager`, …), so `git -C /path <destructive>` cannot
22
+ # dodge the subcommand anchor
23
+ # - `git reset --hard` / `--merge` while the working tree is dirty. Deliberate
24
+ # divergence: upstream blocks unconditionally; Lisa allows clean-tree resets.
25
+ # Residual risk (documented, accepted): the dirty check runs in the hook's
26
+ # cwd at hook time, so a `cd elsewhere && git reset --hard` evades it.
27
+ # - `git checkout` discards (`--`, `-f/--force`, `--pathspec-from-file`,
28
+ # bare `.` — the bare-`.` block exceeds upstream)
29
+ # - `git switch --discard-changes` / `-f/--force`
30
+ # - `git restore` touching the worktree (allowed only with `--staged` and
31
+ # without `--worktree`)
32
+ # - `git stash drop` / `git stash clear`
33
+ # - `git clean` with force and no dry-run (`-n`/`--dry-run` anywhere wins)
34
+ # - `git branch -D` (or `-d` + `-f` in any spelling)
35
+ # - `git tag -d`, `git reflog delete`, `git worktree remove --force`
36
+ # - `find ... -delete`, `find ... -exec rm -rf`, `xargs ... rm -rf`
37
+ # - disk destroyers: `dd of=/dev/...`, `mkfs ... /dev/...`, `shred`
38
+ # - dropping or truncating a database/schema/table (Lisa-only guard)
39
+ # Otherwise it exits 0 and the command proceeds. Malformed hook input fails
40
+ # CLOSED: any parse error exits 2 (a non-2 exit would be a non-blocking hook
41
+ # error in Claude Code, silently failing open).
42
+ #
43
+ # Known accepted false-positive class: this is a text scan, not a shell engine,
44
+ # so display commands quoting a destructive string (`echo "docs about rm -rf /"`)
45
+ # can match. Upstream exempts those via an engine-only DISPLAY_COMMANDS list a
46
+ # grep hook cannot replicate. Workaround: quote-break the string or use the
47
+ # gh-writer heredoc form, whose payload is stripped before the guards run.
15
48
  #
16
49
  # Operators extend the built-in rules with a project-local rule file — one
17
50
  # extended-regex (ERE) per line, blank lines and `#` comments ignored — managed
@@ -20,6 +53,13 @@
20
53
  # ${CLAUDE_PROJECT_DIR:-$PWD}/.claude/safety-net-rules.txt
21
54
  set -euo pipefail
22
55
 
56
+ # Fail CLOSED on any unexpected error (malformed JSON, missing jq, …): exit 2 so
57
+ # the tool call is denied instead of surfacing a non-blocking hook warning.
58
+ # Deliberately NOT `set -E`: errtrace would propagate this trap into command
59
+ # substitutions (e.g. the heredoc parser call, whose non-zero exit codes are
60
+ # meaningful protocol) and rewrite their status to 2 before it can be read.
61
+ trap 'printf "%s\n" "Blocked by safety-net: hook failed while parsing its input; denying fail-closed." >&2; exit 2' ERR
62
+
23
63
  input="$(cat)"
24
64
 
25
65
  tool_name="$(printf '%s' "$input" | jq -r '.tool_name // empty')"
@@ -90,22 +130,154 @@ case "$command_str" in
90
130
  ;;
91
131
  esac
92
132
 
133
+ # matches / matches_cs run an ERE against the guarded command text. matches is
134
+ # case-insensitive (the default for these guards); matches_cs is case-SENSITIVE
135
+ # for guards where flag case is meaningful (`git branch -d` vs `-D`).
136
+ matches() {
137
+ printf '%s' "$command_for_guards" | grep -Eiq -- "$1"
138
+ }
139
+ matches_cs() {
140
+ printf '%s' "$command_for_guards" | grep -Eq -- "$1"
141
+ }
142
+
143
+ # Normalize bash line-continuations (a trailing backslash + newline → space)
144
+ # before segmenting the command. Without this, "git push --force origin
145
+ # \<newline>main" splits into a segment matching --force but not `main`, letting a
146
+ # protected force-push slip past. Uses awk (POSIX) instead of a GNU-only
147
+ # `sed ':a;N;$!ba;…'`, which errors on BSD sed (macOS) and there silently no-ops.
148
+ normalized_command_str="$(printf '%s' "$command_for_guards" \
149
+ | awk '{ if (sub(/\\$/, "")) printf "%s ", $0; else print }')"
150
+
151
+ # Shared ERE fragments. GIT_TOKENS walks over intermediate argv tokens without
152
+ # crossing a statement separator, so a flag in a LATER statement can never be
153
+ # attributed to an earlier git subcommand.
154
+ readonly GIT_TOKENS='([[:space:]]+[^;&|[:space:]]+)*[[:space:]]+'
155
+ # Git GLOBAL options (`-C <path>`, `-c <k>=<v>`, `--git-dir[=…]`, `--no-pager`,
156
+ # …) legally sit between `git` and its subcommand, so every subcommand guard
157
+ # consumes them — otherwise `git -C /path checkout -- f` dodges the anchor
158
+ # (issue #1960 security review F1). Shape: zero or more dash-led tokens, each
159
+ # optionally followed by ONE non-dash value token, which covers both the
160
+ # `--git-dir=/x` and `--git-dir /x` spellings without naming every option.
161
+ readonly GIT_GLOBAL_OPTS='(-[^;&|[:space:]]+([[:space:]]+[^-;&|[:space:]][^;&|[:space:]]*)?[[:space:]]+)*'
162
+ # Anchor for every git subcommand guard: word-bounded `git`, whitespace, then
163
+ # any run of global options. Callers append the subcommand name directly.
164
+ readonly GIT_CMD='(^|[^[:alnum:]_-])git[[:space:]]+'"$GIT_GLOBAL_OPTS"
165
+ # An rm invocation: bare `rm` or a path whose basename is exactly `rm`
166
+ # (`/bin/rm`, `./rm`) — issue #1960 security review F2. The optional prefix must
167
+ # END IN `/` immediately before `rm`, so charm/confirm/informant/rmdir never
168
+ # match. The preceding-char class still excludes `.`, `/`, and `-` to keep
169
+ # `--rm`-style flags and `foo.rm` names out.
170
+ readonly RM_CMD='(^|[^[:alnum:]_./-])([[:alnum:]_./-]*/)?rm'
171
+ # rm invoked with BOTH a recursive and a force flag — clustered (-rf/-fr, any
172
+ # extra letters) or split, in either order. The split gate pairs ANY recursive
173
+ # form (short cluster containing r, or --recursive) with ANY force form (short
174
+ # cluster containing f, or --force), so mixed spellings like `rm -r --force /`
175
+ # and `rm --recursive -f /` cannot slip between the short/short and long/long
176
+ # alternations (PR #1976 review).
177
+ readonly RM_RF_CLUSTER="$RM_CMD"'([[:space:]]+-[[:alnum:]-]+)*[[:space:]]+(-[[:alnum:]]*r[[:alnum:]]*f|-[[:alnum:]]*f[[:alnum:]]*r)([[:space:]]|$)'
178
+ readonly RM_RF_SPLIT="$RM_CMD"'(([[:space:]][^;&|]*)?[[:space:]](-[[:alnum:]]*r[[:alnum:]]*|--recursive)([[:space:]][^;&|]*)?[[:space:]](-[[:alnum:]]*f[[:alnum:]]*|--force)([[:space:]]|$)|([[:space:]][^;&|]*)?[[:space:]](-[[:alnum:]]*f[[:alnum:]]*|--force)([[:space:]][^;&|]*)?[[:space:]](-[[:alnum:]]*r[[:alnum:]]*|--recursive)([[:space:]]|$))'
179
+
93
180
  # 1. Recursive forced delete (`rm -rf`) of a filesystem root, home, or top-level
94
- # wildcard. Two gates ANDed: the command must invoke `rm` with BOTH a
181
+ # wildcard. Two gates ANDed: the statement must invoke `rm` with BOTH a
95
182
  # recursive and a force flag, AND name a catastrophic target. Splitting the
96
183
  # flag check from the target check keeps each regex legible and testable.
97
- if printf '%s' "$command_for_guards" \
98
- | grep -Eiq '(^|[^[:alnum:]_./-])rm([[:space:]]+-[[:alnum:]-]+)*[[:space:]]+(-[[:alnum:]]*r[[:alnum:]]*f|-[[:alnum:]]*f[[:alnum:]]*r)([[:space:]]|$)' \
99
- || printf '%s' "$command_for_guards" \
100
- | grep -Eiq '(^|[^[:alnum:]_./-])rm[[:space:]].*(-r\b.*[[:space:]]-f\b|-f\b.*[[:space:]]-r\b|--recursive\b.*--force\b|--force\b.*--recursive\b)'; then
101
- if printf '%s' "$command_for_guards" \
102
- | grep -Eq '([[:space:]]|=)(/|/\*|/\.\*?|~|~/\*?|\$HOME\b|\$\{HOME\}|\*)([[:space:]]|/?\*?$)'; then
184
+ # The target boundary classes include quote characters (issue #1960): without
185
+ # them, `bash -c "rm -rf /"` and interpreter one-liners like
186
+ # `python -c "… os.system('rm -rf /')"` slip through because the target is
187
+ # quote-adjacent instead of space-bounded.
188
+ # Both gates run PER STATEMENT inside the shared rm loop below (quality
189
+ # review S1): a harmless `/` in a LATER statement (`rm -rf build && cd /`)
190
+ # is never attributed to the rm in an earlier one.
191
+ qc="'\""
192
+ readonly RM_CATASTROPHIC_TARGET='([[:space:]='"$qc"'])(/|/\*|/\.\*?|~|~/\*?|\$HOME\b|\$\{HOME\}|\*)([[:space:]'"$qc"']|/?\*?['"$qc"']?$)'
193
+
194
+ # 1b. rm target hardening (issue #1960). For every statement that invokes rm
195
+ # with recursive+force flags, additionally block when:
196
+ # - cwd is $HOME (any target is one argument away from wiping home), or
197
+ # - the target is the cwd itself (`.` / `./`), or
198
+ # - the target traverses out via `..`, or
199
+ # - the target is home-anchored (`~/…` — the shell expands it to $HOME at
200
+ # execution time, so it is always outside the project), or
201
+ # - the target is an absolute path outside the project — with an allowance
202
+ # for /tmp, /var/tmp, and $TMPDIR — or
203
+ # - the target is a `$VAR` expansion other than the sanctioned $TMPDIR.
204
+ # Globbing is disabled around the token walk so a literal `*` in the command
205
+ # is never expanded against the hook's own cwd.
206
+ project_dir="${CLAUDE_PROJECT_DIR:-$PWD}"
207
+ tmp_dir_allow="${TMPDIR:-/tmp}"
208
+ tmp_dir_allow="${tmp_dir_allow%/}"
209
+ [ -n "$tmp_dir_allow" ] || tmp_dir_allow="/tmp"
210
+ while IFS= read -r rm_stmt; do
211
+ if ! printf '%s' "$rm_stmt" | grep -Eiq -- "$RM_RF_CLUSTER" \
212
+ && ! printf '%s' "$rm_stmt" | grep -Eiq -- "$RM_RF_SPLIT"; then
213
+ continue
214
+ fi
215
+ # Guard 1: catastrophic target named in the SAME statement as the rm -rf.
216
+ if printf '%s' "$rm_stmt" | grep -Eq -- "$RM_CATASTROPHIC_TARGET"; then
103
217
  block "recursive forced delete of a root, home, or wildcard path (rm -rf)"
104
218
  fi
105
- fi
219
+ # Physical-path comparison (pwd -P): on macOS $HOME or the cwd may arrive via
220
+ # a symlink (/var → /private/var), and a string compare would miss the match.
221
+ if [ -n "${HOME:-}" ] \
222
+ && [ "$(pwd -P)" = "$(cd -- "$HOME" 2>/dev/null && pwd -P)" ]; then
223
+ block "recursive forced delete while the working directory is \$HOME (cd into a project first)"
224
+ fi
225
+ set -f
226
+ seen_rm=0
227
+ for raw_token in $rm_stmt; do
228
+ token="${raw_token#\"}"
229
+ token="${token#\'}"
230
+ token="${token%\"}"
231
+ token="${token%\'}"
232
+ if [ "$seen_rm" -eq 0 ]; then
233
+ # Path-prefixed spellings (`/bin/rm`, `./rm`) are still rm (F2).
234
+ case "$token" in
235
+ rm | */rm) seen_rm=1 ;;
236
+ esac
237
+ continue
238
+ fi
239
+ case "$token" in
240
+ -*) continue ;;
241
+ . | ./)
242
+ set +f
243
+ block "recursive forced delete of the current directory (rm -rf .)"
244
+ ;;
245
+ .. | ../* | */.. | */../*)
246
+ set +f
247
+ block "recursive forced delete of a path outside the project (.. traversal)"
248
+ ;;
249
+ '~' | '~'/*)
250
+ set +f
251
+ block "recursive forced delete of a home-anchored path (~/…) outside the project"
252
+ ;;
253
+ /*)
254
+ case "$token" in
255
+ "$project_dir" | "$project_dir"/* | /tmp | /tmp/* | /var/tmp | /var/tmp/* | "$tmp_dir_allow" | "$tmp_dir_allow"/*) : ;;
256
+ *)
257
+ set +f
258
+ block "recursive forced delete of an absolute path outside the project (only the project, /tmp, /var/tmp, and \$TMPDIR are allowed)"
259
+ ;;
260
+ esac
261
+ ;;
262
+ *'$'*)
263
+ case "$token" in
264
+ '$TMPDIR' | '$TMPDIR'/* | '${TMPDIR}' | '${TMPDIR}'/*) : ;;
265
+ *)
266
+ set +f
267
+ block "recursive forced delete of a variable-expanded target (unset or mistyped variables can point anywhere; \$TMPDIR is the only sanctioned dynamic target)"
268
+ ;;
269
+ esac
270
+ ;;
271
+ esac
272
+ done
273
+ set +f
274
+ done < <(printf '%s' "$normalized_command_str" | tr '&|;' '\n' \
275
+ | grep -Ei -- "$RM_CMD"'([[:space:]]|$)' || true)
106
276
 
107
277
  # 2. Force-pushing a protected branch. `--force-with-lease` is the safe,
108
- # non-clobbering alternative and is intentionally NOT blocked.
278
+ # non-clobbering alternative and is intentionally NOT blocked. Deliberate
279
+ # divergence from upstream (which blocks force-push on ANY branch):
280
+ # feature-branch force-push is a sanctioned rebase-and-push agent workflow.
109
281
  #
110
282
  # The force flag AND the protected-branch name must appear in the SAME
111
283
  # `git push` statement. Checking them independently over the whole command is
@@ -116,14 +288,6 @@ fi
116
288
  # (`;`, `&&`, `||`, `|`, newlines), keep only the `git push` segments, and
117
289
  # inspect each in isolation — a real `git push --force origin main` still
118
290
  # matches, while a feature-branch push next to `[ -f ]`/`--base main` passes.
119
- # Normalize bash line-continuations (a trailing backslash + newline → space)
120
- # before segmenting the command. Without this, "git push --force origin
121
- # \<newline>main" splits into a segment matching --force but not `main`, letting a
122
- # protected force-push slip past. Uses awk (POSIX) instead of a GNU-only
123
- # `sed ':a;N;$!ba;…'`, which errors on BSD sed (macOS) and there silently no-ops.
124
- normalized_command_str="$(printf '%s' "$command_for_guards" \
125
- | awk '{ if (sub(/\\$/, "")) printf "%s ", $0; else print }')"
126
-
127
291
  while IFS= read -r push_stmt; do
128
292
  if printf '%s' "$push_stmt" \
129
293
  | grep -Eiq '(--force([[:space:]]|=|$)|[[:space:]]-f([[:space:]]|$))' \
@@ -133,25 +297,125 @@ while IFS= read -r push_stmt; do
133
297
  block "force-pushing a protected branch (use --force-with-lease, or push a feature branch)"
134
298
  fi
135
299
  done < <(printf '%s' "$normalized_command_str" | tr '&|;' '\n' \
136
- | grep -Ei '(^|[^[:alnum:]_-])git[[:space:]]+push\b')
300
+ | grep -Ei -- "${GIT_CMD}push\b" || true)
137
301
 
138
- # 3. `git reset --hard` while the working tree has uncommitted changes — this
139
- # silently discards them. Only blocks when the tree is actually dirty, so a
140
- # clean-tree reset (a legitimate workflow) still passes.
141
- if printf '%s' "$command_for_guards" | grep -Eiq '(^|[^[:alnum:]_-])git[[:space:]]+reset\b.*--hard\b'; then
302
+ # 3. `git reset --hard` / `git reset --merge` while the working tree has
303
+ # uncommitted changes — both silently discard them. Only blocks when the tree
304
+ # is actually dirty, so a clean-tree reset (a legitimate workflow) passes.
305
+ # Deliberate divergence from upstream's unconditional block; the accepted
306
+ # residual risk (dirty check runs at hook time in the hook's cwd) is
307
+ # documented in the header.
308
+ if matches "${GIT_CMD}"'reset\b.*--(hard|merge)\b'; then
142
309
  if git rev-parse --is-inside-work-tree >/dev/null 2>&1 \
143
310
  && [ -n "$(git status --porcelain 2>/dev/null)" ]; then
144
- block "git reset --hard on a dirty working tree would discard uncommitted changes (stash or commit first)"
311
+ block "git reset --hard/--merge on a dirty working tree would discard uncommitted changes (stash or commit first)"
312
+ fi
313
+ fi
314
+
315
+ # 4. `git checkout` worktree discards: the `--` pathspec form (with or without a
316
+ # ref), `-f/--force`, `--pathspec-from-file`, and bare `git checkout .`.
317
+ # Blocking bare `.` exceeds upstream (which allows any single positional) —
318
+ # issue #1960 names it explicitly: it discards the entire tree. Branch
319
+ # switches and creation (`-b`/`-B`) stay allowed.
320
+ readonly GIT_CHECKOUT="${GIT_CMD}checkout"
321
+ if matches "${GIT_CHECKOUT}${GIT_TOKENS}"'--([[:space:]]|$)' \
322
+ || matches "${GIT_CHECKOUT}${GIT_TOKENS}"'(-[[:alnum:]]*f[[:alnum:]]*|--force)([[:space:]]|=|$)' \
323
+ || matches "${GIT_CHECKOUT}"'[[:space:]][^;&|]*--pathspec-from-file' \
324
+ || matches "${GIT_CHECKOUT}"'[[:space:]]+\.(/)?([[:space:]]|$)'; then
325
+ block "git checkout discarding local changes (--, -f/--force, --pathspec-from-file, or bare .) — use git stash to preserve work first"
326
+ fi
327
+
328
+ # 5. `git switch` discards: `--discard-changes` and its `-f/--force` aliases.
329
+ if matches "${GIT_CMD}switch${GIT_TOKENS}"'(--discard-changes|--force|-f)([[:space:]]|=|$)'; then
330
+ block "git switch discarding local changes (--discard-changes/-f/--force)"
331
+ fi
332
+
333
+ # 6. `git restore` defaults to overwriting the WORKTREE — a silent discard. Only
334
+ # the pure staging-area form is safe: `--staged` present and `--worktree`
335
+ # absent. Two conditions, because an ERE has no lookahead: `--staged
336
+ # --worktree` still discards, so `--worktree` blocks regardless of `--staged`.
337
+ if matches "${GIT_CMD}"'restore([[:space:]]|$)'; then
338
+ if matches "${GIT_CMD}"'restore[^;&|]*--worktree' \
339
+ || ! matches "${GIT_CMD}"'restore[^;&|]*--staged'; then
340
+ block "git restore overwriting worktree files (only 'git restore --staged <path>' without --worktree is allowed)"
145
341
  fi
146
342
  fi
147
343
 
148
- # 4. Dropping or truncating a database / schema / table.
149
- if printf '%s' "$command_for_guards" \
150
- | grep -Eiq '\b(drop[[:space:]]+(database|schema|table)|truncate[[:space:]]+(table[[:space:]]+)?[[:alnum:]_."`]+)\b'; then
344
+ # 7. `git stash drop` / `git stash clear` destroy stashed work. push/pop/list/
345
+ # apply the safe alternatives the reset guard recommends — stay allowed.
346
+ if matches "${GIT_CMD}"'stash[[:space:]]+(drop|clear)([[:space:]]|$)'; then
347
+ block "git stash drop/clear destroys stashed work"
348
+ fi
349
+
350
+ # 8. `git clean` with a force flag wipes untracked files. A dry-run flag
351
+ # (`-n`/`--dry-run`) ANYWHERE wins — git itself performs no deletion under
352
+ # dry-run, so `git clean -fdn` is a safe preview.
353
+ readonly GIT_CLEAN="${GIT_CMD}clean"
354
+ if matches "${GIT_CLEAN}${GIT_TOKENS}"'(-[[:alnum:]]*f[[:alnum:]]*|--force)([[:space:]]|=|$)' \
355
+ && ! matches "${GIT_CLEAN}${GIT_TOKENS}"'(-[[:alnum:]]*n[[:alnum:]]*|--dry-run)([[:space:]]|=|$)'; then
356
+ block "git clean --force deletes untracked files (preview with git clean -n first)"
357
+ fi
358
+
359
+ # 9. `git branch` force-delete loses unmerged commits: `-D`, `-d` combined with
360
+ # `-f` (clustered or split), or `--delete` + `--force`. Case-SENSITIVE so the
361
+ # safe `-d` (which refuses unmerged work) and rename `-m` stay allowed.
362
+ readonly GIT_BRANCH="${GIT_CMD}branch"
363
+ if matches_cs "${GIT_BRANCH}${GIT_TOKENS}"'-[[:alnum:]]*D[[:alnum:]]*([[:space:]]|$)' \
364
+ || { matches_cs "${GIT_BRANCH}${GIT_TOKENS}"'-[[:alnum:]]*d[[:alnum:]]*([[:space:]]|$)' \
365
+ && matches_cs "${GIT_BRANCH}${GIT_TOKENS}"'-[[:alnum:]]*f[[:alnum:]]*([[:space:]]|$)'; } \
366
+ || { matches "${GIT_BRANCH}"'[^;&|]*--delete' && matches "${GIT_BRANCH}"'[^;&|]*--force'; }; then
367
+ block "git branch force-delete (-D) loses unmerged commits (use -d, which refuses unmerged work)"
368
+ fi
369
+
370
+ # 10. Cheap destructive-ref guards: `git tag -d` (tags are shared refs),
371
+ # `git reflog delete` (erases recovery history), and
372
+ # `git worktree remove --force` (discards a dirty worktree). Tag deletion is
373
+ # case-SENSITIVE so annotated-tag `-a` and message `-m` flags never match.
374
+ if matches_cs "${GIT_CMD}tag${GIT_TOKENS}"'(-[[:alnum:]]*d[[:alnum:]]*([[:space:]]|$)|--delete([[:space:]]|=|$))'; then
375
+ block "git tag -d deletes a shared ref"
376
+ fi
377
+ if matches "${GIT_CMD}"'reflog[[:space:]]+delete([[:space:]]|$)'; then
378
+ block "git reflog delete erases recovery history"
379
+ fi
380
+ if matches "${GIT_CMD}"'worktree[[:space:]]+remove[^;&|]*(--force([[:space:]]|=|$)|[[:space:]]-[[:alnum:]]*f[[:alnum:]]*([[:space:]]|$))'; then
381
+ block "git worktree remove --force discards a dirty worktree (remove without --force, which refuses dirty trees)"
382
+ fi
383
+
384
+ # 11. Deletion through find/xargs, where the target never appears as a literal
385
+ # argument: `find … -delete`, `find … -exec rm -rf`, and `xargs … rm -rf`
386
+ # (targets arrive from dynamic stdin — unauditable). Plain `rm` (no
387
+ # recursive+force) on find/xargs output stays allowed for normal cleanups.
388
+ if matches '(^|[^[:alnum:]_./-])find[[:space:]][^;&|]*[[:space:]]-delete([[:space:]]|$)'; then
389
+ block "find -delete removes files tree-wide (use -print to preview, or an explicit rm on reviewed paths)"
390
+ fi
391
+ if matches '(^|[^[:alnum:]_./-])find[[:space:]][^;&|]*-exec[[:space:]]+rm[[:space:]]+(-[[:alnum:]]*r[[:alnum:]]*f|-[[:alnum:]]*f[[:alnum:]]*r)([[:space:]]|$)'; then
392
+ block "find -exec rm -rf performs a recursive forced delete on unreviewed paths"
393
+ fi
394
+ if matches '(^|[^[:alnum:]_./-])xargs[[:space:]]([^;&|]*[[:space:]])?rm[[:space:]]+(-[[:alnum:]]*r[[:alnum:]]*f|-[[:alnum:]]*f[[:alnum:]]*r)([[:space:]]|$)'; then
395
+ block "xargs rm -rf performs a recursive forced delete on dynamic stdin input"
396
+ fi
397
+
398
+ # 12. Disk destroyers, always on (exceeds upstream, which only scans these
399
+ # inside interpreter one-liners): writing to a raw /dev node via dd,
400
+ # formatting a device with mkfs, and shred's unrecoverable overwrite.
401
+ # dd/mkfs against regular files (imaging) stays allowed.
402
+ if matches '(^|[^[:alnum:]_./-])dd[[:space:]]+([^;&|]*[[:space:]])?of=/dev/'; then
403
+ block "dd writing to a raw device (of=/dev/…) destroys it"
404
+ fi
405
+ if matches '(^|[^[:alnum:]_./-])mkfs(\.[[:alnum:]]+)?[[:space:]][^;&|]*/dev/'; then
406
+ block "mkfs formatting a device erases it"
407
+ fi
408
+ if matches '(^|[^[:alnum:]_./-])shred([[:space:]]|$)'; then
409
+ block "shred overwrites files unrecoverably"
410
+ fi
411
+
412
+ # 13. Dropping or truncating a database / schema / table (Lisa-only guard —
413
+ # upstream has no SQL protection; keep).
414
+ if matches '\b(drop[[:space:]]+(database|schema|table)|truncate[[:space:]]+(table[[:space:]]+)?[[:alnum:]_."`]+)\b'; then
151
415
  block "destructive SQL (DROP/TRUNCATE) detected"
152
416
  fi
153
417
 
154
- # 5. Project-local custom rules. Each non-comment line is an ERE; a match blocks.
418
+ # 14. Project-local custom rules. Each non-comment line is an ERE; a match blocks.
155
419
  rules_file="${SAFETY_NET_RULES_FILE:-${CLAUDE_PROJECT_DIR:-$PWD}/.claude/safety-net-rules.txt}"
156
420
  if [ -f "$rules_file" ]; then
157
421
  while IFS= read -r rule || [ -n "$rule" ]; do
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/sync/registry.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,8CAA8C;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,2EAA2E;IAC3E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,2EAA2E;AAC3E,MAAM,WAAW,aAAa;IAC5B,yDAAyD;IACzD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,QAAQ,CAAC,YAAY,EAAE,SAAS,CAAC;IACjC,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,SAAS,CAAC;IAClD;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACvD,uEAAuE;IACvE,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IAChD;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,sDAAsD;IACtD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,8DAA8D;AAC9D,MAAM,WAAW,WAAW;IAC1B,uCAAuC;IACvC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,4CAA4C;IAC5C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AASD,iDAAiD;AACjD,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;;GAGG;AACH,eAAO,MAAM,2BAA2B,EAAE,QAAQ,CAAC;IACjD,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC,CAAC;IAC5D,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC,CAAC;CAC5D,CAkCA,CAAC;AA6BF;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,aAAa,EA0JjD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,WAAW,EA0C/C,CAAC"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/sync/registry.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,8CAA8C;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,2EAA2E;IAC3E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,2EAA2E;AAC3E,MAAM,WAAW,aAAa;IAC5B,yDAAyD;IACzD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,QAAQ,CAAC,YAAY,EAAE,SAAS,CAAC;IACjC,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,SAAS,CAAC;IAClD;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACvD,uEAAuE;IACvE,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IAChD;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,sDAAsD;IACtD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,8DAA8D;AAC9D,MAAM,WAAW,WAAW;IAC1B,uCAAuC;IACvC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,4CAA4C;IAC5C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AASD,iDAAiD;AACjD,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;;GAGG;AACH,eAAO,MAAM,2BAA2B,EAAE,QAAQ,CAAC;IACjD,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC,CAAC;IAC5D,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC,CAAC;CAC5D,CAkCA,CAAC;AAyBF;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,aAAa,EA0JjD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,WAAW,EA0C/C,CAAC"}
@@ -10,6 +10,7 @@
10
10
  * completely missing.
11
11
  * @module sync/registry
12
12
  */
13
+ import { ENV_DONE_LABEL_DEFAULTS, JIRA_DONE_STATUS_DEFAULTS, } from "../core/deploy-status-sync.js";
13
14
  import { DEFAULT_PROJECT_RULES_FILE } from "../core/project-config.js";
14
15
  import { validateHealthSchedule } from "../health/contract.js";
15
16
  const WHEN_TRACKER_JIRA = "tracker=jira";
@@ -65,11 +66,7 @@ const BUILD_LABEL_DEFAULTS = {
65
66
  claimed: "status:in-progress",
66
67
  blocked: "status:blocked",
67
68
  human_needed: "human-needed",
68
- done: {
69
- dev: "status:on-dev",
70
- staging: "status:on-stg",
71
- production: "status:done",
72
- },
69
+ done: ENV_DONE_LABEL_DEFAULTS,
73
70
  };
74
71
  const PRD_LABEL_DEFAULTS = {
75
72
  draft: "prd-draft",
@@ -187,7 +184,7 @@ export const SYNC_REGISTRY = [
187
184
  claimed: "In Progress",
188
185
  review: "Code Review",
189
186
  blocked: "Blocked",
190
- done: { dev: "On Dev", staging: "On Stg", production: "Done" },
187
+ done: JIRA_DONE_STATUS_DEFAULTS,
191
188
  },
192
189
  relevantWhen: ["jira", WHEN_TRACKER_JIRA],
193
190
  description: "JIRA workflow status names per lifecycle role",
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/sync/registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/sync/registry.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,7 @@
5
5
  },
6
6
  "enabledPlugins": {
7
7
  "typescript-lsp@claude-plugins-official": true,
8
- "safety-net@cc-marketplace": true,
8
+ "safety-net@cc-marketplace": false,
9
9
  "code-simplifier@claude-plugins-official": true,
10
10
  "code-review@claude-plugins-official": true,
11
11
  "playwright@claude-plugins-official": true,
@@ -6,7 +6,7 @@
6
6
  "enabledPlugins": {
7
7
  "typescript-lsp@claude-plugins-official": true,
8
8
  "playwright@claude-plugins-official": true,
9
- "safety-net@cc-marketplace": true,
9
+ "safety-net@cc-marketplace": false,
10
10
  "code-simplifier@claude-plugins-official": true,
11
11
  "code-review@claude-plugins-official": true,
12
12
  "coderabbit@claude-plugins-official": true,
@@ -5,7 +5,7 @@
5
5
  },
6
6
  "enabledPlugins": {
7
7
  "typescript-lsp@claude-plugins-official": true,
8
- "safety-net@cc-marketplace": true,
8
+ "safety-net@cc-marketplace": false,
9
9
  "code-simplifier@claude-plugins-official": true,
10
10
  "code-review@claude-plugins-official": true,
11
11
  "coderabbit@claude-plugins-official": true,
package/package.json CHANGED
@@ -113,7 +113,7 @@
113
113
  "brace-expansion": ">=5.0.6"
114
114
  },
115
115
  "name": "@codyswann/lisa",
116
- "version": "2.290.0",
116
+ "version": "2.292.0",
117
117
  "description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
118
118
  "main": "dist/index.js",
119
119
  "exports": {
@@ -6,7 +6,7 @@
6
6
  "enabledPlugins": {
7
7
  "typescript-lsp@claude-plugins-official": true,
8
8
  "playwright@claude-plugins-official": true,
9
- "safety-net@cc-marketplace": true,
9
+ "safety-net@cc-marketplace": false,
10
10
  "code-simplifier@claude-plugins-official": true,
11
11
  "code-review@claude-plugins-official": true,
12
12
  "coderabbit@claude-plugins-official": true,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.290.0",
3
+ "version": "2.292.0",
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": "2.290.0",
3
+ "version": "2.292.0",
4
4
  "description": "Universal governance: agents, skills, commands, hooks, and rules for all projects.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -53,11 +53,47 @@ RULES_FILE="${SAFETY_NET_RULES_FILE:-${CLAUDE_PROJECT_DIR:-$PWD}/.claude/safety-
53
53
 
54
54
  ### Built-in guards (always on)
55
55
 
56
- 1. `rm -rf` of a filesystem root, `$HOME`/`~`, or a top-level wildcard.
57
- 2. Force-pushing a protected branch (`main`/`master`/`production`/`release`).
58
- `--force-with-lease` is intentionally allowed.
59
- 3. `git reset --hard` while the working tree is **dirty** (would discard work).
60
- 4. Destructive SQL — `DROP DATABASE/SCHEMA/TABLE`, `TRUNCATE TABLE`.
56
+ 1. `rm -rf` of a filesystem root, `$HOME`/`~`, or a top-level wildcard — with
57
+ quote-aware boundaries, so wrapper/interpreter forms like
58
+ `bash -c "rm -rf /"` and `python -c "… os.system('rm -rf /')"` match too.
59
+ Path-prefixed spellings (`/bin/rm`, `./rm`) count as `rm` for every rm
60
+ guard.
61
+ 2. `rm -rf` target hardening: the cwd itself (`.`/`./`), `..`-traversal paths,
62
+ home-anchored `~/…` paths, absolute paths outside the project (`/tmp`,
63
+ `/var/tmp`, and `$TMPDIR` are allowed), `$VAR` targets other than `$TMPDIR`,
64
+ and **any** recursive forced delete while the working directory is `$HOME`.
65
+ 3. Force-pushing a protected branch
66
+ (`main`/`master`/`production`/`prod`/`release`). `--force-with-lease` is
67
+ intentionally allowed, and so is force-pushing a feature branch (sanctioned
68
+ rebase workflow). Acceptable parity divergence: a refspec force-push
69
+ (`git push origin +main`) is not blocked — upstream 1.0.6 allows it too.
70
+ 4. `git reset --hard` / `git reset --merge` while the working tree is **dirty**
71
+ (would discard work). Clean-tree resets are intentionally allowed.
72
+ 5. `git checkout` discards: the `--` pathspec form (with or without a ref),
73
+ `-f`/`--force`, `--pathspec-from-file`, and bare `git checkout .`.
74
+ Branch switching and `-b`/`-B` creation stay allowed.
75
+ 6. `git switch --discard-changes` / `-f`/`--force`.
76
+ 7. `git restore` touching the worktree — only `git restore --staged <path>`
77
+ without `--worktree` is allowed (unstaging is safe).
78
+ 8. `git stash drop` / `git stash clear` (push/pop/list/apply stay allowed).
79
+ 9. `git clean` with a force flag and no dry-run — `-n`/`--dry-run` anywhere
80
+ makes it a safe preview.
81
+ 10. `git branch -D` (or `-d` combined with `-f`, clustered or split);
82
+ safe `-d` and rename `-m` stay allowed.
83
+ 11. `git tag -d`, `git reflog delete`, `git worktree remove --force`.
84
+ 12. Deletion via `find … -delete`, `find … -exec rm -rf`, and `xargs … rm -rf`
85
+ (plain non-recursive `rm` on find/xargs output stays allowed).
86
+ 13. Disk destroyers: `dd of=/dev/…`, `mkfs … /dev/…`, `shred`.
87
+ 14. Destructive SQL — `DROP DATABASE/SCHEMA/TABLE`, `TRUNCATE TABLE`.
88
+
89
+ Every git guard sees through leading git **global options** (`-C <path>`,
90
+ `-c <k>=<v>`, `--git-dir[=…]`, `--no-pager`, …), so `git -C /path <destructive>`
91
+ is screened the same as `git <destructive>`.
92
+
93
+ Malformed hook input fails **closed** (exit 2 denies the command). A text-scan
94
+ hook cannot exempt display commands, so prose like
95
+ `echo "docs about rm -rf /"` can false-positive — quote-break the string or use
96
+ the gh-writer heredoc form (payload is stripped before the guards run).
61
97
 
62
98
  ## View the current rules
63
99