| name | milestone-brief |
| description | Escalate a hard technical question to a Fable-level review via a self-contained Review Brief (RB), and ingest the resulting Review Report (RR). Use when a question needs stronger review than the session can settle - statistical correctness, high-stakes design - or when the user says "fable review", "review brief", or an RR file needs ingesting. |
| argument-hint | <id> <topic> |
/milestone-brief — Fable escalation (RB → RR)
Read ${CLAUDE_PLUGIN_ROOT}/skills/shared/tracking-rules.md first and obey
it.
Phase header: # Review brief RB<NN> → ## Draft / ## Gate / ## Ingest.
Chapter markers: mark a chapter at each phase transition (session start implicit).
Fable is no longer pay-on-demand, but it typically uses more tokens than Opus:
spawning it requires explicit user approval, every time — a deliberate
per-instance choice, never a standing default — and only ever through this
protocol. The brief artifact comes first either way; it is what makes the
review reproducible and its findings ingestible. (D-062 updated this framing,
retaining D-004's per-instance gate on token-cost grounds.)
Creating a brief
-
Determine the next RB number (max across cairn/reviews/ and its
archive, +1). Create cairn/reviews/RB<NN>-<slug>.md from
${CLAUDE_PLUGIN_ROOT}/skills/shared/templates/brief.md. It must be
fully self-contained (assume zero conversation context): background,
exact files/lines to examine, numbered specific questions (never
"thoughts?"), constraints with D-entry links, and the required output
path cairn/reviews/RR<NN>-<slug>.md.
-
Set the milestone blocked (work-log line: "blocked on RB").
Commit (docs-only, main): brief RB<NN>: <topic>.
-
Approval gate (AskUserQuestion): present the brief's scope, a rough
size estimate (files/lines Fable must read), and a reminder that Fable
typically uses more tokens than Opus. Acceptance chips (tracking-rules): show the drafted RB's
question and scope text verbatim above the gate, never only a
description. Options:
-
Never spawn Fable without this gate, and never proceed past the blocking
question while the RB is open.
Ingesting an RR
Runs immediately after a spawned review returns, or automatically at session
start (any skill) when a manual RR appears:
- Read the RR. Record its answers as dated entries in the milestone's
Decisions section; promote cross-cutting ones to
cairn/DECISIONS.md.
- If a recommendation contradicts a standing D-entry: supersede, don't
ignore — quote the prior rationale to the user and only proceed by
appending a superseding D-entry. Never silently override the record, and
never silently discard Fable's advice.
- Apply or schedule recommendations as tasks (or candidate rows for
out-of-scope ones), each triaged: apply / consider / reject-with-reason
(logged). Binding criteria travel verbatim: when the RR carries a
## Binding criteria section, the milestone it constrains sets its
header's Driving RR: slot to RR<NN> and ingests each criterion
verbatim into its ## Acceptance criteria as a numbered acceptance
criterion carrying its trace tag — - [ ] AC-N (BCn): <verbatim> — and
gives that criterion its own ## Coverage line: coverage-complete
counts every AC checkbox positionally, so a bare, unnumbered BC checkbox
reds that check (M107). This runs through the /milestone-implement
step-6 amendment gate when the AC block already exists. After ingesting,
re-check the plan-owned body with cairn_budget; if the added criteria
push it over, compress the single heaviest plan-owned section in one pass
(tracking-rules), never a nibble-and-recount loop.
Any departure is a row in the "Deviations from RR" table at
the end of that AC section, shown verbatim at this ingestion's preview,
never slipped — IP3 applied to review findings. cairn_validate's
binding criteria check string-compares the AC block against the RR
(whitespace-normalized): a softened criterion is a red check, not a
reading. Copy the RR's numeric projections beside the criteria with
their stated tolerances; an unstated tolerance is strict — any shortfall
forces the accept-shortfall option at the merge gate.
A binding-criteria set is audited before it is ingested, by the same
fresh-context [O] reader /milestone-plan step 3 spawns and the same
two questions — what state of the world satisfies this exactly as
written, and does any IP or D-entry make that state unreachable — asked
of the set as well as of each criterion, because criteria that are
individually satisfiable can still be jointly unsatisfiable, and a
frozen scope in one can forbid the work another mandates. A brief has
already been convened over exactly that, with the collision surfacing at a
review gate instead of here. What the audit returns is raised with the
user, never softened away: binding criteria string-compares the AC block,
so a quietly reworded criterion reds the check, and any departure agreed
at the gate becomes a row in the Deviations table below.
- Relocate the RB/RR pair to
cairn/reviews/archive/ with plain mv then
git add, never git mv — an in-session-generated or hand-dropped RR is
untracked, and git mv fails on an untracked file; milestone status back
to in-progress; durable-record preview (tracking-rules): show the
Decisions entries, D-entries, and candidate rows the ingestion wrote
verbatim in chat before the commit; commit (docs-only): ingest RR<NN>.
- Routing chip (AskUserQuestion), composed from where the RR left the
milestone — e.g. Resume implementation →
/milestone-implement <id>
(recommended) / Stop here. Acceptance chips (tracking-rules):
the RR's conclusions/verdict section is shown verbatim above the chip.
Robustness:
- Pasted RR content: if the user pastes review output into chat instead
of the file, normalize it — write the RR file from the paste verbatim,
then ingest as usual. Never reject usable review output on formal grounds.
- Non-responsive RR: if the RR fails to answer the brief's questions,
mark it unresolved and draft a fresh RB (new number) rather than
re-ingesting a bad artifact.