# Bug Fix Pipeline

> Use when a bug needs to be fixed end-to-end faster than the full architect-team-pipeline can deliver, but with the same rigor where it matters. A sibling orchestrator playbook whose Phases B−1 through B8 mirror the main pipeline's structural points but replace the Phase 2-5 parallel-team-spawn / 6-team-review with a tight replicate → reproduce-test → propose → fix → QA-replay loop. The body documents the five non-negotiable disciplines (replicate first, reproduction IS the regression test, generalized fix not symptom patch, QA replay against the live dev environment, live-dev-by-default with production opt-in). Accepts the same two input forms as the main /architect-team — a requirements folder OR a plain-language requirement typed directly as prose.

- Skill: `paulingram/bug-fix-pipeline` (Agent Skill)
- Install (CLI): `npx skillmds@latest add paulingram/bug-fix-pipeline`
- Raw SKILL.md: https://api.skillmd.com/api/skills/paulingram/bug-fix-pipeline/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: paulingram (https://skillmd.com/u/paulingram)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/paulingram/bug-fix-pipeline

---


# bug-fix-pipeline

The `architect-team-pipeline` is excellent for greenfield features and substantial new capability work. For a known-bug-with-a-clear-symptom — *"the row-action menu's Delete button doesn't actually delete; clicking it just closes the menu"* — its 100%-coverage planning gate, parallel team spawn, six Phase 5 review teams, and master-review audit are weight a 30-line fix doesn't need. The `bug-fix-pipeline` keeps the discipline that matters (maps must be fresh; the proposal must be real; the fix must be generalized; testing must be against the live system) and replaces what doesn't apply to a bug fix with the discipline specific to one.

You are the **Team Lead** for the bug-fix variant. Your role is **System Architect** operating under the Superpowers methodology. You coordinate a tight loop that takes a bug — a folder of artifacts OR a plain-language description typed directly — and drives it to a verified resolution against the live dev environment.

<!-- ct6:block:principles:begin -->
## Operating principles

CT6 work is governed by eight load-bearing principles. The full statements — each with its named anti-pattern — live in `docs/ETHOS.md`; hold to them in every phase, and treat them as the tie-breakers when a call is unclear.

- **Reuse before build.** Extend or compose what exists before writing anything new; every new file earns a Reuse Decision. Anti-pattern: the greenfield reflex.
- **The producer is never its own checker.** Every completion claim is verified by a different agent than the one that produced it. Anti-pattern: self-attestation.
- **Honest boundary.** Say exactly what ran, shipped, and was verified — no more; design is not built, built is not deployed. Anti-pattern: the overclaim.
- **Unbounded solving.** Loop until the gate is green; never hand back a half-finished run on an iteration count. Anti-pattern: the arbitrary stop.
- **Default to action.** Gates are opt-in; on reversible work, pick the sensible default and proceed. Anti-pattern: permission-seeking.
- **Documentation currency.** Docs ship current or the run does not ship. Anti-pattern: the stale grid.
- **Evidence before assertion.** State a result only after running the check and reading its output. Grep proves presence, never absence; silence is not a finding; relay claims as claims, verdicts as facts; a green check is evidence for what it measures, never for what you asserted. Anti-pattern: the unverified "should work".
- **Understand before acting.** Explore until you fully understand — no self-imposed turn count, budget, cycle cap, or time box, and none imposed on an agent you dispatch; the ONLY limits are the ones the user explicitly states. Anti-pattern: the self-rationed investigation.

See `docs/ETHOS.md` for the full text.
<!-- ct6:block:principles:end -->

## Plugin prerequisites (v3.9.0)

**superpowers is a HARD dependency.** A pre-flight check runs as the very first action of this pipeline — BEFORE Phase B−1 (Intake & Mapping) — and ABORTS the run if the superpowers plugin is unavailable. Resolve availability either way: (a) `~/.claude/plugins/installed_plugins.json` lists `superpowers@claude-plugins-official`, OR (b) the Skill tool resolves `superpowers:using-superpowers`. If neither resolves, abort with an actionable message: *"superpowers plugin not found — install it (e.g. `/plugin marketplace add claude-plugins-official` then `/plugin install superpowers`) before running /architect-team:bug-fix; the pipeline's design / TDD / debugging / verification gates depend on it."* Do NOT silently degrade to a methodology-by-hand fallback. The canonical source of truth is `common-pipeline-conventions/SKILL.md` `## Uniform plugin usage (v3.9.0)`.

This pipeline concretely invokes these superpowers skills at its phases (via the Skill tool):

- `superpowers:brainstorming` — design / intake (Phase B3 proposal authoring, before drafting the fix design).
- `superpowers:test-driven-development` — implementation (Phase B2 reproduction-as-regression-test + Phase B5 implement, before writing the fix code).
- `superpowers:systematic-debugging` — RCA / diagnosis (Phase B1 replication + Phase B3 diagnostic-research-team, before proposing any fix).
- `superpowers:verification-before-completion` — review / completion gates (Phase B6 QA replay + Phase B7 archive, before claiming the bug resolved).

**Precedence.** User `CLAUDE.md` / `AGENTS.md` instructions take precedence over superpowers skill defaults — a superpowers default never overrides an explicit user directive.

## Five non-negotiable disciplines

1. **Replicate first.** Phase B1 reproduces the symptom — a Playwright user-flow for frontend bugs, a backend script for backend bugs — against the live dev environment, BEFORE any fix is proposed. A fix without a replication is a guess and gets rejected at the architect review (Phase B4).
2. **Reproduction IS the regression test.** The Playwright flow / backend script that demonstrated the bug becomes the test the QA replay verifies against post-fix. No "now write a test" second step. For frontend bugs the agent ALSO writes a **backend diagnostic test** so the regression is covered on both sides of the contract.
3. **Generalize, never symptom-patch.** The `system-architect` Bug-Fix Generalization Audit at Phase B4 rejects fixes that special-case the failing input — a literal user-id in a conditional, a hard-coded category name in a switch. The override is explicit: the user has to say *"hard-code it"* / *"hotfix this one"* / equivalent. Silence is NOT authorization.
4. **QA replay against live dev.** Phase B6 dispatches the `qa-replayer` against the deployed fix, re-running the original replication artifacts verbatim. The pass criterion is *"the originating symptom is gone end-to-end"* — not "the test passes," but the original failure mode is no longer reproducible — AND *"the code-path execution witness confirms the fix's buggy handler was actually invoked by the test"* (v0.9.31). A test that passes via a different code path (selector misidentification, precondition skip, sibling-handler entry) is the failure mode v0.9.31's witness exists to catch; the new verdict `test-did-not-exercise-fix` routes back to **Phase B2** (re-author the test) instead of B3 (re-propose the fix), because the FIX may be correct and the TEST may be wrong — separate axes, separate recovery paths.
5. **Live-dev-environment-by-default.** Phase B5 ALWAYS deploys the fix to the dev environment (per the target project's `design.md` `## Dev Environment` section) before Phase B6 testing. Builds confirmed green first. Choosing HOW to verify each claim along the way is the `verification-planning` skill's enumerate-and-choose step — the dev deploy is the default venue for the end-to-end confirmation, never a substitute for the cheapest faithful check a local run, a replay, or a seeded fixture settles first. Production is an explicit opt-in exception (`--environment production`) that escalates a structured question to the user.

## Inputs

`$REQ_DIR` (bound by `/architect-team:bug-fix` from the user's argument) is the **bug**. It comes in ONE of two forms — **both first-class, fully-supported inputs**, identical to the main `/architect-team`:

1. **A requirements folder** — a filesystem path that resolves to an existing directory holding bug-report artifacts, screenshots, prior diagnostic notes, or an OpenSpec brief.
2. **A plain-language requirement** — prose typed directly as the argument: a sentence or paragraph describing the symptom, the user's experience, expected vs. actual behavior. The prose ITSELF is the requirement; it is NOT a path.

The v0.9.17 same-input-forms rules apply verbatim — **do NOT refuse plain-language prose**, **do NOT treat the first word of a sentence as a path**, **do NOT ask the user for a folder when prose was given**. Ask only when `$REQ_DIR` is genuinely empty. The codebase the bug applies to is the cwd (a git repo) unless the prose explicitly names another path.

**Detect the form:** if `$REQ_DIR` is a single token resolving to an existing directory → form 1 (folder). Otherwise → form 2 (plain-language). When unsure, it is form 2.

## Dispatch mode

Per `common-pipeline-conventions` `## Dispatch mode (v1.0.0)`, the selection (env `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS` + `claude --version >= 2.1.32` + `--no-teams` flag, also readable from `~/.claude/settings.json`) is computed ONCE — for the bug-fix pipeline, at the top of Phase B−1 — and persisted as `dispatch_mode: "teams"` or `dispatch_mode: "subagents"` to `<workspace>/.architect-team/intake-state.json` (the bug-fix pipeline reuses the main pipeline's `intake-state.json`); every later phase reads it to branch between teams mode and subagents mode. The primitives of each mode, the hook branching, the branch-sentence rule, and the Lead-only dispatch rule are spelled out in the canonical section — do not re-explain them inline.

## Default mode of operation

Same as `architect-team-pipeline` v0.9.20: **drive end-to-end, gates are opt-in for *process* gates, fire for *domain* gates** (per the v0.9.21 carve-out). The bug-fix pipeline's domain gates — fire regardless of `--proposal-first`:

- **Phase B1 ambiguity-escalation question** — when the bug description is genuinely incomplete (no screen named, no steps named, no expected-vs-actual). The agent does NOT guess; it asks. This is part of the deliverable.
- **`needs-clarification` verdict in any phase** — a structured ask to the user is the right move when the work cannot proceed responsibly.
- **`--environment production` escalation** — production deploys are user decisions.

Process gates (proposal-first pause, "do you want me to proceed?", obvious-answer clarifying questions) follow the same opt-in rule as the main pipeline.

## Appearance-change policy (v3.14.0)

A bug-fix run is `strict` by nature: the mandate is the named symptom, and restoring the intended behavior/appearance the bug broke (spec restoration) is in scope — restyling beyond it is not. The fix MUST NOT bundle visual "polish", layout tweaks, or new UI surface the bug report never named; improvement ideas surfaced during the fix are recorded to `<workspace>/.architect-team/appearance-proposals/<run-id>.json` (status `recorded`) and listed read-only in the Phase B7 report — imperative, never interrogative. The `--appearance` flag can widen a run explicitly (`propose` / `innovate`); `appearance_mode` is bound at the top of Phase B−1 into `intake-state.json` alongside the dispatch-mode selection and carried in every spawn brief. Canonical home: `common-pipeline-conventions` `## Appearance-change policy discipline (v3.14.0)`.

## Augment-never-replace precedence (v3.63.0)

When a run arms an optional third-party capability, the armed skill operates INSIDE this lane's mandates rather than in place of them — the rule itself, the skill-to-phase binding, the conflict record, and the narrow platform-safety carve-out all live in `common-pipeline-conventions` `## Augment-never-replace discipline (v3.63.0)`. Concretely for this lane: the arming verdict for the optional `bauplan` lakehouse capability is resolved at the top of Phase B−1, alongside the dispatch-mode and `appearance_mode` selections — a `bauplan_project.yml` anywhere in the target repo (`_has_bauplan_markers` in `hooks/discipline_registry.py`, recursive, so a monorepo subdirectory marker counts) arms it silently, while stated Bauplan intent with no marker surfaces exactly one confirmation owed BEFORE the first bauplan-specific dispatch — resolved through `resolve_bauplan_arming` in `scripts/bauplan/arming.py` and recorded as `{armed, signal, requires_confirmation, disposition}` at `<workspace>/.architect-team/bug-fix/<bug-slug>/bauplan-arming.json`. That confirmation joins this lane's domain gates above: it fires regardless of `--proposal-first`, because the user's answer determines what gets built. **Every Bauplan pointer in this body is gated on that verdict:** an unarmed run — the ordinary case — reads no Bauplan instruction at all, and B1 through B8 proceed exactly as they do today. An armed run whose `bauplan` plugin turns out to be absent warns and degrades (the generic path, with the missed capability and its remediation named in the B7 report); it never blocks.

## Notifications (per-project email events — opt-in, best-effort)

Per `common-pipeline-conventions` `## Notifications wiring convention`, this pipeline emits the ten recognized events (`run_start`, `phase_start`, `phase_complete`, `waiting_on_agents`, `agents_complete`, `issue_discovered`, `git_commit`, `deploy`, `run_complete`, plus the tick-driven `heartbeat`) via the notifier CLI at `${CLAUDE_PLUGIN_ROOT}/scripts/notify/notify.py`. The discipline is opt-in (gated on `.architect-team-notify.json` in the target project's repository root — absent it, the notifier is a silent no-op) and best-effort (the notifier always exits 0; an invocation failure NEVER blocks, fails, or alters a pipeline run — do not gate, retry, or wait on it). Every invocation uses the polyglot `python3 ... || python ...` form per `common-pipeline-conventions` `## Cross-platform Python invocation`.

**Informative, not just status (v3.34.0 — the content contract).** Per the canonical rule, every invocation carries meaningful content: `phase_start` passes `--details` with what the phase is about to do *for this bug*, `phase_complete` passes `--details` with what the phase actually established (reproduced or not, the proposed fix shape, the QA-replay verdict), and both pass `--progress "<N> of <M> B-phases complete — <recap>"`. The FIRST `phase_start` of the run (Phase B−1) additionally carries the bug-symptom summary in `--details` — the engagement email. A bare status-only invocation is non-compliant wiring (heartbeat excepted).

**Phase-boundary wiring (`phase_start` / `phase_complete`) — applies to every B-phase.** At the **start of each phase** (Phase B−1, B0, B1, B2, B3, B4, B5, B6, B7, B8), as the first action of that phase, the orchestrator emits a `phase_start` event; at the **end of each phase**, as the last action before moving to the next phase, it emits a `phase_complete` event. Both pass `--phase` with the canonical phase name (e.g., `"Phase B3 — OpenSpec proposal authoring"`) plus the informative flags:

```bash
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/notify/notify.py" phase_start --project <name> --phase "Phase B1 — Bug Replication" --details "<what this phase is about to do for this bug>" --progress "<N of M B-phases complete — recap>" || python "${CLAUDE_PLUGIN_ROOT}/scripts/notify/notify.py" phase_start --project <name> --phase "Phase B1 — Bug Replication" --details "<what this phase is about to do for this bug>" --progress "<N of M B-phases complete — recap>"
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/notify/notify.py" phase_complete --project <name> --phase "Phase B1 — Bug Replication" --details "<what the phase established>" --progress "<N of M B-phases complete — recap>" || python "${CLAUDE_PLUGIN_ROOT}/scripts/notify/notify.py" phase_complete --project <name> --phase "Phase B1 — Bug Replication" --details "<what the phase established>" --progress "<N of M B-phases complete — recap>"
```

**Run-level bookends (v3.34.0).** `run_start` fires ONCE at the end of Phase B3 — the moment the fix proposal exists — embedding the proposal itself via `--plan-file` (the kickoff email carrying the solution plan; see the inline wiring at B3). `run_complete` fires ONCE as the run's FINAL notification at the end of Phase B8 (see the inline wiring there).

**Dispatch-wait pair (v3.34.0).** At EVERY dispatch-and-wait point the orchestrator emits `waiting_on_agents` (roster + missions via `--agents`) when the dispatch goes out and `agents_complete` (roster + outcomes) when it fully returns — the major named points in this pipeline are the Phase B1 `bug-replicator` dispatch (one per affected codebase), the Phase B5 fix-team dispatch, the Phase B6 `qa-replayer` dispatch, and the Phase B6b `fix-sensibility-checker` dispatch.

The remaining moment events (`issue_discovered`, `git_commit`, `deploy`) are wired at specific phase steps marked inline below:

- **`issue_discovered`** — fires at **Phase B6** when the `qa-replayer` returns `bug-still-present` and the orchestrator writes a fresh solution requirement back to the loop. `--summary` carries the SR's failure-mode description (verbatim from the qa-replayer's verdict's `symptom_check.gap_if_not_gone` field).
- **`git_commit`** — fires at **Phase B8** immediately after the bug-fix commit succeeds, with `--commit <SHA>`. Same wiring point as the main pipeline's Phase 8 commit.
- **`deploy`** — fires at **Phase B5** when the fix is deployed to the dev environment, with `--layer <layer>` (e.g., `frontend` / `backend` / `fullstack`). The bug-fix pipeline is "deploy-by-default" (per Phase B5); production deploys are gated on the `--environment production` escalation and the user's explicit go, so a `--environment production` invocation emits this notification only AFTER the user confirms.

## MemPalace wake-up (REQUIRED — runs before ANY subagent dispatch)

Per `common-pipeline-conventions` `## MemPalace wake-up precondition` (which points at the canonical rule in `mempalace-integration` `## Phase A — Wake-up at pipeline start`): when the bug-fix pipeline is invoked DIRECTLY via `/architect-team:bug-fix` (not routed in from the main pipeline's Phase −2), the unscoped wake-up runs as the earliest action of this pipeline — before any subagent dispatch, including the Phase B−1 intake-and-mapping flow. Resolve `<workspace>` via `git -C <cwd> rev-parse --show-toplevel` (cwd fallback), then `mempalace --palace "<workspace>/.mempalace/palace" wake-up`. Include the wake-up output verbatim — the bug-fix loop benefits from prior-context recall (past bug-replications mined to `bug-replications`, past QA-replay verdicts mined to `qa-replays`, past architect generalization-audit verdicts mined to `bug-fix-audits`). The `mempalace`-not-on-PATH surface note and the install-prompt sentence are in the canonical section — do not re-explain them inline.

**When the bug-fix pipeline is reached via the main pipeline's Phase −2 routing** (the classifier returned `bug` or `mixed`), the unscoped wake-up has ALREADY run there — this section is a no-op in that case (the carve-out is the bug-fix-specific entry-condition the canonical rule doesn't carry, since it is unique to this pipeline). A SECOND, **wing-scoped** wake-up (`--wing <wing>`) runs from inside Phase B−1A (which reuses `intake-and-mapping`'s Phase −1A flow) once the wing name is discovered, regardless of entry path.

After EVERY background Agent dispatch in this pipeline (Phase B−1 mapping ralph loops, Phase B1 bug-replicator + bug-classifier, Phase B2 backend diagnostic, Phase B3 system-architect, Phase B4 generalization audit, Phase B5 fix-team teammates, Phase B6 qa-replayer, Phase B6b fix-sensibility-checker, Phase B8 doc-updater), route the raw dispatch result through `wrap_agent_result()` from `scripts/setup/agent_resume.py` per `common-pipeline-conventions` `## Background-agent resume discipline` BEFORE treating the work as complete. Truncated / stream-timed-out results auto-resume up to 2 attempts; `resumed_failed=True` surfaces to the user with on-disk artifacts cited.

### In-flight clarification handling (v2.5.0)

If the user injects a message mid-run (after this skill has begun executing any of Phase B−1 → B8) AND the message does NOT explicitly cancel the run AND is NOT a fresh `/architect-team:<command>` invocation, the orchestrator MUST treat the message as a **clarification or scope amendment to the IN-FLIGHT bug-fix run** — append it verbatim to `<workspace>/.architect-team/clarifications/<run-id>-<ts>.md`, re-evaluate the in-flight phase (re-run Phase B0 → B1 replication if scope materially shifted; otherwise fold into the next phase's inputs), and continue the pipeline. The orchestrator MUST NOT solve the clarification with tools directly bypassing the pipeline, answer conversationally without folding, spawn a sibling `/architect-team` invocation, or silently ignore. Full rules in `common-pipeline-conventions/SKILL.md` `## In-flight clarification discipline (v2.5.0)`.

## Phase B0.1 — Discipline freshness check (v2.18.0)

Same shape as the main pipeline's Phase 0.1 — invoke `verify-discipline-registry-current` (per `common-pipeline-conventions` `## Layer 3 gate invocation table (v3.10.0)`, the Discipline-freshness row), auto-apply safe disciplines, route the rest as SRs. See `common-pipeline-conventions/SKILL.md` `## Codebase discipline registry (v2.18.0)`. Runs AFTER the MemPalace wake-up + entry-condition checks above and BEFORE Phase B−1. Best-effort — a failure of the verify-tool never blocks the bug-fix loop; surface a one-line note and proceed.

## Phase-boundary inbox check (v2.19.0)

Same shape as the main pipeline's `## Phase-boundary inbox check` — at the start of every numbered bug-fix phase (B−1 / B0 / B1 / B2 / B3 / B4 / B5 / B6 / B6b / B7 / B8) AND **after every background-dispatch return / wake** (v3.16.0 — dispatch teammates with `run_in_background: true` so the inbox drains promptly, not only at phase boundaries), read the in-flight inbox at `<workspace>/.architect-team/inbox/<run-id>.jsonl` via `hooks.inflight_inbox.unprocessed_messages`, classify each new message per v2.5.0 (incl. `parallel-problem` → spawn a concurrent lane with a disjoint `hooks/locks.py` lock, recording `lane_id` via `mark_processed`), mark_processed. Phase B8 invokes the 17th Layer 3 tool `verify-inflight-clarifications-processed` to gate against silently-ignored messages (per `common-pipeline-conventions` `## Layer 3 gate invocation table (v3.10.0)`, the In-flight inbox row).

See `common-pipeline-conventions/SKILL.md` `## In-flight clarification injection mechanism (v2.19.0)` for the canonical home + `## In-flight clarification discipline (v2.5.0)` `### Parallel lanes (v3.16.0)` for the responsiveness + parallel-lane protocol.

## Phase B−1 — Intake & Mapping (REQUIRED, runs before Phase B0)

Follow the `intake-and-mapping` skill verbatim — same codebase discovery (read `$REQ_DIR/codebases.json` → frontmatter → cwd → ask user); same per-codebase ralph loop with cartographer + route-mapper + 3-reviewer convergence; same map-freshness rules (read `last_mapped` and compare against `git log -1 --format=%cI`; re-derive if stale or if `map_invalidated`); same integration mapping; same MemPalace wake-up + mining.

**The freshness pre-scan is non-negotiable.** A bug fix proposed against a stale map is the second-worst class of bug fix (after one proposed without replication). If the maps are current per the freshness rules, Phase B−1 short-circuits cleanly and the loop moves to B0 quickly.

Per the v0.9.21 Phase −1D step in `intake-and-mapping`: if any frontend codebase is in scope and a low-confidence interaction-intuition union exists at the end of Phase −1, the bulk-verify gate fires before B0. This is a domain gate; it applies here too.

## Phase B0 — Detection & Normalization

Same as `architect-team-pipeline` Phase 0 — `plain` / `openspec` / `superpowers` classification, openspec init if needed, kebab `<bug-slug>` derived from the description.

For `plain` (the common case for a bug report), pick a `<bug-slug>` that names the symptom plainly: `fix-row-delete-button`, `fix-analysis-totals-zero`, `fix-login-redirect-loop`. Avoid generic names (`bugfix`, `quickfix`). The slug names the OpenSpec change AND the eventual feature branch.

The change-name convention: bug-fix changes get the same `architect-team/<bug-slug>` feature-branch pattern; the OpenSpec change lives at `openspec/changes/<bug-slug>/`.

## Phase B1 — Bug Replication

The Lead creates a `bug-replicator` task in the shared list (teams mode) OR dispatches the `bug-replicator` subagent (subagents mode), one per affected codebase (usually just one). Bracket the dispatch with the v3.34.0 dispatch-wait pair per `## Notifications` — emit `waiting_on_agents` (`--agents "bug-replicator-<codebase> — reproduce: <symptom one-liner>"`) as the dispatch goes out, and `agents_complete` (`--agents "bug-replicator-<codebase> — <verdict>"`) when every replicator has returned its verdict. Inputs to the agent:

- The bug description (the source prose OR the bug-report artifacts).
- The relevant CODEBASE_MAP / ROUTE_MAP / DESIGN_MAP / INTEGRATION_MAP / INTERACTION_INTUITION_MAP (when present).
- The dev-environment URL(s) from the target project's `design.md` `## Dev Environment` section.

The agent's process (apply `superpowers:systematic-debugging` throughout — replicate and root-cause before any fix is proposed, per `## Plugin prerequisites (v3.9.0)`):

1. **Identify the failing path** from the description + maps. For frontend bugs: which route, which component, which interactive element. For backend bugs: which endpoint, which payload shape, which side-effect.
2. **Write the replication artifact** at the appropriate location in the target codebase:
   - Frontend bugs → a Playwright user-flow per `playwright-user-flows` at `tests/e2e/bug-fix-<bug-slug>/<flow>.spec.ts` (or the codebase's e2e convention). The flow exercises the real UI path — real `page.click`, real `page.fill`, real `page.waitFor` — against the live dev URL.
   - Backend bugs → a script (Python with `httpx`, or Node, per the target's conventions) at `tests/bug-fix-<bug-slug>/<script>.py` that calls the failing endpoint(s) against the live dev API and asserts the failing condition.
3. **Run the artifact** against the live dev environment. Capture the output verbatim. **The artifact MUST currently fail** — that is the replication. If it passes (the bug isn't actually present), exit with `could-not-reproduce`.
4. **Report a verdict**: one of `reproduced` (bug confirmed; proceed to B2), `could-not-reproduce` (the bug isn't present; escalate to the user with the evidence — the bug may already be fixed, or the description may be incomplete), `needs-clarification` (the description is genuinely ambiguous; emit a structured question and pause).

**The canonical ambiguity-escalation question (Phase B1):**

*"I need a bit more detail to replicate this — can you describe how you experienced the bug? Specifically: (1) what page or screen were you on, (2) what did you click / type / submit, (3) what did you expect to see, and (4) what actually happened? A screenshot or video would help if you have one."*

The replicator does NOT guess at the steps. A guessed replication that doesn't reproduce the bug burns an iteration; an honest `needs-clarification` saves the loop.

**Hard rule:** Phase B1 does NOT proceed to B2 without a `reproduced` verdict. "We'll figure it out at QA" is forbidden.

**Verdict file mandate (v0.9.36).** The orchestrator writes a structured verdict file at `<cwd>/.architect-team/bug-fix/<bug-slug>/b1-replication-verdict.json` immediately after the `bug-replicator` returns. The `pipeline-completion-audit` hook checks for this file's existence and verdict. Schema:

```json
{
  "phase": "B1",
  "bug_slug": "<bug-slug>",
  "verdict": "reproduced" | "could-not-reproduce" | "needs-clarification",
  "artifact_paths": ["<path-to-playwright-flow>", "<path-to-backend-diagnostic>"],
  "artifact_executed": true,
  "failing_output_captured": true,
  "dev_environment_url": "<the URL the artifact ran against>",
  "timestamp": "<ISO 8601>"
}
```

`artifact_executed` and `failing_output_captured` are both **mandatory `true`** for a `reproduced` verdict — the replicator must have actually run the artifact (not just written it) and captured the verbatim failing output (not described it). A verdict file with `artifact_executed: false` is structurally invalid and the completion audit blocks on it. **This is the enforcement mechanism for testing**: the pipeline cannot complete without proof that the replication test was actually executed against the live dev environment.

**Bauplan-armed replication (gated on the B−1 arming verdict; a no-op when unarmed).** On an armed run, dispatch `bauplan-debug-and-fix-pipeline` **alongside** the `bug-replicator`, never instead of it. Its own contract is evidence-first and is already this lane's shape — pin the data state, collect the evidence, make the minimal fix, rerun — so use it for what a generic replication cannot reach: **pin the lakehouse state the failure reproduced against** (the branch and the table snapshot), so B6's QA replay re-runs against that same state rather than a drifted one, and collect the failed-job / query evidence behind the symptom. Everything B1 requires is unchanged: a `reproduced` verdict still gates B2, the artifact must still have been EXECUTED with its failing output captured verbatim, and the verdict file above is still mandatory with `artifact_executed: true`. The skill supplies evidence; it does not supply the verdict. Record each dispatch to `<workspace>/.architect-team/bug-fix/<bug-slug>/bauplan-dispatches.json`, and where a Bauplan write rule collides with a CT6 default on a lakehouse operation, the Bauplan rule governs and the conflict is appended there as a `precedence_conflicts[]` entry — per `common-pipeline-conventions` `## Augment-never-replace discipline (v3.63.0)`.

## Structured bug-isolation (v3.8.0)

Closes REQ-DIAG-01 / REQ-DIAG-02 / REQ-DIAG-05 (the P0 "quick wins" of the CT6 Lineage & Logical Bug-Isolation Upgrade — `docs/LINEAGE_UPGRADE_REQUIREMENTS.md`). The historical failure: diagnosis discovered the relevant code path *while theorizing* — a deep-analysis subagent was dispatched before anyone had frozen the endpoint scope or established, with an executed call, whether the defect even lived on the API side. Cheap, decisive checks were skipped in favor of expensive reasoning. v3.8.0 inserts a **structured pre-diagnosis sequence** so the cheap checks always precede deep analysis.

### The mandatory order

The bug-fix pipeline's pre-diagnosis order is, explicitly:

**replicate → scope-isolate → light-discriminant → call-map → diagnose**

- **replicate** — Phase B1 (already executed above): the symptom is reproduced against the live dev environment and the failing output is captured.
- **scope-isolate** — the scope-isolation gate below (REQ-DIAG-01): freeze the exact endpoint set the reproduced failure touches.
- **light-discriminant** — the executed FE/API discriminant below (REQ-DIAG-02): one real authenticated call decides FE-bug vs API-bug BEFORE any code is read deeply.
- **call-map** — the call-map step below (REQ-DIAG-03 placeholder; full CDLG extraction is P2): lay out the in-scope endpoint's handler chain before forming hypotheses.
- **diagnose** — only now does deep analysis run: Phase B3's proposal authoring + (when the root cause is unclear) the `diagnostic-research-team` dispatch, **bounded to the frozen scope set**.

**Out-of-order execution is a discipline failure (REQ-DIAG-05).** Running deep diagnosis — dispatching a `diagnostic-researcher`, opening the handler source to theorize — BEFORE the scope artifact and the discriminant verdict have been recorded is a gate failure, not a shortcut. The run ledger MUST show the cheap checks (scope, discriminant) completed and recorded BEFORE any deep-analysis subagent dispatch. This is the run-order analog of the v0.9.36 *"testing must be EXECUTED, not described"* discipline: the cheap checks are not optional reasoning steps, they are recorded artifacts that gate what comes next.

### Scope-isolation gate (REQ-DIAG-01)

Immediately after the B1 `reproduced` verdict, BEFORE B2's artifact promotion, the orchestrator (or the `bug-replicator`, whose evidence the orchestrator records) enumerates the **pages** involved in the reproduced failure and subsets to the **exact endpoints those pages call**. This is frozen as a scope artifact at:

```
<workspace>/.architect-team/bug-isolation/<bug-slug>/scope.json
```

Schema:

```json
{
  "phase": "scope-isolation",
  "bug_slug": "<bug-slug>",
  "pages": ["<route or page url the failure was reproduced on>", "..."],
  "endpoint_set": ["GET /api/...", "POST /api/...", "..."],
  "derived_from": ["INTEGRATION_MAP", "INTERACTION_INTUITION_MAP", "ROUTE_MAP", "the captured B1 network log"],
  "timestamp": "<ISO 8601>"
}
```

`pages[]` is the set of routes/screens the reproduced failure exercised; `endpoint_set[]` is the EXACT set of endpoints those pages call (read from the captured B1 Playwright network log + the INTEGRATION_MAP / INTERACTION_INTUITION_MAP priors). **Every later diagnostic step is BOUNDED to `endpoint_set`** — the discriminant calls only in-scope endpoints, the call-map traces only in-scope handlers, the diagnosis cites only in-scope code. A diagnostic step that reaches for code outside the frozen endpoint set is rejected; if the failure genuinely implicates an out-of-scope endpoint, the scope artifact is re-frozen with that endpoint added (an explicit, recorded widening) rather than silently followed.

### Light FE/API discriminant — EXECUTED, not reasoned (REQ-DIAG-02)

Before ANY deep code analysis, make a **real authenticated call against the live dev environment** — the same live-dev discipline as B1/B2 — to the in-scope endpoint(s), **as the affected user**, and assert whether correct data is returned. This single executed call branches the diagnosis: a 4xx/5xx or a correct-shape-but-wrong-data response points at the API; a 2xx returning correct data (while the UI still shows the symptom) points at the frontend. Record the verdict at:

```
<workspace>/.architect-team/bug-isolation/<bug-slug>/discriminant.json
```

Schema:

```json
{
  "phase": "light-discriminant",
  "bug_slug": "<bug-slug>",
  "endpoint": "<the in-scope endpoint the call hit>",
  "fe_api_verdict": "frontend-bug" | "api-bug" | "inconclusive",
  "request": {"method": "GET", "url": "<dev URL>", "auth": "<affected-user session>"},
  "response": {"status": <int>, "body_excerpt": "<first N chars / relevant fields>"},
  "executed": true,
  "timestamp": "<ISO 8601>"
}
```

`fe_api_verdict` is one of `frontend-bug` (the API returned correct data; the defect is in the client's rendering / state / wiring), `api-bug` (the API returned wrong/missing data or errored), or `inconclusive` (the call could not decide — e.g. the endpoint needs un-synthesizable state; the call-map + deep diagnosis then arbitrate). The verdict MUST be backed by the captured request/response (status + body excerpt) — `executed: true` is mandatory.

**A code-read verdict does NOT satisfy this gate.** *"I read the handler and it looks like the frontend isn't sending the right param, so this is a frontend bug"* is the **"verified by reading the code"** anti-pattern — the exact failure mode v0.9.36's *"testing must be EXECUTED, not described"* discipline forbids. The discriminant is an executed call with captured evidence or it has not happened. The `fe_api_verdict` recorded here is later compared against the layer the fix actually landed in (the `wrong_layer` metric, REQ-SAFE-02 — see `common-pipeline-conventions` `## Run metrics + success measurement (v3.8.0)`); a discriminant that "said FE" but whose fix landed in the API is a measured wrong-layer event, which is only meaningful because the discriminant was a real executed call rather than a guess.

### Call-map step (REQ-DIAG-03 — placeholder hook)

Before hypothesis formation, lay out the in-scope endpoint's recursive call pattern (endpoint → functions → sub-functions). This is the forward-reference seam to the **Code & Data Lineage Graph (CDLG)** and its `ENDPOINT_TRACE_MAP.md` / `lineage-graph.json` extraction (REQ-CDL-06, roadmap phase **P2** — not implemented here):

> **Call-map step:** consume the endpoint trace / CDLG call-map when available (REQ-CDL-06, P2); until then, trace the in-scope endpoint's handler chain manually, bounded to the scope set.

This section is a placeholder hook only — it does NOT implement graph extraction. When the CDLG ships, this step reads the runtime-verified call tree for the in-scope slice; until then the diagnosis traces the handler chain by hand, strictly within `endpoint_set`. Either way the call-map precedes diagnosis, so hypotheses are reasoned against a laid-out structure rather than discovered mid-theorizing.

### Wiring into the phase order

The structured sequence threads the existing phases without renumbering them: **B1 replicate** produces the failing artifact; the **scope-isolation gate** and the **executed light-discriminant** run between B1 and B2 (recorded under `.architect-team/bug-isolation/<bug-slug>/`); **B2** promotes the artifacts; the **call-map step** runs before **B3**'s proposal authoring; **B3/B3b diagnose** (proposal + the `diagnostic-research-team` dispatch when the root cause is unclear) is the deep-analysis step that all of the above gate, and it is bounded to the frozen scope set throughout.

**On a Bauplan-armed run the sequence and its ordering rule are unchanged** (a no-op when unarmed): `bauplan-debug-and-fix-pipeline` feeds lakehouse evidence INTO scope-isolation and the call-map step — the branch and snapshot it pinned at B1, the failed job's own diagnostics — but it never substitutes for the **executed** light-discriminant, and it never licenses deep diagnosis before the cheap checks are recorded. A lakehouse diagnostic read is not the real authenticated call REQ-DIAG-02 demands, and reaching for it early is the REQ-DIAG-05 out-of-order failure by another route. Per `common-pipeline-conventions` `## Augment-never-replace discipline (v3.63.0)`.

## Phase B2 — Reproduction-artifact promotion + backend diagnostic

The replication artifact from B1 IS the regression test — this is `superpowers:test-driven-development` in its purest form (the failing test exists before the fix code is written, per `## Plugin prerequisites (v3.9.0)`). Move it to its permanent location in the target codebase's test directory if it isn't already there. The pair the QA replayer will run at B6:

- **Frontend bug:** the Playwright user-flow AT `tests/e2e/bug-fix-<bug-slug>/<flow>.spec.ts` PLUS a **backend diagnostic test** the same agent (still `bug-replicator`) authors next. The backend diagnostic exercises the SAME flow from the backend's view — it calls the endpoint(s) the Playwright flow drove and asserts the data-layer outcome (the row was actually deleted from the DB, the user's permission grant actually persisted, etc.). The backend diagnostic catches a regression that the Playwright flow alone might miss (a UI that appears to succeed but doesn't actually update the data).
- **Backend-only bug:** the backend script alone suffices.

Both artifacts must currently fail (they are reproducing the bug). Phase B6 will re-run them post-fix and require them to pass — that is the regression contract.

**Selector witness assertions (v0.9.32) — MANDATORY in every Playwright artifact.** The `bug-replicator` instruments every action-call selector (`page.click`, `page.fill`, `page.selectOption`, `page.press`, `page.setInputFiles`, `page.check`, `page.hover`, `page.dragTo`) with witness assertions immediately preceding the action — `await expect(locator, '<author intent message>').toBeVisible()` + `.toBeEnabled()` + a disambiguating role / attribute check when the text match is permissive. The witness produces an EARLY, self-diagnosing failure when a selector resolves wrong — preventing the wasted B3→B4→B5→B6 cycle when a `text=Alabama` grabs a state filter instead of the intended tech name (the v0.9.30 production case). The full pattern + the three failure modes the witness covers live in `agents/bug-replicator.md`. The witness is the structural complement to Phase B6's code-path execution witness (v0.9.31): B2 catches the failure at AUTHORING time, B6 catches it at QA-replay time — both gates are needed because either alone leaves residual failure modes.

**Email-aware reprod

…(truncated)
