Files
octopus-workflow/core/rules/stash-discipline.md
T

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_md per-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

  1. 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 staged
    

    The 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.

  2. 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>
    
  3. 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 later
    

    Keep the patch under /tmp/octopus/ so it survives the session but is never accidentally committed (see wiki page rules/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>-base
    

    This is the pattern the verify skill uses for the regression-vs-baseline classification check. The script registers the worktree, symlinks node_modules from the source checkout when bun.lock matches, and the sweep backstop reclaims worktrees abandoned by dying sessions — bare git worktree add /tmp/octopus/... has no such recovery ([org-internal #2790]).

Exceptions

  • Running git stash list / git stash show to 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 bare git stash).
  • The TUI's prompt stash (prompt.stash keybind, 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.ts adds /\bgit\s+stash\b(?:\s+(?:push|pop|apply|drop|clear|create|store|branch)|\s*$)/ to SAFETY_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_md injection whitelist (2026-08-27, see header); the L0 guard enforces regardless.
  • L2 (skills): any skill that suggests git stash is a defect — file it under Kind/Enhancement with the retrospective label (verify SKILL.md already uses script/scratch-worktree.sh instead).

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].