@wemuda/launchrail 1.14.0 → 1.15.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 +2 -2
- package/assets/ralph.workflow.js +9 -17
- package/assets/skills/launchrail/launch/SKILL.md +4 -4
- package/assets/skills/launchrail/launch/workflow.md +3 -2
- package/assets/skills/launchrail/launch-browser-smoke/SKILL.md +36 -40
- package/assets/skills/launchrail/launch-implement/SKILL.md +3 -3
- package/assets/skills/launchrail/launch-loop-readiness/SKILL.md +79 -0
- package/assets/skills/launchrail/launch-project-alignment/SKILL.md +1 -1
- package/assets/skills/launchrail/launch-ralph/SKILL.md +5 -6
- package/assets/skills/launchrail/launch-ralph-implement/SKILL.md +5 -5
- package/dist/commands/add.js +6 -10
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/doctor.js +55 -8
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.js +0 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/verify.d.ts +3 -2
- package/dist/commands/verify.js +3 -2
- package/dist/commands/verify.js.map +1 -1
- package/dist/index.js +0 -15
- package/dist/index.js.map +1 -1
- package/dist/lib/browser-testing.d.ts +20 -3
- package/dist/lib/browser-testing.js +79 -79
- package/dist/lib/browser-testing.js.map +1 -1
- package/dist/lib/detect.d.ts +2 -0
- package/dist/lib/detect.js +3 -0
- package/dist/lib/detect.js.map +1 -1
- package/dist/lib/manifest.d.ts +6 -1
- package/dist/lib/manifest.js +17 -5
- package/dist/lib/manifest.js.map +1 -1
- package/dist/lib/migrations.js +76 -1
- package/dist/lib/migrations.js.map +1 -1
- package/dist/lib/readiness.d.ts +57 -0
- package/dist/lib/readiness.js +129 -0
- package/dist/lib/readiness.js.map +1 -0
- package/dist/lib/seeds.js +7 -6
- package/dist/lib/seeds.js.map +1 -1
- package/package.json +1 -1
- package/dist/commands/smoke.d.ts +0 -21
- package/dist/commands/smoke.js +0 -171
- package/dist/commands/smoke.js.map +0 -1
package/README.md
CHANGED
|
@@ -60,9 +60,10 @@ From there, the day-to-day driver is not the CLI — it's the **`launch` skill**
|
|
|
60
60
|
- **`launch-design-handoff`** — the design→code on-ramp: drop a Claude Design export (a zip, a folder, artboards) and it becomes a committed handoff package under `docs/design/` — read against the code and design system, gaps recorded as the grill's agenda — then sized into the loop ([ADR-0024](https://github.com/wemuda/launchrail/blob/master/docs/adr/0024-design-handoff-onramp.md))
|
|
61
61
|
- **`launch-vision-creation`**, **`launch-discovery`**, **`launch-grill`**, **`launch-research`** — vision, then the divergent landscape scan, the grill (the convergent interview that runs both as the foundation's complexity grill and per-feature before speccing, keeping the glossary and ADRs honest as it goes), and primary-source research
|
|
62
62
|
- **`launch-wayfinder`**, **`launch-spec`**, **`launch-tickets`**, **`launch-design-validation`** — break big work into decision maps, synthesize the spec, validate it visually, and cut tracer-bullet tickets with blocking edges
|
|
63
|
-
- **`launch-browser-smoke`** — drives a real browser
|
|
63
|
+
- **`launch-browser-smoke`** — drives the running app in a real browser to see a just-built change working — one-off, from the shell with `agent-browser`, no test suite and no evidence bundle ([ADR-0034](https://github.com/wemuda/launchrail/blob/master/docs/adr/0034-browser-smoke-one-off-driving.md); with the browser-testing module)
|
|
64
64
|
- **`launch-implement`** — the one door to building: `/launch-implement` drives ready tickets to verified merges through the Ralph loop (a ticket number builds just that one; "the next 5 of spec #2" scopes and caps a run)
|
|
65
65
|
- **`launch-ralph`**, **`launch-ralph-implement`**, **`launch-code-review`**, **`launch-resolving-merge-conflicts`** — the verification-gated loop engine behind that door, installed by `init`
|
|
66
|
+
- **`launch-loop-readiness`** — checks and tunes a repo for the loop: measures the gates, sets the fast per-land gate, parallelizes the e2e specs, shares caches for parallel builders, narrows CI triggers, creates the tracker labels, adds hosted-session setup ([ADR-0033](https://github.com/wemuda/launchrail/blob/master/docs/adr/0033-loop-readiness.md)); `doctor` shows the same findings as warn-only readiness lines
|
|
66
67
|
|
|
67
68
|
The CLI is the maintenance surface you return to between sessions:
|
|
68
69
|
|
|
@@ -73,7 +74,6 @@ npx @wemuda/launchrail sync # apply managed updates + run migra
|
|
|
73
74
|
npx @wemuda/launchrail add browser-testing # enable a module
|
|
74
75
|
npx @wemuda/launchrail doctor # repository and environment checks
|
|
75
76
|
npx @wemuda/launchrail verify # deterministic verification gate
|
|
76
|
-
npx @wemuda/launchrail smoke # scaffold a browser-smoke evidence bundle
|
|
77
77
|
npx @wemuda/launchrail eject <module|file> # opt out of management (vendor mode: --all)
|
|
78
78
|
```
|
|
79
79
|
|
package/assets/ralph.workflow.js
CHANGED
|
@@ -30,7 +30,7 @@ export const meta = {
|
|
|
30
30
|
{ title: 'Verify', detail: 'remote ground truth for every claimed land' },
|
|
31
31
|
{ title: 'Checkpoint', detail: 'the full gate on the base every N lands, with one bounded repair when red' },
|
|
32
32
|
{ title: 'Park', detail: 'comment failure history, label needs-info' },
|
|
33
|
-
{ title: 'Release', detail: 'final full gate
|
|
33
|
+
{ title: 'Release', detail: 'final full gate, prune landed branches, the where-it-lives recap' },
|
|
34
34
|
],
|
|
35
35
|
}
|
|
36
36
|
|
|
@@ -93,8 +93,8 @@ const POLICY = {
|
|
|
93
93
|
// counts as a real failure.
|
|
94
94
|
resyncs: A.resyncs ?? 2,
|
|
95
95
|
// Run the FULL verification gate on the base after this many lands (0 = only at release).
|
|
96
|
-
// Every land already passed the fast gate on the merged tree; the full suite (
|
|
97
|
-
//
|
|
96
|
+
// Every land already passed the fast gate on the merged tree; the full suite (e2e
|
|
97
|
+
// specs included) is paid once per checkpoint instead of once per ticket, and a red
|
|
98
98
|
// checkpoint has at most this many suspects.
|
|
99
99
|
checkpointEvery: A.checkpointEvery ?? 5,
|
|
100
100
|
// A sha the caller vouches for: a previous run verified the base green at exactly this
|
|
@@ -153,7 +153,6 @@ const PREFLIGHT_SCHEMA = {
|
|
|
153
153
|
items: { type: 'string' },
|
|
154
154
|
description: 'other verbatim local commands (typecheck, lint, unit tests) implementers should use',
|
|
155
155
|
},
|
|
156
|
-
browserTesting: { type: 'boolean', description: '.launchrail.yml modules.browser-testing' },
|
|
157
156
|
pushedBranches: {
|
|
158
157
|
type: 'array',
|
|
159
158
|
items: {
|
|
@@ -299,7 +298,6 @@ const RELEASE_SCHEMA = {
|
|
|
299
298
|
properties: {
|
|
300
299
|
verified: { type: 'boolean', description: 'the full verification gate is green on the final base (run now, or already proven at this exact tip)' },
|
|
301
300
|
headSha: { type: 'string' },
|
|
302
|
-
smokeBundle: { type: 'string', description: 'path of the smoke evidence bundle, when one was produced' },
|
|
303
301
|
prunedBranches: { type: 'array', items: { type: 'string' }, description: 'the landed ralph/* branches deleted from the remote' },
|
|
304
302
|
summary: { type: 'string' },
|
|
305
303
|
failures: { type: 'array', items: { type: 'string' } },
|
|
@@ -316,7 +314,7 @@ Architecture decisions: read the registry index (docs/adr/README.md) and open on
|
|
|
316
314
|
Tracker access from this environment: ${pre.trackerAccess}
|
|
317
315
|
Blocking edges live on tickets as "Blocked by: #n" lines.
|
|
318
316
|
Verbatim local commands: install: ${pre.installCommand}${pre.localCommands.length > 0 ? ` ; ${pre.localCommands.join(' ; ')}` : ''}
|
|
319
|
-
Two gates. The FAST gate is ${pre.fastGateCommand} — run it before every hand-off; it must exit 0. The FULL gate (${pre.verifyCommand}) belongs to the loop, which runs it on the base at its checkpoints — do not spend your turn on the whole suite; run only the slow test files your change touches (
|
|
317
|
+
Two gates. The FAST gate is ${pre.fastGateCommand} — run it before every hand-off; it must exit 0. The FULL gate (${pre.verifyCommand}) belongs to the loop, which runs it on the base at its checkpoints — do not spend your turn on the whole suite; run only the slow test files your change touches (an e2e spec you edited).
|
|
320
318
|
Several implementers share this machine — run single test files while iterating and save full runs for the gate.`
|
|
321
319
|
}
|
|
322
320
|
|
|
@@ -339,7 +337,7 @@ Implement ticket #${ticket.number} ("${ticket.title}") through to a pushed, fast
|
|
|
339
337
|
${retry}${resyncNote}
|
|
340
338
|
Steps, in order:
|
|
341
339
|
1. Dependency gate: before anything else, confirm every ticket on this ticket's "Blocked by" line is CLOSED with its work landed on ${pre.base}. If any blocker is still open, do NOT build on a missing dependency — report status "blocked", name the open blocker in "failure", and stop. That is a deferral, not a failure; the loop retries you after the blocker lands.
|
|
342
|
-
2. Read the ticket and everything it links (spec sections, ADRs,
|
|
340
|
+
2. Read the ticket and everything it links (spec sections, ADRs, designs). 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. Report status "already-done" if the ticket is already closed.
|
|
343
341
|
3. Label the ticket ralph:building so a lost session leaves a trace.
|
|
344
342
|
4. Branch and push immediately. ${adopt} From here on the pushed branch is your checkpoint: commit and push after every green step (a passing test slice, a finished subtask) — a session that dies keeps everything up to its last push, and its successor resumes from there instead of rebuilding. The pushes are also the loop's liveness signal.
|
|
345
343
|
5. Implement by invoking the launch-ralph-implement skill — it owns the per-ticket contract: TDD, commit-and-push cadence, the fast gate, browser smoke for user-facing changes, self-review via launch-code-review, commit conventions.
|
|
@@ -404,7 +402,7 @@ Failures: ${(cp.failures ?? []).join(' | ') || cp.summary}
|
|
|
404
402
|
|
|
405
403
|
Repair the base through to a pushed, green branch:
|
|
406
404
|
1. Branch from a fresh fetch and push at once: \`git fetch origin ${pre.base} && git checkout -b ralph/repair-${k}-<short-slug> origin/${pre.base} && git push -u origin HEAD\`. Never check out ${pre.base} itself in this worktree.
|
|
407
|
-
2. Reproduce the failure — the failing test files first, the full gate if needed — and find the root cause among the listed landings (\`git log ${cp.greenSha || ''}..${cp.headSha}\`): an integration break between two tickets, a migration-number collision,
|
|
405
|
+
2. Reproduce the failure — the failing test files first, the full gate if needed — and find the root cause among the listed landings (\`git log ${cp.greenSha || ''}..${cp.headSha}\`): an integration break between two tickets, a migration-number collision, an e2e spec a landing invalidated. Fix it properly; regenerate colliding migrations with the project's migration tool.
|
|
408
406
|
3. Make the fast gate green, then the FULL gate (${pre.verifyCommand}) green — this repair lands under the full gate. Self-review via the launch-code-review skill, commit conventionally, push after every green step.
|
|
409
407
|
4. Hand off: report status "ready" with branch, headSha, and a commitTitle like "fix(<scope>): <what>". Then STOP — the loop lands it. Never push to ${pre.base} yourself.
|
|
410
408
|
Report "failed" with the one fact a human must know if the base cannot be repaired without losing behavior.
|
|
@@ -418,20 +416,15 @@ function releasePrompt(pre, opts) {
|
|
|
418
416
|
: opts.needsGate
|
|
419
417
|
? `2. Run the install command (${pre.installCommand}), then the FULL verification gate: ${pre.verifyCommand}. Report the actual exit code.`
|
|
420
418
|
: `2. The full gate already passed at exactly this tip (${opts.greenSha}) during the run — report verified: true without re-running it, unless the tip you synced differs, in which case run ${pre.verifyCommand}.`
|
|
421
|
-
const smokeStep =
|
|
422
|
-
!opts.baseRed && opts.smoke
|
|
423
|
-
? `
|
|
424
|
-
3. The browser-testing module is enabled and tickets landed: start the app (node scripts/dev.mjs --background), scaffold an evidence bundle (npx @wemuda/launchrail smoke), and drive the smoke journeys from docs/testing/smoke-journeys.md per the launch-browser-smoke skill. Report the bundle path. A journey you could not complete is a failure, never a pass.`
|
|
425
|
-
: ''
|
|
426
419
|
const pruneStep =
|
|
427
420
|
opts.prune.length > 0
|
|
428
421
|
? `
|
|
429
|
-
|
|
422
|
+
3. Prune the remote branches of the verified-landed tickets, and ONLY these: ${opts.prune.join(', ')} (\`git push origin --delete <branch>\` each; a branch already gone is fine). Never delete any other branch. Report prunedBranches.`
|
|
430
423
|
: ''
|
|
431
424
|
return `Release verification for a finished Ralph loop run, in THIS checkout. Fix nothing.
|
|
432
425
|
1. Sync a fresh ${pre.base} (\`git fetch origin ${pre.base}\`, \`git checkout ${pre.base}\`, \`git merge --ff-only origin/${pre.base}\`) and record its head sha.
|
|
433
|
-
${gateStep}${
|
|
434
|
-
verified means: the full verification gate is green on the final base
|
|
426
|
+
${gateStep}${pruneStep}
|
|
427
|
+
verified means: the full verification gate is green on the final base.`
|
|
435
428
|
}
|
|
436
429
|
|
|
437
430
|
const graphPrompt = (pre) => `List the open, ready tickets for a Ralph loop run. Change nothing on the tracker.
|
|
@@ -943,7 +936,6 @@ const release = await agent(
|
|
|
943
936
|
baseRedReason,
|
|
944
937
|
needsGate: baseTip !== lastGreenSha,
|
|
945
938
|
greenSha: lastGreenSha,
|
|
946
|
-
smoke: Boolean(pre.browserTesting) && landed.length > 0,
|
|
947
939
|
prune: landed.map((s) => s.branch).filter(Boolean),
|
|
948
940
|
}),
|
|
949
941
|
{ label: 'release-verification', phase: 'Release', schema: RELEASE_SCHEMA },
|
|
@@ -15,7 +15,7 @@ Read `.launchrail.yml` (`origin`, `modules`, `issueTracker`) first — it is the
|
|
|
15
15
|
|
|
16
16
|
| # | Stage | Owner (invoke / run) | Done when |
|
|
17
17
|
|---|---|---|---|
|
|
18
|
-
| 0 | Setup | `npx @wemuda/launchrail init` | Manifest + lockfile committed; `doctor` green (`docs/agents/` is seeded by init) |
|
|
18
|
+
| 0 | Setup | `npx @wemuda/launchrail init`; then `launch-loop-readiness` to tune the repo for the implementation loop (optional — recommended once for an existing codebase) | Manifest + lockfile committed; `doctor` green (`docs/agents/` is seeded by init) — its `ralph …` readiness lines are advice, never a gate |
|
|
19
19
|
| 1 | Vision | `launch-vision-creation` — via `launch-project-alignment` when `origin: existing` | `docs/vision.md` exists and is real (not the bare template) |
|
|
20
20
|
| 2 | Visual exploration | Claude Design | Exploration artifacts linked from `docs/vision.md` |
|
|
21
21
|
| 3 | Discovery | `launch-discovery` | Landscape map committed under `docs/research/` (`discovery-*.md`) |
|
|
@@ -26,7 +26,7 @@ Read `.launchrail.yml` (`origin`, `modules`, `issueTracker`) first — it is the
|
|
|
26
26
|
| 8 | Design validation | `launch-design-validation` (fidelity chosen inside the skill) | The spec carries a `## Design validation` section (a recorded skip counts) |
|
|
27
27
|
| 9 | Tickets | `launch-tickets` † | Tracker has `ready-for-agent` tickets with `Blocked by: #n` edges |
|
|
28
28
|
| 10 | Implementation | `/launch-implement` † — drives the Ralph loop | The ready frontier is drained; PRs merged and verified |
|
|
29
|
-
| 11 | Verification | `npx @wemuda/launchrail verify` · `launch-browser-smoke` | The gate is green;
|
|
29
|
+
| 11 | Verification | `npx @wemuda/launchrail verify` · `launch-browser-smoke` | The gate is green; user-facing behavior seen working in a real browser |
|
|
30
30
|
| 12 | Release | The project's release setup | The release is cut |
|
|
31
31
|
|
|
32
32
|
† User-typed (`disable-model-invocation`): prepare the handoff — inputs committed, exact fully-argumented command handed over, resume when the artifact lands (see the conductor rules). Never call one and get refused, and never reverse-engineer it.
|
|
@@ -50,7 +50,7 @@ A feature that arrives **design-first** — a dropped zip or folder of Claude De
|
|
|
50
50
|
## Running it
|
|
51
51
|
|
|
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
|
-
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.
|
|
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). When `doctor` warns on its `ralph …` readiness lines (fast gate, e2e specs, CI triggers, hosted setup, commands), offer `launch-loop-readiness` once — it measures and tunes the repo for the loop — and move on; readiness never gates the rail. 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
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.
|
|
@@ -61,7 +61,7 @@ Case-insensitive direct jumps:
|
|
|
61
61
|
|
|
62
62
|
- `status` / `where` — render the rail banner for the detected position (with the evidence) and stop.
|
|
63
63
|
- `next` — detect the frontier and drive it (the default).
|
|
64
|
-
- `setup` / `init` — 0 · `align` / `adopt` — the existing-project on-ramp · `vision` — 1 · `explore` — 2 · `discovery` / `landscape` — 3 · `grill` — 4 · `research` — 5 · `deep-research` — 3→5 · `adr` / `architecture` — 6 · `spec` — 7 · `design-validation` / `validate` — 8 · `tickets` — 9 · `implement` / `build` / `ralph` / `loop` — hand over `/launch-implement` · `verify` / `smoke` — 11 · `release` — 12 · `handoff` / `design-handoff` — the design→code on-ramp (`launch-design-handoff`).
|
|
64
|
+
- `setup` / `init` — 0 · `readiness` / `tune` / `optimize` — `launch-loop-readiness` · `align` / `adopt` — the existing-project on-ramp · `vision` — 1 · `explore` — 2 · `discovery` / `landscape` — 3 · `grill` — 4 · `research` — 5 · `deep-research` — 3→5 · `adr` / `architecture` — 6 · `spec` — 7 · `design-validation` / `validate` — 8 · `tickets` — 9 · `implement` / `build` / `ralph` / `loop` — hand over `/launch-implement` · `verify` / `smoke` — 11 · `release` — 12 · `handoff` / `design-handoff` — the design→code on-ramp (`launch-design-handoff`).
|
|
65
65
|
- `feature` / `size` — size a described feature (recommend a path; route on request).
|
|
66
66
|
|
|
67
67
|
Unrecognized keyword → show this list and ask.
|
|
@@ -51,6 +51,7 @@ A planning session (a grill, a wayfinder ticket, an interview) closes with the b
|
|
|
51
51
|
## Prerequisites
|
|
52
52
|
|
|
53
53
|
- The repository is initialized (`npx @wemuda/launchrail init`) and healthy (`npx @wemuda/launchrail doctor`). Init writes the workflow skills, the implementation loop's materials, *and* the `docs/agents/` configuration (issue-tracker conventions and domain-doc rules, seeded from the manifest's answers) — there is no separate install or setup step on the golden path.
|
|
54
|
+
- Before the first `/launch-implement` on an existing codebase, `launch-loop-readiness` (stage 0, optional) measures the verification gates and tunes the repository for the implementation loop — a fast per-land gate, parallel e2e specs, shared caches for parallel builders, CI triggers, tracker labels, hosted-session setup, verbatim commands ([ADR-0033](https://github.com/wemuda/launchrail/blob/master/docs/adr/0033-loop-readiness.md)). `doctor`'s `ralph …` readiness lines say when it is worth running; they warn, never fail.
|
|
54
55
|
|
|
55
56
|
## Stages
|
|
56
57
|
|
|
@@ -66,7 +67,7 @@ A planning session (a grill, a wayfinder ticket, an interview) closes with the b
|
|
|
66
67
|
| 8 | Design validation | Launchrail `design-validation` skill | Spec (+ Claude Design at the top fidelity) | Revised spec with `## Design validation` section |
|
|
67
68
|
| 9 | Tickets | `launch-tickets` † | Validated spec | Tickets in the tracker: `ready-for-agent` label, `Blocked by: #n` edges |
|
|
68
69
|
| 10 | Implementation | `/launch-implement` † → the Ralph loop | Ready tickets | PRs merged and verified; the frontier drained |
|
|
69
|
-
| 11 | Verification | `npx @wemuda/launchrail verify` ·
|
|
70
|
+
| 11 | Verification | `npx @wemuda/launchrail verify` · `launch-browser-smoke` | Merged work | The gate green; user-facing behavior seen working in a real browser |
|
|
70
71
|
| 12 | Release | The project's release setup | Verified base | The release cut |
|
|
71
72
|
|
|
72
73
|
† **User-typed by design** — `disable-model-invocation`: only the user can start these. `launch-wayfinder`/`launch-spec` and `launch-tickets` publish to the tracker; `/launch-implement` spawns agents and merges PRs. A conductor prepares the handoff instead of calling them — see the conductor rules.
|
|
@@ -77,7 +78,7 @@ Stage notes:
|
|
|
77
78
|
- **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
79
|
- **‡ 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
80
|
- **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 --fast` gating every land
|
|
81
|
+
- **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, the full `launchrail verify` at the loop's checkpoints and release, and — where the browser-testing module is enabled — each implementer's one-off browser smoke of its user-facing ticket ([ADR-0034](https://github.com/wemuda/launchrail/blob/master/docs/adr/0034-browser-smoke-one-off-driving.md)) ([ADR-0032](https://github.com/wemuda/launchrail/blob/master/docs/adr/0032-ralph-lean-local-gate-loop.md)).
|
|
81
82
|
|
|
82
83
|
## Sizing the work in the delivery loop
|
|
83
84
|
|
|
@@ -1,49 +1,45 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: launch-browser-smoke
|
|
3
|
-
description: Drive the running app
|
|
3
|
+
description: Drive the running app in a real browser to see a just-built change working — a one-off, agent-driven check of the feature, not a test suite and not an evidence bundle. Use before declaring user-facing work done when .launchrail.yml has modules.browser-testing enabled, or when the user asks to smoke-test or click through the app.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Browser smoke
|
|
6
|
+
# Browser smoke — see the change working
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
A browser smoke is you driving the real stack in a real browser to check that what you just built looks right and works. It is **one-off**: it lives for this change and ends in a verdict, not in a test file, a journeys catalogue, or a committed report ([ADR-0034](https://github.com/wemuda/launchrail/blob/master/docs/adr/0034-browser-smoke-one-off-driving.md)). Deterministic coverage is the other lane — `npx @wemuda/launchrail verify` with the unit command and the thin Playwright e2e specs — and a smoke never grows it by accident.
|
|
9
9
|
|
|
10
10
|
## Preconditions
|
|
11
11
|
|
|
12
12
|
1. `.launchrail.yml` has `modules.browser-testing: true`. If not, stop and suggest `npx @wemuda/launchrail add browser-testing`.
|
|
13
|
-
2.
|
|
14
|
-
3. The app
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
##
|
|
44
|
-
|
|
45
|
-
-
|
|
46
|
-
- Record any deviation from the spec or design in `deviations.md` next to the summary.
|
|
47
|
-
- A journey you could not complete is a failure or a blocker, never a pass.
|
|
48
|
-
- Never mark a journey passed while it has unexplained console or network errors.
|
|
49
|
-
- The committed record is `summary.md`, `deviations.md`, and `meta.json`; bulky evidence stays local or becomes a CI artifact.
|
|
13
|
+
2. The fast gate is green: `npx @wemuda/launchrail verify --fast`. A smoke runs on top of a green build; a red one is fixed first.
|
|
14
|
+
3. The app runs from **this** worktree: `node scripts/dev.mjs --background` (in a fresh clone, `node scripts/setup.mjs` first). Other builders may share the machine — pass `--port <n>` with a port nobody else uses. The script writes the URL to `.launchrail/state/dev.url` and the pid to `.launchrail/state/dev.pid`; read the URL from there rather than assuming `testing.appUrl`.
|
|
15
|
+
4. The driver is `agent-browser`, installed by `scripts/setup.mjs`: `npx agent-browser --version` must answer. If it does not, run setup; if it still cannot install, use the fallback below.
|
|
16
|
+
|
|
17
|
+
## The run
|
|
18
|
+
|
|
19
|
+
1. **Decide what to check.** From the ticket's acceptance criteria and your diff, write three to six steps for *this change*: where to start, what to click or type, what must be visible at the end. They live in your head and your handoff — never in a repository file.
|
|
20
|
+
2. **Drive them, one session per ticket.** `export AGENT_BROWSER_SESSION=<branch-or-ticket>` keeps your browser apart from other builders'. Then, from the shell:
|
|
21
|
+
- `npx agent-browser open <url>` — start on the page the change lives on.
|
|
22
|
+
- `npx agent-browser snapshot -i` — the interactive elements with refs (`@e1`, `@e2`, …).
|
|
23
|
+
- `npx agent-browser click @e3`, `fill @e5 "text"`, `type`, `press Enter` — act as a user would.
|
|
24
|
+
- `npx agent-browser wait --load networkidle`, `wait --text "Saved"`, `wait <selector>` — **after every action that triggers a request or opens a modal, wait before the next snapshot**; a snapshot taken too early is the usual false failure.
|
|
25
|
+
- `npx agent-browser screenshot <path>` — and look at the image yourself (open it with the Read tool). Layout, copy, empty states, and wrong-but-rendering are what a script cannot judge; that judgment is the point of this lane.
|
|
26
|
+
- `npx agent-browser errors`, `console`, `network requests` — after each step, not only at the end.
|
|
27
|
+
3. **Click around beyond the happy path.** The obvious wrong input, the empty state, a reload, the back button. You are looking for what the ticket did not spell out.
|
|
28
|
+
4. **The standard checks, every time:** no uncaught exceptions, no failed requests, the success state visible in a screenshot you looked at, the data still there after a reload.
|
|
29
|
+
5. **Design:** compare the screen to a design only when the ticket or spec names one (a `docs/design/` handoff, a mockup). Never invent a comparison.
|
|
30
|
+
|
|
31
|
+
## When something is wrong
|
|
32
|
+
|
|
33
|
+
1. Fix it.
|
|
34
|
+
2. Add the regression test at the **cheapest seam that would have caught it** — a unit or integration test first. A new Playwright spec under `tests/e2e/` only when the ticket asks for one or the behavior exists only in a real browser; the e2e lane stays thin, and a smoke never becomes a spec by default.
|
|
35
|
+
3. Re-drive the steps that failed.
|
|
36
|
+
|
|
37
|
+
## Done
|
|
38
|
+
|
|
39
|
+
- `npx agent-browser close`, and stop the app you started: `kill $(cat .launchrail/state/dev.pid)`.
|
|
40
|
+
- Your handoff states, in a few lines, what you drove and what you saw — that is the record. Nothing is committed for the smoke: no journeys file, no `artifacts/` bundle, no screenshots in the repo.
|
|
41
|
+
- A smoke you could not drive is a failure, not a pass. Never report one you did not run.
|
|
42
|
+
|
|
43
|
+
## Fallback — no driver
|
|
44
|
+
|
|
45
|
+
If `agent-browser` cannot be installed here, write a throwaway `playwright-core` script under `.launchrail/state/` (gitignored) that drives the same steps and prints what it saw, and run it with the project's Playwright. It stays there — it never moves under `tests/`, and it is no substitute for looking at the screenshots.
|
|
@@ -24,7 +24,7 @@ From `.launchrail.yml`: `issueTracker` and the `testing` commands. From the argu
|
|
|
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). An unset `testing.checkCommand` is not a gap — the fast gate falls back to the unit command — but say once that
|
|
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 when `doctor` warns on its `ralph …` readiness lines (fast gate, e2e specs, CI triggers, hosted setup, commands), say once that `/launch-loop-readiness` measures and fixes them, and proceed; readiness never gates a build.
|
|
28
28
|
|
|
29
29
|
## Step 3 — Route by scope
|
|
30
30
|
|
|
@@ -33,7 +33,7 @@ If the loop's materials are missing — `modules.ralph` off in the manifest, or
|
|
|
33
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
|
-
2. Read the ticket and everything it links (spec sections, ADRs,
|
|
36
|
+
2. Read the ticket and everything it links (spec sections, ADRs, designs), 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
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
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.
|
|
@@ -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 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`
|
|
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` run — the change seen working in a real browser — is part of done.
|
|
48
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
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".
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: launch-loop-readiness
|
|
3
|
+
description: Check and tune a repository for the implementation loop — measure the verification gates, then set the fast per-land gate, parallelize the e2e specs, share caches for parallel builders, narrow CI triggers, create the tracker labels, add hosted-session setup, and document the verbatim commands. Measured first, applied with one confirmation, never a gate on the rail. Run once before the first /launch-implement on an existing codebase, or whenever doctor's `ralph …` readiness lines warn.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Loop readiness — tune the repo for the implementation loop
|
|
7
|
+
|
|
8
|
+
The Ralph loop is only as fast as the repository lets it be. Every land runs the fast gate, every fifth land runs the full gate, every builder starts in a fresh worktree, every push can wake a CI runner, and a hosted session starts from an empty container. A repo tuned for humans typing `pnpm test` once an hour wastes tokens and wall-clock when three fresh-context builders hammer it all night. This skill measures that waste and removes it — without weakening a single test.
|
|
9
|
+
|
|
10
|
+
It is advice, never a gate: `/launch-implement` runs whether or not this skill ever ran. `npx @wemuda/launchrail doctor` shows the same findings as warn-only `ralph …` lines; this skill is where they get fixed with numbers behind them.
|
|
11
|
+
|
|
12
|
+
## Contract
|
|
13
|
+
|
|
14
|
+
- **Measure before proposing.** Every finding carries a number — seconds cold, seconds warm, e2e spec count — from a run you made, not an estimate.
|
|
15
|
+
- **Propose in impact order, with the expected saving**, then apply everything reversible in **one confirmation round** (the interaction contract in [`workflow.md`](../launch/workflow.md): reversible implementation details are yours, the user confirms only what touches their testing methodology — which e2e specs stay serial, what CI still runs).
|
|
16
|
+
- **Never weaken coverage.** No deleted, skipped, or loosened tests; no lowered assertions; latency-sensitive e2e specs stay serial. Speed comes from tiering, parallelism, caching, and not running the same suite twice.
|
|
17
|
+
- **Idempotent.** Re-running on a tuned repo reports "ready" and changes nothing.
|
|
18
|
+
- **One commit** at the end, in the project's convention (`chore: tune the repo for the implementation loop`), listing what changed.
|
|
19
|
+
|
|
20
|
+
## Step 1 — Inventory (read-only)
|
|
21
|
+
|
|
22
|
+
1. `npx @wemuda/launchrail doctor` — collect every `ralph …` line; they are the deterministic half of this checklist.
|
|
23
|
+
2. `.launchrail.yml` `testing.*` (unit, check, e2e, dev) and `AGENTS.md`'s Commands section: which commands exist verbatim, which are missing.
|
|
24
|
+
3. The package manager and its install command (frozen-lockfile form); the scripts (`test`, `lint`, `typecheck`, `build`, `check`); the monorepo tool (turbo, nx, workspaces) and its cache configuration; the test runners and their configs (vitest/jest workers and cache, Playwright `workers`, `fullyParallel`, `projects`, `retries`).
|
|
25
|
+
4. CI: every workflow's triggers and jobs; whether the required check is the same command the loop runs locally.
|
|
26
|
+
5. Data: the migration tool and its generate/renumber command; whether tests need a database, ports, or external services, and how they isolate per run.
|
|
27
|
+
6. Tracker: the labels the loop uses (`ready-for-agent`, `ralph:building`, `needs-info`, `spec`) exist — check with the tracker tools named in `docs/agents/issue-tracker.md`.
|
|
28
|
+
7. `.claude/settings.json`: hooks (the Ralph guard, any `SessionStart`), permissions; the seeded `scripts/setup.mjs` when the browser-testing module is on.
|
|
29
|
+
|
|
30
|
+
## Step 2 — Measure
|
|
31
|
+
|
|
32
|
+
Run, and time, in this order — twice each, so cold and warm are both known:
|
|
33
|
+
|
|
34
|
+
- `npx @wemuda/launchrail verify --fast` (the per-land gate).
|
|
35
|
+
- `npx @wemuda/launchrail verify` (the checkpoint and release gate); note the per-package breakdown the runner prints and, with e2e specs, their count and their share of the time.
|
|
36
|
+
- The install command in a fresh worktree (`git worktree add ../readiness-probe HEAD`, install, then remove it) — what every builder pays before its first test.
|
|
37
|
+
|
|
38
|
+
Write the numbers down; they anchor every proposal and the closing card.
|
|
39
|
+
|
|
40
|
+
## Step 3 — The catalogue
|
|
41
|
+
|
|
42
|
+
Work through these; each names the check, the fix, and why it matters to the loop.
|
|
43
|
+
|
|
44
|
+
1. **The fast gate** — `testing.checkCommand` unset, or slower than ~2 minutes warm. Set it to lint + typecheck + the unit suites without e2e specs (on turbo: `turbo run lint typecheck test --filter=!<web-package>` plus the web package's unit runner). Every land and every hand-off runs this; the e2e specs move to the checkpoints.
|
|
45
|
+
2. **E2e specs** — a global `workers: 1` or `fullyParallel: false`. Split: a `serial` Playwright project holding the latency-asserting specs (matched by directory or a `@serial` tag) and a `parallel` project for the rest; run them as two invocations from the e2e command (`playwright test --project=parallel --workers=4 && playwright test --project=serial --workers=1`). Which specs are latency-sensitive is the user's call — ask with the list in hand. Target: the full suite in a fraction of its serial time with identical assertions.
|
|
46
|
+
3. **Caches for parallel builders** — each builder starts in a fresh worktree with an empty cache. Enable the monorepo tool's shared cache: turbo remote cache, or `TURBO_CACHE_DIR` pointing at a path outside the worktree (persist it for hosted sessions via `$CLAUDE_ENV_FILE` in the SessionStart hook); a shared vitest `cacheDir`; the package manager's content-addressable store (pnpm has one by default). Unchanged packages then cost nothing at the builder's gate and at the lander's.
|
|
47
|
+
4. **CI triggers** — a workflow that runs on every push. The loop pushes `ralph/*` on every green step and the integration branch on every land; each would start a run nobody waits on. Trigger on `pull_request` and pushes to the default branch only, and add a `concurrency` group with `cancel-in-progress` so a release PR's re-pushes do not queue behind each other. Cloud CI runs once, on the release PR — make sure the required check there is the same full gate the loop ran at release.
|
|
48
|
+
5. **Tracker labels** — create any of `ready-for-agent`, `ralph:building`, `needs-info`, `spec` that are missing, with the descriptions from `docs/agents/issue-tracker.md`. A run refuses or mislabels without them.
|
|
49
|
+
6. **Hosted-session setup** — no `SessionStart` hook. Hosted sessions (Claude Code on the web) start from a fresh container: add `.claude/hooks/session-start.sh` that exits early unless `$CLAUDE_CODE_REMOTE` is `true`, runs the install command, and — with the browser-testing module — `node scripts/setup.mjs` so the pinned browser build is present (a version mismatch here is a preflight refusal in the field). Register it additively under `hooks.SessionStart` in `.claude/settings.json` (merge; the Ralph guard's `PreToolUse` entry stays). Synchronous first; offer async mode only if the user wants faster session starts. Validate it once with `CLAUDE_CODE_REMOTE=true` before committing.
|
|
50
|
+
7. **Verbatim commands** — `AGENTS.md`'s Commands section still holds the seeded TODO, or lacks any of install, fast gate, full gate, dev, and the migration generate/renumber command. Builders and the pre-land sync read these verbatim; fill them in from the inventory, and mirror the test ones into `.launchrail.yml` `testing.*`.
|
|
51
|
+
8. **Test isolation for parallel builders** — fixed ports, a shared database or schema, temp files at fixed paths. Three builders run the suites at once on one machine: use ephemeral ports (`0`), per-run database names or schemas, and `os.tmpdir()`-based paths. A flake that only appears at width 3 is this.
|
|
52
|
+
9. **Worktree hygiene** — configs or scripts that assume the checkout path (absolute paths, `..` walks out of the repo), generated files that are not ignored, install steps that write outside the repo. Builders work in `git worktree`s; anything path-bound breaks there first.
|
|
53
|
+
10. **Unattended runs** — remind, once, that an unattended run launches in a non-prompting permission mode (the guard hook warns at launch), and that any MCP or CLI the loop needs (the tracker tools) must be reachable from the session that launches it.
|
|
54
|
+
|
|
55
|
+
## Step 4 — Confirm, apply, re-measure
|
|
56
|
+
|
|
57
|
+
Present the proposals as one list — finding, fix, expected saving — and ask one round of at most three questions, only about what needs the user's judgment (which e2e specs stay serial; whether CI may be narrowed; anything touching production or secrets). Then apply everything approved, run `doctor` again, re-run the Step 2 timings, and commit.
|
|
58
|
+
|
|
59
|
+
## Step 5 — The readiness card
|
|
60
|
+
|
|
61
|
+
Close with a card the user can act on without scrolling back:
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
Loop readiness — <project>
|
|
65
|
+
Fast gate: <before> → <after> (warm <n>s) · <command>
|
|
66
|
+
Full gate: <before> → <after> · e2e specs <n> (<parallel>/<serial>)
|
|
67
|
+
Builder cold start: install <n>s · first fast gate <n>s
|
|
68
|
+
Changed: <one line per change, with the file>
|
|
69
|
+
Left for you: <anything that needs a human — secrets, remote cache login, CI settings>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Then hand back: when reached through `launch`, close with the rail banner from [`workflow.md`](../launch/workflow.md) — stage 0 under Done, the next stage under Now.
|
|
73
|
+
|
|
74
|
+
## What this skill does not do
|
|
75
|
+
|
|
76
|
+
- It never starts the loop, and never blocks it — `/launch-implement` runs without it.
|
|
77
|
+
- It never touches product artifacts (vision, specs, tickets) or the managed Launchrail files.
|
|
78
|
+
- It never deletes, skips, or weakens a test, and never lowers an assertion to buy speed.
|
|
79
|
+
- It never changes what CI verifies, only when it runs; a project's required checks stay required.
|
|
@@ -39,7 +39,7 @@ How each Launchrail artifact shows up in an existing project, and what to do:
|
|
|
39
39
|
| Architecture decisions (`docs/adr/`) | ADRs beyond the template; or de-facto decisions in code/docs | Note stage 6 as largely satisfied | Note as a gap; capture load-bearing existing decisions as ADRs later |
|
|
40
40
|
| MVP spec (`docs/specs/`) | Spec docs, PRDs, design docs | Note stage 7 as partial/satisfied | Real gap — owned by the spec stage |
|
|
41
41
|
| Tickets | The tracker in `.launchrail.yml` (issues/backlog) | Note stage 9 as partial | Real gap — owned by `launch-tickets` |
|
|
42
|
-
| Verification | Test suite, CI config, Playwright | Wire `testing` commands in `.launchrail.yml`; note stage 11 partial | Note as a gap |
|
|
42
|
+
| Verification | Test suite, CI config, Playwright | Wire `testing` commands in `.launchrail.yml`; note stage 11 partial; recommend `launch-loop-readiness` before the first `/launch-implement` — it measures the gates and tunes the repo for the loop | Note as a gap |
|
|
43
43
|
|
|
44
44
|
## What this skill does not do
|
|
45
45
|
|
|
@@ -58,7 +58,7 @@ Sync → compute frontier → keep *width* builders busy → land each finished
|
|
|
58
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:
|
|
59
59
|
|
|
60
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.
|
|
61
|
-
2. Read the ticket and everything it links (spec sections, ADRs,
|
|
61
|
+
2. Read the ticket and everything it links (spec sections, ADRs, designs), 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.
|
|
62
62
|
3. Label the ticket `ralph:building` so a lost session leaves a trace.
|
|
63
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
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.
|
|
@@ -81,7 +81,7 @@ A conflict, a gate that only fails on the merged tree, or a stale remote hands t
|
|
|
81
81
|
|
|
82
82
|
## Checkpoints and the repair
|
|
83
83
|
|
|
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,
|
|
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, an e2e spec 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
85
|
|
|
86
86
|
Every dispatch — retries, re-syncs, repairs included — also carries these two clauses verbatim:
|
|
87
87
|
|
|
@@ -117,9 +117,8 @@ When the Ralph loop runs as the `ralph` workflow instead of through this skill,
|
|
|
117
117
|
When the frontier drains (or the cap, the build backstop, a red base, or a stop condition hits):
|
|
118
118
|
|
|
119
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.
|
|
121
|
-
3.
|
|
122
|
-
4. Report the campaign recap — it must let the user act without scrolling back:
|
|
120
|
+
2. Prune the remote `ralph/*` branches of the verified-landed tickets — only those; held and parked branches stay.
|
|
121
|
+
3. Report the campaign recap — it must let the user act without scrolling back:
|
|
123
122
|
- **Where the work lives:** the integration target and its head SHA; in consolidation mode, say explicitly that the default branch is untouched.
|
|
124
123
|
- 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.
|
|
125
124
|
- Follow-ups and operator steps implementers punted, gathered into one list.
|
|
@@ -131,7 +130,7 @@ When the frontier drains (or the cap, the build backstop, a red base, or a stop
|
|
|
131
130
|
- Fresh context per dispatch, per retry, per re-sync. No exceptions.
|
|
132
131
|
- 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.
|
|
133
132
|
- 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.
|
|
134
|
-
- Name the skills (`launch-ralph-implement`, `launch-resolving-merge-conflicts
|
|
133
|
+
- Name the skills (`launch-ralph-implement`, `launch-resolving-merge-conflicts`); never paraphrase their contents into a prompt. The browser smoke is each implementer's, inside `launch-ralph-implement` — the loop dispatches no smoke run of its own.
|
|
135
134
|
- Blocking edges are parsed from the verbatim `Blocked by` line, by you — never resolved by a model in between.
|
|
136
135
|
- Nothing counts as landed until the remote says so; nothing counts as done until the full gate is green on the final base.
|
|
137
136
|
- A deferral is not a failure; a re-sync is not an attempt; a failure is never silently retried without its summary.
|
|
@@ -7,12 +7,12 @@ description: Implement a single ticket end to end under the Launchrail completio
|
|
|
7
7
|
|
|
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
|
-
1. **Read before coding.** The ticket, every artifact it links (spec sections, ADRs,
|
|
10
|
+
1. **Read before coding.** The ticket, every artifact it links (spec sections, ADRs, designs), and `AGENTS.md`/`CLAUDE.md`. The commands you run come from `.launchrail.yml` (`testing.*`) and `AGENTS.md`, verbatim.
|
|
11
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
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` (
|
|
14
|
-
5. **User-facing behavior, with `modules.browser-testing` enabled:**
|
|
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` (e2e specs included) at its checkpoints — so do not spend your turn on the whole suite; run only the slow test files your change touches (an e2e spec 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:** drive the change in a real browser per the `launch-browser-smoke` skill — a one-off check of what you built, its steps taken from the ticket's acceptance criteria, ending in your handoff's few lines on what you drove and saw. No journeys file, no evidence bundle, no spec written from it; a regression test for anything it finds goes at the cheapest seam that catches it. A smoke you could not drive is a failure, not a pass.
|
|
15
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,
|
|
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, design note) in the same change.
|
|
17
17
|
|
|
18
|
-
Done means: the gate is green, the review found nothing unaddressed, the branch is pushed, and the evidence (test output,
|
|
18
|
+
Done means: the gate is green, the review found nothing unaddressed, the branch is pushed, and the evidence (test output, the smoke's verdict) exists — not that the code "should work".
|
package/dist/commands/add.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import * as p from "@clack/prompts";
|
|
4
|
-
import { BROWSER_TESTING_MODULE, browserTestingFiles } from "../lib/browser-testing.js";
|
|
4
|
+
import { BROWSER_DRIVER_PACKAGE, BROWSER_TESTING_MODULE, browserTestingFiles } from "../lib/browser-testing.js";
|
|
5
5
|
import { applyRalphGuardHook, CLAUDE_SETTINGS_PATH, planRalphGuardHook, } from "../lib/claudeSettings.js";
|
|
6
6
|
import { detectRepo } from "../lib/detect.js";
|
|
7
7
|
import { emptyLockfile, readLockfile, writeLockfile } from "../lib/lockfile.js";
|
|
@@ -24,7 +24,6 @@ function defaultAnswers(manifest, detection) {
|
|
|
24
24
|
appUrl: manifest.testing.appUrl ?? "http://localhost:3000",
|
|
25
25
|
devCommand: manifest.testing.devCommand ?? (detection.devScript ? `${pm} run dev` : null),
|
|
26
26
|
e2eCommand: manifest.testing.e2eCommand ?? "npx playwright test",
|
|
27
|
-
smokeCommand: manifest.testing.smokeCommand ?? "node scripts/smoke.mjs",
|
|
28
27
|
};
|
|
29
28
|
}
|
|
30
29
|
async function interview(defaults) {
|
|
@@ -43,10 +42,6 @@ async function interview(defaults) {
|
|
|
43
42
|
message: "Deterministic browser-test command",
|
|
44
43
|
initialValue: defaults.e2eCommand,
|
|
45
44
|
}),
|
|
46
|
-
smokeCommand: () => p.text({
|
|
47
|
-
message: "Smoke entry command",
|
|
48
|
-
initialValue: defaults.smokeCommand,
|
|
49
|
-
}),
|
|
50
45
|
}, {
|
|
51
46
|
onCancel: () => {
|
|
52
47
|
p.cancel("Cancelled — nothing was written.");
|
|
@@ -57,7 +52,6 @@ async function interview(defaults) {
|
|
|
57
52
|
appUrl: answers.appUrl.trim() || defaults.appUrl,
|
|
58
53
|
devCommand: answers.devCommand.trim() === "" ? null : answers.devCommand.trim(),
|
|
59
54
|
e2eCommand: answers.e2eCommand.trim() || defaults.e2eCommand,
|
|
60
|
-
smokeCommand: answers.smokeCommand.trim() || defaults.smokeCommand,
|
|
61
55
|
};
|
|
62
56
|
}
|
|
63
57
|
function planBrowserTesting(parsed, detection, answers) {
|
|
@@ -70,11 +64,13 @@ function planBrowserTesting(parsed, detection, answers) {
|
|
|
70
64
|
if (detection.playwrightConfigFile) {
|
|
71
65
|
notes.push(`Existing ${detection.playwrightConfigFile} detected — keeping it; no config or baseline spec seeded.`);
|
|
72
66
|
}
|
|
73
|
-
const nextSteps = [
|
|
67
|
+
const nextSteps = [
|
|
68
|
+
`Run \`node scripts/setup.mjs\` — installs @playwright/test, ${BROWSER_DRIVER_PACKAGE} (the browser smoke's driver) and their browsers.`,
|
|
69
|
+
];
|
|
74
70
|
if (!answers.devCommand) {
|
|
75
71
|
nextSteps.push("Set the dev command: edit scripts/dev.mjs (DEV_COMMAND) and testing.devCommand in .launchrail.yml.");
|
|
76
72
|
}
|
|
77
|
-
nextSteps.push("Review the seeded files — they are yours: playwright config, tests/e2e
|
|
73
|
+
nextSteps.push("Review the seeded files — they are yours: playwright config, tests/e2e/baseline.spec.ts, scripts/.", "Verify: `node scripts/verify.mjs` runs the deterministic gate (unit + the e2e baseline).", "Browser smoke: after building user-facing behavior, the launch-browser-smoke skill drives the running app with agent-browser — a one-off check of the change, not a test suite (ADR-0034).");
|
|
78
74
|
return {
|
|
79
75
|
manifest,
|
|
80
76
|
testing: { ...answers },
|
|
@@ -107,7 +103,7 @@ function planRalph(parsed) {
|
|
|
107
103
|
"Produce tickets with explicit `Blocked by: #n` edges and the ready-for-agent label (launch-tickets, stage 9 of the workflow).",
|
|
108
104
|
"Start building: /launch-implement in Claude Code drives the ready tickets to verified merges (add a ticket number to build just one).",
|
|
109
105
|
"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
|
-
"
|
|
106
|
+
"Tune the repo for the loop: run /launch-loop-readiness in Claude Code — it measures the gates, sets testing.checkCommand (the fast per-land gate; without it the fast gate is the unit command), parallelizes the e2e specs, narrows CI triggers, creates the tracker labels, and adds hosted-session setup. `doctor` shows the same readiness lines.",
|
|
111
107
|
"Start with width 1 until a few tickets have landed cleanly, then widen.",
|
|
112
108
|
],
|
|
113
109
|
};
|