Skip to content

T-XKWA-start-task-drops-orphan-stashes

Status: closed/obsoleted · Impact: low · Complexity: small

Auto-generated from a /sdlc:task-work post-mortem. Review and promote to open/ready before picking up.

When /sdlc:task-work Step 4 (or its start_task.ts helper) stashes a working-tree dirty file before rebasing, the stash can outlive the file: if the path doesn’t exist on the post-rebase tree (because it was deleted, moved, or restructured upstream), the stash becomes orphaned and accumulates in git stash list indefinitely. Cite T-5VN7-pr-check-cursor-bootstrap-misses-existing-comments — the sub-agent stashed an unrelated dirty docs/decisions/0001-github-ref-leases.md that no longer existed (the file was restructured into a folder) on the post-rebase tree, and stash@{0} is still sitting there. start_task.ts could detect this class of stash before stashing (or right after rebase) and prompt to drop.

LocationRole today
plugin/skills/task-work/start_task.tsStashes any dirty working-tree files before performing the start-of-task rebase; does not inspect the stash post-rebase for orphan-file references.
plugin/skills/task-work/SKILL.md (Step 4)Documents the stash step; does not call out the orphan-stash risk.
plugin/skills/task-work/tests/start_task.test.tsExercises start-task flows; no fixture for the orphan-stash case.

Today the operator only discovers orphaned stashes by running git stash list weeks later, by which point the context for what they contain is lost.

start_task.ts (or a Step 4 hook it shells out to) checks for pre-existing stashes whose stashed paths do not exist on the post-rebase tree. When it finds one, it prints the stash entry + contained paths and prompts the operator to drop it (or, when running non-interactively, logs the warning and proceeds without dropping — never silently dropping work).

The check is bounded: only stashes the script itself created (or all stashes in the list, with the orphan-file heuristic to filter relevance) — implementer’s call. The prompt happens at the end of Step 4 so the operator sees the question while task context is hot.

  1. Decide on detection scope: only stashes whose message starts with the marker start_task.ts writes, or every stash in the list with an additional file-existence filter. The first option is tighter; the second handles operator-created stashes too.
  2. Implement the post-rebase scan: git stash list --format=%gd %gs, then for each entry, git stash show --name-only <stash> and check each path against the post-rebase tree. If all paths are missing, mark the stash as orphan-candidate.
  3. Add the interactive prompt (TTY) / non-interactive log (no TTY) path. Never drop a stash without operator approval.
  4. Add a fixture and a regression test that exercises both branches (TTY-prompt-approved and non-interactive-log-only).
LocationKindChange
plugin/skills/task-work/start_task.tsmodifyAfter the rebase succeeds, scan stash list for orphans and surface them.
plugin/skills/task-work/tests/start_task.test.tsmodifyAdd a fixture/test for the orphan-stash detection path.
plugin/skills/task-work/SKILL.mdmodifyStep 4 prose mentions the new orphan-stash check.
  • AC-1: After start_task.ts’s rebase completes, the script scans git stash list for stashes whose stashed paths are all missing on the post-rebase tree.
  • AC-2: When orphan stashes are found AND stdout is a TTY, the script prompts the operator to drop or keep each one.
  • AC-3: When orphan stashes are found AND stdout is NOT a TTY, the script logs the orphans (basename + paths) to stderr and proceeds — never silently dropping.
  • AC-4: A regression test exercises both branches with a fixture that creates a stash, performs a rebase that removes the stashed file, and asserts the post-rebase behavior matches the TTY mode.
  • Cleaning up orphaned stashes from BEFORE this task ships. The detection is forward-looking; existing orphan stashes get cleaned by hand or by a separate sweep skill.
  • Reconciling stash contents that conflict with the post-rebase tree (the operator may want to re-apply the change to the new location). The prompt only handles drop-or-keep, not migration.
  • none

Spawned by /sdlc:task-work post-mortem of T-5VN7-pr-check-cursor-bootstrap-misses-existing-comments on 2026-05-23.

Bullet: The sub-agent stashed an unrelated working-tree dirty file that turned out to no longer exist on the post-rebase tree. The stash is still in the stash list and orphaned. start_task.py (or a Step 4 hook) could check for pre-existing stashes referencing files that no longer exist on the target rebase and prompt to drop them. Keywords searched: working-tree, pre-existing, post-rebase, referencing, start_task, sub-agent, unrelated, orphaned Excluded: 2026-05-21-pr-check-cursor-bootstrap-misses-existing-comments Top candidates (score / status / headline):

  • 26 / closed/done / 2026-05-20-task-work-sub-agent-verdict-contract-clarity — Tighten task-work sub-agent verdict contract so ensure-ready’s READY marker isn’t mistaken for task-work’s final verdict
  • 22 / closed/done / 2026-05-21-start-task-preserves-readiness-stamp — start_task.py should preserve readiness_verified_at across rebase
  • 19 / closed/done / 2026-05-19-extract-start-task-script — Extract task-work Step 5b into scripts/start_task.py
  • 19 / planning/draft / 2026-05-21-audit-entities-baseline-allow — audit_entities.py: distinguish pre-existing drift from PR-introduced drift
  • 18 / planning/draft / 2026-05-21-start-task-handles-frontmatter-rebase-cleanly — start_task.py auto-merges frontmatter on stamp/start rebase conflict Decision: SPAWNED

← Back to Tasks