fix(issue-21): PR #29 review R1-R3 - untracked-safe cleanliness checks; a worktree gets its own venv
R1/R2: `git status --porcelain` honours status.showUntrackedFiles, so a `no` setting in a submodule (or the worktree) hid untracked files from the checks that justify worktree_remove.sh's single --force and from the review snapshot guard (_dirty_submodules), which then approved content it never captured. All three checks (lib_py/worktree.py, worktree_remove.sh, runner._dirty_submodules) now pass --untracked-files=all. The source tree's own snapshot was already safe: `git add -A` ignores that setting. R3: worktree_prepare.sh no longer links .venv to the control root's. It creates the worktree's own venv with the control root's interpreter and installs requirements*.txt; a leftover link is refused (exit 1), a control root without an interpreter is a warning (VENV=skipped); VENV= is printed. Tests: w1 (real venv, kept on re-run), w1b (link refused / skipped), w6e parametrised over the hidden setting for the post-stop recheck, w6e2 (hidden untracked file in the submodule and in the worktree blocks the removal), l17 untracked-hidden / during-hidden (guard refuses before the first review; a mid-round hidden file makes the round stale). Each new case fails without the fix. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
This commit is contained in:
1 parent
90a289da44
commit
08db1da9d5
9 files changed
+107
-29
No files matched your search
@@ -8,8 +8,8 @@
|
||||
# [--creator-agent <agent> [--session <name>] [--role <role>]
|
||||
# [--herdr-session <s>] [--herdr-workspace <w>] [--onboard]] [--dry-run]
|
||||
#
|
||||
# Steps: git worktree (idempotent) -> .venv link to the control root's ->
|
||||
# /.venv and .pytest_cache/ in the shared info/exclude -> submodules only with
|
||||
# Steps: git worktree (idempotent) -> the worktree's own .venv (control root
|
||||
# interpreter + requirements*.txt) -> /.venv and .pytest_cache/ in the shared info/exclude -> submodules only with
|
||||
# --submodules (a failed init is rolled back: it would otherwise leave a
|
||||
# modules/ trace that makes a plain `git worktree remove` refuse) -> optional
|
||||
# creator session registered in the control root's .mam -> summary with BASE=.
|
||||
@@ -79,7 +79,7 @@ fi
|
||||
if [ "$DRY_RUN" = "1" ]; then
|
||||
echo "[dry-run] control root: $MAIN"
|
||||
echo "[dry-run] worktree: $WT (branch $BRANCH${BASE_REF:+, base $BASE_REF})"
|
||||
echo "[dry-run] .venv link and shared info/exclude entries; submodules: $([ "$SUBMODULES" = 1 ] && echo init || echo skipped)"
|
||||
echo "[dry-run] own .venv (from $MAIN/.venv/bin/python + requirements*.txt) and shared info/exclude entries; submodules: $([ "$SUBMODULES" = 1 ] && echo init || echo skipped)"
|
||||
[ -n "$CREATOR_AGENT" ] && echo "[dry-run] creator: $CREATOR_AGENT as $SESSION (role $ROLE)"
|
||||
exit 0
|
||||
fi
|
||||
@@ -108,13 +108,30 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
# 2. .venv: a link to the control root's, never a copy.
|
||||
if [ -e "$MAIN/.venv" ]; then
|
||||
if [ ! -e "$WT/.venv" ] && [ ! -L "$WT/.venv" ]; then
|
||||
ln -s "$MAIN/.venv" "$WT/.venv"
|
||||
elif [ "$(readlink "$WT/.venv" 2>/dev/null || true)" != "$MAIN/.venv" ]; then
|
||||
echo "WARNING: '$WT/.venv' exists and is not a link to '$MAIN/.venv'; left as it is" >&2
|
||||
# 2. .venv: the worktree's own environment, created with the control root's
|
||||
# interpreter and its requirements files, never a link (review R3: a link
|
||||
# aliases the control root's environment, and a `git add -A` in the
|
||||
# worktree once committed the link itself - see .gitignore's managed
|
||||
# block). Idempotent: an existing usable venv is kept.
|
||||
VENV_STATE="skipped"
|
||||
if [ -L "$WT/.venv" ]; then
|
||||
echo "ERROR: '$WT/.venv' is a symbolic link; a worktree needs its own venv - remove the link and re-run" >&2
|
||||
exit 1
|
||||
elif [ -x "$WT/.venv/bin/python" ]; then
|
||||
VENV_STATE="kept"
|
||||
elif [ -x "$MAIN/.venv/bin/python" ]; then
|
||||
"$MAIN/.venv/bin/python" -m venv "$WT/.venv" || { echo "ERROR: could not create '$WT/.venv'" >&2; exit 1; }
|
||||
req=()
|
||||
for f in requirements.txt requirements-dev.txt; do
|
||||
[ -f "$WT/$f" ] && req+=(-r "$WT/$f")
|
||||
done
|
||||
if [ "${#req[@]}" -gt 0 ]; then
|
||||
"$WT/.venv/bin/python" -m pip install -q "${req[@]}" \
|
||||
|| { echo "ERROR: pip install into '$WT/.venv' failed; fix it and re-run (the worktree is kept)" >&2; exit 1; }
|
||||
fi
|
||||
VENV_STATE="created"
|
||||
else
|
||||
echo "WARNING: '$MAIN/.venv/bin/python' not found; no venv created in the worktree" >&2
|
||||
fi
|
||||
|
||||
# 3. Ignore rules. A linked worktree's info/exclude is the shared
|
||||
@@ -228,6 +245,7 @@ echo "WORKTREE=$WT"
|
||||
echo "BRANCH=$BRANCH"
|
||||
echo "BASE=$BASE_SHA"
|
||||
echo "SUBMODULES=$SUB_STATE"
|
||||
echo "VENV=$VENV_STATE"
|
||||
[ -n "$CREATOR_AGENT" ] && echo "SESSION=$SESSION"
|
||||
echo "next: bash $SKILL_DIR/multi-agent-mux-loop/scripts/run_loop.sh --worktree '$WT' --base $BASE_SHA --review-only --creator <creator> --reviewer <reviewers> --task '...'"
|
||||
echo "then: bash $SKILL_DIR/multi-agent-mux-stop/scripts/worktree_remove.sh --path '$WT' --stop"
|
||||
Reference in new issue
Block a user