@wemuda/launchrail 1.12.0 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +3 -1
  2. package/assets/agents-docs/domain.md +2 -2
  3. package/assets/agents-docs/issue-tracker-github.md +1 -1
  4. package/assets/agents-docs/issue-tracker-linear.md +1 -1
  5. package/assets/ralph.workflow.js +640 -273
  6. package/assets/skills/NOTICE.md +4 -0
  7. package/assets/skills/launchrail/launch/SKILL.md +9 -7
  8. package/assets/skills/launchrail/launch/workflow.md +57 -4
  9. package/assets/skills/launchrail/launch-code-review/SKILL.md +1 -1
  10. package/assets/skills/launchrail/launch-design-handoff/SKILL.md +3 -2
  11. package/assets/skills/launchrail/launch-design-validation/SKILL.md +3 -3
  12. package/assets/skills/launchrail/launch-discovery/SKILL.md +3 -3
  13. package/assets/skills/launchrail/launch-grill/SKILL.md +51 -15
  14. package/assets/skills/launchrail/launch-grill/domain-modeling.md +3 -1
  15. package/assets/skills/launchrail/launch-implement/SKILL.md +10 -10
  16. package/assets/skills/launchrail/launch-project-alignment/SKILL.md +3 -3
  17. package/assets/skills/launchrail/launch-ralph/SKILL.md +79 -59
  18. package/assets/skills/launchrail/launch-ralph-implement/SKILL.md +8 -7
  19. package/assets/skills/launchrail/launch-resolving-merge-conflicts/SKILL.md +1 -1
  20. package/assets/skills/launchrail/launch-spec/SKILL.md +8 -6
  21. package/assets/skills/launchrail/launch-tickets/SKILL.md +10 -7
  22. package/assets/skills/launchrail/launch-vision-creation/SKILL.md +2 -2
  23. package/assets/skills/launchrail/launch-wayfinder/SKILL.md +15 -9
  24. package/dist/commands/add.js +2 -1
  25. package/dist/commands/add.js.map +1 -1
  26. package/dist/commands/doctor.js +29 -0
  27. package/dist/commands/doctor.js.map +1 -1
  28. package/dist/commands/init.js +2 -1
  29. package/dist/commands/init.js.map +1 -1
  30. package/dist/commands/verify.d.ts +11 -2
  31. package/dist/commands/verify.js +22 -7
  32. package/dist/commands/verify.js.map +1 -1
  33. package/dist/index.js +4 -1
  34. package/dist/index.js.map +1 -1
  35. package/dist/lib/adr.d.ts +27 -0
  36. package/dist/lib/adr.js +87 -0
  37. package/dist/lib/adr.js.map +1 -0
  38. package/dist/lib/manifest.d.ts +7 -1
  39. package/dist/lib/manifest.js +8 -1
  40. package/dist/lib/manifest.js.map +1 -1
  41. package/dist/lib/project.d.ts +2 -0
  42. package/dist/lib/project.js +2 -1
  43. package/dist/lib/project.js.map +1 -1
  44. package/dist/lib/seeds.d.ts +2 -0
  45. package/dist/lib/seeds.js +14 -6
  46. package/dist/lib/seeds.js.map +1 -1
  47. package/package.json +1 -1
@@ -1,33 +1,38 @@
1
1
  ---
2
2
  name: launch-ralph
3
- description: The Ralph implementation loop's contract — policies, dispatch steps, the loop-owned merge gate, and the supervisor's duties when the loop runs as the ralph workflow (the default engine for any multi-ticket run). Skill-mode orchestration of fresh-context implementers lives here too, as the declared exception. Behind /launch-implement (the user-typed front door) — never invoke it on your own initiative; reach it through that door or an explicit user request to run the loop.
3
+ description: The Ralph implementation loop's contract — policies, dispatch steps, the loop-owned local landing gate, checkpoints, and the supervisor's duties, whether the loop runs as the ralph workflow (the default engine) or as skill-mode orchestration (the declared exception). Behind /launch-implement — reach it through that door or an explicit user request, never on your own initiative.
4
4
  ---
5
5
 
6
6
  # Ralph — the autonomous implementation loop
7
7
 
8
- The user starts this loop through `/launch-implement` (or by asking for it in so many words); it is never started unprompted — a campaign spawns many agents and merges PRs, so the start is always a human decision.
8
+ The user starts this loop through `/launch-implement` (or by asking for it in so many words); it is never started unprompted — a campaign spawns many agents and lands code, so the start is always a human decision.
9
9
 
10
- You are the orchestrator. **You do not write code. You do not read diffs. You do not fix failing branches yourself.** You compute what's ready, dispatch, verify, and keep a running log. Tracker state and subagent reports in, decisions out.
10
+ You are the orchestrator. **You do not write code. You do not read diffs. You do not fix failing branches yourself.** You compute what's ready, dispatch, land, verify, and keep a running log. Tracker state and subagent reports in, decisions out.
11
11
 
12
12
  **Output budget: decisions, not working.** You owe the user two reports per run — a one-line pre-launch echo (scope, target, engine) and the close-out recap — plus any *failure* or *changed plan* the moment it happens. Everything else is working, not output: precondition checks, base-branch resolution, guard-hook state, journal reads, arming check-ins. Do it silently. A passing check is not a status update; a launched run is not a recap; the scope, target, and engine are stated once at the echo and once at close-out, never restated between. Keep the running log for yourself — surface it only at those two moments.
13
13
 
14
- One agent implementing a whole backlog in a single session degrades — context fills with diffs and half-remembered state, and quality drops with every ticket. This loop inverts that: every ticket gets a fresh-context implementer subagent that owns the build through an open PR, the loop's merge gate lands it, and nothing anyone reports is trusted until the remote confirms it.
14
+ One agent implementing a whole backlog in a single session degrades — context fills with diffs and half-remembered state, and quality drops with every ticket. This loop inverts that: every ticket gets a fresh-context implementer subagent that owns the build through a pushed, fast-gate-green `ralph/<n>-*` branch; the loop lands that branch itself — a local squash-merge onto the integration base under its own gate run, pushed straight to the remote — and nothing anyone reports is trusted until the remote confirms it. There is no per-ticket PR and no cloud-CI wait anywhere in the loop: the same gate that CI would run runs locally in minutes (or seconds, on warm caches), and cloud CI runs once, on the release PR the run offers at the end (ADR-0032).
15
15
 
16
- This skill is the loop's contract and its supervisor. The loop itself runs as the deterministic `ralph` workflow (`.claude/workflows/ralph.js`, installed by init; `launchrail sync` restores it) — **the workflow is the engine for every multi-ticket run**, launched with the resolved scope and integration target as JSON args and then supervised per this skill; its script state cannot be compacted away. Orchestrating dispatches from this session instead is the exception, and it is chosen out loud — name the engine and why before anything dispatches: the user asked to watch each dispatch, the Workflow tool is unavailable in this environment, or this is a targeted intervention (one parked ticket, re-run watchably). A hand-rolled fan-out that is neither is not the loop. And the exception swaps only who orchestrates, never the shape: fresh context per ticket, per-ticket PRs into the target, and the loop-owned gate survive every engine. An environment rule about branches or PRs re-targets the run (see Integration target) — it never selects this exception and never licenses sequential in-session implementation. The two forms share one policy block: change a policy here, change it in the workflow too (ADR-0005, field-revised by ADR-0010, ADR-0022, and ADR-0026).
16
+ This skill is the loop's contract and its supervisor. The loop itself runs as the deterministic `ralph` workflow (`.claude/workflows/ralph.js`, installed by init; `launchrail sync` restores it) — **the workflow is the engine for every multi-ticket run**, launched with the resolved scope and integration target as JSON args and then supervised per this skill; its script state cannot be compacted away. Orchestrating dispatches from this session instead is the exception, and it is chosen out loud — name the engine and why before anything dispatches: the user asked to watch each dispatch, the Workflow tool is unavailable in this environment, or this is a targeted intervention (one parked ticket, re-run watchably). A hand-rolled fan-out that is neither is not the loop. And the exception swaps only who orchestrates, never the shape: fresh context per ticket, per-ticket pushed branches landed one at a time by the loop's own local gate onto the target, and the full gate at checkpoints survive every engine. An environment rule about branches or PRs re-targets the run (see Integration target) — it never selects this exception and never licenses sequential in-session implementation. The two forms share one policy block: change a policy here, change it in the workflow too (ADR-0005, field-revised by ADR-0010, ADR-0022, ADR-0026, and ADR-0032).
17
17
 
18
18
  ## Policies
19
19
 
20
- - **Integration target: declared, singular, restated.** Every run merges its per-ticket PRs into exactly one base, named before anything dispatches and again in the close-out. **Consolidation** (the default, ADR-0026): one integration branch (e.g. `spec/44-mvp`) collects the whole campaign and the default branch is never touched; the front door names it scope-native — the session's designated working branch when the environment pinned one at start, else the scope's own spec/epic/slice name when it maps to one, else a generated `launch/*` fallback — and passes it as the `target` arg. A pinned-branch session (ADR-0028) changes only that name: the user's start authorizes the loop's mechanics, per-ticket `ralph/*` branches and PRs included, and the pin's real demands — default branch untouched, release PR offered not opened — are exactly what consolidation already does. The run ends by *offering* one release PR `<target> → <default>` — opened only when the user says so. **Trunk** (the explicit opt-in): the repository's default branch — each verified merge is immediately on mainline, and when the run ends there is nothing left to integrate; select it only when the user asks for per-ticket merges to the default branch, and never when the environment forbids pushing there. A named target missing from the remote is created from the default branch's tip before preflight verifies it; a missing *default* branch stays a refusal. In consolidation mode `Closes #n` never auto-fires (auto-close only triggers from the default branch), so the explicit post-merge close is load-bearing, not belt-and-suspenders.
21
- - **Width: 3** implementers at once. Width multiplies conflict rate and shared-machine load, not just throughput — use 1 until a run has landed tickets cleanly on this project (the workflow's `canary: true` encodes exactly that). Cut a batch below width when its tickets would obviously collide (same module, same files); when in doubt, narrow. Tickets that add DB migrations are a known collision: two parallel implementers both claim the next migration number — serialize them, or expect the second to renumber at pre-PR sync.
22
- - **Cap: none** by default. The user may bound a run ("the next 5"): stop once that many merges have been *verified*, keeping every batch within the remainder so the run cannot overshoot. Failed and deferred dispatches never consume the cap — their slots go to other tickets. Hitting the cap ends the run cleanly: the rest of the frontier stays ready (reported, never parked), and close-out runs as usual.
23
- - **Attempts: 2** — retry a failed ticket once with a fresh context, then park it.
24
- - **Deferrals are not attempts.** An implementer that stops at its dependency gate (a declared blocker had not actually landed) hands the attempt back and is retried after the blocker lands — capped at 2 deferrals, then it counts as a real failure.
25
- - **Max rounds: 25** — a backstop, not a target; deferral rounds spend from it too. Stop and report if the frontier hasn't drained.
26
- - **Checkpoints: none** by default — run to completion, report once. The user may ask for a pause after each round instead.
27
- - **Review gate:** the implementer's own self-review via `/launch-code-review`, inside `launch-ralph-implement`.
28
- - **Verification gate:** `npx @wemuda/launchrail verify` — per ticket before the PR, and once more on the final base before the loop may report success.
29
- - **Merge ownership: the loop, not the implementer.** Implementers build, open the PR, and hand off at PR-open; the merge gate — CI wait, mergeability re-check, squash-merge, explicit issue close, `ralph:building` removal — belongs to the loop (you in skill mode, a per-ticket gate agent in the workflow). An implementer subagent must never sit in a CI wait: it cannot foreground-sleep, and a background sleep surfaces to its parent without resuming it — tokens burn, nothing advances. Merge ordering stays optimistic and remote-arbitrated (re-check mergeability immediately before merging, up to 3 retries if the base moves; no merge locks), and the single gate owner serializes where it matters — critical-path first, schema-touching tickets one at a time.
30
- - **Labels:** tickets enter as `ready-for-agent`, are marked `ralph:building` while owned, and leave as closed or `needs-info` (parked).
20
+ - **Integration target: declared, singular, restated.** Every run lands its per-ticket branches onto exactly one base, named before anything dispatches and again in the close-out. **Consolidation** (the default, ADR-0026): one integration branch (e.g. `spec/44-mvp`) collects the whole campaign and the default branch is never touched; the front door names it scope-native — the session's designated working branch when the environment pinned one at start, else the scope's own spec/epic/slice name when it maps to one, else a generated `launch/*` fallback — and passes it as the `target` arg. A pinned-branch session (ADR-0028) changes only that name: the user's start authorizes the loop's mechanics, per-ticket `ralph/*` branches included, and the pin's real demands — default branch untouched, release PR offered not opened — are exactly what consolidation already does. The run ends by *offering* one release PR `<target> → <default>` — opened only when the user says so; that PR is where cloud CI runs, once. **Trunk** (the explicit opt-in): the repository's default branch — each verified land is immediately on mainline, and when the run ends there is nothing left to integrate; select it only when the user asks for per-ticket lands on the default branch, and never when the environment forbids pushing there. A named target missing from the remote is created from the default branch's tip before preflight verifies it; a missing *default* branch stays a refusal. `Closes #n` never auto-fires off the default branch, so the explicit post-land close is load-bearing, not belt-and-suspenders.
21
+ - **The loop lands in the checkout it was launched from.** Preflight syncs the base into it (clean tree required — commit or stash first; a local base that has diverged from the remote is a refusal), builders work in their own worktrees, and every land and checkpoint runs there one at a time — the warm caches are what make the gate cheap. At the end the checkout sits on the target at its landed tip.
22
+ - **Width: 3** implementers at once, kept busy by a **work pool** — when one finishes, the next ready ticket dispatches; a slow ticket never holds the others. Width multiplies conflict rate and shared-machine load, not just throughput — use 1 until a run has landed tickets cleanly on this project (the workflow's `canary: true` encodes exactly that). Cut a batch below width when its tickets would obviously collide (same module, same files); when in doubt, narrow. Tickets that add DB migrations are a known collision (two parallel implementers both claim the next migration number): the workflow keeps **one migration-adding ticket in flight at a time** from the graph reader's flag; in skill mode, serialize them yourself.
23
+ - **Ordering: critical path first.** Among ready tickets, the one with the most transitive dependents dispatches first, so a wide graph unblocks quickly — computed from the parsed edges, never by a model.
24
+ - **Cap: none** by default. The user may bound a run ("the next 5"): stop once that many lands have been *verified*, keeping dispatch within the remainder so the run cannot overshoot. Failed and deferred dispatches never consume the cap. Hitting the cap ends the run cleanly: the rest of the frontier stays ready (reported, never parked), and close-out runs as usual.
25
+ - **Persistence: the pushed branch is the checkpoint.** An implementer pushes its `ralph/<n>-<slug>` branch the moment it branches and after every green step. A lost container costs the minutes since the last push, never a build: the next dispatch (this run's retry, or a relaunch after a recycle) adopts the pushed branch and continues from its last commit. Pushed `ralph/*` branches are never deleted mid-run; the release prunes only the branches of verified-landed tickets.
26
+ - **Attempts: 2** — retry a failed ticket once with a fresh context, then park it. The retry adopts the pushed branch and fixes forward; only when the failure shows the approach itself was wrong does it reset the branch and start over.
27
+ - **Re-syncs: 2 — a land hand-back spends no attempt.** When the base moved under a finished branch (the squash conflicts, or the merged tree fails the gate although the branch was fine on its own, or the remote base kept moving), the builder did nothing wrong: a fresh implementer re-syncs the pushed branch — merge the latest base in, resolve, fast gate, push, hand off again — up to twice per ticket before it counts as a real failure.
28
+ - **Deferrals are not attempts.** An implementer that stops at its dependency gate (a declared blocker had not actually landed) hands the attempt back and is retried after the next land or tracker refresh — capped at 2 deferrals, then it counts as a real failure.
29
+ - **Two gates, tiered.** The **fast gate** — `npx @wemuda/launchrail verify --fast` (`testing.checkCommand`, else the unit command; never e2e) — runs before every hand-off and again, by the loop, on every merged tree before it is pushed. The **full gate** — `npx @wemuda/launchrail verify` — runs at preflight, at **checkpoints** (after every 5 lands: `checkpointEvery`), and at release before the loop may report success. The full suite is paid once per checkpoint instead of once per ticket, and a red checkpoint has at most five suspects.
30
+ - **A red checkpoint gets one repair.** The loop dispatches a single fresh implementer with the failures and the tickets landed since the last green base; its branch lands under the *full* gate and becomes the new green checkpoint. If that repair does not land, the base is **red**: nothing else lands, finished tickets are **held** on their pushed branches, and the run ends unverified with the reason — a human fixes the base and relaunches with `knownGreen`.
31
+ - **Max builds: 60** — a backstop, not a target; retries, deferrals, re-syncs, and repairs all spend from it. Stop and report if the frontier hasn't drained.
32
+ - **Checkpoints: none** in the human sense by default — run to completion, report once. The user may ask for a pause after each land instead.
33
+ - **Review gate:** the implementer's own self-review via the `launch-code-review` skill, inside `launch-ralph-implement`.
34
+ - **Landing ownership: the loop, not the implementer.** Implementers build, push, and hand off at a green fast gate; the landing — fetch, fast-forward the base, squash-merge, the loop's own gate run, push, explicit issue close, `ralph:building` removal — belongs to the loop (you in skill mode, a per-ticket lander agent in the workflow), strictly one at a time. A lander never writes code: a conflict or a red gate is reported and handed back, never repaired in place.
35
+ - **Labels:** tickets enter as `ready-for-agent`, are marked `ralph:building` while owned, and leave as closed or `needs-info` (parked). A held ticket keeps `ralph:building` — the next run owns it.
31
36
 
32
37
  ## Preconditions — refuse to start if any fails
33
38
 
@@ -35,85 +40,100 @@ Verify them silently: a green base and a reachable tracker are the expected case
35
40
 
36
41
  1. `.launchrail.yml` exists with `issueTracker` not `none`, and the tracker is reachable **from this environment**: check whether the CLI the project docs assume (e.g. `gh`) is installed here; if not, identify the substitute (e.g. GitHub MCP tools) and name it in every dispatch.
37
42
  2. Open tickets labeled `ready-for-agent` exist and carry explicit `Blocked by: #n` edges (or the tracker's native blocking relations). No tickets with edges → nothing to orchestrate; point the user at `launch-tickets`. If anything wearing `ready-for-agent` is plainly not an implementable ticket — a published spec, research notes, an epic — stop and have it relabeled (e.g. `spec`) before starting: the frontier is computed from the label alone and cannot tell prose from work.
38
- 3. The integration target is resolved (a consolidation branch by default, or trunk when the user opts in — see Policies) and its branch is green on a fresh checkout: sync it (creating a named consolidation branch from the default branch's tip if the remote lacks it), run the install command, then `npx @wemuda/launchrail verify` — report actual exit codes, not the reassuring summary line; a broken base poisons every implementer after it. A missing *default* branch is a refusal, not a cue to guess another. An **empty verification contract fails `verify` and is a refusal condition**: a run whose completion nothing can verify must not start. Tell the user to configure `testing` commands in `.launchrail.yml` first.
39
- 4. The verbatim local commands are known (from `AGENTS.md` / `.launchrail.yml`), including which checks belong to CI rather than the shared local machine.
43
+ 3. The integration target is resolved (a consolidation branch by default, or trunk when the user opts in — see Policies) and its branch is green **in this checkout**: the tree is clean, the base is synced (creating a named consolidation branch from the default branch's tip if the remote lacks it; a local base that has diverged from the remote is a refusal — push or reset it first), the install command has run, and `npx @wemuda/launchrail verify` exited 0 — report actual exit codes, not the reassuring summary line; a broken base poisons every implementer after it. A missing *default* branch is a refusal, not a cue to guess another. An **empty verification contract fails `verify` and is a refusal condition**: a run whose completion nothing can verify must not start. Tell the user to configure `testing` commands in `.launchrail.yml` first. **On a relaunch** whose base still sits at a sha a previous run verified green, pass that sha as `knownGreen`: preflight syncs and installs but skips re-proving the base.
44
+ 4. The verbatim local commands are known (from `AGENTS.md` / `.launchrail.yml`): install, the fast gate, the full gate, and which checks belong to the shared local machine. If `testing.checkCommand` is unset the fast gate is the unit command — fine, but a project that names a quicker lint/typecheck/unit gate there makes every land cheaper.
40
45
 
41
46
  ## The loop
42
47
 
43
- Sync → compute frontier → dispatch batch → verify → handle outcomes → back to sync.
48
+ Sync → compute frontier → keep *width* builders busy → land each finished branch as it arrives → verify on the remote → checkpoint every N lands → back to the frontier.
44
49
 
45
- - **You resolve blocking edges yourself,** deterministically, from tracker state — read each ticket's `Blocked by` line verbatim and parse the `#n` references; never ask a subagent what's ready, and never let one paraphrase the edges. A single misread edge silently builds a ticket on a dependency that hasn't landed. The frontier is every ticket that is open, labeled `ready-for-agent`, not `needs-info`, not already attempted twice, and whose blockers are all settled (closed before the run, or merged and verified by this run). Parked tickets never block the loop; anything behind them is reported as stuck.
46
- - Dispatch up to *width* frontier tickets, **spawning the batch's subagents in a single message** so they run concurrently.
47
- - **Verify every claimed merge against the remote** before it counts: PR merged, its merge commit actually in the base branch's history, issue closed. A subagent's report is a claim, not evidence. Use a cheap, separate check (tracker API only — a PR description or comment is not evidence).
50
+ - **You resolve blocking edges yourself,** deterministically, from tracker state — read each ticket's `Blocked by` line verbatim and parse the `#n` references; never ask a subagent what's ready, and never let one paraphrase the edges. A single misread edge silently builds a ticket on a dependency that hasn't landed. The frontier is every ticket that is open, labeled `ready-for-agent`, not `needs-info`, not already attempted twice, not in flight, and whose blockers are all settled (closed before the run, or landed and verified by this run). Parked and held tickets never block the loop; anything behind them is reported as stuck.
51
+ - Dispatch up to *width* frontier tickets, **spawning the subagents in a single message** so they run concurrently, and dispatch the next ready ticket the moment a slot frees — never wait for a whole batch.
52
+ - **Adopt pushed work.** Before dispatching, list the remote's `ralph/*` branches; a ticket that already has one is dispatched with that branch named so the builder adopts it instead of starting over.
53
+ - **Land one at a time, in your checkout,** as branches arrive — never two lands interleaved, and never a land onto a red base.
54
+ - **Verify every claimed land against the remote** before it counts: the landing commit is on the base branch, the issue is closed. A subagent's report is a claim, not evidence. Use a cheap, separate check (tracker/API only — a comment is not evidence).
48
55
 
49
56
  ## The dispatch prompt
50
57
 
51
- Each implementer prompt is self-contained — assume it knows nothing about this session or the other implementers. It carries: the ticket number and title, the verbatim commands, how to reach the tracker from this environment, which branch is the base (the integration target), and these seven steps:
58
+ Each implementer prompt is self-contained — assume it knows nothing about this session or the other implementers. It carries: the ticket number and title, the verbatim commands (install, fast gate, full gate), how to reach the tracker from this environment, which branch is the base (the integration target), any pushed branch to adopt, and these seven steps:
52
59
 
53
- 1. **Dependency gate:** before anything else, confirm every ticket on the `Blocked by` line is closed with its work merged into the base. If any blocker is still open, do not build on a missing dependency — report "blocked" naming the open blocker, and stop. A deferral, not a failure; the loop retries after the blocker lands.
60
+ 1. **Dependency gate:** before anything else, confirm every ticket on the `Blocked by` line is closed with its work landed on the base. If any blocker is still open, do not build on a missing dependency — report "blocked" naming the open blocker, and stop. A deferral, not a failure; the loop retries after the blocker lands.
54
61
  2. Read the ticket and everything it links (spec sections, ADRs, journeys), plus `AGENTS.md`/`CLAUDE.md`. If the tracker tool truncates the body (long code spans are a known trigger), fetch the full text by another route — the tracker's search API, the spec file in the repo — and never implement from a truncated ticket. If the ticket is already closed, report "already-done" and stop.
55
62
  3. Label the ticket `ralph:building` so a lost session leaves a trace.
56
- 4. Branch from a fresh sync of the base: `ralph/<n>-<short-slug>`.
57
- 5. Implement by invoking the **`launch-ralph-implement`** skill — it owns TDD, the verification gate, browser smoke for user-facing changes, self-review via `/launch-code-review`, and commit conventions. Name the skill; do not paraphrase it.
58
- 6. Pre-PR sync: merge the latest base into the branch; resolve conflicts with the **`launch-resolving-merge-conflicts`** skill; if the base gained DB migrations since branching, regenerate yours to follow them with the project's migration tool — never hand-edit the journal; re-run the verification gate if anything changed.
59
- 7. Open a PR against the base, titled from the ticket, with `Closes #<n>` in the body. Never open a second PR for a ticket — adopt an existing one. Opening against an up-to-date base means CI tests the state that will actually land. Then **report PR-open and stop**: the CI wait, the merge, and the issue close belong to the loop's merge gate, not to you. Never push to the base directly.
63
+ 4. **Branch and push immediately.** Adopt a pushed `ralph/<n>-*` branch when one exists (fetch it, continue from its last commit — never start over); otherwise branch from a fresh fetch of the base — `git checkout -b ralph/<n>-<short-slug> origin/<base>`, never a checkout of the base itself in the worktree — and push at once. From then on **commit and push after every green step**: the pushed branch is the checkpoint a lost session resumes from and the loop's liveness signal.
64
+ 5. Implement by calling the Skill tool with **`launch-ralph-implement`** — it owns TDD, the commit-and-push cadence, the fast gate, browser smoke for user-facing changes, self-review via `launch-code-review`, and commit conventions. Name the skill; do not paraphrase it.
65
+ 6. Pre-land sync: merge the latest base into the branch; resolve conflicts by calling the Skill tool with **`launch-resolving-merge-conflicts`**; if the base gained DB migrations since branching, regenerate yours to follow them with the project's migration tool — never hand-edit the journal; re-run the fast gate if anything changed, then push.
66
+ 7. **Hand off:** confirm the pushed tip matches `HEAD`, then report "ready" with the branch, its sha, and a Conventional Commit title for the squash — and stop. The landing belongs to the loop. Never push to the base, never merge your work into it, and never open a PR — the campaign is released by one PR at the end.
60
67
 
61
- ## The merge gate — owned by the loop
68
+ ## The landing — owned by the loop
62
69
 
63
- In skill mode, you run the gate for every PR the implementers hand off (the workflow runs it as a per-ticket gate agent). Order merges yourself — critical-path first, schema-touching PRs one at a time:
70
+ In skill mode you land every branch the implementers hand off, in your own checkout, one at a time (the workflow runs it as a per-ticket lander agent, serialized by a script lock). Landing is bookkeeping, not repair:
64
71
 
65
- 1. Wait for the PR's CI from *this* session, spacing checks with your own timers (a background sleep here wakes you — the orchestrator can wait; implementer subagents cannot). ~20 minutes is the budget.
66
- 2. Green → re-check mergeability (the base may have moved since CI started), then squash-merge; if the base moves between check and merge, re-check and retry up to 3 times.
67
- 3. Merged → read the issue back and close it explicitly if still open — in consolidation mode auto-close never fires — and remove `ralph:building`. Then verify as always: the remote's word, not yours.
68
- 4. CI failed on the PR, or a real conflict → the ticket becomes a failed attempt with the failing check or conflicting files as its summary; the fresh retry adopts the PR (idempotency clause), repairs, and hands off again. A failure that reproduces on the base itself is systemic — stop the run, not the ticket.
72
+ 1. Preconditions: a clean tree (never stash or discard); fetch the base and the branch; check out the base and fast-forward it to the remote — a local base that has diverged is a stop, not a reset.
73
+ 2. Note whether the base moved since the implementer synced (is the base tip an ancestor of the branch?).
74
+ 3. `git merge --squash origin/ralph/<n>-<slug>`; on conflicts, reset to the remote base and hand back "conflict" with the files. Otherwise commit with the implementer's Conventional Commit title, `(#n)`, and a `Closes #n` trailer.
75
+ 4. If the change touched a dependency manifest or lockfile, run the install command. Then run the **fast gate** on the merged tree. Red → reset to the remote base and hand back "gate-failed" with the failing checks; a red base is never pushed.
76
+ 5. Push the base. A rejected push means the remote moved outside the loop: reset to it and redo once; a second rejection is "stale".
77
+ 6. Confirm on the remote that the base tip is your commit — that sha is the landing commit.
78
+ 7. Close the issue explicitly (auto-close never fires off the default branch), read it back closed, remove `ralph:building`, leave one comment naming the base and the sha. Then verify as always: the remote's word, not yours.
69
79
 
70
- Every dispatch — retries included — also carries these two clauses verbatim:
80
+ A conflict, a gate that only fails on the merged tree, or a stale remote hands the ticket back for a **re-sync** (no attempt spent, twice at most); a gate that fails on a branch that already contained the base tip is the builder's own failure and spends the attempt. Order lands as branches arrive; when two are ready at once, land the one with more dependents first.
71
81
 
72
- > **Integrity.** No placeholders, no stubs, no "simplified for now". Never delete, skip, or weaken a test to get a green run; if a test is genuinely wrong, fix it deliberately and say so in the PR body. Never claim verification passed without having run it.
82
+ ## Checkpoints and the repair
73
83
 
74
- > **Idempotency.** This step can be replayed after an interruption, so check before acting: if the ticket is already closed, report "already-done"; if a `ralph/<n>-*` branch or open PR already exists, adopt it and continue — don't restart. Never open a second PR for a ticket.
84
+ After every `checkpointEvery` lands (default 5) — and always at release — run the **full gate** on the synced base, in the same checkout, with no land interleaved. Green → the base tip is proven; note the sha. Red → dispatch exactly one **repair** implementer with the failures and the tickets landed since the last green base; it branches `ralph/repair-*` from the base, fixes the root cause (an integration break between two tickets, a migration-number collision, a journey a landing invalidated), makes the fast *and* full gates green, pushes, and hands off; land it under the full gate. Landed → green again, carry on. Not landed → the base is red: stop landing, hold finished tickets on their branches, and end the run unverified naming the failure. A failure that reproduces on the base at preflight is systemic — stop the run before it starts.
85
+
86
+ Every dispatch — retries, re-syncs, repairs included — also carries these two clauses verbatim:
87
+
88
+ > **Integrity.** No placeholders, no stubs, no "simplified for now". Never delete, skip, or weaken a test to get a green run; if a test is genuinely wrong, fix it deliberately and say so in the commit message. Never claim a gate passed without having run it.
89
+
90
+ > **Idempotency.** This step can be replayed after an interruption, so check before acting: if the ticket is already closed, report "already-done"; if a pushed `ralph/<n>-*` branch already exists, adopt it and continue from its last commit — don't restart, and never create a second branch for a ticket.
75
91
 
76
92
  ## Outcome handling
77
93
 
78
- - **Verified merge** → one log line; the ticket settles and may unblock others.
79
- - **Blocked (deferred)** → the dependency gate stopped the build. Hand the attempt back and retry in a later round; after 2 deferrals it becomes a real failure. A deferral costs a round, never an attempt.
80
- - **First failure** → delete the failed branch, then re-dispatch later with a *fresh context* plus the failure summary. A failed attempt's context is assumed poisoned — never resume it.
81
- - **Claimed merged, remote disagrees** — including merged-but-issue-still-open — → a failure like any other; the retry adopts the merged PR (idempotency clause), finishes the bookkeeping, and settles cleanly.
82
- - **Second failure** → park: comment both failure summaries on the ticket, remove `ralph:building`, add `needs-info`, move on.
83
- - **Systemic failure** — the base breaks, the tracker becomes unreachable, or the *same* infrastructure error hits different tickets → stop the whole run and report; another retry won't fix it.
94
+ - **Verified land** → one log line; the ticket settles and may unblock others.
95
+ - **Blocked (deferred)** → the dependency gate stopped the build. Hand the attempt back and retry after the next land or tracker refresh; after 2 deferrals it becomes a real failure. A deferral costs a dispatch, never an attempt.
96
+ - **Land hand-back (re-sync)** → the base moved under a finished branch. Re-dispatch a fresh implementer to adopt the pushed branch, merge the latest base, fast gate, push, hand off — no attempt spent, twice at most.
97
+ - **First failure** → re-dispatch later with a *fresh context* plus the failure summary; the retry adopts the pushed branch and fixes forward. A failed attempt's *context* is assumed poisoned — never resume it; its *code* is persisted and reused.
98
+ - **Claimed landed, remote disagrees** — including landed-but-issue-still-open — → a failure like any other; the retry finds the work on the base (an empty squash) or the issue open, finishes the bookkeeping, and settles cleanly.
99
+ - **Second failure** → park: comment both failure summaries and the pushed branch on the ticket, remove `ralph:building`, add `needs-info`, move on.
100
+ - **Held** → built and pushed while the base is red. Report it with its branch; a relaunch adopts it. Nothing to fix on the ticket.
101
+ - **Systemic failure** — the base breaks and the repair does not land, the tracker becomes unreachable, or the *same* infrastructure error hits different tickets (three dead agents in a row) → stop the whole run and report; another retry won't fix it.
84
102
 
85
103
  ## Supervising a workflow run
86
104
 
87
105
  When the Ralph loop runs as the `ralph` workflow instead of through this skill, you are still on the hook — the script runs headless, but a human is watching *you*, not it. Babysit the run like a deploy:
88
106
 
89
- 0. **Launch it unattended-safe.** An unattended run must start in a non-prompting permission mode (bypass / autonomous). In an interactive mode (default / plan / acceptEdits) a single benign permission prompt — an un-allowlisted MCP or Bash call — stalls the whole run, and an idle ephemeral container can be reclaimed mid-ticket, leaving a half-finished ticket. A guard hook warns at launch, but switching modes before you walk away is yours to do.
90
- 1. **Read the resolved scope back, immediately.** The first `log()` lines state it ("Scoped to #11, #12", "Stopping after 5 verified merge(s)", or "No scope — building the whole ready frontier"). An unscoped run when the user asked for three tickets is the cheapest failure to catch and the most expensive to miss — stop and relaunch if it is wrong. Scan the listed numbers for anything that is not an implementable ticket: a spec or research issue wearing `ready-for-agent` will be built as if it were work (the workflow excludes and logs obvious cases, but the label is the fix — have it corrected).
91
- 2. **Establish ground truth from the remote, never from the run's own reports.** On every check-in read the workflow journal (`journal.jsonl`) *and* the tracker/PRs. A merge is real only when the commit is on the base branch and the issue is closed.
107
+ 0. **Launch it unattended-safe.** An unattended run must start in a non-prompting permission mode (bypass / autonomous). In an interactive mode (default / plan / acceptEdits) a single benign permission prompt — an un-allowlisted MCP or Bash call — stalls the whole run, and an idle ephemeral container can be reclaimed mid-ticket. A guard hook warns at launch, but switching modes before you walk away is yours to do.
108
+ 1. **Read the resolved scope back, immediately.** The first `log()` lines state it ("Scoped to #11, #12", "Stopping after 5 verified land(s)", or "No scope — building the whole ready frontier"), the width and cadence, and any pushed branches being adopted. An unscoped run when the user asked for three tickets is the cheapest failure to catch and the most expensive to miss — stop and relaunch if it is wrong. Scan the listed numbers for anything that is not an implementable ticket: a spec or research issue wearing `ready-for-agent` will be built as if it were work (the workflow excludes and logs obvious cases, but the label is the fix — have it corrected).
109
+ 2. **Establish ground truth from the remote, never from the run's own reports.** On every check-in read the workflow journal (`journal.jsonl`) *and* the remote: `git ls-remote --heads origin` shows the base tip and every `ralph/*` branch with its sha; the tracker shows what closed. A land is real only when the commit is on the base branch and the issue is closed.
92
110
  3. **Arm check-ins across the long waits.** If the session can schedule a self-message, arm one a few minutes out (confirm scope and the first dispatches) and a longer fallback (catch completion or a stall). The workflow's completion notification is the primary signal; the check-ins are the backstop so the run survives an interruption.
93
- 4. **Know the healthy shapes so you don't cry wolf.** A ticket can appear twice in Build — that is the retry policy, or a *deferral* because its dependency had not landed yet (not a failure). Build ending at PR-open with a separate Gate agent doing the merge is the design, not a stall. Several Gate dispatches for one PR (`gate:#n`, then `gate:#n:ci-wait1…`) are the loop re-polling a still-running CI in place — cheap, expected on anything but the fastest CI, and *not* a build attempt: a slow CI costs re-polls, never a rebuild (ADR-0027). A ticket only truly fails after two real attempts, then it parks.
94
- 5. **Intervene by exception, not by reflex.** Parked ticket → dispatch a fresh scoped run for just that one. Stall (an agent stops writing, CI never returns) → diagnose from the journal. Wrong scope or wrong base → stop, fix, relaunch. Otherwise stay out of the way; the loop is built to self-correct.
95
- 6. **Report once at the end, concretely** — PR numbers, merge commits, issues closed, the verification outcome, anything punted — then disarm the check-ins.
111
+ 4. **Know the healthy shapes so you don't cry wolf.** `build:#n` → `land:#n` → `verify:#n` is one ticket landing; `checkpoint:k` is the full gate on the base after N lands; `repair:k` followed by `land:repair:k` is a red checkpoint being fixed, not a stall; `build:#n:resync1` is a land hand-back after the base moved (not an attempt); `build:#n:retry` is the one real retry; a ticket can appear twice in Build without either (a *deferral* because its dependency had not landed yet). A long build is *alive* while its `ralph/<n>-*` branch keeps moving on the remote (`git ls-remote`, or the branch's last commit time on the tracker) — that is the liveness signal; a silent journal alone means nothing. A ticket only truly fails after two real attempts, then it parks.
112
+ 5. **Intervene by exception, not by reflex.** Parked ticket → dispatch a fresh scoped run for just that one. Held tickets or a red base → the run's recap names the failure; fix the base by hand (or have a scoped run do it), verify it, then relaunch with `knownGreen: <that sha>` — the pushed branches are adopted, nothing is rebuilt. Container recycled mid-run → relaunch the same scope with `knownGreen` set to the last green sha from the journal or the recap; adopted branches resume from their last push. Never delete `ralph/*` branches by hand while a run may still adopt them. Wrong scope or wrong base → stop, fix, relaunch. Otherwise stay out of the way; the loop is built to self-correct.
113
+ 6. **Report once at the end, concretely** — landing commits, issues closed, checkpoint verdicts, the verification outcome, held and parked tickets with their branches, anything punted — then disarm the check-ins.
96
114
 
97
115
  ## Loop close-out — verification-gated completion
98
116
 
99
- When the frontier drains (or max rounds / a stop condition hits):
117
+ When the frontier drains (or the cap, the build backstop, a red base, or a stop condition hits):
100
118
 
101
- 1. Sync a fresh base and run `npx @wemuda/launchrail verify`. **The loop may not report success while this fails** — report "unverified" with the failures instead.
102
- 2. If `.launchrail.yml` has `modules.browser-testing: true` and any merged ticket changed user-facing behavior, dispatch one smoke run per the `launch-browser-smoke` skill and reference its evidence bundle (`artifacts/verification/<run-id>/`).
103
- 3. Report the campaign recap — it must let the user act without scrolling back:
119
+ 1. Sync a fresh base and run `npx @wemuda/launchrail verify` — unless the last green checkpoint already proved this exact tip. **The loop may not report success while this fails** — report "unverified" with the failures instead; a red base is unverified by definition.
120
+ 2. If `.launchrail.yml` has `modules.browser-testing: true` and any landed ticket changed user-facing behavior, dispatch one smoke run per the `launch-browser-smoke` skill and reference its evidence bundle (`artifacts/verification/<run-id>/`).
121
+ 3. Prune the remote `ralph/*` branches of the verified-landed tickets — only those; held and parked branches stay.
122
+ 4. Report the campaign recap — it must let the user act without scrolling back:
104
123
  - **Where the work lives:** the integration target and its head SHA; in consolidation mode, say explicitly that the default branch is untouched.
105
- - The ticket → PR → merge-commit table; parked tickets with their failure histories; stuck tickets and what blocks them.
124
+ - The ticket → landing-commit table; held tickets with their branches; parked tickets with their failure histories; stuck tickets and what blocks them; the checkpoint verdicts.
106
125
  - Follow-ups and operator steps implementers punted, gathered into one list.
107
126
  - The verification outcome with its evidence. Evidence over assertion — link what was run, never summarize what wasn't.
108
- - **The single next step:** consolidation (the default) — offer the one release PR `<target> → <default>` with this recap as its body, and open it only when the user says so. Trunk — nothing; every merged ticket is already live on the default branch.
127
+ - **The single next step:** consolidation (the default) — offer the one release PR `<target> → <default>` with this recap as its body (cloud CI runs there, once), and open it only when the user says so; a red base or held tickets add the relaunch-with-`knownGreen` step. Trunk — nothing; every landed ticket is already live on the default branch.
109
128
 
110
129
  ## Rules
111
130
 
112
- - Fresh context per dispatch, per retry. No exceptions.
131
+ - Fresh context per dispatch, per retry, per re-sync. No exceptions.
113
132
  - One integration target and one engine per run, declared in the pre-launch echo and restated once in the close-out recap — never in between.
114
- - Never implement, review, or repair code in the orchestrator session — dispatch instead. Running the merge gate is bookkeeping, not repair.
133
+ - Never implement, review, or repair code in the orchestrator session — dispatch instead. Landing is bookkeeping, not repair; a red gate is handed back, never fixed by the lander.
115
134
  - Name the skills (`launch-ralph-implement`, `launch-resolving-merge-conflicts`, `launch-browser-smoke`); never paraphrase their contents into a prompt.
116
135
  - Blocking edges are parsed from the verbatim `Blocked by` line, by you — never resolved by a model in between.
117
- - Nothing counts as merged until the remote says so; nothing counts as done until `verify` is green.
118
- - A deferral is not a failure; a failure is never silently retried without its summary.
136
+ - Nothing counts as landed until the remote says so; nothing counts as done until the full gate is green on the final base.
137
+ - A deferral is not a failure; a re-sync is not an attempt; a failure is never silently retried without its summary.
138
+ - Push early, push often: work that is not on the remote does not exist to the next session.
119
139
  - Width is a lever, not a goal. Narrow it whenever tickets might collide.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: launch-ralph-implement
3
- description: Implement a single ticket end to end under the Launchrail completion contract — TDD, the deterministic verification gate, browser smoke for user-facing changes, self-review, and conventional commits. Used by Ralph loop dispatches and by /launch-implement's single-ticket mode.
3
+ description: Implement a single ticket end to end under the Launchrail completion contract — TDD, commit-and-push after every green step, the fast verification gate before hand-off, browser smoke for user-facing changes, self-review, and conventional commits. Used by Ralph loop dispatches and by /launch-implement's single-ticket mode.
4
4
  ---
5
5
 
6
6
  # Implement one ticket
@@ -8,10 +8,11 @@ description: Implement a single ticket end to end under the Launchrail completio
8
8
  The per-ticket implementation contract. Ralph dispatches name this skill so the contract lives in one place — every implementer, on every run, gets the same one.
9
9
 
10
10
  1. **Read before coding.** The ticket, every artifact it links (spec sections, ADRs, smoke journeys), and `AGENTS.md`/`CLAUDE.md`. The commands you run come from `.launchrail.yml` (`testing.*`) and `AGENTS.md`, verbatim.
11
- 2. **TDD at the seams the ticket names.** Write the failing test first where the ticket or spec defines behavior. Typecheck and run single test files as you go; save full-suite runs for the gate — the machine may be shared with other implementers.
12
- 3. **The gate:** `npx @wemuda/launchrail verify` must exit 0 before the work is done. Never delete, skip, or weaken a test to get there; if a test is genuinely wrong, fix it deliberately and say so in the PR body.
13
- 4. **User-facing behavior, with `modules.browser-testing` enabled:** update or add the affected journey in `docs/testing/smoke-journeys.md` and drive it per the `launch-browser-smoke` skill. A journey you could not complete is a failure, not a pass.
14
- 5. **Self-review:** run `/launch-code-review` on the result and fix what it finds before handing off.
15
- 6. **Commit to the current branch** following the project's commit conventions (Conventional Commits when `.launchrail.yml` says so). Update any artifact the change invalidates (spec, ADR, journey) in the same change.
11
+ 2. **Push early, push often.** Your branch is pushed before you write a line, and you **commit and push after every green step** — a passing test slice, a finished subtask. The pushed branch is the checkpoint a lost session resumes from (a successor adopts it at its last commit instead of rebuilding) and the loop's liveness signal. Work that is not on the remote does not exist to the next session. Never push to the base branch and never open a PR from inside a loop dispatch — the loop lands your branch.
12
+ 3. **TDD at the seams the ticket names.** Write the failing test first where the ticket or spec defines behavior. Typecheck and run single test files as you go; save whole-suite runs for the gate — the machine may be shared with other implementers.
13
+ 4. **The gate — tiered.** Before you hand off, `npx @wemuda/launchrail verify --fast` (the fast gate: `testing.checkCommand`, else the unit command) must exit 0 on your branch. Inside a Ralph dispatch that is your gate: the loop runs it again on the merged tree before pushing the base, and runs the full `npx @wemuda/launchrail verify` (browser journeys included) at its checkpoints — so do not spend your turn on the whole suite; run only the slow test files your change touches (a journey you edited). Outside the loop (single-ticket mode, a PR of your own), the full `npx @wemuda/launchrail verify` must exit 0 before the PR. Never delete, skip, or weaken a test to get there; if a test is genuinely wrong, fix it deliberately and say so in the commit message.
14
+ 5. **User-facing behavior, with `modules.browser-testing` enabled:** update or add the affected journey in `docs/testing/smoke-journeys.md` and drive it per the `launch-browser-smoke` skill. A journey you could not complete is a failure, not a pass.
15
+ 6. **Self-review:** call the Skill tool with `launch-code-review` on the result and fix what it finds before handing off.
16
+ 7. **Commit to the current branch** following the project's commit conventions (Conventional Commits when `.launchrail.yml` says so); the loop squashes your branch onto the base, so also hand it a Conventional Commit title for that squash. Update any artifact the change invalidates (spec, ADR, journey) in the same change.
16
17
 
17
- Done means: the gate is green, the review found nothing unaddressed, and the evidence (test output, journey results) exists — not that the code "should work".
18
+ Done means: the gate is green, the review found nothing unaddressed, the branch is pushed, and the evidence (test output, journey results) exists — not that the code "should work".
@@ -11,5 +11,5 @@ When parallel work lands against the same base, conflicts are ordinary work with
11
11
  2. **Understand both sides.** For each conflicted file, find out what the other side's change was *for* — read its commit message, PR, or ticket if needed. You are merging intents, not text blocks.
12
12
  3. **Preserve both behaviors.** The resolved code must do what your change does *and* what theirs does. Taking "ours" or "theirs" wholesale is only correct when the two changes are genuinely the same fix.
13
13
  4. **Regenerate, don't hand-merge, generated files.** Lockfiles and other generated artifacts are re-created by their tool after resolving the source of truth — never merged line by line.
14
- 5. **Prove it.** After resolving, run the verification gate (`npx @wemuda/launchrail verify`). A resolution that was never run is not a resolution.
14
+ 5. **Prove it.** After resolving, run the gate you own at that point — the fast gate (`npx @wemuda/launchrail verify --fast`) inside a Ralph dispatch, the full gate (`npx @wemuda/launchrail verify`) otherwise — then push. A resolution that was never run is not a resolution.
15
15
  6. **Escalate ambiguity.** If both sides changed the same logic and any resolution you can see loses behavior, stop and report the conflict (which files, which intents collide) instead of guessing. In the Ralph loop that is the `conflict` outcome — a legitimate result, unlike a quiet wrong merge.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: launch-spec
3
- description: Turn the current conversation into a spec published to the project's tracker (a spec-labeled issue), or committed under docs/specs/ in local mode — no interview, just synthesis of what has already been discussed and decided. Owns stage 7's synthesis half (launch-wayfinder owns the breakdown of work too big for one session).
3
+ description: Synthesize what the conversation already decided into a spec — published as a spec-labeled issue on the tracker, or committed under docs/specs/ in local mode. No interview.
4
4
  disable-model-invocation: true
5
5
  ---
6
6
 
@@ -8,13 +8,15 @@ disable-model-invocation: true
8
8
 
9
9
  This skill takes the current conversation context and codebase understanding and produces a spec. Do NOT interview the user — just synthesize what you already know: the vision, the grill's surviving constraints, the research notes, and the ADRs are the inputs; a conductor handing off this stage names them.
10
10
 
11
+ Synthesis preserves the grill's labels ([ADR-0029](https://github.com/wemuda/launchrail/blob/master/docs/adr/0029-planning-interaction-contract.md)): **Locked** decisions are stated as decisions; **Provisional** agent-defaults stay marked provisional in the spec (changeable without re-planning); **Deferred** questions land in Out of Scope with the trigger that reopens them — never silently dropped, never silently promoted into scope.
12
+
11
13
  ## Process
12
14
 
13
- 1. Explore the repo to understand the current state of the codebase, if you haven't already. Use the project's domain glossary vocabulary (`CONTEXT.md`) throughout the spec, and respect any ADRs in the area you're touching.
15
+ 1. Explore the repo to understand the current state of the codebase, if you haven't already. Use the project's domain glossary vocabulary (`CONTEXT.md`) throughout the spec, and respect any ADRs in the area you're touching — find them through the registry index (`docs/adr/README.md`) rather than reading the whole directory, and remember an ADR records a decision, not what exists; the codebase is the evidence for current state.
14
16
 
15
17
  2. Sketch out the seams at which you're going to test the feature. Existing seams should be preferred to new ones. Use the highest seam possible. If new seams are needed, propose them at the highest point you can. The fewer seams across the codebase, the better — the ideal number is one.
16
18
 
17
- Check with the user that these seams match their expectations.
19
+ Check the seams with the user through the structured question tool (`AskUserQuestion`) rather than a freetext ask — one question, recommended answer first ([ADR-0029](https://github.com/wemuda/launchrail/blob/master/docs/adr/0029-planning-interaction-contract.md)): the seams as sketched, ready to write and publish. The other options are the real alternative placements you considered (a different existing seam, fewer seams, a higher one). Selecting the recommended answer flows straight into step 3 — write and publish with no further confirmation; an alternative answer re-sketches the seams and asks again. In an environment without a structured question tool, fall back to a numbered question with a ➡️ recommended answer.
18
20
 
19
21
  3. Write the spec using the template below and publish it to **its tracker-appropriate home** — the spec's home follows the configured tracker, exactly as tickets do ([ADR-0025](https://github.com/wemuda/launchrail/blob/master/docs/adr/0025-spec-home-follows-tracker.md)). Read `docs/agents/issue-tracker.md` to know which applies:
20
22
 
@@ -23,7 +25,7 @@ This skill takes the current conversation context and codebase understanding and
23
25
 
24
26
  On a real tracker, also bundle the spec under a **milestone** named for the feature: create the milestone, put the spec issue in it, and set its description to a one-line goal plus a link back to the spec issue. That milestone is the rollup `launch-tickets` hangs every ticket on, so the whole feature reads as one progress bar — a *view*, not the spec's home; the `spec`-labelled issue stays canonical. See `docs/agents/issue-tracker.md` for the exact per-tracker commands; local mode has no milestone (the feature's files are its bundle).
25
27
 
26
- The spec then flows on: design validation (stage 8) revises it in place, and `launch-tickets` (stage 9) breaks it into tickets that reference it.
28
+ The spec then flows on: design validation (stage 8) revises it in place, and `launch-tickets` (stage 9) breaks it into tickets that reference it. Close by rendering the rail banner ([`workflow.md`](../launch/workflow.md)'s phase view) — the published spec under Done, design validation as Now, tickets as Next — with the one next command on the `➤` line.
27
29
 
28
30
  <spec-template>
29
31
 
@@ -45,7 +47,7 @@ A LONG, numbered list of user stories. Each user story should be in the format o
45
47
  1. As a mobile bank customer, I want to see balance on my accounts, so that I can make better informed decisions about my spending
46
48
  </user-story-example>
47
49
 
48
- This list of user stories should be extremely extensive and cover all aspects of the feature.
50
+ This list of user stories should be extremely extensive and cover all aspects of the feature *as decided* — behavior an approved prototype shows is in scope by presumption, while questions the grill deferred belong in Out of Scope, not as invented stories.
49
51
 
50
52
  ## Implementation Decisions
51
53
 
@@ -73,7 +75,7 @@ A list of testing decisions that were made. Include:
73
75
 
74
76
  ## Out of Scope
75
77
 
76
- A description of the things that are out of scope for this spec.
78
+ A description of the things that are out of scope for this spec — including every question the grill deferred, each with the trigger that reopens it.
77
79
 
78
80
  ## Further Notes
79
81
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: launch-tickets
3
- description: Break a validated spec, plan, or the current conversation into tracer-bullet tickets, each declaring its blocking edges, published to the configured tracker with the ready-for-agent label — the exact input contract the implementation loop's frontier is computed from. Owns stage 9.
3
+ description: Break a validated spec, plan, or the current conversation into tracer-bullet tickets with blocking edges, published ready-for-agent to the configured tracker — the implementation loop's input.
4
4
  disable-model-invocation: true
5
5
  ---
6
6
 
@@ -20,7 +20,7 @@ Work from whatever is already in the conversation context. If the user passes a
20
20
 
21
21
  ### 2. Explore the codebase (optional)
22
22
 
23
- If you have not already explored the codebase, do so to understand the current state of the code. Ticket titles and descriptions should use the project's domain glossary vocabulary (`CONTEXT.md`), and respect ADRs in the area you're touching.
23
+ If you have not already explored the codebase, do so to understand the current state of the code. Ticket titles and descriptions should use the project's domain glossary vocabulary (`CONTEXT.md`), and respect ADRs in the area you're touching — found through the registry index (`docs/adr/README.md`), not by reading the whole directory. An ADR records a decision, not what exists: when a ticket depends on a component an ADR describes, verify in the code that it is actually built before slicing on that assumption.
24
24
 
25
25
  Look for opportunities to prefactor the code to make the implementation easier. "Make the change easy, then make the easy change."
26
26
 
@@ -49,13 +49,12 @@ Present the proposed breakdown as a numbered list. For each ticket, show:
49
49
  - **Blocked by**: which other tickets (if any) must complete first
50
50
  - **What it delivers**: the end-to-end behaviour this ticket makes work
51
51
 
52
- Ask the user:
52
+ Then put the checkpoint through the structured question tool (`AskUserQuestion`) instead of freetext prose questions — one round, at most three questions, each shipping its recommended answer first ([ADR-0029](https://github.com/wemuda/launchrail/blob/master/docs/adr/0029-planning-interaction-contract.md)):
53
53
 
54
- - Does the granularity feel right? (too coarse / too fine)
55
- - Are the blocking edges correct — does each ticket only depend on tickets that genuinely gate it?
56
- - Should any tickets be merged or split further?
54
+ - **Granularity** — recommended answer: publish as proposed. The other options are the concrete folds or splits you already weighed against this breakdown ("Fold #5 into #4", "Split #2"), never abstract "too coarse / too fine".
55
+ - **Blocking edges** — recommended answer: the edges as drawn. The other options name the specific edge to add or drop ("Make capture serial", "Let #4 start without #2").
57
56
 
58
- Iterate until the user approves the breakdown.
57
+ Selecting the recommended answers **is** the approval — go straight to publishing (step 5), no freetext confirmation in between. An adjustment answer reshapes the breakdown: apply it, re-present what changed, and ask again. Freetext stays available through the tool's own "Other" escape, but the quick path never requires typing. In an environment without a structured question tool, fall back to the same questions as a numbered list, each carrying a ➡️ recommended answer.
59
58
 
60
59
  ### 5. Publish the tickets to the configured tracker
61
60
 
@@ -68,6 +67,10 @@ Work the **frontier**: any ticket whose blockers are all done. For a purely line
68
67
 
69
68
  Do NOT close or modify any parent issue. Each new ticket is closed later by its own implementing PR (`Closes #n`, per the tracker doc's Issue ↔ PR linkage), not by hand here.
70
69
 
70
+ ### 6. Close with the rail banner
71
+
72
+ End by rendering the banner from [`workflow.md`](../launch/workflow.md)'s phase view: the published tickets under Done (count and where they live), Build as Now, and `➤ /launch-implement` — the user-typed door — as the one next command. Never start it yourself.
73
+
71
74
  <local-ticket-template>
72
75
 
73
76
  # <NN> — <Ticket title>
@@ -18,7 +18,7 @@ Produce `docs/vision.md`: a short, honest statement of what this product is, who
18
18
  ## Process
19
19
 
20
20
  1. **Read what exists.** Check for `docs/vision.md`, a README, and any notes the user points at. Do not ask questions the repository already answers.
21
- 2. **Interview the user** — briefly, a few questions at a time, in their language:
21
+ 2. **Interview the user** — briefly, in their language, at most three questions per round with your recommended answer where you have one (the interaction contract in [`workflow.md`](../launch/workflow.md) applies here as everywhere):
22
22
  - What problem hurts, and for whom? How do those people cope today?
23
23
  - Why this, why now — what is the bet that makes this worth building?
24
24
  - Who is the first concrete user (a person or team you could name), as opposed to the eventual market?
@@ -30,7 +30,7 @@ Produce `docs/vision.md`: a short, honest statement of what this product is, who
30
30
  5. **Present and iterate** until the user approves.
31
31
  6. **Sync the agent contract.** If the seeded `AGENTS.md` still carries the TODO under `## Project purpose`, replace it with a one-paragraph distillation of the approved vision — what this is, who it serves, what it is not. Touch only that section: `AGENTS.md` belongs to the project, and the rest of it is not this skill's business.
32
32
  7. **Commit** `docs/vision.md` and the `AGENTS.md` update together (respect the project's commit conventions).
33
- 8. **Hand off.** Point the user at the next stages of the loop: visual exploration in Claude Design to make the intent concrete, discovery research (`launch-discovery`) to map the real options for the vision's hard parts, then the complexity grill (`launch-grill`) to attack the assumptions just recorded. See [`workflow.md`](../launch/workflow.md) for the full stage order.
33
+ 8. **Hand off with the rail banner.** Close with the banner from [`workflow.md`](../launch/workflow.md)'s phase view — the committed vision under Done, visual exploration (Claude Design, to make the intent concrete) as Now, discovery research (`launch-discovery`, mapping the real options for the vision's hard parts) as Next, and the grill on the Later arc — so the user sees exactly where they are and what one thing comes next.
34
34
 
35
35
  ## Template
36
36
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: launch-wayfinder
3
- description: Plan a huge chunk of work — more than one agent session can hold — as a shared map of decision tickets on the project's issue tracker, and resolve them one at a time until the way to the destination is clear. Stage 7's breakdown half for large features; launch-spec synthesizes once the way is clear.
3
+ description: Chart work too big for one session as a shared map of decision tickets on the tracker, then resolve them one at a time until the way to the destination is clear — planning only, never execution; launch-spec synthesizes once the way is clear.
4
4
  disable-model-invocation: true
5
5
  ---
6
6
 
@@ -12,7 +12,12 @@ The destination varies per effort, and naming it is the first act of charting
12
12
 
13
13
  ## Plan, don't do
14
14
 
15
- Wayfinder is **planning** by default: each ticket resolves a decision, and the map is done when the way is clear — nothing left to decide before someone goes and does the thing. The pull to just do the work is usually the signal you've reached the edge of the map and it's time to hand off. An effort can override this in its **Notes** — carrying execution into the map itself — but absent that, produce decisions, not deliverables.
15
+ Wayfinder is **planning, only**: each ticket resolves a decision, and the map is done when the way is clear — nothing left to decide before someone goes and does the thing. **Execution never enters the map** ([ADR-0029](https://github.com/wemuda/launchrail/blob/master/docs/adr/0029-planning-interaction-contract.md)): a ticket that would *deliver* part of the destination — build the worker, ship the page, migrate the data for real — is implementation wearing a planning label, and it belongs after the spec, in `launch-tickets` and the build loop. The test, applied at creation and again if a ticket balloons: **name the decision this ticket unblocks.** No decision named, no ticket. The pull to just do the work is usually the signal you've reached the edge of the map and it's time to hand off.
16
+
17
+ Two more bounds keep the map from recursing into itself:
18
+
19
+ - **One layer of map.** A ticket never spawns its own map, and its grill never re-runs the foundation's. If a single ticket looks big enough to need either, the destination is drawn too far out — redraw this map instead.
20
+ - **Touch ground every two tickets.** Never resolve more than **two planning tickets in a row without a runnable or visual checkpoint** — a prototype ticket, a spike, or pausing the map to build a slice that's already safe. When charting, sequence the frontier so those checkpoints land; when working the map, track the count and force the checkpoint before the third.
16
21
 
17
22
  ## Refer by name
18
23
 
@@ -76,10 +81,10 @@ The answer isn't part of the body — it's recorded on resolution (see [Work thr
76
81
 
77
82
  Every ticket is either **HITL** — human in the loop, worked _with_ a human who speaks for themselves — or **AFK**, driven by the agent alone. A HITL ticket only resolves through that live exchange; the agent never stands in for the human's side of it (a grilling agent that answers its own questions has broken this).
78
83
 
79
- - **Research** (AFK): Reading documentation, third-party APIs, or local resources like knowledge bases to surface a fact a decision waits on. Resolved by a `launch-research` **subagent**. Use when knowledge outside the current working directory is required.
84
+ - **Research** (AFK): Reading documentation, third-party APIs, or local resources like knowledge bases to surface a fact a decision waits on. Resolved by a **subagent** that calls the Skill tool with `launch-research`. Use when knowledge outside the current working directory is required.
80
85
  - **Prototype** (HITL): Raise the fidelity of the discussion by making a cheap, rough, concrete artifact to react to — an outline, a rough take, a stub, or throwaway UI/logic code. Links the prototype as an asset. Use when "how should it look" or "how should it behave" is the key question.
81
- - **Grilling** (HITL): Conversation. The default case. Always invoke the `launch-grill` skill — the ticket's resolution comment is the artifact, in place of the grill's usual `docs/research/` doc.
82
- - **Task** (HITL or AFK): Manual work that must happen before a _decision_ can be made — nothing to decide, prototype, or research, but the discussion is blocked until it's done. Signing up for a service so its API can be judged, provisioning access, moving data so its shape can be seen. This is the one type that _does_ rather than decides — and it earns its place by unblocking a decision, not by delivering the destination. The agent drives it alone where it can (AFK); otherwise it hands the human a precise checklist (HITL). Resolved when the work is done; the answer records what was done and any resulting facts (credentials location, new URLs, row counts) later tickets depend on.
86
+ - **Grilling** (HITL): Conversation. The default case. Always call the Skill tool with `launch-grill` — the ticket's resolution comment is the artifact, in place of the grill's usual `docs/research/` doc. The ticket's question is the grill's **entire scope**, and the map's Decisions-so-far (plus the foundation's constraints) are **inherited, never re-opened** — hand the grill those settled decisions as context and a tight budget (a few decide-now questions, not a fresh session's six). A ticket grill that re-converges what the map already closed is the recursion this rule exists to stop.
87
+ - **Task** (HITL or AFK): Manual work that must happen before a _decision_ can be made — nothing to decide, prototype, or research, but the discussion is blocked until it's done. Signing up for a service so its API can be judged, provisioning access, moving data so its shape can be seen. This is the one type that _does_ rather than decides — and it earns its place **only** by unblocking a decision: its body names that decision (an "Unblocks:" line pointing at the ticket or fog patch that waits on it), and a task that can't name one is implementation mis-filed on the map — delivering the destination belongs after the spec, in `launch-tickets` (see [Plan, don't do](#plan-dont-do)). The agent drives it alone where it can (AFK); otherwise it hands the human a precise checklist (HITL). Resolved when the work is done; the answer records what was done and any resulting facts (credentials location, new URLs, row counts) later tickets depend on.
83
88
 
84
89
  ## Fog of war
85
90
 
@@ -110,11 +115,11 @@ Two modes. Either way, **never resolve more than one ticket per session** — wi
110
115
 
111
116
  User invokes with a loose idea.
112
117
 
113
- 1. **Name the destination.** Run a `launch-grill` session to pin down what this map is finding its way to — the spec, decision, or change. The destination fixes the scope, so it's settled first.
114
- 2. **Map the frontier.** Grill again, **breadth-first** this time: fan out across the whole space rather than deep on any one thread, surfacing the open decisions and the first steps takeable now. **If this surfaces no fog** — the way to the destination is already clear, the whole journey small enough for one session — you don't need a map. Stop and ask the user how they'd like to proceed.
118
+ 1. **Name the destination.** Call the Skill tool with `launch-grill` to pin down what this map is finding its way to — the spec, decision, or change. The destination fixes the scope, so it's settled first.
119
+ 2. **Map the frontier.** Grill again, **breadth-first** this time: fan out across the whole space rather than deep on any one thread, surfacing the open decisions and the first steps takeable now. Both charting grills share **one session budget** — breadth-mapping is mostly triage (the agent's job: label, default, park), and the user's questions go to naming the destination and the genuinely consequential forks. **If this surfaces no fog** — the way to the destination is already clear, the whole journey small enough for one session — you don't need a map. Stop and ask the user how they'd like to proceed.
115
120
  3. **Create the map** (label `wayfinder:map`): Destination and Notes filled in, Decisions-so-far empty, the fog sketched into **Not yet specified**.
116
121
  4. **Create the tickets you can specify now** as child issues of the map — then wire blocking edges in a **second pass** (issues need ids before they can reference each other). Wiring sorts them into the frontier and the blocked; everything you can't yet specify stays in the fog — the **Not yet specified** section.
117
- 5. **Fire the research subagents.** For each `research` ticket you just created, spin up a `launch-research` subagent to resolve it in parallel, capturing its findings on a throwaway `research/<name>` branch with a context pointer from the ticket.
122
+ 5. **Fire the research subagents.** For each `research` ticket you just created, spin up a subagent that calls the Skill tool with `launch-research` to resolve it in parallel, capturing its findings on a throwaway `research/<name>` branch with a context pointer from the ticket.
118
123
  6. Stop — charting is one session's work; it hand-resolves nothing.
119
124
 
120
125
  ### Work through the map
@@ -123,8 +128,9 @@ User invokes with a map (URL or number). A ticket is **optional** — without on
123
128
 
124
129
  1. Load the **map** — the low-res view, not every ticket body.
125
130
  2. Choose the ticket. If the user named one, use it. Otherwise take the first frontier ticket in order. **Claim it**: assign it to yourself before any work.
126
- 3. Resolve it — **zoom as needed**: fetch the full body of any related or closed ticket on demand; invoke the skills the `## Notes` block names. If in doubt, use `launch-grill`.
131
+ 3. Resolve it — **zoom as needed**: fetch the full body of any related or closed ticket on demand; call the Skill tool for whichever skills the `## Notes` block names. If in doubt, `launch-grill`.
127
132
  4. Record the resolution: post the answer as a **resolution comment**, **close** the issue, and **append a context pointer** to the map's Decisions-so-far.
128
133
  5. Add newly-surfaced tickets (create-then-wire); graduate any fog the answer has made specifiable, clearing each graduated patch from **Not yet specified** so it lives only as its new ticket. If the answer reveals a ticket — this one or another — sits beyond the destination, **rule it out of scope** rather than resolving it on the route. If the decision invalidates other parts of the map, update or delete those tickets.
134
+ 6. **Close legibly.** End the session with the rail banner and the four-block summary — **Locked** (this resolution), **Provisional**, **Deferred**, **Next command** (the next frontier ticket by name, the checkpoint now due, or the handoff once the way is clear) — per [`workflow.md`](../launch/workflow.md)'s phase view. Check the checkpoint count here: if this was the second planning ticket since the last runnable or visual checkpoint, the next move is the checkpoint, not another ticket.
129
135
 
130
136
  The user may run unblocked tickets in parallel, so expect other sessions to be editing the tracker concurrently.
@@ -107,6 +107,7 @@ function planRalph(parsed) {
107
107
  "Produce tickets with explicit `Blocked by: #n` edges and the ready-for-agent label (launch-tickets, stage 9 of the workflow).",
108
108
  "Start building: /launch-implement in Claude Code drives the ready tickets to verified merges (add a ticket number to build just one).",
109
109
  "For an unattended run, launch in a non-prompting permission mode (bypass/autonomous) — a guard hook warns if you start Ralph in an interactive mode, since one benign prompt can stall a walk-away run.",
110
+ "Name a fast gate as testing.checkCommand in .launchrail.yml (lint + typecheck + quick unit tests) — the loop runs `verify --fast` before every land and the full `verify` at its checkpoints; without it the fast gate is the unit command.",
110
111
  "Start with width 1 until a few tickets have landed cleanly, then widen.",
111
112
  ],
112
113
  };
@@ -150,7 +151,7 @@ export async function runAdd(opts) {
150
151
  const lockBefore = JSON.stringify(lockfile);
151
152
  const specs = [
152
153
  ...plan.specs,
153
- claudeGeneratedFile({ projectName: detection.projectName, manifest: plan.manifest, launchrailVersion: VERSION }),
154
+ claudeGeneratedFile({ projectName: detection.projectName, manifest: plan.manifest, launchrailVersion: VERSION, cwd: opts.cwd }),
154
155
  ];
155
156
  const actions = planWrites(opts.cwd, specs, lockfile);
156
157
  // Ralph's guard hook file rides `actions`; its registration in the shared,