navori 0.5.0 → 0.5.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.
@@ -80,13 +80,41 @@ fi
80
80
 
81
81
  # 2. Force-push to the base branch. force-with-lease is allowed (safe rebase
82
82
  # flow on feature branches); bare --force/-f against the base branch is not.
83
- # The leading boundary accepts ; & | so `true;git push --force main` (no
84
- # space after the separator) is caught too. The `git( -opt …)*` middle
85
- # allows git global options before `push` (`git -C /repo push --force …`).
86
- if printf '%s' "$scan" | grep -qE '(^|[[:space:]]|[;&|])git([[:space:]]+-[a-zA-Z-]+(=[^[:space:]]+)?([[:space:]]+[^-][^[:space:]]*)?)*[[:space:]]+push' \
87
- && printf '%s' "$scan" | grep -qE '(--force([[:space:]]|$)|[[:space:]]-f([[:space:]]|$)|[[:space:]]\+)' \
88
- && ! printf '%s' "$scan" | grep -qE 'force-with-lease' \
89
- && printf '%s' "$scan" | grep -qE "(^|[[:space:]+/])${base}([[:space:]]|\$)"; then
83
+ # #307: every sub-check is scoped to the ACTUAL `git push` invocation(s),
84
+ # never the whole command string. Splitting on the shell separators (&& || ;
85
+ # | newline) and keeping only segments that START a `git push` means a `+`
86
+ # in a commit message (`-m "format:check + test"`), a base-branch name in a
87
+ # sibling command (`gh pr create --base main`), or a heredoc/`--body` can no
88
+ # longer be misread as a force-push refspec or as the pushed ref — that
89
+ # false positive blocked legit compound commit+push+PR commands. The refspec
90
+ # `+` is matched only when glued to a ref (`+main`, never `+ test`), the way
91
+ # git actually spells a force-push refspec.
92
+ push_seg=""
93
+ _split="$scan"
94
+ _split="${_split//&&/$'\n'}"
95
+ _split="${_split//||/$'\n'}"
96
+ _split="${_split//;/$'\n'}"
97
+ _split="${_split//|/$'\n'}"
98
+ while IFS= read -r _seg; do
99
+ _seg="${_seg#"${_seg%%[![:space:]]*}"}" # strip leading ws
100
+ while [[ "$_seg" =~ ^[A-Za-z_][A-Za-z0-9_]*= ]]; do # strip VAR=val prefixes
101
+ case "$_seg" in
102
+ *[[:space:]]*)
103
+ _seg="${_seg#*[[:space:]]}"
104
+ _seg="${_seg#"${_seg%%[![:space:]]*}"}"
105
+ ;;
106
+ *) _seg=""; break ;;
107
+ esac
108
+ done
109
+ if printf '%s' "$_seg" | grep -qE '^git([[:space:]]+-[a-zA-Z-]+(=[^[:space:]]+)?([[:space:]]+[^-][^[:space:]]*)?)*[[:space:]]+push([[:space:]]|$)'; then
110
+ push_seg="${push_seg}${_seg}"$'\n'
111
+ fi
112
+ done <<< "$_split"
113
+
114
+ if [ -n "$push_seg" ] \
115
+ && printf '%s' "$push_seg" | grep -qE '(--force([[:space:]]|$)|[[:space:]]-f([[:space:]]|$)|[[:space:]]\+[^[:space:]])' \
116
+ && ! printf '%s' "$push_seg" | grep -qE 'force-with-lease' \
117
+ && printf '%s' "$push_seg" | grep -qE "(^|[[:space:]+/])${base}([[:space:]]|\$)"; then
90
118
  block "force-push to the base branch '${base}'"
91
119
  fi
92
120
 
@@ -113,6 +113,15 @@ TRIGGER_RE='^git([[:space:]]+-[a-zA-Z-]+(=[^[:space:]]+)?([[:space:]]+[^-][^[:sp
113
113
  # navori:include gate-trigger
114
114
 
115
115
  if is_scan_trigger "$cmd"; then
116
+ # Pin the cwd to the repo root before anything below runs. Claude Code fires
117
+ # PreToolUse hooks from the session's persistent cwd, which is NOT always the
118
+ # repo root — but the gate command, the lockfile-based PM detection and the
119
+ # receipt paths all assume the root. A relative gate (`cd packages/cli &&
120
+ # pnpm lint`) otherwise fails with "No such file or directory" from a subdir.
121
+ # Prefer $CLAUDE_PROJECT_DIR; fall back to the git top-level. When neither
122
+ # resolves (not a git repo, no env), the substitution is empty and `cd ""`
123
+ # is a no-op, so behavior outside a repo is unchanged. #309
124
+ cd "${CLAUDE_PROJECT_DIR:-$(git rev-parse --show-toplevel 2>/dev/null)}" || exit 2
116
125
  # Content-bind first: refuse to commit bytes that drifted from the approval
117
126
  # before spending the fast gate on them.
118
127
  check_content_receipt