Files

114 lines
4.8 KiB
Markdown

## 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):
```bash
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):
```bash
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):
```bash
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
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].