fix(deploy): final-review fixes — NEXT.sh-absence regen, git-ignored fail-loud (rc5), bootstrap gitignore guard, doc polish

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ho5EQCFTSvYamuRtVZpp2d
This commit is contained in:
Bastien Chanot
2026-06-27 18:11:14 +02:00
co-authored by Claude Opus 4.8
parent 91850eb63a
commit 79741e36e7
4 changed files with 38 additions and 12 deletions
+8
View File
@@ -23,6 +23,8 @@ _out_of_scope() { # 0 = forbidden, 1 = in scope
_scope_violations() { local p; for p in "$@"; do _out_of_scope "$p" && printf '%s\n' "$p"; done; }
_ignored() { git check-ignore -q "$1"; } # rc 0 = ignored
_changed_only() { # echo passed files that actually have changes
local p; for p in "$@"; do
[ -n "$(git status --porcelain -- "$p" 2>/dev/null)" ] && printf '%s\n' "$p"; done
@@ -52,6 +54,12 @@ case "$cmd" in
echo "deploy-commit: NOTHING committed. Caller must pass only .claude/deploy/ files."; } >&2
exit 4
fi
mapfile -t ignored_paths < <(for p in "$@"; do _ignored "$p" && printf '%s\n' "$p"; done)
if [ "${#ignored_paths[@]}" -gt 0 ]; then
{ echo "deploy-commit: REFUSED — path(s) are git-ignored and will NOT persist; \`.claude/deploy/\` must be committable in this project:";
printf ' - %s\n' "${ignored_paths[@]}"; } >&2
exit 5
fi
_unsafe_state && { echo "deploy-commit: unsafe git state (detached/merge/rebase) — not committing" >&2; exit 3; }
mapfile -t changed < <(_changed_only "$@")
[ "${#changed[@]}" -gt 0 ] || exit 1
+5
View File
@@ -45,4 +45,9 @@ check T7-three-files "$(git -C "$d" show --name-only --format= HEAD | grep -c de
d=$(mkrepo); printf 'b\n' >"$d/src.txt"
( cd "$d" && bash "$H" pending src.txt ) >/dev/null 2>&1; check T8-pending-out-of-scope-rc "$?" 4
d=$(mkrepo); printf '.claude/\n' >"$d/.gitignore"
printf 'run\n' >"$d/.claude/deploy/PROCEDURE.md"
( cd "$d" && bash "$H" commit "docs(deploy): t" .claude/deploy/PROCEDURE.md ) >/dev/null 2>&1
check T9-ignored-rc "$?" 5
printf 'PASS=%s FAIL=%s\n' "$pass" "$fail"; [ "$fail" -eq 0 ]