Skip to content

Commit 421ae97

Browse files
committed
Narrow tracked-humanize guard to .humanize/ to avoid false blocks
The tracked-state check used '.humanize-*' globs which matched unrelated dot-prefixed files the command-side guard already allows (for example .humanize-backup and .humanizeconfig, per tests/test-humanize-escape.sh). In an active loop, a repo that intentionally tracked such a file was incorrectly blocked with "Tracked Humanize State Blocked" even with no RLCR artifacts present. Scope the detection to .humanize/ via a single ls-files pathspec. This stays consistent with git_adds_humanize, correctly omits paths the user has staged for removal via git rm --cached, and drops the redundant diff --cached probe. Update the block message (inline fallback and prompt template) to drop the dangerous "git rm --cached -r .humanize-*" hint, which could strip user files like .humanize-backup from the index. Add a stop-gate regression test asserting that tracked .humanize-backup and .humanizeconfig do not trigger the tracked-state block reason.
1 parent a9078aa commit 421ae97

3 files changed

Lines changed: 54 additions & 29 deletions

File tree

hooks/lib/loop-common.sh

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1322,21 +1322,21 @@ IMPORTANT: The commit message must NOT contain the literal string \".humanize\"
13221322
# Return success if local Humanize runtime state has entered git tracking or the index.
13231323
# Untracked .humanize state is allowed; tracked or staged state must be blocked.
13241324
# Usage: git_has_tracked_humanize_state [project_root]
1325+
#
1326+
# Intentionally scoped to .humanize/ to stay consistent with git_adds_humanize,
1327+
# which explicitly allows unrelated paths like .humanize-backup or
1328+
# .humanizeconfig (see tests/test-humanize-escape.sh). ls-files covers both
1329+
# committed entries and paths staged via git add; paths the user has staged for
1330+
# removal via git rm --cached are correctly omitted so the user can unstick
1331+
# themselves without being re-blocked.
13251332
git_has_tracked_humanize_state() {
13261333
local project_root="${1:-.}"
13271334

13281335
if [[ ! -d "$project_root/.git" ]] && ! git -C "$project_root" rev-parse --git-dir >/dev/null 2>&1; then
13291336
return 1
13301337
fi
13311338

1332-
if git -C "$project_root" ls-files --error-unmatch .humanize >/dev/null 2>&1; then
1333-
return 0
1334-
fi
1335-
if git -C "$project_root" ls-files '.humanize/*' '.humanize-*' | grep -q '.'; then
1336-
return 0
1337-
fi
1338-
1339-
if git -C "$project_root" diff --cached --name-only -- .humanize '.humanize-*' | grep -q '.'; then
1339+
if git -C "$project_root" ls-files -- .humanize 2>/dev/null | grep -q '.'; then
13401340
return 0
13411341
fi
13421342

@@ -1348,20 +1348,16 @@ git_has_tracked_humanize_state() {
13481348
git_tracked_humanize_blocked_message() {
13491349
local fallback="# Tracked Humanize State Blocked
13501350
1351-
Detected tracked or staged files under \`.humanize/\` (or legacy \`.humanize-*\`).
1351+
Detected tracked or staged files under \`.humanize/\`.
13521352
13531353
These files are local Humanize loop state and must remain outside version control.
13541354
13551355
## Required Fix
13561356
1357-
1. Remove Humanize state from the index, for example:
1357+
1. Remove Humanize state from the index:
13581358
13591359
git rm --cached -r .humanize
13601360
1361-
If legacy tracked state exists, remove those entries too:
1362-
1363-
git rm --cached -r .humanize-*
1364-
13651361
2. Keep only real project files staged.
13661362
3. Retry the stop action after the local state is no longer tracked.
13671363

prompt-template/block/git-tracked-humanize.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
11
# Tracked Humanize State Blocked
22

3-
Detected tracked or staged files under `.humanize/` or legacy `.humanize-*`.
3+
Detected tracked or staged files under `.humanize/`.
44

55
These files are local Humanize loop state and must remain outside version control.
66

77
## Required Fix
88

9-
1. Remove Humanize state from the index, for example:
9+
1. Remove Humanize state from the index:
1010

1111
git rm --cached -r .humanize
1212

13-
If legacy tracked state exists, remove those entries too:
14-
15-
git rm --cached -r .humanize-*
16-
1713
2. Keep only real project files staged.
1814
3. Retry the stop action after the local state is no longer tracked.
1915

tests/test-stop-gate.sh

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -144,30 +144,63 @@ else
144144
fail "rlcr-stop-gate reports tracked Humanize state with dedicated reason" "output containing Tracked Humanize State Blocked" "$OUTPUT3"
145145
fi
146146

147-
# Test 4: No active loop -> gate allows exit (exit 0)
147+
# Test 4: Unrelated dot-prefixed files that happen to start with .humanize-
148+
# must not be treated as loop state. .humanize-backup and .humanizeconfig are
149+
# explicitly allowed by the git add validator (tests/test-humanize-escape.sh);
150+
# the tracked-state guard must stay consistent and ignore them.
148151
T4_DIR="$TEST_DIR/t4"
149-
mkdir -p "$T4_DIR/empty-project"
152+
mkdir -p "$T4_DIR"
153+
setup_active_loop_fixture "$T4_DIR/project"
154+
echo "not loop state" > "$T4_DIR/project/.humanize-backup"
155+
echo "not loop state" > "$T4_DIR/project/.humanizeconfig"
156+
git -C "$T4_DIR/project" add -f .humanize-backup .humanizeconfig
150157

151158
set +e
152159
(
153-
cd "$T4_DIR/empty-project"
160+
cd "$T4_DIR/project"
154161
"$GATE_SCRIPT"
155162
) > "$T4_DIR/out.txt" 2>&1
156163
EXIT4=$?
157164
set -e
158165

159-
if [[ "$EXIT4" -eq 0 ]]; then
160-
pass "rlcr-stop-gate exits 0 when no active loop exists"
166+
if [[ "$EXIT4" -eq 10 ]]; then
167+
pass "rlcr-stop-gate does not confuse .humanize-backup with loop state"
161168
else
162169
OUTPUT4=$(cat "$T4_DIR/out.txt" 2>/dev/null || true)
163-
fail "rlcr-stop-gate exits 0 when no active loop exists" "exit 0" "exit $EXIT4; output: $OUTPUT4"
170+
fail "rlcr-stop-gate does not confuse .humanize-backup with loop state" "exit 10" "exit $EXIT4; output: $OUTPUT4"
164171
fi
165172

166-
if grep -q "^ALLOW:" "$T4_DIR/out.txt" 2>/dev/null; then
167-
pass "rlcr-stop-gate reports ALLOW when no active loop"
173+
if ! grep -q "Tracked Humanize State Blocked" "$T4_DIR/out.txt" 2>/dev/null; then
174+
pass "rlcr-stop-gate does not emit tracked-state reason for .humanize-backup"
168175
else
169176
OUTPUT4=$(cat "$T4_DIR/out.txt" 2>/dev/null || true)
170-
fail "rlcr-stop-gate reports ALLOW when no active loop" "output containing ALLOW:" "$OUTPUT4"
177+
fail "rlcr-stop-gate does not emit tracked-state reason for .humanize-backup" "no Tracked Humanize State Blocked line" "$OUTPUT4"
178+
fi
179+
180+
# Test 5: No active loop -> gate allows exit (exit 0)
181+
T5_DIR="$TEST_DIR/t5"
182+
mkdir -p "$T5_DIR/empty-project"
183+
184+
set +e
185+
(
186+
cd "$T5_DIR/empty-project"
187+
"$GATE_SCRIPT"
188+
) > "$T5_DIR/out.txt" 2>&1
189+
EXIT5=$?
190+
set -e
191+
192+
if [[ "$EXIT5" -eq 0 ]]; then
193+
pass "rlcr-stop-gate exits 0 when no active loop exists"
194+
else
195+
OUTPUT5=$(cat "$T5_DIR/out.txt" 2>/dev/null || true)
196+
fail "rlcr-stop-gate exits 0 when no active loop exists" "exit 0" "exit $EXIT5; output: $OUTPUT5"
197+
fi
198+
199+
if grep -q "^ALLOW:" "$T5_DIR/out.txt" 2>/dev/null; then
200+
pass "rlcr-stop-gate reports ALLOW when no active loop"
201+
else
202+
OUTPUT5=$(cat "$T5_DIR/out.txt" 2>/dev/null || true)
203+
fail "rlcr-stop-gate reports ALLOW when no active loop" "output containing ALLOW:" "$OUTPUT5"
171204
fi
172205

173206
print_test_summary "RLCR Stop Gate Wrapper Test Summary"

0 commit comments

Comments
 (0)