# Bmad Loop Resolve

> Interactive escalation-resolution workflow for the bmad-loop orchestrator. A bmad-loop run paused on a CRITICAL escalation (a contradiction or gap a dev/review session could not safely resolve alone); you and the human disambiguate the frozen spec so the story can be re-driven. Invoked as /bmad-loop-resolve <story-key>. Unlike the automated dev/review sessions this session is interactive — a human is present and you SHOULD ask.

- Skill: `websoft9/bmad-loop-resolve-2` (Agent Skill)
- Install (CLI): `npx skillmds@latest add websoft9/bmad-loop-resolve-2`
- Raw SKILL.md: https://api.skillmd.com/api/skills/websoft9/bmad-loop-resolve-2/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Productivity
- Author: websoft9 (https://skillmd.com/u/websoft9)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/websoft9/bmad-loop-resolve-2

---


# bmad-loop Escalation Resolution

A `bmad-loop` run drove a story through dev → review, a session raised a
**CRITICAL escalation** (work could not proceed safely — usually a contradiction
or an unanswered question in the _frozen spec_), and the orchestrator paused the
whole run for a human. The session that escalated is gone; you are a fresh
interactive session whose job is to **resolve the ambiguity with the human and
update the frozen spec**, so the orchestrator can re-arm the story and re-drive
it against a corrected spec.

This is **interactive**: a human IS present. Ask questions, present options,
recommend — but the human makes the call. (`$BMAD_LOOP_MODE` is intentionally
unset for this session; the never-ask automation rules do NOT apply.)

## Identity & I/O contract

These environment variables are set:

- `$BMAD_LOOP_RUN_DIR` — the paused run's directory.
- `$BMAD_LOOP_STORY_KEY` — the escalated story key (also your invocation argument).
- `$BMAD_LOOP_RESOLVE_CONTEXT` — path to a `context.json` written for you.

**Read `$BMAD_LOOP_RESOLVE_CONTEXT` FIRST.** Its schema:

```json
{
  "story_key": "6-4-cli-list-command",
  "run_id": "20260613-111429-6a14",
  "spec_file": "/abs/path/to/_bmad-output/implementation-artifacts/spec-<story>.md",
  "baseline_commit": "<sha>",
  "paused_reason": "CRITICAL escalation from review session: ...",
  "escalations": [
    {
      "type": "<kind>",
      "severity": "CRITICAL",
      "detail": "<what's ambiguous/contradictory>"
    }
  ],
  "resolution_path": "/abs/path/to/<run>/resolve/<story>/resolution.json"
}
```

In **stories mode** (folder+id dispatch) the context also carries a `stories`
block — the manifest intent for this story, so you can see WHAT it is meant to do
without hunting for it:

```json
{
  "stories": {
    "spec_folder": "_bmad-output/epic-1",
    "story": {
      "id": "6-4-cli-list-command",
      "title": "CLI list command",
      "description": "…",
      "spec_checkpoint": false,
      "done_checkpoint": false,
      "invoke_dev_with": "…free-text planner→dev note, or ''…"
    },
    "sentinel": {
      "kind": "unresolved",
      "path": ".../stories/6-4-cli-list-command-unresolved.md",
      "blocking_condition": "…the reason planning halted…"
    }
  }
}
```

The `sentinel` sub-block is present ONLY when the escalated story is a **sentinel**
(see the stories-mode section below); an ordinary escalation omits it.

Your **output marker** is the file at `resolution_path`. Writing it is the LAST
action of a successful resolution. Schema:

```json
{
  "story_key": "<key>",
  "decision": "<one or two sentences: the rule you and the human chose>",
  "spec_file": "<the spec you edited>",
  "spec_updated": true
}
```

## What you MUST do

1. **Read the context**, then read the **frozen spec** at `spec_file` in full —
   especially its `<frozen-after-approval>` block (the intent the dev/review
   sessions treat as authoritative). The escalation is almost always that this
   block is silent on, or contradicts, a case the implementation hit.
2. **Present the escalation plainly** to the human: what is ambiguous or
   contradictory, why it blocks safe implementation, and **2–4 concrete
   resolution options** with a clear recommendation and its trade-offs. Keep it
   tight — quote the relevant spec lines.
3. **Get the human's decision.** Ask follow-ups if the choice is unclear. Do not
   invent requirements; if the human is unsure, help them reason, don't guess.
4. **Update the frozen spec** to encode the decision unambiguously: amend the
   `<frozen-after-approval>` block and any affected acceptance criteria / test
   matrix rows so a fresh dev session has exactly one correct reading. Make the
   smallest change that removes the ambiguity. You MAY use the `bmad-spec` or
   `bmad-correct-course` skills if a larger spec change is warranted.
5. **Write the resolution marker** at `resolution_path` (schema above), then tell
   the human the resolution is recorded and they can exit this session — the
   orchestrator will offer to **re-arm the story and resume the run** (a clean
   rebuild against the corrected spec).

## What you MUST NOT do

- **Do NOT** write the orchestrator's `result.json` — that is a dev/review
  artifact; this is not one of those sessions.
- **Do NOT** change `sprint-status.yaml`, and **do NOT** set the spec's `status:`
  field — the orchestrator deterministically re-arms the spec status on resume.
  Edit spec **content** only.
- **Do NOT** implement the story, write feature code, run tests, or commit. Your
  job ends at a corrected spec + the resolution marker.
- **Do NOT** widen scope. Resolve exactly the escalated ambiguity; if you notice
  unrelated problems, note them to the human but leave them alone.

## Stories mode: sentinels and the preserved copy

In stories mode a story that could not even be **planned** — the dev session hit
a contradiction or gap before it could write a real spec — leaves a fixed-slug
**sentinel** file instead of a frozen spec: `<id>-unresolved.md` (the intent was
too ambiguous to plan) or `<id>-ambiguous.md` (more than one story spec matched
the id). The context's `stories.sentinel` block names it and carries the
`blocking_condition` the session recorded.

A sentinel is **not a spec you edit** — there is no plan or `<frozen-after-approval>`
block inside it. So for a sentinel:

- **Do not try to amend a frozen spec** (step 4's "edit the frozen spec" does not
  apply — there isn't one). Instead resolve the _upstream_ ambiguity so a fresh
  planning pass can succeed: usually that means clarifying `SPEC.md` (the epic
  spec) or this story's entry in `stories.yaml` — the `title` / `description` /
  `invoke_dev_with` the planner reads — with the human.
- On **re-arm** the orchestrator does NOT flip the sentinel to `ready-for-dev`
  (there is no plan to route to). It **preserves a copy** of the sentinel under
  `{run}/sentinels/<id>-<kind>.md` as a breadcrumb, **deletes** the sentinel, and
  the next dispatch re-plans the story from scratch (leg 1 again for a
  `spec_checkpoint` story). You do not touch the sentinel file yourself.
- Write the resolution marker as usual once the human has decided how to
  disambiguate; set `spec_file` to whatever you edited (e.g. `SPEC.md`), or omit
  it if the fix was entirely in `stories.yaml`.

### Not a sentinel: more than one file matches the id

Distinct from the single-file `<id>-ambiguous.md` sentinel above: when **more
than one** file in `stories/` matches `<id>-*.md` (say `3-login.md` AND
`3-signup.md`), the id itself is ambiguous _on disk_ and the orchestrator wedges
the story without picking either file. You can recognize this state by the
escalation reason (`ambiguous story file match: <names>`) and by what the
context does NOT have: no `stories.sentinel` block and no single spec path.

The auto-clear above does **not** apply — there is no sentinel to preserve and
delete, and re-arming alone just re-wedges on the same duplicates. The
resolution IS the cleanup: with the human, decide which file is the story's real
spec and remove or rename the other (merge content first if both carry real
work; renaming must move it out of the `<id>-*` pattern or to another id).
Exactly one match re-dispatches that spec; zero matches re-plans from scratch.
Then write the resolution marker as usual — re-arm + resume takes it from there.

## If you cannot resolve it

If the human defers, the information needed is genuinely unavailable, or the
right fix is out of scope for a spec edit (e.g. it needs a PRD/architecture
change), say so plainly and **do not** write the resolution marker. Exiting
without the marker leaves the story escalated and the run paused — the safe
default. The orchestrator will not re-arm a story with no recorded resolution.

