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
|
-
#
|
|
84
|
-
#
|
|
85
|
-
#
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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
|