Ship feature
The full loop, one command: dump a feature brief and it plans (/plan-feature), builds and raises the MR (/build-feature), gets independent external-AI reviews (/mr-review), triages and fixes the findings (/address-review), then re-reviews — looping until the review comes back clean — and exits at a merge gate: --merge=ask (default) stops and asks you to approve the merge, --merge=auto merges when converged + CI green, --merge=never just reports. Safeguards: max review rounds (default 3), no-progress detection (same finding surviving two rounds stops the loop instead of thrashing), and honest convergence (threads are never resolved just to make the loop exit). Human touchpoints: the planner's clarifying questions at the start (skippable with --autonomous), a genuine architectural concern, a red build, and the merge gate itself. Use when: "ship this feature", "run the whole loop", "build and merge this", dumping a feature brief you want taken all the way to a merge-ready (or merged) MR.From its SKILL.md
npx -y skills add ohyesgocool/feature-loop --skill ship-featureAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
11.2 KB, ~2.5k tokens by cl100k_base, as published. Nobody here has run it
Ship Feature
Run the whole feature lifecycle as one supervised loop:
brief ─→ PLAN ─→ BUILD (+MR) ─→ REVIEW ─→ ADDRESS ─→ converged? ──no──┐
▲ │ │
└──────────────────────┴── round+1 ─┘
│yes
▼
MERGE GATE
ask / auto / never
You are the loop supervisor. The stages themselves are the four skills — invoke them, don't re-implement them. Your job is sequencing, state, convergence judgment, and honest exits.
Flags
Parse from $ARGUMENTS (everything that isn't a flag is the brief / plan path):
| Flag | Default | Meaning |
|---|---|---|
--merge=ask|auto|never | ask (or SHIP_MERGE_MODE env) | what happens when the loop converges |
--max-rounds=N | 3 | maximum review→address rounds before an honest non-converged exit |
--autonomous | off | planner answers its own clarifying questions (recorded as Decisions) instead of asking |
--plan=path | — | skip planning; start from an existing plan file |
--resume | auto-detected | continue an interrupted loop from its recorded stage and round |
State the resolved flags in your first status line so a misparse is caught immediately. Track the loop in your task tracker: plan · build · round 1 (review, address) · … · merge gate.
Loop state — the loop survives its session
A loop that dies with its session (crash, interrupt, context loss) and restarts from zero is not a tool a team can trust. Persist state and make every stage re-entrant:
Write .loop/<feature-slug>.state.json at every stage boundary (entering and leaving a
stage). Shape:
{
"feature": "csv-export", "plan": "docs/plans/2026-07-03-csv-export.md",
"branch": "feat/csv-export", "mr": "!87",
"stage": "address", "round": 2, "reviewed_sha": "abc1234",
"flags": {"merge": "ask", "max_rounds": 3, "autonomous": false},
"rounds": [{"valid": 3, "partial": 1, "invalid": 2, "verdicts": ["Request changes", "..."]}],
"started_at": "…", "updated_at": "…"
}
Recommend adding .loop/ to the project's .gitignore — state is transient scaffolding, not
history (metrics are recorded separately and durably; see the Ship Report).
On start: if a state file exists for the current branch, say so and resume from its
recorded stage and round — --resume just makes the intent explicit. A new brief while
stale state exists for a different feature is a fresh loop (leave the old file; its loop can
still be resumed on its own branch). Never silently restart a loop from zero when state says
it was mid-flight.
Idempotency contracts per stage (what makes resume safe):
- Plan/Build: the plan file and branch are checked before recreating — existing plan + branch with commits means resume, not redo.
- Review: before invoking
/mr-review, check the MR for a brief already footered with the current round — present means the round's review is done; skip to address. - Address:
/address-reviewalready never double-posts replies or re-triages resolved threads — safe to re-enter. - Merge gate: check the MR's actual state first; an MR that is already merged reports merged, it doesn't error.
Stages
Stage 1 — Plan
Invoke /plan-feature with the brief (skip if --plan given and the file exists). This is the
loop's one designed human touchpoint at the start: answer the planner's blocking questions
now, then walk away. With --autonomous, instruct the planner to convert every would-be
question into a recorded default in the Decisions section — the user reviews decisions in the
MR instead of answering questions up front.
Stage 2 — Build
Invoke /build-feature with the plan. It branches fresh from main, executes the phases, and
ends with the branch pushed and the MR raised (Problem / Solution / Technical details / Review
notes). Capture the MR reference — every later stage uses it.
Its two hard stops are real and pass through the loop: an architectural concern pauses everything for the user; a red build ends the run with a report. Don't route around either.
Stage 3 — Review round r
Invoke /mr-review on the MR. External reviewers (whichever of OpenAI / Grok are configured)
post their briefs as MR comments. Note each reviewer's verdict line.
Stage 4 — Address round r
Invoke /address-review on the MR. It triages every open comment against the real diff, fixes
VALID/PARTIAL findings, dismisses INVALID ones with reasons, pushes, and replies to every
thread. Record the round's tally: valid / partial / invalid, and the list of finding titles.
Convergence check — after every round
The loop converges when a full round shows the work is clean:
- The latest review round produced zero VALID or PARTIAL findings after triage (dismissed-with-reasons findings don't block), or every reviewer's verdict is "No blocking issues"; and
- every review thread on the MR has been replied to (resolved or explicitly deferred with an owner); and
- the MR's head pipeline is green (poll
glab api "projects/:id/merge_requests/<iid>"→.head_pipeline.statusuntil it settles; a failed pipeline is a red build → hard stop).
Not converged → increment the round and go back to Stage 3, subject to the safeguards below.
Safeguards against thrash:
- Max rounds (
--max-rounds, default 3). External reviewers can generate low-value findings forever; three rounds is where returns go negative. Hitting the cap is an honest exit: report what's still open and stop — never merge past it silently. - No-progress detection. If a finding you fixed in round r comes back in round r+1 (same file/issue), or the valid-finding count doesn't drop between rounds, stop and escalate to the user with both rounds' tallies — the loop is oscillating, and a human call beats a fourth attempt.
- Honest convergence only. Never resolve a thread without a fix or a stated dismissal,
never soften a triage verdict, never skip
/mr-review"because it'll probably pass" — a loop that games its own exit criteria is worse than no loop. - Cost awareness. Each round spends reviewer API tokens. Note the round count in the final report so the user sees what convergence cost.
Merge gate — on convergence
First run the readiness checklist (all must hold, whatever the merge mode):
- Converged per the check above (findings clean + threads closed + CI green).
- The MR is mergeable: no conflicts with the target branch (
.has_conflicts == false,.merge_status). If the target moved and there are conflicts, stop and report — resolving a conflicted rebase is a human-supervised task, not a loop step. - Surface the build report's follow-ups (manual migrations to apply, cross-repo deploy order) — merging does not make those happen; they go in the final report either way.
Then act per the flag:
ask(default): print the Ship Report (below) ending with READY TO MERGE and the exact merge command — then stop. The user merges, or replies "merge it" and you run the command. This is the safe default; auto-merge is opt-in per invocation.auto: merge it:glab mr merge <iid> --remove-source-branch(GitHub:gh pr merge <n> --delete-branch, honoring the repo's merge method). Verify the MR state ismerged, then report. If the merge API refuses (permissions, approvals required, protected branch rules), report the refusal verbatim — don't try to bypass review requirements.never: report and end with the MR open — useful when merging is someone else's call.
Record the run, then report
On every exit — merged, ready, or stopped — append one line to docs/loops/metrics.jsonl,
built from the state file:
{"ts":"<iso8601>","type":"run","feature":"csv-export","mr":"!87","outcome":"merged|ready|stopped:<reason>","rounds":2,"lead_time_min":94,"tokens":{"openai":48210,"xai":39102},"flags":{"merge":"ask","max_rounds":3}}
Commit it as docs: record loop metrics when your workflow permits a direct docs commit
(append-only JSONL merges trivially); otherwise leave it staged and say so in the report.
/loop-stats renders the trends. A loop that doesn't measure itself can't prove it's worth
running.
Ship Report (final output, always)
## Ship Report — {feature} (MR !{N})
Outcome: MERGED ✅ | READY TO MERGE (awaiting approval) | STOPPED ({reason})
Loop: plan {✅/skipped} · build ✅ ({n} commits) · {r} review round(s)
Rounds:
1. {v} valid / {p} partial / {i} invalid → fixed {v+p} · verdicts: {…}
2. …
Ledgers: hacks {n} · sync points {n} (see MR description / build report)
Follow-ups: {manual migrations + order · deploy sequence · deferred items · none}
Rules
- Orchestrate, don't re-implement. Each stage is its skill, with its skill's rules. If a stage skill is missing, stop and say which one — no inline approximations of it.
- The sub-skills' hard stops are the loop's hard stops. Architectural concern, red build, red pipeline, merge conflicts: all surface to the user immediately. The loop makes routine iteration autonomous; it never makes judgment calls autonomous.
- Merging is gated by the flag, and
askis the default.automust have been explicitly requested this invocation (or viaSHIP_MERGE_MODE) — never assume it, never upgrade to it mid-run, and record in the report which mode ran. - Exits are honest. Converged, max-rounds, no-progress, or hard stop — the report names which, with what's still open. "Merged" is only claimed after verifying the MR state.
- One feature per loop. Don't batch unrelated briefs into one run; queue them as separate invocations so each MR stays reviewable.
- Keep round outputs terse. The sub-skills print their own detail; the loop supervisor adds one tally line per stage, and the Ship Report at the end.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.