Worktree discipline, per docs/adr/0022-worktree-discipline.md.
THE RULE: one task per worktree, and the worktree is removed when its task lands. Worktrees live OUTSIDE the repo root so nothing here can dirty the shared tree, and off /tmp (a 32 GB tmpfs that dies on reboot).
tools/wt.sh new
test runs TWO gates: TEST_CMD below (our three crates, --lib only) and
tools/lib_gate.sh (vendor/dormouse-fused, a separate cargo workspace, every crate
on ndarray). Either red fails the worktree. lib_gate.sh also runs standalone.
Builds are SERIAL. One heavy thing at a time (AGENTS.md doctrine 4): a cold
worktree target dir compiles the whole burn+cubecl stack, and a mold link
spikes tens of GB, so test refuses to start while another cargo is running
rather than racing it.
#!/usr/bin/env bash
THE RULE: one task per worktree, and the worktree is removed when its task
Section titled “THE RULE: one task per worktree, and the worktree is removed when its task”lands. Worktrees live OUTSIDE the repo root so nothing here can dirty the
Section titled “lands. Worktrees live OUTSIDE the repo root so nothing here can dirty the”shared tree, and off /tmp (a 32 GB tmpfs that dies on reboot).
Section titled “shared tree, and off /tmp (a 32 GB tmpfs that dies on reboot).”tools/wt.sh new create a worktree for one task, off HEAD
Section titled “tools/wt.sh new create a worktree for one task, off HEAD”tools/wt.sh test the real test command, inside that worktree
Section titled “tools/wt.sh test the real test command, inside that worktree”tools/wt.sh rm land or discard the task, then drop the worktree
Section titled “tools/wt.sh rm land or discard the task, then drop the worktree”tools/wt.sh list what exists
Section titled “tools/wt.sh list what exists”test runs TWO gates: TEST_CMD below (our three crates, --lib only) and
Section titled “test runs TWO gates: TEST_CMD below (our three crates, --lib only) and”tools/lib_gate.sh (vendor/dormouse-fused, a separate cargo workspace, every crate
Section titled “tools/lib_gate.sh (vendor/dormouse-fused, a separate cargo workspace, every crate”on ndarray). Either red fails the worktree. lib_gate.sh also runs standalone.
Section titled “on ndarray). Either red fails the worktree. lib_gate.sh also runs standalone.”Builds are SERIAL. One heavy thing at a time (AGENTS.md doctrine 4): a cold
Section titled “Builds are SERIAL. One heavy thing at a time (AGENTS.md doctrine 4): a cold”worktree target dir compiles the whole burn+cubecl stack, and a mold link
Section titled “worktree target dir compiles the whole burn+cubecl stack, and a mold link”spikes tens of GB, so test refuses to start while another cargo is running
Section titled “spikes tens of GB, so test refuses to start while another cargo is running”rather than racing it.
Section titled “rather than racing it.”set -u REPO=/home/sehaxe/dormouse WT_ROOT=${WT_ROOT:-/home/sehaxe/dormouse-wt}
The repo’s real check. --lib only: bare cargo test also builds examples,
Section titled “The repo’s real check. --lib only: bare cargo test also builds examples,”and the tree has unbuildable ones.
Section titled “and the tree has unbuildable ones.”TEST_CMD=“cargo test -p dormouse-core -p dormouse-data -p dormouse-train –lib”
die() { echo “wt: $*” >&2; exit 1; } slug() { echo “$1” | tr ’A-Z ’ ‘a-z-’; }
Uncommitted work in the shared tree is NOT in a new worktree. A worktree is
Section titled “Uncommitted work in the shared tree is NOT in a new worktree. A worktree is”a checkout of a COMMIT; if the thing you need exists only as a dirty file,
Section titled “a checkout of a COMMIT; if the thing you need exists only as a dirty file,”this script will hand you a tree without it and you will debug the wrong
Section titled “this script will hand you a tree without it and you will debug the wrong”build. Say so out loud rather than let it surprise you.
Section titled “build. Say so out loud rather than let it surprise you.”warn_dirty() {
local n
n=$(git -C “$REPO” status –porcelain | wc -l)
[ “$n” -gt 0 ] || return 0
echo “wt: NOTE the shared tree has $n dirty paths. They are NOT in this worktree.”
local missing
missing=$(git -C “$REPO” status –porcelain | awk ‘{print $2}’
| grep -E ‘^(vendor/|Cargo.(toml|lock)$)’ || true)
if [ -n “$missing” ]; then
echo “wt: WARNING uncommitted manifest/vendor changes are the ones that change the build:”
echo “$missing” | sed ‘s/^/wt: /’
echo “wt: This worktree builds from HEAD, which may be a DIFFERENT dependency graph.”
echo “wt: Land (or commit) those first if the task needs them.”
fi
}
case “${1:-}” in
new)
[ $# -eq 2 ] || die “usage: wt.sh new -p cannot reach them: the crossing is
# a second cargo run from inside the fork. Without this branch the whole
# technology library - including the 31 integration targets the --lib
# above never builds - was ungated locally.
tools/lib_gate.sh “$path” || rc=$?
echo “wt: lib_gate exit $rc”
[ “$rc” -eq 0 ] || die “gate red: see above”
;;
rm)
[ $# -eq 2 ] || die “usage: wt.sh rm