Skip to content
Back to skills

Fr Goal

ASecurity

Run a feature goal end-to-end autonomously via the `fr-goal` workflow shape (optional shape-name argument; no argument resolves `fr-goal`): brainstorm, one question round sized to the feature (rarely two), then spec → review → fr-plan → review → TDD implementation → review → single PR, fixing every finding in scope and filing the rest, no intermediate approval gates. ALWAYS use when the operator invokes /fr-goal or /goal, says "build this autonomously", "ask your questions once then build it"...

  • 2 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 19, 2026
ai-agentsgoshellbashcode-reviewgitdevops

Works with

  • claude code
  • cursor
  • cli

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned October 19, 2026

npx -y skills add derio-net/super-fr --skill fr-goal --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Fr Goal?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Fr Goal
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/derio-net-fr-goal/badge)](https://www.skillsdirectory.com/skills/derio-net-fr-goal)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: fr-goal
description: >
  Run a feature goal end-to-end autonomously via the `fr-goal` workflow shape (optional
  shape-name argument; no argument resolves `fr-goal`): brainstorm, one question round sized
  to the feature (rarely two), then
  spec → review → fr-plan → review → TDD implementation → review → single PR, fixing every
  finding in scope and filing the rest, no intermediate approval gates. ALWAYS use when the operator invokes /fr-goal or
  /goal, says "build this autonomously", "ask your questions once then build it", "take this
  to a PR", hands a feature to run unattended, says "auto mode" or spec-to-PR.
---

# fr-goal

One operator gate — a question round sized to the feature, rarely two — from goal to reviewed PR, driven by a **workflow
shape** (spec §4.A, `2026-08-14-workflow-shapes-and-workitem-dispatch-design.md`): `fr run
start <shape> --branch <b>` (defaults to `fr-goal`), then loop resolve-with-record (each `fr run resolve … --record` prints the next brief); `fr run advance <run-id>` is for starting, `cli` failures and recovery.
**Shape lookup:** repo `docs/superpowers/workflows/<shape>.yaml` (overrides wholesale) →
`$FR_SHIPPED_WORKFLOWS_DIR` → the `fr` wheel's own copy → the Claude Code marketplace clone, so
shipped shapes resolve on a hermes pod or under OpenCode with no plugin installed. **`start` enters isolation itself** and writes the run inside that workspace — the
first action, before anything else ("start with X" changes the first work item, never the
first action); run every later command from the workspace it prints. **Bind the session** so the workspace is attributable, not `sessions=none`: pass `--session <id> --harness <h>` to `start` when your harness exposes its session id (a harness with a session-bind hook does it for you); otherwise `fr isolation attach --session <id> --branch <b> --harness <h>` binds it after the fact — traceability only, so a missing binding never blocks work. No devcontainer profile
→ pause for fr-init. `kind: cli` executes directly — exit code is the verdict, fix and
re-`advance` on failure. `kind: agent` never executes itself: it prints a dispatch brief
(skill/agent/needs/emits/tier/for_each) you fulfill per that step below, then ONE `fr run
resolve <run-id> --step <id> [--item <unit>] --record <file>`, which also advances: after a `done` record it runs any following `cli` steps and prints the next brief in that same call (`--no-advance` opts out; a `failed`/`blocked` record stops). Exit 1 there means the record applied and a chained `cli` step failed; exit 2 with `record applied` means it applied and the advance was refused — fix and `fr run advance`, never re-apply the record. The brief's `record` is a
pre-filled **step record** — only the sections that step's `emits` allows: fill it as the work
happens, commit it with the work, and fr applies ticks, journal entries, resolutions, acceptance
rows, `emitted` artifacts (a `spec`/`plan` path must exist) and evidence with the cursor move in
one commit, one line back; a refused record changes nothing. `--state`/`--evidence`/`--emitted`
remain for humans and runners. `gate:
operator` blocks until you resolve it (same command; a gated `cli` step then runs on the next `advance`). Blocked → stop, say what you tried, ask. Another shape, same mechanics.

**`fr` refused with "artifacts … must be migrated"?** Expected — a pod, CI and an agent's Bash
tool are all non-interactive, where fr never migrates or commits by itself. Run `fr migrate
artifacts --yes` yourself and continue; it is exempt and needs no TTY. **Work already in
flight when your `fr` changed under it?** A run whose shape drifted: `fr run reshape <run-id>`
previews moving it onto the current step list (`--yes` applies; it refuses, changing nothing,
when that would lose something the run recorded). When reshape refuses, or a review ran in an
earlier session: `fr run adopt <plan-dir> --supersede` replaces the run, carrying gate answers,
artifacts, units and evidence forward and closing open attempts as abandoned (preview unless
`--yes`). A plan with no run: `fr run adopt <plan-dir|spec>` rebuilds a cursor from disk —
offered, never forced (`--yes --adopt` does all). A phase whose plan journal already holds its
review (created before the cursor, after the work, no open findings, no `visual` owed) is adopted
with that review `done` as `reviewer=historical`, listed in the PR body's `## Historical reviews`.

**Announce at start:** "I'm using fr-goal to run this goal autonomously."

**Interactive touchpoints (all else autonomous):** `brainstorm`'s question round(s) (`gate: operator`),
with any cross-repo location question folded in; manual phases from `plan`; PR merge after
`deliver` — never self-merged — and the post-merge Test Plan.

### Light path — `fr-goal-light`, for a goal that plans to one agentic phase
A second shipped shape, same mechanics, fewer round trips (spec `2026-09-29-fr-goal-light-path`): `brainstorm` → `plan` → `spec-plan-review` → `plan-review` → `implement` {`implement-phase`, `review-phase`} → `journal-check` → `deliver`. Take it when the goal's asks plan to ONE agentic phase (a `[manual]` phase beside it is fine): either `fr run start fr-goal-light`, or — decided by the question round — put `shape: fr-goal-light` in the brainstorm record, and that record's resolve rebinds the run (only at `brainstorm`, only before anything else moved; a same-shape `shape:` is a no-op). `plan` is written BEFORE the review: its resolve derives `single-phase` and refuses a plan with more than one agentic phase, naming them — merge them, or start a new run on `fr-goal`. Then ONE `fr-spec-reviewer` dispatch, `spec-plan-review`, reviews spec AND plan: brief it with both paths; plan findings go into the SPEC journal tagged `target: plan`, and the step is held to §2's gate unchanged (review, reviewer, findings). `plan-review` (`fr plan self-review`) runs after it, chained by that record's resolve. `implement`, `journal-check` and `deliver` are §5–§8 unchanged, and `deliver` may say `tests: reuse` (§8). Three context rules keep the orchestrator small — they are most of what the light path saves: act on a subagent's structured return (the executor's `record`/`outcome`/`tests_log`/`summary`, the reviewer's record YAML); never open a subagent's transcript — fr reads it where it must; and never re-read a spec or plan the brief or `fr pickup` already carries.

### 1. brainstorm — a question round sized to the feature, in isolation (`gate: operator`)
Invoke `fr-brainstorming`. Explore, collect EVERY operator-owned decision — including one repo-location question per other repo of a cross-repo spec (ask only if not found on disk) — one question per decision, recommended option first, leaving out anything the code answers; past ~10, say why inline or propose splitting the goal instead. **Label every question, and forecast a second round only when you expect one:** each question text starts `(Round K · question i of N)` — K the round, N its question count, i this question's position in the round (counted across every call of it, never restarting per call), all exact because a round's questions are collected before the first is asked. The label never counts rounds: the total is a forecast (an operator request adds a round; an announced one may not happen). Every round-1 label adds `· a 2nd round may follow` iff round 1's answers could still change the design significantly (a choice between approaches whose sub-decisions differ, or an unknown the code cannot settle); without it, say once that a second round is available on request. Add the standing verification question (fr-brainstorming §1: which strategy verifies this run, recorded in the spec's `## Verification`; the answer also settles the run's gate — `gate: tester|devops` holds the merge's close-out, any other gate is recorded only — and `fr verification set` changes it later, but once spec-review is done lowering it needs the operator's answer) — the Test Plan then holds only the post-merge rows no pre-merge strategy can exercise, so ask for one only when the deliverable deploys and such a row exists — a model-per-tier one for every tier the `brainstorm` brief's `unbound_tiers` lists (`null` — fr could not detect your harness — means ask for every tier; `[]` means skip it), plus a question per entry of the brief's `dead_bindings` (a bound model its provider no longer serves; recommended: its `proposal`) and per `binding_offers` entry (a newer same-family model; recommended: keep the current one) — each answer a `decision` whose body names old, new, reason (`retired` | `upgrade`), `decider: operator` and rule, and an accepted change applied with `fr models set` (both keys are `null` where fr cannot probe the harness: nothing to ask). Each answer is a `decision` in the brainstorm record, each acceptance row an `acceptance:` entry — a row for user-visible UI also carries `visual`: the states and interactions it names, limits included (fr-brainstorming §3). **Hard gate, per round:** an unanswered round is a stop signal — restate the open questions, never default. After an answered round 1 that said `a 2nd round may follow`, check every answer against the code — open the files and run the searches the answers point at; that check is what separates the rounds — then ask round 2 in the SAME turn — each round-2 question is labelled `(Round 2 · question i of N)` and names the round-1 answer or code finding behind it — then STOP again; there is never a round 3. An announced round 2 is a ceiling, not a promise: if round 1's answers opened nothing, tell the operator so and resolve with `rounds: 1`. An operator's prose request for a second round during round 1 turns a round 1 without the forecast into `rounds: 2, trigger: operator-request`. Resolve `brainstorm` only once every round you asked is answered; the record carries `questions: {rounds, trigger, reason}` (absent ≡ `rounds: 1`; `trigger`/`reason` required together iff `rounds: 2`) alongside `emitted: {spec: <path>}`. A `rounds: 2` declaration is written to the spec journal (`gate-question-rounds-<step>`), so the PR body shows the gate took two rounds. "The request already decided everything" is still a round to run, not a reason to skip it; the one bypass is `no_questions: true` + `reason: "…"` in the record (with `--record`, fr refuses the `--no-questions`/`--reason` flags, and refuses `questions` alongside `no_questions`), written to the spec journal and the PR body.

**Harness — questions:** Claude Code takes at most 4 questions per `AskUserQuestion` call, so a round of N questions is `ceil(N/4)` calls, split evenly (5 questions are 3 + 2, 9 are 3 + 3 + 3), so no call is left holding a lone question. The calls are SEQUENTIAL: never more than one question call per message, and each next call is made only after the previous call is answered — calls sent together in one message are shown last-first, so the operator would answer the end of the round before its start. Make no other tool call between them; any other tool call between two question calls starts a new round. Every question carries its own position, so a tab never reads as a range: the second of five is `(Round 1 · question 2 of 5)`, whichever call it sits in. Round 1's cross-examination therefore uses real tool calls (`Read`, `Grep`, `Bash`) before round 2's first `AskUserQuestion` call — without them the two rounds merge into one and a declared `rounds: 2` is refused. Progress-tracking tools do not separate rounds: `TodoWrite`/`TaskCreate`/`TaskUpdate`/`TaskList`/`TaskGet` read/write no project state, so they neither split one round nor count as the cross-examination. `resolve` VERIFIES the declared round count against the session transcript — it counts answered rounds since the gate blocked and refuses a mismatch, a `design-risk` round 2 whose round-1 question text never announced it, or any third round. OpenCode takes the same labelling and sequencing rules through its `question` tool, and fr verifies the answers there exactly as on Claude Code (answered rounds in the run session's parts; a declined question is no answer). Hermes has no question tool: label each question in your reply (`(Round 1 · question 1 of 5)` … `(Round 1 · question 5 of 5)`, adding `· a 2nd round may follow` only when you forecast one) and END THE TURN, then `evidence: {answered_by: operator}` in the record (`--answered-by operator` in the flag form) once the operator answered — unverified, so advisory. There is no default `answered_by`: where fr cannot read who answered, a resolve that states none is refused, and the PR body reports a claimed answer as claimed.

### 2. spec-review
Never review the spec yourself: dispatch the read-only `fr-spec-reviewer` (the brief's `agent` and `tier`) INTO this workspace with the spec and spec-journal paths — only those: no step record is an input (`brainstorm`'s was applied to that journal and deleted when it resolved; this step's is the reviewer's return). It checks the spec against the Q&A decisions AND codebase reality (a file:line for every named file/helper/service), and tags each finding in or out of scope (§6's definitions). Its return IS the step's record (findings with `review_scope`, plus a `kind: review` entry): save it at the brief's `record` path, fix every finding in scope, add a `resolves:` entry per finding (the rest `state: out-of-scope`, the body saying why this change did not cause it) and `evidence: {review: <entry-id>, reviewer: <agent-id>}`, then `fr run resolve <run-id> --step spec-review --record <file>`. fr refuses a review entry older than the step, a reviewer this session did not dispatch after it opened, and — `findings` is derived — any spec finding still open. Cross-repo spec: this session owns ONE repo's plan + PR; for each other repo, dispatch one agent with the spec ref and this pipeline from `plan` onward — one plan, one PR, one workspace per repo: brief it to enter isolation in ITS repo first, `fr isolation up --repo <path> --branch <b>` (it inherits your cwd).
**Harness — spec reviewer:** Claude Code dispatches `fr-spec-reviewer` with no `isolation` argument (a worktree cut from main cannot see the spec) and fr verifies the id from the transcript; OpenCode dispatches `fr-spec-reviewer-<tier>` through its task tool and fr verifies the reviewer id there too (the `task` parts of the run session; a tiered agent name counts), while Hermes uses `delegate_task` with the agent's brief in `context` and records `reviewer=` as claimed, unverified.
**Harness — cross-repo agents:** Claude Code's `isolation: "worktree"` only cuts a worktree of THIS repo — optional, never the isolation; OpenCode's task tool and Hermes' `delegate_task` take no isolation argument. On all three, that `fr isolation up --repo` is what isolates the agent.

### 3. plan — fr-plan, then review it
Invoke `fr-plan`, skipping section-by-section approval (the spec encodes the design). Keep
TDD-shaped steps (red → green → refactor, or a `refactor:` reason in the phase's step record — an older run's `no-refactor-because:` journal entry still counts);
fr-plan tags each phase a `tier`. Size phases to the asks: one agentic phase per independently
reviewable ask, so a one-agentic-phase plan is first-class (no skeleton marker, no override) and
usually right. Every phase after the first records a `phase-split-<plan>-p<N>` spec-journal
decision (`fr journal add --scope spec --slug <spec-journal-slug>`: the spec file's stem without
`-design`; supersede one with `phase-split-<plan>-p<N>-<k>`) — `ask:` for its own ask, else
`tier:`, `risk-first:` or `review-size:`. With two or more
agentic phases the skeleton is the first ask's phase, marked, its first task the smoke — CI green on
a trivial test (`fr services` says `ci none` → the local suite on a trivial test), minimum runtime exercised, external fixtures captured never constructed. `fr plan self-review`
must pass and phases must read back against the spec. An operator verification step is a Test Plan
line or a `verify: live` row, never a phase. fr-plan's agentic-purity gate collects the rest of
the manual work — a prerequisite agentic work depends on, or a real dispatch/deploy — into
`[manual]` phases; **back-load by default** (last phase, no dependent agentic phase —
PR ships it unimplemented, operator pushes to the same PR); **front-load only when agentic work
depends on it** (spec+plan PR, pause for the go). Multi-repo `depends_on` is within-plan only. The record carries `emitted: {plan: <path>}`.

### 4. plan-review
The `plan` record's resolve runs `fr plan self-review {{ artifacts.plan }}` in the same call (a `cli` step chains) — deterministic, exit code is the verdict (exit 1 there: the record applied, the self-review failed). Fix findings against the spec and `fr run advance`; no `resolve` needed (`cli` steps self-complete).

### 5. implement — grouped per-phase loop, journal-fed, TDD
The run's workspace is the working copy (`fr isolation exec`); spec/plan aren't on main yet, so NOT dispatched (`fr apply --yes` refuses). `implement` is a grouped `for_each`: per phase in dependency order, dispatch ONE phase-executor for `implement-phase` — brief = `fr pickup` + spec + `fr journal handoff --scope plan --phase N` + the brief's `record` path: TDD (`superpowers:test-driven-development`) plus fr-execute's browser check when the phase's linked acceptance rows carry `visual` (states/interactions captured into a git-ignored worktree dir or a scratch dir the host sees — never the container's `/tmp` — every screenshot opened, filled into the record's `visual:` section), keeps that step record (ticks, `refactor:` reasons, discoveries/findings) and commits it with its work, returns a fixed structured result — `record`, `outcome`, `tests_log` (the host-visible log of the full suite it ran LAST, outside `<run>.records/`, or `none`), `summary` (≤5 lines, the suite's pass/fail summary among them), never pasted output (return is the only reporting channel, #461) — the handoff IS the context. Its record names that log as `evidence: {tests: <log>}`: fr verifies the executor wrote it, that the code tree was committed-clean and the log is newer than every code path, and stores the tree it covered — a log that is dirty-tree or stale is refused, so brief the executor to run the suite after its last code commit. **Or `tests: ci`** (R22), where the local suite is too slow to run (a small cloud container): brief the executor to commit, push and return `tests_log: ci` instead of running the full suite, and its record names `evidence: {tests: ci}`. For that fr verifies HEAD is pushed with no uncommitted code path, the branch has an open, non-conflicting PR, and every gate check — `.fr/ci.yaml`'s `gate_checks` at HEAD, else the base branch's required checks; neither is refused — completed with success on the CI sha: HEAD, or the nearest first-parent ancestor with the same code tree (fr's own `chore(fr):` commits change none). Any other check is ignored. It records `ci:<ci sha>+<base sha>;tree=<code tree>` — CI tested the head merged into that base, not HEAD alone — which `tests: reuse` accepts like a log; refused outright under `ci none` (`fr services`) or a forge other than GitHub. **Waiting on CI:** exit 75 from that resolve means a gate has not finished — not idle and not refused: the unit stays held and the cursor did not move. In a cloud session, wait for the PR-activity event that CI's end delivers; elsewhere re-run the same resolve every 2 minutes, for at most 45 minutes, then report the unit blocked with the gate's URL. A failed, cancelled, skipped or absent gate exits 2 naming it: fix and push, never wait. Its return is resolved with `--record`, which completes the phase and briefs `review-phase` in the same call. Copy the brief's `long_commands` rule into the task prompt VERBATIM, beside any suite command you name: its agent file says the same, and an executor handed an exact command ran it anyway until the tool killed it (#582). Model = the brief's `resolved_tier` (falls back to the phase header's `tier` only when the brief lacks that key — an older `fr`) via `fr models resolve --harness <h>` (unbound → set at step 1); `resolved_tier: null` is the untiered case the dispatch clause below already handles, not a fourth rule; blocked → run inline; never a manual phase. A broken environment (wedged container, changed profile) is repaired with `fr isolation restart`, then `rebuild` (worktree, cursor and uncommitted work kept), never `down --force`; a forced down preserves the run record for the next `up --branch`, but still ends the run there.
**Per phase the loop is dispatch → claim → wait → review → resolve (which advances), and that last arrow is the next dispatch: the cycle closes, it does not stop.** Name a dispatch's holder as soon as your harness tells you who it is: `fr run claim <run-id> --step implement-phase --item phase/<n> --agent <id>` (`--harness` defaults to what fr detects, `--model` when you know it). It annotates the record `advance` already opened — fr times its own act and resolves the tier's model, but only YOU know which agent took it — so "who is holding phase 2 *right now*" is answerable while it matters, not only after the return (#503). `advance` then REFUSES a unit whose record is still open: exit 2, naming the holder, no brief printed — #499's double-dispatch hazard, now backed by recorded state instead of inferred from `items`.
Executor lost, or never coming back? `fr run claim <run-id> --step implement-phase --item phase/<n> --abandoned` closes the record and leaves the unit `running`, so the next `advance` briefs it again; `fr run advance <run-id> --redispatch` closes it and re-briefs in one move. Neither erases the old holder — records accumulate oldest-first per unit, which is the trail #503 asked for. `fr run status` shows who holds each unit and since when (harness beside model: a tier resolves FOR a harness, never in the abstract), with each attempt's context estimate and, where the transcript is reachable, what it actually billed — the two differ by orders of magnitude and are not comparable; `fr run check` counts open and unclaimed dispatches as debt, not failure.
**Picking the run up somewhere else?** The cursor travels with the branch; transcripts, session bindings and the agent do not. So a unit whose holder was dispatched from ANOTHER session says so — `advance`'s refusal names it, and its cost reads `not observable from here` rather than zero or a borrowed figure (fr never measures a window another session opened). That agent may have died with its host, so do not wait on it: close it with `claim … --abandoned` (or `advance --redispatch`) and re-brief from the last COMMIT — uncommitted work did not travel either. Bind the new session (`fr isolation up --branch … --session …`, or `fr isolation attach`) or the idle guard below cannot find the run at all.
**Harness — dispatch:** Claude Code uses the `fr-phase-executor` Agent without `isolation: "worktree"`
— **mustn't**, not "needn't" (#420, hook-refused): the flag cuts a *second* worktree from main where
spec/plan are invisible and writes are denied, yet the dispatch succeeds, so the run looks healthy
while nothing happens. The two isolations don't compose. (Contrast §2's cross-repo agents, which
*keep* the flag — each starts a fresh pipeline in a different repo; these share this one's workspace.)
Hermes `delegate_task(goal, context)` carries the brief in `context`, serial; child loads
`fr-execute`. OpenCode dispatches the same brief, serially, through its task tool as `subagent_type: fr-phase-executor-<tier>`: the call carries no model, so the agent NAME is the only place a tier can live. Two cases take the untiered `fr-phase-executor` instead — a phase declaring no `tier`, and a tier that is UNRESOLVED (`fr models resolve` prints nothing) — and you journal which: a tier agent with no binding just inherits the session model, a row indistinguishable from a working tiered dispatch, whereas the untiered name makes the absence visible.
The `--agent` id you claim with is whatever that dispatch handed you: on Claude Code the task id the `Agent` call returns, on OpenCode the child session id its task tool returns, on Hermes the `delegate_task` handle. WHEN you learn it differs too: Claude Code hands the task id back at once, so claim while the executor works; a dispatch call that BLOCKS (OpenCode's task tool) returns the id only with the result. On OpenCode the super-fr plugin claims from inside the child on its first tool call (`fr run claim --open-unit`, gh#530), so the holder is usually named already; still claim it when the call returns, before you resolve — the same id is idempotent — and until someone claims, `fr run status` reads `HELD BY an unclaimed agent`. Where the tier rides in the agent's name (`fr-phase-executor-<tier>`), add `--agent-type <that name>` so the cursor records the tier agent that ran, not only the manifest's id. Never invent one — an unclaimed record still refuses a second dispatch, it just can't say who it is waiting on.
Price stated, not hidden: ~7x an inline run ($7.59 measured against ~$1), bought for the fastest measured wall clock (56.2 min against 77.6 and 105.2) and real per-phase context isolation; inline only when dispatch is unavailable. An executor that both returns and messages: keep the return, log the drop (#461).

### 6. review-phase — per phase, inside the loop, then push (never a PR)
After each `implement-phase` return, resolve it with `--record` — that same call advances and prints the brief for `review-phase` (never a separate `fr run advance`: the unit is then held and it refuses) — a unit nothing briefed cannot be resolved (exit 2), because the brief is what opens its record — and run it: BOTH skills its brief lists, in order: `superpowers:requesting-code-review` over spec + plan + code, then `superpowers:receiving-code-review` on what it raised (verify each finding against the code; fix it with a test, or refute it with reasoning — never a silent drop, never performative agreement). When the phase's linked rows carry `visual`, the reviewer also drives the UI itself — or re-runs the capture script — and opens its own fresh screenshots, never reading the executor's, trying each named control at its limits, checking the script covers every name the row declares, and returns the shots it took and opened; it writes nothing, so YOU fill the review-phase record's `visual:` section from its return (fr reads the reviewer's transcript for the opens). Brief the reviewer to tag every finding with a one-line reason: **in scope** — this change is wrong, incomplete, or worse than it needs to be (an asymptotically worse algorithm than necessary counts); **out of scope** — true, but not caused by this change. Put the brief's `review_findings` text verbatim into each reviewer's prompt — when you dispatch several reviewers for one phase, give each its own letter (`p<N>a-r<k>`, `p<N>b-r<k>`, …) so their ids never collide. Fix every finding in scope, file the rest as `resolves:` entries, `state: out-of-scope` with a body saying why — the gate passes them and `deliver` lists them; overriding the reviewer's `in` tag renders as reclassified in the PR body. Moving an out-of-scope finding to `fixed` later is the operator's call alone: `answered_by: operator` on that resolution (verified against an answered question where fr can read the transcript), else `fr journal check` and this gate report an unauthorized fix; record each as a `finding` in the review-phase record (`state`, `review_scope` from the reviewer's tag) — the next phase's handoff includes them, `deliver` renders the PR body from them; later-fixed findings close with a `resolves:` entry (`state: fixed`), never by re-adding the id (refused). **Push the branch ONLY — never open the PR** (#320, 3×). One exception (R22): a run whose phases use `tests: ci` opens its draft PR when `implement` starts — CI runs only on a pull request — the same draft §8 would open, never marked ready. Resolve `implement` done only once every phase's BOTH members land.
**The review is closed with EVIDENCE, not an assertion.** Put it in the review-phase record — a `kind: review` entry naming the findings raised, or that none were, and `evidence: {review: <entry-id>, reviewer: <agent-id>, model: <the model you are running on>}` — then `fr run resolve <run-id> --step review-phase --item phase/<n> --record <file>` (fr observes your model where it can read your transcript; elsewhere only you can say). The review itself is done by a DISPATCHED reviewer subagent — a separate context, never the phase's implementer and never you — named by the id its dispatch returned; fr refuses the implementer, and on a readable transcript an id this session never dispatched after the review opened (you writing the review entry about work nobody reviewed was the #497 run). Without that evidence the resolve exits 2 and names it; the id is verified against the plan journal, so it must be a `kind=review` entry for THAT phase — another phase's review, or a `finding`, is refused. `outcome: failed` needs none: a failed review met no obligation, and demanding proof of one would make a failure unreportable. So "review skipped" and "review passed clean" are now different states — the first cannot reach `done` at all. **Nor can a review whose findings were left lying:** the step also owes `findings`, which fr DERIVES from the journal and you never pass (`--evidence findings=` is refused) — `done` exits 2 while any finding filed against THAT phase is still open, printing the `fr journal resolve … --state fixed` line for each (`refuted` with reasoning when it is wrong; `deferred --tracked-by <issue>` when it is real but another change's (`fr services` says `tracking none` → there is no issue to cite: it stays out-of-scope in the journal) — never `refuted` for that); fr then records the ids it saw closed, or `none`. A finding that belongs to a later phase is filed against that phase (`--phase M`) and gates its review instead. A unit from before this gate reads `done, unevidenced (predates the evidence gate)`: visible debt, never a failure, never retroactively failed. §7 is the same rule read a second time, for phases no cursor ever walked — it still fails delivery without the entry.
**An iteration ENDS ON A DISPATCH, not a report** (#518). When an executor returns: review, fix, push, resolve the review with its evidence (that `--record` call advances and prints the next unit's brief), then IN THE SAME TURN dispatch the next unit — report AFTER dispatching, never instead of it. A delivered report plus a pile of just-fixed findings is peak pressure to summarise and stop, which is precisely where a run strands. This skill's autonomy contract outranks an output-style preference: insight is welcome, ending a turn on it mid-run is not. The only legitimate turn ends are an operator gate, a genuine block, a unit HELD by a working executor, and the finished run.
**Harness — idle guard:** `fr run check --idle` is the harness-neutral predicate — exit 3 iff the run is advanceable and nobody is working, naming the next command; every adapter calls it, none re-derives it. Claude Code registers a stop-time hook that refuses to end a turn on an idle run and hands that command back; it acts at most once per cursor position (stopping on purpose just means stopping again), and a turn ending while a unit is HELD is correct and is never blocked. Two costs, stated: it calls the `fr` on PATH, so a stale global install exits 2 and SILENTLY disables it, and it adds one `fr` start-up — roughly two seconds — to every turn end of a bound session. OpenCode cannot block a stop, so its plugin continues the session with that command instead: weaker, and not yet proven on a live session. Hermes has no adapter — there, the prose above is all there is.

### 7. journal-check — the review-owed gate, run by the cursor
The last `review-phase` record's resolve runs `fr journal check --scope plan --plan-dir {{ artifacts.plan }} --require-reviews` in the same call (`fr run advance` after a fix) — exit code is the verdict (#430: an instruction-only obligation gets absorbed). Fails on a locally-complete, non-manual phase with no `kind=review` entry naming it; fix by completing/journaling that review, then re-`advance` (`cli` steps self-complete). Strands runs started against the older shape, by design — recover with `fr run reshape <run-id>` (then `--yes`) first: it inserts the new step pending and keeps every unit. When reshape refuses (the added step is at or behind the cursor), or the reviews ran in an earlier session, use `fr run adopt <plan-dir> --supersede` (preview, then `--yes`) instead of moving the run file aside by hand: it carries the old cursor's gate provenance, units and evidence, and infers a historical review (`reviewer=historical`, journal entry created before the cursor and after the phase's work, no visual evidence owed) for each phase the plan journal already reviewed, re-dispatching `review-phase` only for the rest. A review by hand takes `--evidence reviewer=historical` only within that same bound.

### 8. deliver — one PR per repo, all artifacts aboard
**First, push the branch and open or refresh the draft PR** (a merge request on GitLab), as soon as `deliver` opens (the last `review-phase` record's resolve prints its brief) and before any verification, so CI runs while your local suite does (#799): `git push`, then, if no PR exists yet (a batch dispatch usually opened one), open it as a draft with a provisional body through this repo's forge (on GitHub, `gh pr create --draft`; never `gh` on a non-GitHub remote). A red CI run on a draft is harmless; a red local suite still blocks `deliver`. Then verify (`superpowers:verification-before-completion`): run the full suite YOURSELF into a log with a shell redirect (`> $TMPDIR/full-suite.log 2>&1`), as its own command AFTER the resolve that opened `deliver` (the last `review-phase` record's resolve, which runs `journal-check` and prints `deliver`'s brief); a suite run inside that same call predates the unit and is refused, outside the repo and never under `<run-id>.records/` — an executor's "green" is a claim, not evidence, and a log you compose by hand is refused — named in the deliver record's `evidence: {tests: <log>}` — or `tests: ci` (§5's rule: the gate checks green on the pushed head's CI sha) — or `tests: reuse` instead: accepted while HEAD's code tree (everything outside `docs/superpowers/` and `docs/acceptance/`) equals the one the latest phase unit's recorded suite log covered and no code path is uncommitted, so a run whose last phase log is green on the final tree skips the second full suite; a review-phase fix changed the tree, so it needs its own recorded log or a fresh run here, and the refusal names the paths that moved; self-review pass, steps ticked, `journal-check` passed (§7). **A walk, when owed:** if the spec's `## Verification` gives the run, or any row, an agent-driven pre-merge strategy (`candidate`), `deliver` also owes `evidence: {walk: <log>}`. Produce it by running `fr verification walk --run <run-id> --model <your model>` as a BARE command (`fr` or `uv run fr`, no env prefix, pipe or redirect — only a bare walk is witnessed, and its log is bound to this run, the strategy and the manifest's hash), on a clean committed code tree, as its own command after the resolve that opened `deliver`. It installs the candidate into a throwaway prefix through the repo's `.fr/candidate-install` (the operator's own `fr` is never touched), runs the smoke (install, version, status in a fresh fixture) and each row's scenario, writes the log outside the repo, prints `walk log: <path>` and exits non-zero on any failing step — fix and walk again. `deliver` refuses a log for another run or strategy, one whose code tree is not HEAD's, with a failing step, or missing an owed row by name; `walk: none` is accepted only when no walk is owed, and a run with no `## Verification` section behaves as before. When the run owes `visual` rows, take fresh screenshots of the delivered branch and open them — phase evidence does not carry over — filling deliver's record `visual:` section. **The PR's labels:** fr keeps one `verification:<kind>` label per kind and one `gate:<tester|devops>` label on it (synced when `brainstorm` and `spec-review` resolve, warning on failure, and again at `deliver`, which refuses on GitHub when it cannot, printing the retry; a forge that cannot label a PR only warns, and `tracking none` syncs nothing). **Leftovers, before the body:** `deliver` refuses while an out-of-scope finding, an `owed` entry, an owed row citing the spec (`not-implemented`/`unwired`/`walk-owed`) or a narrowing decision (`fr journal add --kind decision --narrows <refs> [--gate owner] [--answered-by operator]`) is unaccounted, printing each with its fix — `fr journal file --scope <s> --slug <slug> --id <id>` (files it as a `follow-up` or `fr:owed` issue through the archive's filers and records where it went), the row's `fr acceptance set-status --issue`, or `fr verification set --gate` to gate it; under `tracking none` only the gate applies. **fr renders the PR body:** resolve `deliver` with its record (`emitted: {pr: <url>}`, the PR opened above) and fr writes `docs/superpowers/runs/<run-id>.records/pr-body.md` — in-scope findings from BOTH journals, the out-of-scope ones (or "None."), the operator-driven pre-merge rows with their exact walk command and a Ready-checklist line for the operator to tick after walking (`## Pre-merge verification owed`, or "None." — `deliver` does not wait for that walk), the rows still owed a live run (`## Post-merge verification owed`, each with its reason or `no reason recorded (legacy)`, or "None."), `fr plan proportionality` (above 2× the estimate, add a justification line), the `fr run cost` table (`—` is unobservable, never zero) — then REFUSES until the live PR, read back through the repo's forge adapter (GitHub, GitLab or Gitea), carries every one of those sections (so #612's missing out-of-scope section cannot ship), and refuses a line that shares one closing keyword across several issues (`Closes #a and #b` closes only `#a` on merge): one `Closes #n` per issue, one per line. **A gated issue gets `Refs #n`, never `Closes #n`:** `deliver` refuses a live body that closes, fixes or resolves an issue cited by a row that is post-merge or gated by a post-merge gate (`tester`, `devops`) and not yet walk-verified, or named by a narrowing decision the operator did not answer (`decided_by=operator`), or an owed row's `issues:` tracking issue, printing the line and the `Refs` fix; the issue closes when the operator records a passing walk (`fr acceptance set-status --walk`, which prints the close command).
Put that file on the draft PR and resolve again — the refusal prints the exact edit/create command for this repo's forge (on GitHub, `gh pr edit --body-file <it>`, or `gh pr create --draft --body-file <it>` if no PR exists yet); run that one, never `gh` on a non-GitHub remote. Above fr's marker add: summary + spec/plan paths, decisions, the issues `fr journal file` filed (none under `tracking none` — leftovers stay recorded in the journal and PR body), an **Operator gates** section verbatim from `fr run gates <run-id>` (never blank), the back-loaded manual phase marked "unimplemented — operator pushes to this PR", the Test Plan verbatim (only the post-merge rows: "post-merge — operator-driven"), acceptance debt (`fr acceptance status`) and rows-added-since-brainstorm (`fr acceptance check --added-since origin/main`), each with a one-line defense, and a Ready-checklist guard — the operator's checklist, not yours: CI green (under `ci none` "local suite green (evidence: <log>)"), explicit review ok, no commits since the ok (fr's own `chore(fr):` record commits do not count). The explicit review ok is the operator's, given on the PR after delivery: your review-phase reviewer, a re-dispatched reviewer or a passing `journal-check` is never it (#814). Never tick a guard box yourself, and never mark the PR ready — the ready transition is the operator's too (`gh pr ready` · `glab mr update <n> --ready` · `tea pulls edit <n> --ready`, run by them once all three hold). Never self-merge.
**Devcontainer mode:** `fr run` and `fr usage` run on the harness host — `fr isolation exec` refuses them and prints the host-side command; run that.

**Hand off, in every mode.** The `done` resolve prints the cursor commit's push line (or a NOT-committed line: commit it), then, as its last lines, the `closeout: … fr pickup --run <run-id>` pair. `git push`, then report the local suite and CI's state, and relay the closeout line verbatim as the last line of your final message, with nothing after it (#814). Stop; the operator reviews, marks the PR ready and merges.

### Post-merge close-out
Runs in a **NEW session** from the base clone, not the delivering one — the operator opens it with the `fr pickup --run <run-id>` line relayed at `deliver` (or the same line `fr run advance` reprints for an already-finished run); for a triage batch, the batch's driver (`fr triage batch drive`) starts that session through the batch's runner once the PR merges. That command refuses, exit 2, a run whose `deliver` isn't done; otherwise it prints a self-contained brief — branch, PR, spec/plan paths, and the closeout steps as exact commands, built only from the run file, so the new session needs none of the delivering one's memory. Follow it in order: `fr isolation verify-merge --branch <b>` (no `--default-branch` needed — it resolves the remote's own default) — not verified → STOP and recover (cherry-pick / fresh PR); the spec's Test Plan if present; `fr status`; `fr isolation up --branch chore/archive-<slug>` (never inside the just-merged feature workspace), then the one archive command the brief prints — `fr archive --branch <b> --issues <qid,…>`, where each out-of-scope finding the brief lists is named by its qualified id `<scope>/<slug>/<id>`: archive files one tracker issue per id you keep (`--no-issues` files none; under `tracking none` no tracker is configured, so the findings stay recorded in the journal and PR body) and defers each finding to its issue in its journal, staged for the same housekeeping commit — and it refreshes the usage files and retargets the matrix refs itself, so there is no separate `fr usage` or matrix step; commit and push, open the housekeeping PR; `fr isolation down --branch <b>` (or let gc reap it); once the housekeeping PR has merged, `fr isolation down --branch chore/archive-<slug>` too — the brief brought that workspace up, so it takes it down.

Files in this skill

  • .source119 B
  • SKILL.md42.2 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.