---
name: subagent-pre-existing-misattribution
description: |
  Catch per-task subagent reviewers misattributing test failures CAUSED by an
  earlier task as "pre-existing baseline" failures. Use when: (1) a multi-task
  subagent-driven plan reports "N pre-existing failures, unrelated" across
  consecutive tasks and the count never changes, (2) an architectural / final
  reviewer at the end catches assertions that should have been updated 5 tasks
  ago, (3) an implementer reports "verified pre-existing on clean tree by
  running git stash" but the breaking change is already committed on the
  branch, (4) you're building or executing a multi-task plan with subagent
  reviewers that compare suite-wide pass/fail counts to a "baseline." Root
  cause: `git stash` only stashes UNCOMMITTED changes — it does NOT reset to
  mainline. Stashing on a branch where the offending commit has already landed
  leaves the working tree identical to the branch state. The "clean tree"
  check verifies nothing. Fix: subagent reviewers must verify "pre-existing"
  by `git diff origin/main` or `git show origin/main:<test_file>` for the
  specific failing tests — not by `git stash`. The orchestrator should
  challenge any "verified on clean tree" claim that doesn't cite the exact
  ref.
author: Claude Code
version: 1.0.0
date: 2026-05-07
---

# Subagent-Driven Development: Pre-Existing Failure Misattribution

## Problem

In subagent-driven development, each task's reviewer evaluates spec compliance + code quality for THAT task in isolation. When the implementer or reviewer runs the full suite and finds N failures, they look up whether those failures are "new from this task" or "pre-existing baseline." If they classify them wrong, the failures get carried forward as "known unrelated failures" through every subsequent task — and the final architectural reviewer is the only checkpoint that catches the misattribution.

The specific failure mode: an early task removes an item from a list (e.g., a sidebar nav entry, a collection of dashboard cards). Other test files have HARDCODED COUNT ASSERTIONS for that list (`assert count == 5`) that nobody notices because:

1. The implementer of the breaking task fixes the parametrize lists they SEE but misses count assertions in OTHER test files.
2. The implementer reports "8 failures, all pre-existing — verified on clean tree."
3. Subsequent task implementers/reviewers see "baseline = 8 failures" and treat anything matching that count as expected.
4. The architectural final reviewer compares against the actual mainline branch (not the branch tip pre-commit) and discovers N of those "pre-existing" failures are actually caused by the early task.

## Context / Trigger Conditions

- Multi-task plan executed via `superpowers:subagent-driven-development` or similar
- Reviewer report contains "N pre-existing failures, verified unrelated to this task"
- Reviewer cites `git stash` or "clean tree check" as verification mechanism
- Failure count is suspiciously stable across consecutive tasks (e.g., "8 pre-existing" through Tasks 7, 8, 9, 10 — even after the suite grew)
- A test file references a count of items in a list that the plan modifies (sidebar tabs, library cards, sub-nav entries, primary routes, etc.)
- Final architectural review surfaces failures that map directly to changes from earlier tasks

## Why `git stash` is Insufficient

`git stash` saves the working directory's **uncommitted** modifications and restores HEAD to a clean state. But on a feature branch where the breaking commit has already landed, the working directory IS HEAD — there's nothing to stash. The "clean tree" the stash produces is identical to the dirty tree, because the breaking change is part of HEAD itself.

```
$ git status                    # already clean — no uncommitted changes
$ git stash                     # "No local changes to save"
$ pytest tests/ -q              # same failures as before — they're committed
$ # but reviewer reports: "verified failures pre-existing on clean tree"
```

The reviewer isn't lying — `git stash` ran and the suite ran "on the clean tree" — but that "clean tree" is the post-breaking-change branch state, not mainline.

## Solution

### For implementers/reviewers

When reporting "N failures, all pre-existing":

1. **Cite the exact mainline ref you compared against**, not "clean tree":
   ```bash
   git fetch origin main                    # ensure mainline ref is current
   git stash 2>/dev/null                    # save WIP if any
   git checkout origin/main -- tests/       # restore tests dir to mainline state
   pytest tests/<failing-file> -q           # verify failures on actual mainline
   git checkout HEAD -- tests/              # restore branch state
   ```
2. **Or compare the specific test file** between branch and mainline:
   ```bash
   git diff origin/main..HEAD -- tests/<file>
   ```
   If the file has changed in your branch, "pre-existing" claims need extra scrutiny.
3. **Run the failing tests against `origin/main` directly**:
   ```bash
   git worktree add /tmp/main-check origin/main
   cd /tmp/main-check && pytest tests/<failing-file>
   git worktree remove /tmp/main-check
   ```

### For orchestrators

When a subagent reports "N pre-existing failures":

- Reject the report if the subagent didn't cite the mainline ref used for verification.
- Cross-check by maintaining a baseline FAILURE LIST (test names, not just count) at the start of execution. If a "pre-existing" failure isn't in the original baseline list, it was introduced by the plan.
- Run a final-task suite-wide comparison BEFORE opening the PR:
  ```bash
  git fetch origin main
  diff <(pytest tests/ --co -q 2>/dev/null) <(git checkout origin/main -- tests/ && pytest tests/ --co -q 2>/dev/null)
  ```

### For plan authors

If your plan removes items from a UI list (sidebar tabs, library cards, sub-navs, primary routes), add an explicit task step:

```
- [ ] Grep for hardcoded COUNT assertions on the affected list. Update both the
      parametrize/fixture lists AND any `assert count == N` integer assertions.
      Search: `rg "count == [0-9]" tests/ | grep -i <list_concept>`.
```

## Verification

A claim of "pre-existing failures" is verified when:

1. The reviewer cites `git diff origin/main..HEAD -- <test_file>` showing the file unchanged.
2. OR the reviewer ran the same test on `origin/main` directly (worktree, checkout, or `git show origin/main:<file>` extraction) and observed the same failure.
3. AND the failure name (not just count) appears in a baseline list captured BEFORE plan execution started.

## Example

In one session, a 12-task plan executed via subagent-driven-development for issue #272 (Drivers tab + per-value drilldown):

- Task 6 removed the Methods card from the Library hub + Methods sub-nav entry.
- Task 6's implementer/reviewer fixed the parametrize lists they saw but missed `tests/test_loading_overlay_wiring.py` lines 109 and 133 with `assert count == 5` for `.library-card` and `.library-subtab`.
- Task 7's full-suite run reported 8 failures, including 5 from `test_loading_overlay_wiring.py`.
- Task 10's implementer reported "8 pre-existing — verified by running them on `git stash`'d clean tree." `git stash` saved nothing (no uncommitted changes); the suite ran identically.
- Tasks 8, 9, 10 all carried "8 pre-existing failures" forward in their reports.
- The final architectural reviewer compared against `origin/main` and surfaced 5 of those 8 failures as direct consequences of Task 6.

Fix landed in commit `0361a582`: change `5` → `4` in two places + comment refresh.

Total cost of misattribution: ~4 task cycles where reviewers didn't catch the issue + final-review cycle to surface it. Could have been caught at Task 6 review with the right verification framing.

## Notes

- This is a SISTER pattern to `lint-allowlist-substring-stale-after-rewrite` (which covers stale STRING substring assertions); this skill covers stale NUMERIC count assertions specifically.
- The git-worktree variant of the verification is most robust but slow. The `git diff origin/main..HEAD -- <file>` quick-check is sufficient for most cases.
- Subagent reviewer prompts in `superpowers:subagent-driven-development` should require the verification ref. Consider amending the reviewer template to explicitly forbid "verified on clean tree" and require "verified vs origin/main at SHA <X>."
- This pattern compounds across long plans: if Task K introduces N stale assertions and the misattribution survives until Task K+5's review, a third of the plan's review cycles operated on a wrong baseline.

## References

- Originated session: PR #303 final-review fix at commit `0361a582` (issue #272)
- Related skill: `lint-allowlist-substring-stale-after-rewrite` (string-version sibling)
- Related skill: `multi-agent-skill-silent-phase-compression` (different failure mode in multi-agent orchestration)
