4.8 KiB
Stash Discipline (mandatory)
Enforcement layer: L0 tool-enforced (bash guard + husky hooks) — this file is reference/documentation, NOT part of any
agents_mdper-turn injection whitelist since the 2026-08-27 injection-budget batch-1. Do not re-add it to a whitelist; the guard enforces regardless.
In the octopus worktree model, multiple parallel sessions share a single git
repository. The git stash stack is repository-global (stash@{0},
stash@{1}, …) and is NOT isolated per worktree. When two sessions in
different worktrees run git stash / git stash pop, they silently index
each other's entries and one session's pop returns the other session's
content — or drop/clear wipes uncommitted work belonging to a session in
a different worktree.
This failure mode has already destroyed completed work in production ([org-internal #1655] / [org-internal #1629] — a finished 25-test implementation overwritten on the shared stack).
Iron Law: NEVER use git stash (or git stash pop / push / drop /
clear / apply) inside an octopus worktree.
The bash tool enforces this at L0 via a safety-floor pattern that blocks
git stash invocations. Use one of the following instead — they are
worktree-local and cannot be clobbered by a parallel session:
Approved alternatives
-
WIP commit on the current workflow branch (preferred for mid-iteration checkpoints):
git add -A git commit -m "wip: <slug> — <one-line state>" # … later, before the real commit: git reset --soft HEAD~1 # un-commit but keep the work stagedThe per-iteration commit model already expects these to be cleaned up by amend / interactive rebase before merge, so a
wip:commit is never a long-term smell. -
Throwaway side branch (preferred when you must switch branches and cannot commit yet):
git switch -c wip/<slug>-<topic> git add -A && git commit -m "wip: <slug> — <one-line state>" git switch - # back to the workflow branch # … later: git cherry-pick wip/<slug>-<topic> # or merge / reset as needed git branch -D wip/<slug>-<topic> -
git diff > /tmp/octopus/<slug>.patch(last resort, when even a WIP commit is impossible — e.g. the index is in a conflicted state you do not want to disturb):git diff --binary > /tmp/octopus/<slug>.patch git apply /tmp/octopus/<slug>.patch # restore laterKeep the patch under
/tmp/octopus/so it survives the session but is never accidentally committed (see wiki pagerules/temp-files, L2 on-demand).
What about switching away from a dirty tree?
If you must git checkout <base> to reproduce a failure but the worktree is
dirty, do not reach for stash. Instead:
-
WIP-commit first (option 1), or
-
Use the lifecycle-managed scratch-worktree script ([org-internal #2790]) to materialise the base commit in a separate worktree and run the failing test there:
bash script/scratch-worktree.sh create <slug>-base <base> bash script/scratch-worktree.sh remove <slug>-baseThis is the pattern the
verifyskill uses for the regression-vs-baseline classification check. The script registers the worktree, symlinksnode_modulesfrom the source checkout whenbun.lockmatches, and thesweepbackstop reclaims worktrees abandoned by dying sessions — baregit worktree add /tmp/octopus/...has no such recovery ([org-internal #2790]).
Exceptions
- Running
git stash list/git stash showto inspect the stack (no mutation) is allowed — it cannot lose work. The safety-floor pattern only blocks mutating subcommands (push,pop,apply,drop,clear,create,store,branch, and baregit stash). - The TUI's prompt stash (
prompt.stashkeybind,usePromptStash) is unrelated — it stashes input text in memory, not git refs, and is not affected by this rule.
Enforcement
- L0 (tool-enforced):
packages/octopus/src/tool/bash.tsadds/\bgit\s+stash\b(?:\s+(?:push|pop|apply|drop|clear|create|store|branch)|\s*$)/toSAFETY_FLOOR_PATTERNS. Safety-floor items cannot be unblocked via configuration; bypass requires--no-security-config. - L1 (this file): reference documentation only — removed from every
agents_mdinjection whitelist (2026-08-27, see header); the L0 guard enforces regardless. - L2 (skills): any skill that suggests
git stashis a defect — file it under Kind/Enhancement with theretrospectivelabel (verifySKILL.md already usesscript/scratch-worktree.shinstead).
If a parallel-session stash collision happens again despite this rule, treat
it as a Sev-2 process incident: stop work, recover via
git fsck --unreachable / git log -g --walk-reflogs stash, open a follow-up
referencing [org-internal #1655].