# The observation backlog (refactor Step 0e / `backlog` mode)

Loaded on demand by `/multi-agent:refactor`. The SKILL.md carries the band intro; this file is the flow.

## 1. Why a queue exists at all

`/multi-agent:refactor` derives its findings from scratch on every invocation. That is the right design for a sweep, and it has one consequence nobody chose: a friction noticed on Tuesday is gone by Wednesday unless it was fixed within the hour. Most are not, because they surface mid-task, when stopping to fix them is the wrong call.

So the friction is written down the moment it is noticed, and this band decides what to do with it later. The two halves are deliberately separate: noticing is cheap and must never wait for a decision, deciding is expensive and must never happen mid-task.

Store: `$HOME/.claude/memory/multi-agent/_pipeline/observations/NNNN-slug.md`, one file per observation, frontmatter per `schemas/skill-observation.schema.json`. The directory listing is the index - there is no index file, because an index is a second copy of the truth and the second copy is the one that goes stale.

## 2. Reading the queue

```bash
node "$HOME/.claude/scripts/observations.mjs" scan --status open --json
```

`scan` reads frontmatter only and never opens a body, so a queue of several hundred costs almost nothing.

**Exit 3 is `SCAN BROKEN` and it is not an empty queue.** It means files exist on disk and none parsed - the reader is broken. Halt the band and say so. An empty scan otherwise reports two different facts with one answer ("nothing to find" and "the question was never asked"), and only the first is a finding; the guard exists so those two can never be confused again.

## 3. Splitting the queue

Every open observation lands in exactly one of three buckets:

| Bucket | Meaning | What happens |
|---|---|---|
| Actionable | a change worth making now | goes into the plan as a normal band item with its file and fix |
| Sibling propagation | already fixed in one copy, not the others | goes into the plan as a propagation item, with the exact surfaces named |
| To decline | not worth doing, or wrong | proposed for `declined` with a one-line reason |

The second bucket is the one this tree specifically needs. A command is never one file: it is authored under `commands/`, mirrored into `skills/shared/core/`, and installed again into the Claude, Copilot and Codex trees. A fix applied to whichever copy was open drifts from the rest silently - nothing errors and every gate stays green. Resolve the surfaces mechanically, never from memory:

```bash
node "$HOME/.claude/scripts/skill-siblings.mjs" <path> --json
node "$HOME/.claude/scripts/skill-siblings.mjs" --audit      # every command at once
```

## 4. Deciding, and the deferral that wears a disguise

An observation leaves the queue with a status, never by being ignored:

- `actioned` - a change shipped. Record the commit in `reference`.
- `declined` - decided against. A decline with no `resolution` is indistinguishable from neglect, so the reason is written.
- `superseded` - another observation covers it. Name which.
- `parked` - decided, but blocked on something outside this repo.

`parked` requires `parked_until` naming the concrete event that unblocks it: a version, a release, an upstream fix. "Let us gather more data" is not an event. If no observation could change the decision and no date is nameable, the honest status is `declined` - a park with no expiry leaves the queue and never comes back, which is a silent decline wearing a friendlier word.

```bash
node "$HOME/.claude/scripts/observations.mjs" resolve --id 0007 --status actioned \
  --resolution "backlog mode added" --reference "<sha>"
```

## 5. Applying

Changes go to a staged copy and are shown before anything is installed, exactly as the drift band does. The user installs; this band never edits an installed skill in place.

When any observation is resolved, stamp the review:

```bash
date +%Y-%m-%d > "$HOME/.claude/memory/multi-agent/_pipeline/last-review-date.txt"
```

`capture-resume.sh` reads that stamp at session start and offers one line when it is seven days old and the queue is non-empty. One line, never a block - the user's own work does not wait on the pipeline's housekeeping.

## 6. Writing an observation

Any session may add one, in the same turn the friction appears, and then carry on:

```bash
node "$HOME/.claude/scripts/observations.mjs" add \
  --title "<the friction, not the fix>" \
  --target <repo-relative path> [--target ...] \
  --area <phase|gates|docs|...> \
  --session "<what the session was doing>" \
  --body "<detail>"
```

State the friction, not the remedy: "refactor re-derives its findings every run" is an observation, "add a backlog mode" is a proposal, and proposals age badly while observations do not. `siblings_checked` is filled by `skill-siblings.mjs` automatically and cannot be empty - the whole point is that the answer is computed rather than recalled, because recollection is the faculty that produced the drift.
