@wemuda/launchrail 1.13.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.
- package/README.md +1 -1
- package/assets/agents-docs/domain.md +2 -2
- package/assets/agents-docs/issue-tracker-github.md +1 -1
- package/assets/agents-docs/issue-tracker-linear.md +1 -1
- package/assets/ralph.workflow.js +640 -273
- package/assets/skills/NOTICE.md +4 -0
- package/assets/skills/launchrail/launch/SKILL.md +2 -2
- package/assets/skills/launchrail/launch/workflow.md +2 -2
- package/assets/skills/launchrail/launch-code-review/SKILL.md +1 -1
- package/assets/skills/launchrail/launch-design-handoff/SKILL.md +1 -1
- package/assets/skills/launchrail/launch-design-validation/SKILL.md +2 -2
- package/assets/skills/launchrail/launch-discovery/SKILL.md +2 -2
- package/assets/skills/launchrail/launch-grill/SKILL.md +8 -2
- package/assets/skills/launchrail/launch-grill/domain-modeling.md +3 -1
- package/assets/skills/launchrail/launch-implement/SKILL.md +10 -10
- package/assets/skills/launchrail/launch-project-alignment/SKILL.md +1 -1
- package/assets/skills/launchrail/launch-ralph/SKILL.md +79 -59
- package/assets/skills/launchrail/launch-ralph-implement/SKILL.md +8 -7
- package/assets/skills/launchrail/launch-resolving-merge-conflicts/SKILL.md +1 -1
- package/assets/skills/launchrail/launch-spec/SKILL.md +3 -3
- package/assets/skills/launchrail/launch-tickets/SKILL.md +6 -7
- package/assets/skills/launchrail/launch-wayfinder/SKILL.md +6 -6
- package/dist/commands/add.js +2 -1
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/doctor.js +29 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.js +2 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/verify.d.ts +11 -2
- package/dist/commands/verify.js +22 -7
- package/dist/commands/verify.js.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/adr.d.ts +27 -0
- package/dist/lib/adr.js +87 -0
- package/dist/lib/adr.js.map +1 -0
- package/dist/lib/manifest.d.ts +7 -1
- package/dist/lib/manifest.js +8 -1
- package/dist/lib/manifest.js.map +1 -1
- package/dist/lib/project.d.ts +2 -0
- package/dist/lib/project.js +2 -1
- package/dist/lib/project.js.map +1 -1
- package/dist/lib/seeds.d.ts +2 -0
- package/dist/lib/seeds.js +13 -5
- package/dist/lib/seeds.js.map +1 -1
- package/package.json +1 -1
package/assets/skills/NOTICE.md
CHANGED
|
@@ -16,6 +16,10 @@ into `docs/agents/`. Each derived file carries its own derivation note. If
|
|
|
16
16
|
Launchrail is useful to you, the inspiration credit belongs upstream — see the
|
|
17
17
|
Launchrail README's Credits section.
|
|
18
18
|
|
|
19
|
+
Upstream is monitored as inspiration, never re-vendored (ADR-0020). The
|
|
20
|
+
derived skills were last reviewed against upstream commit `6654f6b`
|
|
21
|
+
(2026-08-24).
|
|
22
|
+
|
|
19
23
|
---
|
|
20
24
|
|
|
21
25
|
MIT License
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: launch
|
|
3
|
-
description: The planning conductor
|
|
3
|
+
description: The planning conductor — the single entry point to the Launchrail loop. Detects the project's stage from its committed artifacts, runs or routes to the stage's owner, sizes each new feature (large / semi / small) once the foundation exists, and hands implementation to /launch-implement — reporting position as six phases with the rail banner at every transition. Use to start or continue the workflow, ask what stage or phase the project is at, size a new feature, or jump straight to a named stage.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Launch — the loop conductor
|
|
@@ -52,7 +52,7 @@ A feature that arrives **design-first** — a dropped zip or folder of Claude De
|
|
|
52
52
|
1. **Did the user name a stage or a feature?** A stage keyword (below): sanity-check its inputs exist, offer the earlier stage if one is missing, but honor the jump if they insist — then invoke or hand off and stop. A new feature on a founded project: size it (above) and run the path.
|
|
53
53
|
2. **Otherwise orient, then find the frontier.** A cheap read-only look first: `git status`, current branch, recent commits — is something already in flight for the stage you're about to start? If the tracker is configured and reachable, read the live discussion on relevant tickets and PRs, not just titles; skip what isn't there (orientation sharpens routing, never gates it). Then close stage-0 gaps yourself without asking (init, commit init output, `sync` — it seeds `docs/agents/` too). Walk stages 1 → 12 and stop at the first whose "done when" fails, skipping only what the vision's non-goals record as deliberately skipped. `origin: existing` with no real vision → route to `launch-project-alignment`, not a blank vision.
|
|
54
54
|
3. **Confirm the read — with the banner.** Render the rail banner for the position you detected, then say why — which artifacts you found and which you didn't. Ambiguous signals (template-only vision, several specs) are questions, not guesses.
|
|
55
|
-
4. **Route.** Invoke the owner
|
|
55
|
+
4. **Route.** Invoke the owner — call the Skill tool with its exact name — or prepare the handoff for a user-typed stage (†). For stage 7, name the authoritative inputs in order; if the stack isn't stood up yet, tell it to name its seams but leave harness mechanics to the foundation work. For stage 10, hand over `/launch-implement` — never start it yourself.
|
|
56
56
|
5. **Close every transition with the banner.** When a stage finishes or a handoff is prepared, re-render the banner — the just-closed artifact under Done, the next mover under Now, the `➤` line carrying the one next action (the exact fully-argumented command when the stage is user-typed). Add a sentence on what the next stage does and whether it's optional here, and that any stage is reachable by keyword — a bare stage name reads as a turnstile; explain, don't gate.
|
|
57
57
|
|
|
58
58
|
## Stage keywords
|
|
@@ -77,7 +77,7 @@ Stage notes:
|
|
|
77
77
|
- **Stage 4 converges far enough to build, not exhaustively.** The grill's stopping rule is build-safety — the decisions the next slice depends on are locked or safely defaulted — never an empty question tree: product design is generative, and "everything answered before implementation" is not a reachable state ([ADR-0029](https://github.com/wemuda/launchrail/blob/master/docs/adr/0029-planning-interaction-contract.md)). "Nothing silently assumed" still holds, but it means every open question is *labeled and parked*, not answered. And stage 4 ends in a committed file, always: `launch-grill` closes its interview by writing the surviving constraints to `docs/research/` — the conversation alone never closes the stage, and the skill treats the committed doc as part of its own contract.
|
|
78
78
|
- **‡ The stage-7 spec's home follows the tracker** ([ADR-0025](https://github.com/wemuda/launchrail/blob/master/docs/adr/0025-spec-home-follows-tracker.md)), exactly as stage-9 tickets do. On a real tracker (GitHub, GitLab, Linear) the spec **is** a `spec`-labeled issue and no `docs/specs/` file is written; in local mode (`local`, or no tracker) it is a committed `docs/specs/<slug>.md` file. Detection is therefore tracker-aware — read `docs/agents/issue-tracker.md` to know where to look. `ready-for-agent` still marks tickets only; the spec issue wears `spec` so the loop never dispatches prose as work.
|
|
79
79
|
- **Stage 8 scales to the spec's design surface** through a fidelity ladder ([ADR-0016](https://github.com/wemuda/launchrail/blob/master/docs/adr/0016-design-validation-fidelity-ladder.md)): recorded skip, flow diagrams, screen mockups, or Claude Design. The level choice lives inside `design-validation` (recommend, user confirms). It exists to catch "specified but wrong on screen" while the finding still costs a spec edit rather than re-cut tickets — that's why it precedes stage 9 and is not stage 11, which checks the *built* product. Even a skip is recorded through the skill, so the gate stays artifact-based.
|
|
80
|
-
- **Stage 10 is one door.** `/launch-implement` drives the Ralph loop ([ADR-0017](https://github.com/wemuda/launchrail/blob/master/docs/adr/0017-implementation-loop-provider.md) as amended by [ADR-0020](https://github.com/wemuda/launchrail/blob/master/docs/adr/0020-independent-skill-set.md)). Launchrail owns both edges of the loop: `ready-for-agent` tickets with `Blocked by: #n` edges in, `launchrail verify` (+ browser smoke where enabled)
|
|
80
|
+
- **Stage 10 is one door.** `/launch-implement` drives the Ralph loop ([ADR-0017](https://github.com/wemuda/launchrail/blob/master/docs/adr/0017-implementation-loop-provider.md) as amended by [ADR-0020](https://github.com/wemuda/launchrail/blob/master/docs/adr/0020-independent-skill-set.md)). Launchrail owns both edges of the loop: `ready-for-agent` tickets with `Blocked by: #n` edges in, `launchrail verify --fast` gating every land and the full `launchrail verify` (+ browser smoke where enabled) at the loop's checkpoints and release ([ADR-0032](https://github.com/wemuda/launchrail/blob/master/docs/adr/0032-ralph-lean-local-gate-loop.md)).
|
|
81
81
|
|
|
82
82
|
## Sizing the work in the delivery loop
|
|
83
83
|
|
|
@@ -119,7 +119,7 @@ How every stage spends the user's attention ([ADR-0029](https://github.com/wemud
|
|
|
119
119
|
The contract for `launch`, `/launch-implement`, and any agent driving the rail. The conductors execute these rules; this document owns them.
|
|
120
120
|
|
|
121
121
|
- **Every transition renders the rail banner.** Orientation, routing, stage close, session summary — position is announced with the banner from the phase view above, never gestured at in prose. The user should never have to ask "where are we, and what happens now?"
|
|
122
|
-
- **One owner per stage, invoked by name.** Every stage has exactly one owning skill. Invoke it by name; do not paraphrase, wrap, re-prompt, or re-derive its work inline — the skill is the only place its stage's behavior lives.
|
|
122
|
+
- **One owner per stage, invoked by name.** Every stage has exactly one owning skill. Invoke it by calling the Skill tool with the owner's exact name (a user-typed stage gets the prepared handoff instead); do not paraphrase, wrap, re-prompt, or re-derive its work inline — the skill is the only place its stage's behavior lives.
|
|
123
123
|
- **Artifacts gate stages, not chat memory.** A stage is done only when its committed artifact exists; detect by reading the repository, and when a signal is ambiguous (a template-only vision, an abandoned spec draft), ask rather than assume. Detection and sizing are read-only — every write happens inside the stage owner.
|
|
124
124
|
- **User-typed stages get a prepared handoff, never reverse-engineering.** A `disable-model-invocation` refusal is the cue to hand over, not to reproduce the skill's work by hand or grep vendored skill files. A prepared handoff is three moves: confirm the stage's input artifacts are committed; hand the user the exact, fully-argumented command naming those inputs (a bare `/skill` sends it re-deriving what your inputs already settle — arguments that point at committed inputs are parameters, not paraphrase); pick up automatically once the stage's artifact lands.
|
|
125
125
|
- **The grill feeds research.** Run the grill before technical research and hand research the grill's surviving constraints as its brief.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: launch-code-review
|
|
3
|
-
description: Review the changes since a fixed point (commit, branch, tag, or merge-base) along two axes — Standards (
|
|
3
|
+
description: Review the changes since a fixed point (commit, branch, tag, or merge-base) along two axes — Standards (the repo's documented coding standards) and Spec (what the originating ticket or spec asked for) — in parallel sub-agents, reported side by side. The self-review gate inside launch-ralph-implement; also on request for a branch, a PR, or work in progress.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
<!-- Contains text derived from Matt Pocock's skills (https://github.com/mattpocock/skills), MIT — see ../NOTICE.md -->
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: launch-design-handoff
|
|
3
|
-
description: The design→code on-ramp —
|
|
3
|
+
description: The design→code on-ramp — turn a Claude Design prototype dropped into the session (a .zip export, an extracted folder, artboard/HTML files, or a published canvas link) into a committed handoff package under docs/design/, then route it into the delivery loop. Use when the user drops design files from Claude Design and wants them documented or implemented — "here is the prototype of feature X" — or asks to bring designs back from Claude Design into code.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Design handoff — from Claude Design back into the loop
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: launch-design-validation
|
|
3
|
-
description: Validate
|
|
3
|
+
description: Validate a drafted spec visually before tickets are cut — at a confirmed fidelity level (recorded skip, flow diagrams, screen mockups, or Claude Design) — and feed the findings back into a revised spec. Use when a spec is drafted and the user wants design validation, a visual review, or pre-implementation sign-off.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Design validation
|
|
@@ -39,6 +39,6 @@ Every level answers the same question — does the specified behavior survive co
|
|
|
39
39
|
- **Screen mockups** — build one artifact page mocking the key screens and states per flow, including the empty, loading, and error states the spec claims to handle.
|
|
40
40
|
- **Claude Design** — drive it flow by flow when the session can reach it. When it can't, prepare a fully-argumented handoff — the flows, the states each must show, links to the spec and vision, and any existing design-system baseline (see `project-alignment`) — hand it to the user to run, and resume when the design artifacts land. Never silently downgrade a level-4 choice to mockups; a downgrade is the user's decision.
|
|
41
41
|
5. **Harvest findings.** For each flow record: what the design confirmed, what it contradicted in the spec, and what the spec turned out to be silent on. Ambiguities count as findings. Findings at a low level are also a signal — if the diagrams alone surface deep uncertainty, recommend re-running a flow at a higher level before revising.
|
|
42
|
-
6. **Revise the spec.** Apply the accepted findings to the spec in place. If a finding invalidates an ADR, update or supersede that ADR in the same change. Note rejected findings and why in the handoff note, so the question does not resurface every review.
|
|
42
|
+
6. **Revise the spec.** Apply the accepted findings to the spec in place. If a finding invalidates an ADR, update or supersede that ADR in the same change, mirroring the status change in the registry index (`docs/adr/README.md`). Note rejected findings and why in the handoff note, so the question does not resurface every review.
|
|
43
43
|
7. **Write the handoff note** at the end of the spec (section `## Design validation`) with: date, the level that ran, flows validated, links to the artifact pages / design artifacts, accepted changes, rejected findings with reasons, and open questions. This section is the evidence that validation happened — the ticket stage (`launch-tickets`) reads the spec as validated only if it is present.
|
|
44
44
|
8. **Hand off with the rail banner.** Confirm with the user that the revised spec is approved, save it in place — commit the file, or update the spec issue on the tracker — respecting the project's commit conventions. Then close with the banner from [`workflow.md`](../launch/workflow.md)'s phase view: the validated spec under Done, ticket creation (`launch-tickets`) as Now, and the exact command on the `➤` line.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: launch-discovery
|
|
3
|
-
description: The divergent option-space scan
|
|
3
|
+
description: The divergent option-space scan before the complexity grill — map the real landscape of libraries, frameworks, vendors, and patterns for the hard parts of the product (alternatives with trade-offs, no winners) and commit the landscape map the grill narrows. Use after the vision (and visual exploration) and before the grill, or when the user asks to explore the tech landscape, survey vendors or libraries, or do discovery research. Composes `launch-research` for depth on any single thread.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Discovery research — map the option space before you narrow it
|
|
@@ -13,7 +13,7 @@ Diverge here; converge in the grill; de-risk in technical research. This stage o
|
|
|
13
13
|
|
|
14
14
|
- **Diverge, don't decide.** Your job is to widen, not to pick. For each area, present the real contenders and their trade-offs; do **not** crown a winner or collapse to one option — that is the grill's job (stage 4), fed by what you surface here. A discovery doc that recommends exactly one tool per area has skipped its own stage.
|
|
15
15
|
- **Bounded by the vision and the intended stack.** This is not open-ended reading. The vision says what's being built; the intended stack (and any existing design system) says what it must fit. Explore the landscape *for this product on this stack* — options that can't plug into the stack are noted and set aside, not explored in depth. This boundary is what keeps discovery from wandering into research nobody asked for.
|
|
16
|
-
- **Compose, never duplicate.** Discovery is divergent framing over `launch-research`. Do the framing yourself — carve the product into areas, enumerate contenders — and
|
|
16
|
+
- **Compose, never duplicate.** Discovery is divergent framing over `launch-research`. Do the framing yourself — carve the product into areas, enumerate contenders — and call the Skill tool with `launch-research` to go deep on any single thread that needs primary sources (real capabilities, maintenance health, license, integration cost). Don't reimplement research; drive it.
|
|
17
17
|
- **Everything here is project-owned.** The landscape map is committed to the project under `docs/research/`; Launchrail tooling never overwrites it.
|
|
18
18
|
- **Evidence over vibes.** A contender listed from memory is a lead, not a finding. Where a choice is load-bearing, confirm the fact — does it actually do X, is it maintained, what's the license — through `launch-research` rather than asserting it.
|
|
19
19
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: launch-grill
|
|
3
|
-
description: The grill — a budgeted, round-based interview that stress-tests a plan, decision, or idea until the next slice can be built safely,
|
|
3
|
+
description: The grill — a budgeted, round-based interview that stress-tests a plan, decision, or idea until the next slice can be built safely, keeps the domain model current as terms crystallise, and always commits what settled under docs/research/. Runs as the foundation's complexity grill (stage 4) and as the feature grill opening every delivery-loop path. Use whenever the user wants to be grilled, stress-test thinking, or get aligned before building.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
<!-- Contains text derived from Matt Pocock's skills (https://github.com/mattpocock/skills), MIT — see ../NOTICE.md -->
|
|
@@ -38,11 +38,17 @@ Map the discussion as a **design tree**: every decision branches into the decisi
|
|
|
38
38
|
|
|
39
39
|
1. Recompute the frontier; label everything new on it.
|
|
40
40
|
2. Work the non-user labels: dispatch `research`, pick and record `agent-default`s, park `defer`s, propose a `prototype` when one would collapse several questions at once.
|
|
41
|
-
3. Ask at most **three** `decide-now` questions — the most load-bearing ones on the frontier. A genuinely consequential decision **rides alone**, with the context it deserves. Number each question
|
|
41
|
+
3. Ask at most **three** `decide-now` questions — the most load-bearing ones on the frontier. A genuinely consequential decision **rides alone**, with the context it deserves. Number each question, give your recommended answer, and separate questions with a horizontal rule — format a round like so:
|
|
42
42
|
|
|
43
43
|
```
|
|
44
44
|
❓ **Q1** - **<question title>**: <question body, might be multiple paragraphs, including multiple choices>
|
|
45
45
|
|
|
46
|
+
➡️ <your recommended answer>
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
❓ **Q2** - **<question title>**: <question body, might be multiple paragraphs, including multiple choices>
|
|
51
|
+
|
|
46
52
|
➡️ <your recommended answer>
|
|
47
53
|
```
|
|
48
54
|
|
|
@@ -42,4 +42,6 @@ Only offer to create an ADR when all three are true:
|
|
|
42
42
|
2. **Surprising without context** — a future reader will wonder "why did they do it this way?"
|
|
43
43
|
3. **The result of a real trade-off** — there were genuine alternatives and you picked one for specific reasons
|
|
44
44
|
|
|
45
|
-
If any of the three is missing, skip the ADR
|
|
45
|
+
If any of the three is missing, skip the ADR — an implementation choice that fails the bar lives in the spec or the ticket, not `docs/adr/`. And when the decision refines one an existing ADR already owns, amend that ADR (update its `## Status` line and its registry row) instead of minting a sibling; a corpus of revisions reads worse than a decision with a history.
|
|
46
|
+
|
|
47
|
+
ADRs use the **project's own format**: copy `docs/adr/0000-template.md` (seeded by `launchrail init`), take the next free number — check both the files in `docs/adr/` and the registry index (`docs/adr/README.md`) — and add the new record's row to the registry index **in the same commit**. One format per project; do not introduce a second.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: launch-implement
|
|
3
|
-
description: Start building —
|
|
3
|
+
description: Start building — drive ready tickets to verified merges through the Ralph loop. Bare, it works the whole ready frontier; `/launch-implement 15` builds one ticket end to end; several numbers scope the loop; a count ("the next 5") caps it; a spec reference ("spec #2's tickets") resolves to its tickets. Repairs its own setup instead of stopping.
|
|
4
4
|
disable-model-invocation: true
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -18,25 +18,25 @@ From `.launchrail.yml`: `issueTracker` and the `testing` commands. From the argu
|
|
|
18
18
|
- **a count** — "the next 5", "max 5" → the loop with a merge cap. Don't hand-pick which five: the cap is a stop condition, and the frontier decides the order — the loop stops after that many *verified merges* and leaves the rest ready;
|
|
19
19
|
- **a spec, slice, or epic reference** — "spec #2's tickets", "the rest of slice 1" → resolve it to explicit numbers against the live tracker: the open tickets that belong to it (a "Part of: #n" line, the spec issue's ticket list, or a label), plus any open in-set blockers so the scope stays dependency-closed. Combinations compose: "the next 5 of spec #2" → that spec's tickets *and* a cap of 5.
|
|
20
20
|
|
|
21
|
-
**Resolve the integration target with the scope.** Every multi-ticket run **consolidates by default** (ADR-0022, ADR-0026): its per-ticket
|
|
21
|
+
**Resolve the integration target with the scope.** Every multi-ticket run **consolidates by default** (ADR-0022, ADR-0026): its per-ticket branches are landed onto one integration branch by the loop's own local gate, the default branch stays untouched, and the run ends by *offering* one release PR `<target> → <default>` for the user to review and merge — the one place cloud CI runs — never merging to the default branch on its own. You name that branch before anything launches, scope-native: the branch the user named if they gave one ("collect spec #44 on `spec/44-mvp`"); else **the session's designated working branch** when the environment pinned one at start — a hosted session's `claude/...` branch exists to receive exactly this run, so use it rather than minting a `spec/*` twin beside it (ADR-0028); else the scope's own name when it maps to a spec, epic, or slice (`spec/<n>-<slug>`); else a generated fallback for an ad-hoc frontier (`launch/frontier-<today>`, or `launch/tickets-<n>-<m>` for a handful of loose numbers). A named target the remote lacks is created from the default branch's tip by the run's preflight. **Trunk** — each ticket merged straight to the default branch, live the moment it lands — is now the explicit opt-in: choose it only when the user asks in so many words ("land each ticket on master as it goes"), and never when the environment forbids pushing to the default branch. A pinned-branch environment ("develop on this branch; no unprompted PRs") constrains the *deliverable*, which consolidation already honors — the default branch stays untouched, the release PR stays offered-only. It never constrains the *engine*: the user typing `/launch-implement` is the explicit go-ahead for the loop's own mechanics — per-ticket `ralph/*` branches, pushed as they grow and landed on the target by the loop, no PR among them — and is never a reason to drop to sequential in-session building. Whichever target, restate it in the echo — a choice the user should recognize, never silent.
|
|
22
22
|
|
|
23
23
|
**Resolve prose to data before anything launches.** The loop's inputs are ticket numbers and policy values (`only`, `max`, `width`, `target`) — the workflow takes them as JSON args and refuses a natural-language string by design. Translating the user's words into that scope, against live tracker state, is *your* job, and it ends with an echo before any dispatch: "Scope: #14, #15, #19 — the remaining slice-1 tickets; #19 builds after #14. Cap: none. Target: consolidate on `spec/2-checkout` (`master` untouched; one release PR offered at the end). Engine: the `ralph` workflow." A misread scope corrected here costs a sentence; corrected after launch it costs a run. That echo is your one pre-launch report — resolve the scope, repair setup (Step 2), and route (Step 3) without narrating the checks in between; surface a step only when it fails or changes the scope.
|
|
24
24
|
|
|
25
25
|
## Step 2 — Repair setup, don't gatekeep
|
|
26
26
|
|
|
27
|
-
If the loop's materials are missing — `modules.ralph` off in the manifest, or `.claude/workflows/ralph.js` absent — run `npx @wemuda/launchrail sync` (additive and idempotent; its migration installs them) and say what it did. Never answer the user's "build this" with "first go run a command" for anything this skill can run itself. What you cannot repair, report precisely: no tracker configured (`issueTracker: none`), or an empty verification contract (no `testing` commands — `verify` fails on an empty contract and the loop refuses a start it cannot gate).
|
|
27
|
+
If the loop's materials are missing — `modules.ralph` off in the manifest, or `.claude/workflows/ralph.js` absent — run `npx @wemuda/launchrail sync` (additive and idempotent; its migration installs them) and say what it did. Never answer the user's "build this" with "first go run a command" for anything this skill can run itself. What you cannot repair, report precisely: no tracker configured (`issueTracker: none`), or an empty verification contract (no `testing` commands — `verify` fails on an empty contract and the loop refuses a start it cannot gate). An unset `testing.checkCommand` is not a gap — the fast gate falls back to the unit command — but say once that naming a quicker lint/typecheck/unit gate there makes every land cheaper.
|
|
28
28
|
|
|
29
29
|
## Step 3 — Route by scope
|
|
30
30
|
|
|
31
|
-
**The frontier (or any multi-ticket scope):** the engine is the `ralph` workflow (`.claude/workflows/ralph.js`) — launch it with the resolved scope and target as JSON args, e.g. `{ only: [14, 15, 19], max: 5, target: 'spec/2-checkout' }` (`canary: true` on a project's first run), then supervise it per the `launch-ralph` skill, which owns the policies (width, attempts, cap, deferrals, the
|
|
31
|
+
**The frontier (or any multi-ticket scope):** the engine is the `ralph` workflow (`.claude/workflows/ralph.js`) — launch it with the resolved scope and target as JSON args, e.g. `{ only: [14, 15, 19], max: 5, target: 'spec/2-checkout' }` (`canary: true` on a project's first run), then supervise it per the `launch-ralph` skill, which owns the policies (width and the work pool, attempts, re-syncs, cap, deferrals, the local landing gate, checkpoints, remote-verified lands) and the supervisor's contract. Relaunching after a lost container passes `knownGreen: '<sha>'` so preflight skips re-proving a base a previous run verified; pushed `ralph/*` branches are adopted, never rebuilt. Orchestrating dispatches by hand under that skill instead is the exception, chosen out loud in the echo: the user asked to watch each dispatch, the Workflow tool is unavailable here, or the run is a targeted intervention (one parked ticket). One engine, one shape — a session that invents its own fan-out is not running the loop.
|
|
32
32
|
|
|
33
|
-
**One ticket:** build it here, watchable, under the same contract a Ralph dispatch carries (kept textually parallel with `launch-ralph` — change one, change both). A single ticket has nothing to consolidate, so its base is the **default branch** and its one CI-gated PR merges there — consolidation-by-default is a multi-ticket policy (use a different base only if the user names one, or the session pins a designated branch — then that is the base).
|
|
33
|
+
**One ticket:** build it here, watchable, under the same contract a Ralph dispatch carries (kept textually parallel with `launch-ralph` — change one, change both). A single ticket has nothing to consolidate, so its base is the **default branch** and its one CI-gated PR merges there — consolidation-by-default is a multi-ticket policy (use a different base only if the user names one, or the session pins a designated branch — then that is the base). Two deliberate divergences from a loop dispatch: a single ticket's PR *is* the review checkpoint, so it keeps the PR and its cloud CI, and you are the session, not a subagent, so you run that merge gate yourself — waiting on CI here is fine:
|
|
34
34
|
|
|
35
35
|
1. **Dependency gate:** every ticket on the `Blocked by:` line is closed with its work merged. An open blocker stops you before any code — name it and offer to build it first.
|
|
36
36
|
2. Read the ticket and everything it links (spec sections, ADRs, journeys), plus `AGENTS.md`/`CLAUDE.md`.
|
|
37
37
|
3. Label the ticket `ralph:building`; branch `ralph/<n>-<short-slug>` from a fresh sync of the base resolved above.
|
|
38
|
-
4. Implement by the **`launch-ralph-implement`**
|
|
39
|
-
5. Pre-PR sync: merge the latest base; resolve conflicts with `launch-resolving-merge-conflicts`; re-run the gate if anything changed.
|
|
38
|
+
4. Implement by calling the Skill tool with **`launch-ralph-implement`** — it owns TDD, the push cadence, the gates (the full `verify` before a PR of your own), browser smoke for user-facing changes, self-review, and commit conventions. Never paraphrase it inline.
|
|
39
|
+
5. Pre-PR sync: merge the latest base; resolve conflicts by calling the Skill tool with `launch-resolving-merge-conflicts`; re-run the gate if anything changed.
|
|
40
40
|
6. Open a PR titled from the ticket with `Closes #<n>`; adopt an existing `ralph/<n>-*` branch or PR rather than opening a second.
|
|
41
41
|
7. Wait for CI (Monitor or a background sleep, never a foreground busy-wait); fix what the branch broke; merge; confirm on the remote that the PR merged and the issue closed — close it explicitly if squash-merge didn't. Remove `ralph:building`.
|
|
42
42
|
8. **Integrity:** no placeholders, no stubs, never delete or weaken a test to get green, never claim verification you didn't run.
|
|
@@ -44,6 +44,6 @@ If the loop's materials are missing — `modules.ralph` off in the manifest, or
|
|
|
44
44
|
## Ground rules
|
|
45
45
|
|
|
46
46
|
- **Only the user starts this.** Conductors and other skills hand over the command (`/launch-implement`); they never invoke it. The engines behind it inherit the same rule — reaching them through this door *is* the explicit user start.
|
|
47
|
-
- **Nothing is done until `npx @wemuda/launchrail verify`
|
|
48
|
-
- **Report evidence, not assertions:** PR numbers
|
|
49
|
-
- **Every loop run ends with the campaign recap** (the `launch-ralph` close-out): where the work lives — target branch and head SHA — the ticket →
|
|
47
|
+
- **Nothing is done until the gates are green** — `npx @wemuda/launchrail verify --fast` on every land, the full `npx @wemuda/launchrail verify` at the loop's checkpoints and once more on the final base when a run ends (and before a single ticket's PR). Where `modules.browser-testing` is enabled and the change is user-facing, a `launch-browser-smoke` journey is part of done.
|
|
48
|
+
- **Report evidence, not assertions:** landing commits (PR numbers in single-ticket mode), issues closed, checkpoint and verify outcomes — and what was held, parked, or punted, with why.
|
|
49
|
+
- **Every loop run ends with the campaign recap** (the `launch-ralph` close-out): where the work lives — target branch and head SHA — the ticket → landing-commit table, held, parked, and stuck tickets, punted follow-ups in one list, and the single next step. By default that step is *offering* the one release PR `<target> → <default>` (where cloud CI runs, once), opened only when the user says so; in the opt-in trunk mode it is nothing — every ticket is already live on the default branch. Under the recap, render the rail banner ([`workflow.md`](../launch/workflow.md)'s phase view) — Build done for this scope, verification/release as what remains — so even the build door closes with "where we are and where we're going".
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: launch-project-alignment
|
|
3
|
-
description: The on-ramp for adopting an existing, mid-development codebase
|
|
3
|
+
description: "The on-ramp for adopting an existing, mid-development codebase: inventory what the project already has, infer a draft vision from the code, interview only the gaps, detect the existing design system — then route back into the normal workflow. Use when initializing Launchrail on a project that already has code (origin: existing in .launchrail.yml), when the user asks to adopt, align, or onboard an existing project, or when launch sends one to stage 1."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Project alignment — adopting an existing project
|
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
21
|
-
- **
|
|
22
|
-
- **
|
|
23
|
-
- **
|
|
24
|
-
- **
|
|
25
|
-
- **
|
|
26
|
-
- **
|
|
27
|
-
- **
|
|
28
|
-
- **
|
|
29
|
-
- **
|
|
30
|
-
- **
|
|
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
|
|
39
|
-
4. The verbatim local commands are known (from `AGENTS.md` / `.launchrail.yml`),
|
|
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 →
|
|
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
|
|
46
|
-
- Dispatch up to *width* frontier tickets, **spawning the
|
|
47
|
-
- **
|
|
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
|
|
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
|
|
57
|
-
5. Implement by
|
|
58
|
-
6. Pre-
|
|
59
|
-
7.
|
|
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
|
|
68
|
+
## The landing — owned by the loop
|
|
62
69
|
|
|
63
|
-
In skill mode
|
|
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.
|
|
66
|
-
2.
|
|
67
|
-
3.
|
|
68
|
-
4.
|
|
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
|
-
|
|
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
|
-
|
|
82
|
+
## Checkpoints and the repair
|
|
73
83
|
|
|
74
|
-
|
|
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
|
|
79
|
-
- **Blocked (deferred)** → the dependency gate stopped the build. Hand the attempt back and retry
|
|
80
|
-
- **
|
|
81
|
-
- **
|
|
82
|
-
- **
|
|
83
|
-
- **
|
|
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
|
|
90
|
-
1. **Read the resolved scope back, immediately.** The first `log()` lines state it ("Scoped to #11, #12", "Stopping after 5 verified
|
|
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
|
|
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.**
|
|
94
|
-
5. **Intervene by exception, not by reflex.** Parked ticket → dispatch a fresh scoped run for just that one.
|
|
95
|
-
6. **Report once at the end, concretely** —
|
|
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
|
|
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
|
|
102
|
-
2. If `.launchrail.yml` has `modules.browser-testing: true` and any
|
|
103
|
-
3.
|
|
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 →
|
|
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
|
|
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.
|
|
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
|
|
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.
|