General-purpose coding policy for Baruch's AI agents
73
91%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
#!/usr/bin/env bash
# Outcome-based tests for hooks/check-leftover-worktrees.sh.
#
# Each case builds its own bare "origin", a shared clone, its own worktree
# root and a fake `gh` first on PATH that answers from files in the case's
# directory, so no case sees another's state and they run in any order
# (rules/testing-standards.md Independence). Every commit and reflog entry is
# dated FIXTURE_DATE, every aged file is touched to a fixed mtime, and the
# owner scripts judge at PRUNE_NOW, never the wall clock (Determinism).
#
# The owner scripts' decisions have their own suites
# (skills/herdr-foreman/tests/test_prune_worktrees.sh,
# test_prune_remote_branches.sh); these cases cover what the hook adds: it
# runs them live for this repository, lists only what the operator must
# decide, never acts in a worker session or in portable mode, and turns a
# failure into one "could not check" line.
#
# Covers:
# 1. Removable -> an idle clean worktree origin holds, a merged
# local branch and a merged branch on origin are
# removed; nothing is printed.
# 2. Questionable -> an idle dirty worktree, an idle unpushed
# worktree, an unpushed local branch and a stale
# unmerged branch on origin are listed and left.
# An open pull request's branch and another
# repository's dirty worktree are not listed.
# 3. Not yet idle -> a fresh dirty worktree is not listed.
# 4. In use -> a process inside keeps a removable worktree,
# unlisted.
# 5. gh failing -> nothing on origin is deleted; one could-not-check
# line, never the URL gh printed.
# 6. Worker session -> HERDR_ENV in a linked worktree: nothing deleted,
# nothing printed.
# 7. Portable mode -> nothing deleted; the questionable list still
# printed.
# 8. No origin, no repo -> silent.
# 13. Portable, linked -> under tessl a linked worktree runs neither owner
# script and changes no ref.
# 12. Malformed result -> an owner result missing documented fields is a
# could-not-check status.
# 11. Newline path -> a shared checkout whose name ends in a newline
# is cleaned, never truncated.
# 10. Missing tool -> a missing git or python3 still prints the
# could-not-check status, as fixed JSON.
# 9. Out of time -> a could-not-check line naming the budget (a
# stand-in runner reports the timeout; no case
# waits on a clock, and every other run gets an
# hour).
# 14. Inventory failure -> a git worktree list that fails after printing a
# valid prefix is a could-not-check status naming
# git's own exit, and runs neither owner script.
# 15. SSH BatchMode -> appended to a user-set GIT_SSH_COMMAND, and the
# default when none is set.
#
# The harness drops `set -e` to aggregate results; every fixture command is
# checked explicitly (rules/error-handling.md aggregate-reporting carve-out).
#
# Run: bash hooks/tests/test_check_leftover_worktrees.sh
set -uo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
HOOK="${HERE}/../check-leftover-worktrees.sh"
PASS=0
FAIL=0
TMP=""
SLEEPER=""
#: Every fixture commit and reflog entry carries this date.
FIXTURE_DATE="2020-01-01T00:00:00Z"
AGED_MTIME=202001010000
#: A mtime inside the idle window of PRUNE_NOW in any time zone.
FRESH_MTIME=202001092000
#: 2020-01-10T00:00:00Z: nine days after FIXTURE_DATE.
PRUNE_NOW=1578614400
die() { echo "fatal: $*" >&2; exit 2; }
pass() { PASS=$((PASS+1)); }
fail() { FAIL=$((FAIL+1)); echo " ✗ FAIL: $1" >&2; }
cleanup() {
stop_sleeper
if [[ -n "$TMP" ]] && ! rm -rf "$TMP"; then echo "warn: could not remove $TMP" >&2; fi
return 0
}
# Run a fixture command with stderr captured; a failure stops the harness
# with the command's own words.
quiet() { # <what> <command...>
local what="$1" rc=0; shift
"$@" 2>"$TMP/quiet.err" || rc=$?
if (( rc != 0 )); then
die "${what} (exit ${rc}): $(tr '\n' ' ' < "$TMP/quiet.err") — rerun \`$*\` by hand"
fi
}
# A fake gh answering from $CASE: `prs` lists open pull-request heads; `fail`
# makes every call exit 1 with a credential-bearing message.
write_fake_gh() {
mkdir -p "$CASE/bin" || die "mkdir $CASE/bin failed"
cat > "$CASE/bin/gh" <<'SH' || die "cannot write the fake gh"
#!/usr/bin/env bash
set -euo pipefail
d="${FAKE_GH_DIR:?}"
if [[ -e "$d/fail" ]]; then echo "gh: HTTP 502 from https://s3cr3t@example.invalid" >&2; exit 1; fi
case "$1" in
api)
if [[ "$2" == *'?protected'* ]]; then
if [[ -f "$d/protected" ]]; then cat "$d/protected"; fi
else
# GitHub routes a raw slash as another path segment: 404, as here.
seg="${2#*/branches/}"
if [[ "$seg" == */* ]]; then echo "gh: HTTP 404: Not Found (branches/${seg})" >&2; exit 1; fi
printf '%s\n' "$seg" >> "$d/api-branches"
b="$(python3 -c 'import sys, urllib.parse; print(urllib.parse.unquote(sys.argv[1]))' "$seg")"
if [[ -f "$d/protected" ]] && grep -qxF -- "$b" "$d/protected"; then echo true; else echo false; fi
fi
exit 0 ;;
pr)
head=""
while (( $# )); do
if [[ "$1" == --head ]]; then head="$2"; shift; fi
shift
done
[[ -f "$d/prs" ]] || exit 0
if [[ -n "$head" ]]; then grep -xF -- "$head" "$d/prs" || [[ $? -eq 1 ]]; else cat "$d/prs"; fi
exit 0 ;;
esac
echo "fake gh: unexpected call $*" >&2
exit 3
SH
chmod +x "$CASE/bin/gh" || die "chmod the fake gh failed"
}
# A git first on PATH that answers `remote get-url` with a GitHub URL, so the
# bare origin can pose as a GitHub repository for prune-remote-branches.sh;
# every other call is the real git's.
write_fake_git() {
local real
real="$(command -v git)" || die "git is required"
printf '#!/usr/bin/env bash\nREAL_GIT=%q\n' "$real" > "$CASE/bin/git" || die "cannot write the fake git"
cat >> "$CASE/bin/git" <<'SH' || die "cannot write the fake git"
set -euo pipefail
args=("$@")
i=0
if [[ "${args[0]:-}" == -C ]]; then i=2; fi
if [[ "${args[i]:-}" == remote && "${args[i+1]:-}" == get-url ]]; then
# A missing origin still fails as git's own does.
"$REAL_GIT" "$@" >/dev/null
echo https://github.com/acme/widgets.git; exit 0
fi
exec "$REAL_GIT" "$@"
SH
chmod +x "$CASE/bin/git" || die "chmod the fake git failed"
}
# Per case: origin, a shared clone, a worktree root and the fake gh. Sets
# CASE, BARE, SHARED, ROOT.
mk_case() { # <name>
CASE="$TMP/$1"; BARE="$CASE/origin.git"; SHARED="$CASE/shared"; ROOT="$CASE/worktrees"
mkdir -p "$CASE" "$ROOT" || die "mkdir $CASE failed"
quiet "init origin" git init -q --bare -b main "$BARE"
quiet "clone" git clone -q "$BARE" "$SHARED"
quiet "switch main" git -C "$SHARED" switch -q -C main
printf 'base\n' > "$SHARED/f" || die "write f failed"
quiet "add f" git -C "$SHARED" add f
quiet "commit base" git -C "$SHARED" commit -q -m base
quiet "push main" git -C "$SHARED" push -q -u origin main
quiet "set-head" git -C "$SHARED" remote set-head origin --auto >/dev/null
write_fake_gh
write_fake_git
}
commit_file() { # <checkout> <file>
printf '%s\n' "$2" > "$1/$2" || die "write $2 failed"
quiet "add $2" git -C "$1" add "$2"
quiet "commit $2" git -C "$1" commit -q -m "$2"
}
# Touch a worktree's files and its gitdir's activity files to <mtime>.
age_wt() { # <worktree> <mtime>
local gitdir f
gitdir="$(git -C "$1" rev-parse --absolute-git-dir)" || die "rev-parse --absolute-git-dir failed in $1"
for f in "$gitdir/HEAD" "$gitdir/index" "$gitdir/logs/HEAD"; do
if [[ -e "$f" ]]; then touch -t "$2" "$f" || die "touch $f failed"; fi
done
find "$1" -path "$1/.git" -prune -o -exec touch -h -t "$2" {} + || die "touch the files of $1 failed"
}
# A branch on origin cut from main with one commit; merged into main or not.
push_branch() { # <branch> <merged 0|1>
quiet "branch $1" git -C "$SHARED" switch -q -c "$1" main
commit_file "$SHARED" "file-${1//\//-}"
quiet "push $1" git -C "$SHARED" push -q origin "$1"
quiet "switch main" git -C "$SHARED" switch -q main
if (( $2 )); then
quiet "merge $1" git -C "$SHARED" merge -q --ff-only "$1"
quiet "push main" git -C "$SHARED" push -q origin main
fi
quiet "drop local $1" git -C "$SHARED" branch -q -D "$1"
}
on_origin() { git -C "$BARE" show-ref --verify --quiet "refs/heads/$1"; }
has_branch() { git -C "$SHARED" show-ref --verify --quiet "refs/heads/$1"; }
# Run the hook from <dir> with the case's environment; sets OUT, RC, ERR.
run_hook() { # <dir> [VAR=value...]
local dir="$1"; shift
RC=0
OUT="$(cd "$dir" && env PATH="$CASE/bin:$PATH" FAKE_GH_DIR="$CASE" WORKTREE_ROOT="$ROOT" \
PRUNE_NOW="$PRUNE_NOW" PRUNE_IDLE_HOURS=24 PRUNE_REMOTE_IDLE_HOURS=24 LEFTOVER_BUDGET_SEC=3600 "$@" \
bash "$HOOK" </dev/null 2>"$CASE/hook.err")" || RC=$?
ERR="$(cat "$CASE/hook.err")"
}
# The additionalContext text of OUT, or empty when OUT is empty.
context() {
[[ -n "$OUT" ]] || return 0
printf '%s' "$OUT" | python3 -c 'import json,sys; print(json.load(sys.stdin)["additionalContext"])'
}
# A process with its cwd inside <dir>, registered with the fake lsof;
# returns once it is there. The FIFO read returns when the child writes after
# its cd: no polling, no deadline.
start_sleeper() { # <dir>
local ready="$CASE/sleeper.ready" said
mkfifo "$ready" || die "mkfifo $ready failed"
(
if cd "$1"; then
printf 'in' > "$ready"
exec sleep 3600
fi
printf 'cd-failed' > "$ready"
) &
SLEEPER=$!
said="$(cat "$ready")" || die "cannot read the sleeper's FIFO $ready"
[[ "$said" == in ]] || die "the sleeper could not enter $1"
printf '%s %s\n' "$SLEEPER" "$1" >> "$FAKE_LSOF_CWDS" || die "cannot register the sleeper with the fake lsof"
}
stop_sleeper() {
if [[ -n "$SLEEPER" ]]; then
if ! kill "$SLEEPER"; then echo "warn: could not stop sleeper $SLEEPER" >&2; fi
# A killed sleeper exits non-zero: that is the expected outcome here.
wait "$SLEEPER"
fi
SLEEPER=""
if [[ -n "${FAKE_LSOF_CWDS:-}" && -e "${FAKE_LSOF_CWDS:-}" ]] && ! : > "$FAKE_LSOF_CWDS"; then
echo "warn: could not clear the fake lsof's records" >&2
fi
return 0
}
# The process probe every run uses: a stand-in for lsof that prints one
# NUL-framed cwd record per "<pid> <cwd>" line of $FAKE_LSOF_CWDS and nothing
# else, so the host's own process table never reaches a test. A case that
# needs a process inside a worktree registers it there; a case exercising the
# probe's failure modes names its own stand-in through PRUNE_LSOF.
write_fake_lsof() { # <path>
mkdir -p "$(dirname "$1")" || die "mkdir for the fake lsof failed"
cat > "$1" <<'SH' || die "write the fake lsof failed"
#!/usr/bin/env bash
set -euo pipefail
list="${FAKE_LSOF_CWDS:-}"
if [[ -z "$list" || ! -s "$list" ]]; then exit 0; fi
while IFS=' ' read -r pid cwd; do
printf 'p%s\0\nfcwd\0n%s\0\n' "$pid" "$cwd"
done < "$list"
SH
chmod +x "$1" || die "chmod the fake lsof failed"
}
# A staged plugin: the hook and the result-check module it imports, laid out
# as the plugin ships them. Each case adds its own owner scripts.
stage_plugin() { # <dir> [hooks-dir-name]
local hooks="${2:-hooks}"
mkdir -p "$1/$hooks" "$1/skills/herdr-foreman/foreman" || die "mkdir stage $1 failed"
cp "$HOOK" "$1/$hooks/" || die "stage the hook failed"
cp "${HERE}/../../skills/herdr-foreman/foreman/__init__.py" "${HERE}/../../skills/herdr-foreman/foreman/prune_result.py" \
"$1/skills/herdr-foreman/foreman/" || die "stage the result checks failed"
}
# A staged plugin with the real runner and owner scripts that record their
# name and GIT_SSH_COMMAND to <calls>, then fail.
stage_recording_plugin() { # <dir> <calls>
stage_plugin "$1"
cp "${HERE}/../../skills/herdr-foreman/bounded-run.sh" "$1/skills/herdr-foreman/" || die "stage the runner failed"
local owner
for owner in prune-worktrees.sh prune-remote-branches.sh; do
# shellcheck disable=SC2016 # GIT_SSH_COMMAND expands in the stand-in, not here.
printf '#!/usr/bin/env bash\nset -euo pipefail\nprintf "%%s %%s\\n" "%s" "${GIT_SSH_COMMAND:-}" >> %q\nexit 1\n' "$owner" "$2" \
> "$1/skills/herdr-foreman/$owner" || die "write the recording $owner failed"
done
}
main() {
command -v python3 >/dev/null || die "python3 is required"
TMP="$(mktemp -d)" || die "mktemp failed"
TMP="$(cd "$TMP" && pwd -P)" || die "cannot resolve $TMP"
trap cleanup EXIT
write_fake_lsof "$TMP/fake-lsof/lsof"
export PRUNE_LSOF="$TMP/fake-lsof/lsof" FAKE_LSOF_CWDS="$TMP/fake-lsof/cwds"
export HOME="$TMP/home" GIT_CONFIG_NOSYSTEM=1
mkdir -p "$HOME" || die "mkdir HOME failed"
export GIT_AUTHOR_NAME=Ada GIT_AUTHOR_EMAIL=ada@example.invalid
export GIT_COMMITTER_NAME=Ada GIT_COMMITTER_EMAIL=ada@example.invalid
export GIT_AUTHOR_DATE="$FIXTURE_DATE" GIT_COMMITTER_DATE="$FIXTURE_DATE"
unset HERDR_ENV SESSION_START_MODE GIT_SSH_COMMAND
local ctx
echo "1. removable worktrees and branches go, and nothing is printed"
mk_case c1
quiet "wt add" git -C "$SHARED" worktree add -q --detach "$ROOT/spent" origin/main
age_wt "$ROOT/spent" "$AGED_MTIME"
quiet "local branch" git -C "$SHARED" branch -q --no-track feat/local-merged main
push_branch feat/remote-merged 1
run_hook "$SHARED"
if [[ $RC -eq 0 && -z "$OUT" && ! -e "$ROOT/spent" ]] && ! has_branch feat/local-merged \
&& ! on_origin feat/remote-merged && on_origin main; then pass
else fail "c1: RC=$RC OUT=$OUT ERR=$ERR"; fi
echo "2. only work the operator must decide on is listed, and none of it is touched"
mk_case c2
quiet "wt dirty" git -C "$SHARED" worktree add -q -b review/dirty "$ROOT/dirty" origin/main
printf 'notes\n' > "$ROOT/dirty/notes.txt" || die "write notes failed"
age_wt "$ROOT/dirty" "$AGED_MTIME"
quiet "wt unpushed" git -C "$SHARED" worktree add -q -b feat/unpushed "$ROOT/unpushed" origin/main
commit_file "$ROOT/unpushed" u.txt
age_wt "$ROOT/unpushed" "$AGED_MTIME"
quiet "local unpushed" git -C "$SHARED" switch -q -c feat/local-only main
commit_file "$SHARED" l.txt
quiet "switch main" git -C "$SHARED" switch -q main
push_branch feat/stale 0
push_branch feat/open-pr 0
printf 'feat/open-pr\n' > "$CASE/prs" || die "write prs failed"
local other="$CASE/other"
quiet "clone other" git clone -q "$BARE" "$other"
quiet "wt other" git -C "$other" worktree add -q -b review/other "$ROOT/other-dirty" origin/main
printf 'x\n' > "$ROOT/other-dirty/x.txt" || die "write other failed"
age_wt "$ROOT/other-dirty" "$AGED_MTIME"
run_hook "$SHARED"
ctx="$(context)"
if [[ $RC -eq 0 ]] && [[ "$ctx" == "Session-start status — 4 item(s)"* ]] \
&& [[ "$ctx" == *"$ROOT/dirty (review/dirty): 1 uncommitted file(s)"* ]] \
&& [[ "$ctx" == *"$ROOT/unpushed (feat/unpushed): 1 commit(s) origin does not hold"* ]] \
&& [[ "$ctx" == *"local branch feat/local-only: 1 unpushed commit(s)"* ]] \
&& [[ "$ctx" == *"origin branch feat/stale: 1 commit(s) not in main"*"by Ada"* ]] \
&& [[ "$ctx" == *"one at a time"* ]] \
&& [[ "$ctx" != *feat/open-pr* && "$ctx" != *other-dirty* ]] \
&& [[ -e "$ROOT/dirty/notes.txt" && -e "$ROOT/unpushed" && -e "$ROOT/other-dirty" ]] \
&& has_branch feat/local-only && on_origin feat/stale && on_origin feat/open-pr; then pass
else fail "c2: RC=$RC OUT=$OUT ERR=$ERR"; fi
echo "3. a dirty worktree inside the idle window is not listed"
mk_case c3
quiet "wt fresh" git -C "$SHARED" worktree add -q -b review/fresh "$ROOT/fresh" origin/main
printf 'wip\n' > "$ROOT/fresh/wip.txt" || die "write wip failed"
age_wt "$ROOT/fresh" "$FRESH_MTIME"
run_hook "$SHARED"
if [[ $RC -eq 0 && -z "$OUT" && -e "$ROOT/fresh/wip.txt" ]]; then pass
else fail "c3: RC=$RC OUT=$OUT ERR=$ERR"; fi
echo "4. a process inside keeps a removable worktree, and it is not listed"
mk_case c4
quiet "wt busy" git -C "$SHARED" worktree add -q --detach "$ROOT/busy" origin/main
age_wt "$ROOT/busy" "$AGED_MTIME"
start_sleeper "$ROOT/busy"
run_hook "$SHARED"
stop_sleeper
if [[ $RC -eq 0 && -z "$OUT" && -e "$ROOT/busy" ]]; then pass
else fail "c4: RC=$RC OUT=$OUT ERR=$ERR"; fi
echo "5. a failing gh deletes nothing on origin and says so in one line"
mk_case c5
push_branch feat/remote-merged 1
: > "$CASE/fail" || die "write fail flag failed"
run_hook "$SHARED"
ctx="$(context)"
if [[ $RC -eq 0 ]] && on_origin feat/remote-merged \
&& [[ "$ctx" == "Session-start status — could not check this repository"*"prune-remote-branches.sh"* ]] \
&& [[ "$ctx" != *$'\n'* && "$OUT$ERR" != *s3cr3t* ]]; then pass
else fail "c5: RC=$RC OUT=$OUT ERR=$ERR"; fi
echo "6. a Herdr worker session deletes nothing and prints nothing"
mk_case c6
quiet "wt worker" git -C "$SHARED" worktree add -q -b review/worker "$ROOT/worker" origin/main
quiet "wt spent" git -C "$SHARED" worktree add -q --detach "$ROOT/spent" origin/main
age_wt "$ROOT/spent" "$AGED_MTIME"
push_branch feat/remote-merged 1
run_hook "$ROOT/worker" HERDR_ENV=1
local rc_set=$RC out_set=$OUT
# Set but empty is still Herdr: the role is unknown, so it acts as a worker.
run_hook "$ROOT/worker" HERDR_ENV=
if [[ $rc_set -eq 0 && -z "$out_set" && $RC -eq 0 && -z "$OUT" && -e "$ROOT/spent" ]] && on_origin feat/remote-merged; then pass
else fail "c6: set RC=$rc_set OUT=$out_set; empty RC=$RC OUT=$OUT ERR=$ERR"; fi
echo "7. portable mode deletes nothing and still lists what awaits the operator"
mk_case c7
quiet "wt spent" git -C "$SHARED" worktree add -q --detach "$ROOT/spent" origin/main
age_wt "$ROOT/spent" "$AGED_MTIME"
quiet "wt dirty" git -C "$SHARED" worktree add -q -b review/dirty "$ROOT/dirty" origin/main
printf 'notes\n' > "$ROOT/dirty/notes.txt" || die "write notes failed"
age_wt "$ROOT/dirty" "$AGED_MTIME"
push_branch feat/remote-merged 1
run_hook "$SHARED" SESSION_START_MODE=portable
ctx="$(context)"
if [[ $RC -eq 0 && -e "$ROOT/spent" ]] && on_origin feat/remote-merged \
&& [[ "$ctx" == "Session-start status — 1 item(s)"*"$ROOT/dirty"* ]]; then pass
else fail "c7: RC=$RC OUT=$OUT ERR=$ERR"; fi
echo "8. a repository without origin, and a directory outside any, are silent"
mk_case c8
quiet "remove origin" git -C "$SHARED" remote remove origin
run_hook "$SHARED"
local rc_a=$RC out_a=$OUT err_a=$ERR
mkdir -p "$CASE/plain" || die "mkdir plain failed"
run_hook "$CASE/plain" GIT_CEILING_DIRECTORIES="$CASE"
if [[ $rc_a -eq 0 && -z "$out_a" && -z "$err_a" && $RC -eq 0 && -z "$OUT" && -z "$ERR" ]]; then pass
else fail "c8: no-origin RC=$rc_a OUT=$out_a ERR=$err_a; plain RC=$RC OUT=$OUT ERR=$ERR"; fi
echo "9. a run past the budget is a could-not-check line, never silence"
mk_case c9
quiet "wt spent" git -C "$SHARED" worktree add -q --detach "$ROOT/spent" origin/main
age_wt "$ROOT/spent" "$AGED_MTIME"
# A staged plugin whose bounded runner reports every command out of time:
# the budget ends by the runner's own verdict, never by waiting on a clock.
local stage="$CASE/stage"
stage_plugin "$stage"
cp "${HERE}/../../skills/herdr-foreman/prune-worktrees.sh" "${HERE}/../../skills/herdr-foreman/prune-remote-branches.sh" \
"$stage/skills/herdr-foreman/" || die "stage the owner scripts failed"
printf '#!/usr/bin/env bash\nset -euo pipefail\necho "bounded-run: stand-in budget spent" >&2\nexit 124\n' > "$stage/skills/herdr-foreman/bounded-run.sh" \
|| die "write the stand-in runner failed"
local real_hook="$HOOK"
HOOK="$stage/hooks/$(basename "$real_hook")"
run_hook "$SHARED"
HOOK="$real_hook"
ctx="$(context)"
if [[ $RC -eq 0 && -e "$ROOT/spent" ]] && [[ "$ctx" == "Session-start status — could not check"*"time budget"* ]]; then pass
else fail "c9: RC=$RC OUT=$OUT ERR=$ERR"; fi
echo "10. a missing git or python3 is a could-not-check status, never stderr alone"
mk_case c10
local bare_path="$CASE/path-nogit" real_bash
real_bash="$(command -v bash)" || die "bash not found"
mkdir -p "$bare_path" "$CASE/path-nopy" || die "mkdir the PATH dirs failed"
ln -s "$(command -v git)" "$CASE/path-nopy/git" || die "link git failed"
local ctx_git ctx_py
RC=0; OUT="$(cd "$SHARED" && PATH="$bare_path" "$real_bash" "$HOOK" </dev/null 2>"$CASE/hook.err")" || RC=$?
ctx_git="$(context)"
local rc_git=$RC
RC=0; OUT="$(cd "$SHARED" && PATH="$CASE/path-nopy" "$real_bash" "$HOOK" </dev/null 2>"$CASE/hook.err")" || RC=$?
ctx_py="$(context)"
if [[ $rc_git -eq 0 && $RC -eq 0 ]] \
&& [[ "$ctx_git" == "Session-start status — could not check this repository"*"git is not on PATH"* ]] \
&& [[ "$ctx_py" == "Session-start status — could not check this repository"*"python3 is not on PATH"* ]]; then pass
else fail "c10: git=$ctx_git python3=$ctx_py"; fi
echo "13. under tessl a linked worktree runs neither owner script and changes no ref"
mk_case c13
quiet "wt linked" git -C "$SHARED" worktree add -q -b review/linked13 "$ROOT/linked" origin/main
push_branch feat/remote-merged 1
local stage13="$CASE/stage13" calls13="$CASE/calls13"
stage_plugin "$stage13"
cp "${HERE}/../../skills/herdr-foreman/bounded-run.sh" "$stage13/skills/herdr-foreman/" || die "stage the runner failed"
local owner
for owner in prune-worktrees.sh prune-remote-branches.sh; do
printf '#!/usr/bin/env bash\nset -euo pipefail\nprintf "%%s\\n" "%s" >> %q\nexit 1\n' "$owner" "$calls13" > "$stage13/skills/herdr-foreman/$owner" \
|| die "write the recording $owner failed"
done
local refs_before refs_after
refs_before="$(git -C "$SHARED" for-each-ref)" || die "for-each-ref failed"
local real_hook13="$HOOK"
HOOK="$stage13/hooks/$(basename "$real_hook13")"
run_hook "$ROOT/linked" SESSION_START_MODE=portable
HOOK="$real_hook13"
refs_after="$(git -C "$SHARED" for-each-ref)" || die "for-each-ref failed"
if [[ $RC -eq 0 && -z "$OUT" && ! -e "$calls13" && "$refs_before" == "$refs_after" ]] && on_origin feat/remote-merged; then pass
else fail "c13: RC=$RC OUT=$OUT ERR=$ERR calls=$(cat "$calls13" 2>&1)"; fi
echo "12. an owner result missing its documented fields is a could-not-check status, never a clean one"
mk_case c12
local stage12="$CASE/stage"
stage_plugin "$stage12"
cp "${HERE}/../../skills/herdr-foreman/bounded-run.sh" "$stage12/skills/herdr-foreman/" || die "stage the runner failed"
printf '#!/usr/bin/env bash\nset -euo pipefail\nprintf "{}\\n"\n' > "$stage12/skills/herdr-foreman/prune-worktrees.sh" || die "write the stand-in prune failed"
printf '#!/usr/bin/env bash\nset -euo pipefail\nprintf "{\\"deleted\\": [], \\"questionable\\": [{\\"branch\\": 7}], \\"kept\\": [], \\"failed\\": [], \\"could_not_check\\": null, \\"default_branch\\": \\"main\\"}\\n"\n' \
> "$stage12/skills/herdr-foreman/prune-remote-branches.sh" || die "write the stand-in remote pass failed"
local real_hook12="$HOOK"
HOOK="$stage12/hooks/$(basename "$real_hook12")"
run_hook "$SHARED"
HOOK="$real_hook12"
ctx="$(context)"
if [[ $RC -eq 0 ]] && [[ "$ctx" == "Session-start status — could not check this repository"* ]] \
&& [[ "$ctx" == *"prune-worktrees.sh exited 0 with a result holding no worktrees_removed list"* ]] \
&& [[ "$ctx" == *"prune-remote-branches.sh exited 0 with a result holding a malformed questionable entry"* ]]; then pass
else fail "c12: RC=$RC OUT=$OUT ERR=$ERR"; fi
echo "11. a shared checkout whose name ends in a newline is cleaned, never truncated"
local nl=$'\n'
if mkdir "$TMP/nl-probe${nl}" 2>"$TMP/nl.err"; then
rmdir "$TMP/nl-probe${nl}" || die "rmdir the newline probe failed"
mk_case c11
local nl_shared="$CASE/shared-nl${nl}"
quiet "clone newline" git clone -q "$BARE" "$nl_shared"
quiet "set-head newline" git -C "$nl_shared" remote set-head origin --auto
quiet "wt spent" git -C "$nl_shared" worktree add -q --detach "$ROOT/spent" origin/main
age_wt "$ROOT/spent" "$AGED_MTIME"
push_branch feat/remote-merged 1
run_hook "$nl_shared"
if [[ $RC -eq 0 && -z "$OUT" && ! -e "$ROOT/spent" ]] && ! on_origin feat/remote-merged; then pass
else fail "c11: RC=$RC OUT=$OUT ERR=$ERR"; fi
else
echo "11. skipped: this filesystem refuses a name ending in a newline ($(cat "$TMP/nl.err"))"
fi
echo "14. a git worktree list that fails after a valid prefix runs neither owner script"
mk_case c14
local stage14="$CASE/stage14" calls14="$CASE/calls14" real_git
stage_recording_plugin "$stage14" "$calls14"
real_git="$(command -v git)" || die "git not found"
mkdir -p "$CASE/failing-git" || die "mkdir failing-git failed"
# Prints the real inventory, then fails: the prefix alone parses cleanly.
# shellcheck disable=SC2016 # The $@ belongs to the stand-in git.
printf '#!/usr/bin/env bash\nset -euo pipefail\nif [[ "${1:-}" == worktree && "${2:-}" == list ]]; then\n %q "$@"\n echo "fatal: stand-in failure after the listing" >&2\n exit 1\nfi\nexec %q "$@"\n' \
"$real_git" "$real_git" > "$CASE/failing-git/git" || die "write the failing git failed"
chmod +x "$CASE/failing-git/git" || die "chmod the failing git failed"
local real_hook14="$HOOK"
HOOK="$stage14/hooks/$(basename "$real_hook14")"
RC=0
OUT="$(cd "$SHARED" && env PATH="$CASE/failing-git:$CASE/bin:$PATH" FAKE_GH_DIR="$CASE" LEFTOVER_BUDGET_SEC=3600 \
bash "$HOOK" </dev/null 2>"$CASE/hook.err")" || RC=$?
HOOK="$real_hook14"
ctx="$(context)"
if [[ $RC -eq 0 && ! -e "$calls14" ]] \
&& [[ "$ctx" == "Session-start status — could not check this repository"*"git worktree list --porcelain -z"*"exited 1"* ]]; then pass
else fail "c14: RC=$RC OUT=$OUT ERR=$(cat "$CASE/hook.err") calls=$(if [[ -e "$calls14" ]]; then cat "$calls14"; fi)"; fi
echo "15. BatchMode reaches the owner scripts whether or not GIT_SSH_COMMAND is already set"
mk_case c15
local stage15="$CASE/stage15" calls15="$CASE/calls15" set_line unset_line
stage_recording_plugin "$stage15" "$calls15"
local real_hook15="$HOOK"
HOOK="$stage15/hooks/$(basename "$real_hook15")"
run_hook "$SHARED" GIT_SSH_COMMAND="ssh -i /keys/case15"
set_line="$(head -n 1 "$calls15")"
: > "$calls15" || die "clear calls15 failed"
run_hook "$SHARED"
unset_line="$(head -n 1 "$calls15")"
HOOK="$real_hook15"
if [[ "$set_line" == "prune-worktrees.sh ssh -i /keys/case15 -o BatchMode=yes" \
&& "$unset_line" == "prune-worktrees.sh ssh -o BatchMode=yes" ]]; then pass
else fail "c15: set=$set_line unset=$unset_line ERR=$ERR"; fi
echo "16. a hooks directory whose name ends in a newline still reaches its owner scripts"
# A `$(dirname ...)` capture drops the newline, and the hook then looks for
# its owner scripts beside a directory that does not exist (#487).
if mkdir "$TMP/nl-probe16${nl}" 2>"$TMP/nl16.err"; then
rmdir "$TMP/nl-probe16${nl}" || die "rmdir the newline probe failed"
mk_case c16
quiet "wt add" git -C "$SHARED" worktree add -q --detach "$ROOT/spent" origin/main
age_wt "$ROOT/spent" "$AGED_MTIME"
local stage16="$CASE/stage16"
stage_plugin "$stage16" "hooks${nl}"
cp "${HERE}/../../skills/herdr-foreman/bounded-run.sh" "${HERE}/../../skills/herdr-foreman/prune-worktrees.sh" \
"${HERE}/../../skills/herdr-foreman/prune-remote-branches.sh" "$stage16/skills/herdr-foreman/" \
|| die "stage the owner scripts failed"
mkdir -p "$stage16/skills/release" || die "mkdir the staged release skill failed"
cp "${HERE}/../../skills/release/origin-repo.py" "$stage16/skills/release/" || die "stage origin-repo.py failed"
local real_hook16="$HOOK"
HOOK="$stage16/hooks${nl}/$(basename "$real_hook16")"
run_hook "$SHARED"
HOOK="$real_hook16"
if [[ $RC -eq 0 && -z "$OUT" && ! -e "$ROOT/spent" ]]; then pass
else fail "c16: RC=$RC OUT=$OUT ERR=$ERR"; fi
else
echo "16. skipped: this filesystem refuses a name ending in a newline ($(cat "$TMP/nl16.err"))"
fi
echo
echo "passed=${PASS} failed=${FAIL}"
(( FAIL == 0 ))
}
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
main "$@"
fi.tessl-plugin
hooks
rules
skills
adopt-fork-pr
herdr-foreman
classify
foreman
references
templates
tests
herdr-standup
migrate-to-plugin
onboard-repo
release
references
tests