@wemuda/launchrail 1.6.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +38 -23
  2. package/assets/agents-docs/domain.md +59 -0
  3. package/assets/agents-docs/issue-tracker-github.md +51 -0
  4. package/assets/agents-docs/issue-tracker-gitlab.md +52 -0
  5. package/assets/agents-docs/issue-tracker-linear.md +52 -0
  6. package/assets/agents-docs/issue-tracker-local.md +45 -0
  7. package/assets/ralph.permission-guard.py +90 -0
  8. package/assets/ralph.workflow.js +43 -8
  9. package/assets/skills/NOTICE.md +41 -0
  10. package/assets/skills/launchrail/launch/SKILL.md +67 -0
  11. package/assets/skills/launchrail/launch/workflow.md +77 -0
  12. package/assets/skills/launchrail/launch-browser-smoke/SKILL.md +49 -0
  13. package/assets/skills/launchrail/launch-code-review/SKILL.md +89 -0
  14. package/assets/skills/launchrail/launch-design-validation/SKILL.md +44 -0
  15. package/assets/skills/launchrail/launch-discovery/SKILL.md +33 -0
  16. package/assets/skills/launchrail/launch-grill/CONTEXT-FORMAT.md +62 -0
  17. package/assets/skills/launchrail/launch-grill/SKILL.md +48 -0
  18. package/assets/skills/launchrail/launch-grill/domain-modeling.md +45 -0
  19. package/assets/skills/launchrail/launch-implement/SKILL.md +46 -0
  20. package/assets/skills/launchrail/launch-project-alignment/SKILL.md +48 -0
  21. package/assets/skills/launchrail/launch-ralph/SKILL.md +100 -0
  22. package/assets/skills/launchrail/launch-ralph-implement/SKILL.md +17 -0
  23. package/assets/skills/launchrail/launch-research/SKILL.md +16 -0
  24. package/assets/skills/launchrail/launch-resolving-merge-conflicts/SKILL.md +15 -0
  25. package/assets/skills/launchrail/launch-spec/SKILL.md +77 -0
  26. package/assets/skills/launchrail/launch-tickets/SKILL.md +107 -0
  27. package/assets/skills/launchrail/launch-vision-creation/SKILL.md +60 -0
  28. package/assets/skills/launchrail/launch-wayfinder/SKILL.md +130 -0
  29. package/dist/commands/add.js +21 -4
  30. package/dist/commands/add.js.map +1 -1
  31. package/dist/commands/doctor.js +42 -32
  32. package/dist/commands/doctor.js.map +1 -1
  33. package/dist/commands/init.d.ts +3 -7
  34. package/dist/commands/init.js +62 -85
  35. package/dist/commands/init.js.map +1 -1
  36. package/dist/commands/sync.js +11 -0
  37. package/dist/commands/sync.js.map +1 -1
  38. package/dist/index.js +0 -5
  39. package/dist/index.js.map +1 -1
  40. package/dist/lib/agentsDocs.d.ts +4 -0
  41. package/dist/lib/agentsDocs.js +32 -0
  42. package/dist/lib/agentsDocs.js.map +1 -0
  43. package/dist/lib/claudeSettings.d.ts +74 -11
  44. package/dist/lib/claudeSettings.js +185 -17
  45. package/dist/lib/claudeSettings.js.map +1 -1
  46. package/dist/lib/detect.d.ts +0 -2
  47. package/dist/lib/detect.js +0 -1
  48. package/dist/lib/detect.js.map +1 -1
  49. package/dist/lib/manifest.d.ts +14 -1
  50. package/dist/lib/manifest.js +18 -1
  51. package/dist/lib/manifest.js.map +1 -1
  52. package/dist/lib/migrations.js +202 -1
  53. package/dist/lib/migrations.js.map +1 -1
  54. package/dist/lib/project.js +9 -1
  55. package/dist/lib/project.js.map +1 -1
  56. package/dist/lib/ralph.d.ts +16 -5
  57. package/dist/lib/ralph.js +32 -9
  58. package/dist/lib/ralph.js.map +1 -1
  59. package/dist/lib/seeds.js +4 -2
  60. package/dist/lib/seeds.js.map +1 -1
  61. package/dist/lib/skills.d.ts +12 -0
  62. package/dist/lib/skills.js +57 -0
  63. package/dist/lib/skills.js.map +1 -0
  64. package/dist/lib/upstream.d.ts +6 -6
  65. package/dist/lib/upstream.js +1 -1
  66. package/dist/lib/upstream.js.map +1 -1
  67. package/package.json +1 -1
  68. package/dist/lib/claudeCli.d.ts +0 -51
  69. package/dist/lib/claudeCli.js +0 -71
  70. package/dist/lib/claudeCli.js.map +0 -1
@@ -1,16 +1,16 @@
1
1
  // Managed by Launchrail. Do not hand-edit — `launchrail sync` may replace this file.
2
- // Override policy per run via args instead, e.g. { width: 1, only: [9, 10] }.
2
+ // Override policy per run via args instead, e.g. { width: 1, only: [9, 10], max: 5 }.
3
3
  //
4
4
  // The Ralph loop as a deterministic workflow: the plan, the frontier bookkeeping,
5
5
  // and every intermediate report live in script variables — not in any context window —
6
6
  // so long or wide runs cannot compact away their own state. The watchable, checkpointed
7
- // variant of the same loop is the launchrail:ralph skill; the two share one policy block,
7
+ // variant of the same loop is the launch-ralph skill; the two share one policy block,
8
8
  // and a policy change belongs in both places (ADR-0005, field-revised by ADR-0010).
9
9
  export const meta = {
10
10
  name: 'ralph',
11
11
  description: 'Autonomous Ralph loop: implement ready tickets with fresh-context subagents, verification-gated',
12
12
  whenToUse:
13
- 'Run the Ralph implementation loop over the ticket backlog when the dependency graph is wide or the run is long. Scope a run via args: { only: [9, 10], width: 2 } or just [9, 10]. For a watchable, checkpointed run (or when something is already going wrong), use the launchrail:ralph skill instead.',
13
+ 'Run the Ralph implementation loop over the ticket backlog when the dependency graph is wide or the run is long. Scope a run via args: { only: [9, 10], width: 2 }, just [9, 10], or { max: 5 } to stop after 5 verified merges ("the next five" — the frontier picks which, in dependency order). Args must be JSON — resolve any natural-language scope to ticket numbers and a cap before launching. For a watchable, checkpointed run (or when something is already going wrong), use the launch-ralph skill instead.',
14
14
  phases: [
15
15
  { title: 'Preflight', detail: 'read project config, sync the base, run the verification gate' },
16
16
  { title: 'Graph', detail: 'list ready tickets and their blocking edges, verbatim' },
@@ -22,7 +22,7 @@ export const meta = {
22
22
  }
23
23
 
24
24
  // ---------------------------------------------------------------------------
25
- // Policy — the launchrail:ralph policy block, as code. Override via args.
25
+ // Policy — the launch-ralph policy block, as code. Override via args.
26
26
  // ---------------------------------------------------------------------------
27
27
 
28
28
  // args may arrive as an object ({ only, width, ... }), a bare array of ticket numbers,
@@ -46,6 +46,10 @@ const A = resolveArgs(args)
46
46
  const POLICY = {
47
47
  // Scope the run to specific ticket numbers ([] = the whole ready frontier).
48
48
  only: A.only ?? [],
49
+ // Stop after this many verified merges (0 = no cap). "The next five": the frontier
50
+ // decides which five, in dependency order. Batches never exceed the remainder, so a
51
+ // run has at most `max` merges and leaves the rest of the frontier ready, not parked.
52
+ max: A.max ?? 0,
49
53
  // Parallel implementers. Width also caps local build concurrency — several implementers
50
54
  // share one machine, and fanning out test runs buys backpressure, not speed. Use 1 until
51
55
  // a run has landed tickets cleanly on this project.
@@ -125,6 +129,12 @@ const GRAPH_SCHEMA = {
125
129
  },
126
130
  },
127
131
  },
132
+ notTickets: {
133
+ type: 'array',
134
+ items: { type: 'integer' },
135
+ description:
136
+ 'Issue numbers wearing ready-for-agent that are plainly not implementable tickets (a published spec, research notes, an epic) — a labeling error to surface, not work to dispatch.',
137
+ },
128
138
  },
129
139
  }
130
140
 
@@ -208,8 +218,8 @@ Steps, in order:
208
218
  2. Read the ticket and everything it links (spec sections, ADRs, journeys). Report status "already-done" if it is already closed.
209
219
  3. Label the ticket ralph:building so a lost session leaves a trace.
210
220
  4. Branch from a fresh sync of ${pre.base}: ralph/${ticket.number}-<short-slug>.
211
- 5. Implement by invoking the launchrail:ralph-implement skill — it owns the per-ticket contract: TDD, the verification gate, browser smoke for user-facing changes, self-review via /code-review, commit conventions.
212
- 6. Pre-PR sync: merge the latest ${pre.base} into your branch. Conflicts are ordinary work — resolve them with the launchrail:resolving-merge-conflicts skill and re-run the verification gate if anything changed.
221
+ 5. Implement by invoking the launch-ralph-implement skill — it owns the per-ticket contract: TDD, the verification gate, browser smoke for user-facing changes, self-review via /code-review, commit conventions.
222
+ 6. Pre-PR sync: merge the latest ${pre.base} into your branch. Conflicts are ordinary work — resolve them with the launch-resolving-merge-conflicts skill and re-run the verification gate if anything changed.
213
223
  7. Open a PR titled from the ticket, with "Closes #${ticket.number}" in the body. Never open a second PR if one already exists — adopt it. Opening against an up-to-date base means CI tests the state that will actually land.
214
224
  8. Wait for CI if the repository has it, spacing polls with the Monitor tool or a background sleep — never a foreground sleep, never a busy loop; treat ~20 minutes as the budget and report status "ci-timeout" beyond it. Fix what your branch broke and push. If a failure reproduces on ${pre.base} itself, report "ci-red" and stop — that is systemic, not this ticket's problem.
215
225
  9. Immediately before merging, re-sync with ${pre.base} once more (retry up to 3 times if the base keeps moving), then squash-merge. Squash-merge does not reliably fire "Closes" — read the issue back, close it explicitly if it is still open, and remove the ralph:building label. Never push to ${pre.base} directly; the PR is the only door.
@@ -232,9 +242,18 @@ Report merged: true only when (1) and (2) both hold. A PR description or comment
232
242
  const graphPrompt = (pre) => `List the open, ready tickets for a Ralph loop run. Change nothing on the tracker.
233
243
  Tracker access: ${pre.trackerAccess}
234
244
  Include every open ticket labeled ready-for-agent, excluding any labeled needs-info.
245
+ An open issue wearing ready-for-agent that is plainly not an implementable ticket — a published spec, research notes, an epic — is a labeling error: leave it out of tickets and report its number in notTickets instead. When in doubt, include it as a ticket.
235
246
  For each, report its number, its exact title, and its "Blocked by" line copied VERBATIM (the whole line, e.g. "**Blocked by:** #11, #9"), or "" when it has none. If the tracker records blocking through native relations instead of a body line, render those relations as one "Blocked by: #n, #m" line and nothing else.
236
247
  Do NOT interpret, resolve, or filter the edges — copy the characters and let the caller parse the #n. Getting a blocker wrong dispatches a ticket before its dependency lands.`
237
248
 
249
+ // A non-ticket wearing ready-for-agent (a published spec, research notes) is excluded from
250
+ // the frontier but never silently: the label is the bug, and the supervisor should fix it.
251
+ function warnNotTickets(graph) {
252
+ for (const n of graph?.notTickets ?? []) {
253
+ log(`#${n} wears ready-for-agent but is not an implementable ticket — excluded from the frontier; relabel it (e.g. spec)`)
254
+ }
255
+ }
256
+
238
257
  // Blocking edges are parsed here, deterministically, from the verbatim line — never by a
239
258
  // model. A single misread edge silently builds a ticket on a dependency that hasn't landed.
240
259
  function parseGraph(graph) {
@@ -368,10 +387,12 @@ log(
368
387
  (POLICY.only.length > 0
369
388
  ? `Scoped to ${POLICY.only.map((n) => `#${n}`).join(', ')}.`
370
389
  : 'No scope — building the whole ready frontier.') +
390
+ (POLICY.max > 0 ? ` Stopping after ${POLICY.max} verified merge(s).` : '') +
371
391
  ` Width ${POLICY.width}, ${POLICY.attempts} attempts per ticket.`,
372
392
  )
373
393
  let graph = await agent(graphPrompt(pre), { label: 'read-graph', phase: 'Graph', schema: GRAPH_SCHEMA, model: 'haiku', effort: 'low' })
374
394
  if (!graph) throw new Error('graph agent died — refusing to start')
395
+ warnNotTickets(graph)
375
396
  let tickets = parseGraph(graph)
376
397
  log(`${tickets.length} ready ticket(s) on the tracker`)
377
398
 
@@ -382,16 +403,28 @@ for (const t of tickets) {
382
403
  }
383
404
  }
384
405
 
406
+ const mergedCount = () => [...state.values()].filter((s) => s.status === 'merged').length
407
+
385
408
  let rounds = 0
409
+ let maxReached = false
386
410
  while (rounds < POLICY.maxRounds) {
387
411
  if (budget.total && budget.remaining() < POLICY.reserve) {
388
412
  log(`token budget at reserve (${Math.round(budget.remaining() / 1000)}k left) — stopping before a new round`)
389
413
  break
390
414
  }
415
+ // The cap counts verified merges only — a failed or deferred dispatch frees its slot
416
+ // for a different ticket next round. Capping the batch at the remainder means even a
417
+ // fully successful round cannot overshoot.
418
+ const capLeft = POLICY.max > 0 ? POLICY.max - mergedCount() : Infinity
419
+ if (capLeft <= 0) {
420
+ maxReached = true
421
+ log(`cap reached: ${POLICY.max} verified merge(s) — stopping; the rest of the frontier stays ready`)
422
+ break
423
+ }
391
424
  const ready = frontier(tickets, closedBefore)
392
425
  if (ready.length === 0) break
393
426
  rounds += 1
394
- const batch = ready.slice(0, POLICY.width)
427
+ const batch = ready.slice(0, Math.min(POLICY.width, capLeft))
395
428
  log(`round ${rounds}: dispatching ${batch.map((t) => `#${t.number}`).join(', ')} (${ready.length} unblocked)`)
396
429
  const results = await parallel(batch.map((t) => () => drive(pre, t)))
397
430
  const landed = results.filter((r) => r?.ok)
@@ -410,6 +443,7 @@ while (rounds < POLICY.maxRounds) {
410
443
  if (POLICY.refreshGraph && frontier(tickets, closedBefore).length > 0) {
411
444
  graph = await agent(graphPrompt(pre), { label: `read-graph:r${rounds}`, phase: 'Graph', schema: GRAPH_SCHEMA, model: 'haiku', effort: 'low' })
412
445
  if (graph) {
446
+ warnNotTickets(graph)
413
447
  const fresh = parseGraph(graph)
414
448
  for (const t of fresh) {
415
449
  if (!tickets.some((x) => x.number === t.number)) tickets.push(t)
@@ -454,7 +488,7 @@ const release = await agent(
454
488
  2. Run the verification gate: npx @wemuda/launchrail verify. Report the actual exit code.
455
489
  ${
456
490
  pre.browserTesting && merged.length > 0
457
- ? `3. The browser-testing module is enabled: 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 launchrail:browser-smoke skill. Report the bundle path. A journey you could not complete is a failure, never a pass.`
491
+ ? `3. The browser-testing module is enabled: 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.`
458
492
  : ''
459
493
  }
460
494
  verified means: the verification gate exited 0${pre.browserTesting && merged.length > 0 ? ' AND no smoke journey failed' : ''}.`,
@@ -464,6 +498,7 @@ verified means: the verification gate exited 0${pre.browserTesting && merged.len
464
498
  return {
465
499
  rounds,
466
500
  verified: release?.verified ?? false,
501
+ maxReached,
467
502
  release,
468
503
  merged: merged.map((s) => ({ ticket: s.ticket.number, title: s.ticket.title, pr: s.pr, mergeCommit: s.mergeCommit })),
469
504
  parked: parked.map((s) => ({ ticket: s.ticket.number, title: s.ticket.title, failures: s.failures })),
@@ -0,0 +1,41 @@
1
+ # Attribution
2
+
3
+ The skills in this directory are Launchrail's own — one complete, `launch-`
4
+ prefixed workflow (ADR-0020), managed by `launchrail sync`.
5
+
6
+ Several of them absorb methodology and contain text derived from
7
+ [Matt Pocock's skills](https://github.com/mattpocock/skills), used and adapted
8
+ under the MIT License reproduced below:
9
+
10
+ - `launch-research`, `launch-grill` (including its `domain-modeling.md` and
11
+ `CONTEXT-FORMAT.md`), `launch-wayfinder`, `launch-spec`, `launch-tickets`,
12
+ `launch-code-review`
13
+
14
+ The same applies to the issue-tracker and domain-doc files Launchrail seeds
15
+ into `docs/agents/`. Each derived file carries its own derivation note. If
16
+ Launchrail is useful to you, the inspiration credit belongs upstream — see the
17
+ Launchrail README's Credits section.
18
+
19
+ ---
20
+
21
+ MIT License
22
+
23
+ Copyright (c) 2026 Matt Pocock
24
+
25
+ Permission is hereby granted, free of charge, to any person obtaining a copy
26
+ of this software and associated documentation files (the "Software"), to deal
27
+ in the Software without restriction, including without limitation the rights
28
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
29
+ copies of the Software, and to permit persons to whom the Software is
30
+ furnished to do so, subject to the following conditions:
31
+
32
+ The above copyright notice and this permission notice shall be included in all
33
+ copies or substantial portions of the Software.
34
+
35
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
36
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
37
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
38
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
39
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
40
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
41
+ SOFTWARE.
@@ -0,0 +1,67 @@
1
+ ---
2
+ name: launch
3
+ description: The planning conductor and single entry point to the Launchrail loop. Detects how far a project has moved from idea toward release — setup, vision, visual exploration, discovery, grill, research, ADRs, spec, design validation, tickets — then runs or routes to the stage that owns the next step, and hands implementation to /launch-implement. Once the foundation exists it also sizes each new feature (large / semi / small) and routes the planning subset that size needs. Use to start or continue the workflow, ask what stage a project is at, size a new feature, or jump straight to a named stage.
4
+ ---
5
+
6
+ # Launch — the loop conductor
7
+
8
+ One command for the whole rail. You are the **conductor**, not a stage: find where the project sits, then run or hand off to the skill that owns the next step. Every stage has exactly one owner; [`workflow.md`](workflow.md) is the contract for who owns what and for the conductor rules — compose owners by name, gate on committed artifacts, prepare handoffs for user-typed stages, keep detection read-only. Follow those rules; this file only tells you how to route.
9
+
10
+ ## The stage map
11
+
12
+ Read `.launchrail.yml` (`mode`, `origin`, `modules`, `issueTracker`) first — it is the source of truth for configuration; `npx @wemuda/launchrail status` for what's installed and current.
13
+
14
+ | # | Stage | Owner (invoke / run) | Done when |
15
+ |---|---|---|---|
16
+ | 0 | Setup | `npx @wemuda/launchrail init` | Manifest + lockfile committed; `doctor` green (`docs/agents/` is seeded by init) |
17
+ | 1 | Vision | `launch-vision-creation` — via `launch-project-alignment` when `origin: existing` | `docs/vision.md` exists and is real (not the bare template) |
18
+ | 2 | Visual exploration | Claude Design | Exploration artifacts linked from `docs/vision.md` |
19
+ | 3 | Discovery | `launch-discovery` | Landscape map committed under `docs/research/` (`discovery-*.md`) |
20
+ | 4 | Complexity grill | `launch-grill` | Grill constraints committed under `docs/research/` |
21
+ | 5 | Technical research | `launch-research`, fed the grill constraints | Research notes committed under `docs/research/` |
22
+ | 6 | Architecture decisions | ADRs (`docs/adr/0000-template.md`) | `docs/adr/NNNN-*.md` beyond the template |
23
+ | 7 | MVP specification | `launch-wayfinder` / `launch-spec` † | A spec exists under `docs/specs/` |
24
+ | 8 | Design validation | `launch-design-validation` (fidelity chosen inside the skill) | The spec carries a `## Design validation` section (a recorded skip counts) |
25
+ | 9 | Tickets | `launch-tickets` † | Tracker has `ready-for-agent` tickets with `Blocked by: #n` edges |
26
+ | 10 | Implementation | `/launch-implement` † — drives the Ralph loop | The ready frontier is drained; PRs merged and verified |
27
+ | 11 | Verification | `npx @wemuda/launchrail verify` · `launch-browser-smoke` | The gate is green; smoke evidence where behavior is user-facing |
28
+ | 12 | Release | The project's release setup | The release is cut |
29
+
30
+ † 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.
31
+
32
+ `deep-research` = stages 3 → 4 → 5 as one arc: discovery widens the option space, the grill narrows it, research de-risks what survives. The workflow doc's stage notes carry the judgment calls for stages 3, 4, 8, and 10.
33
+
34
+ ## Sizing the next feature
35
+
36
+ Once the foundation exists (a real vision, ADRs beyond the template) and the user brings **one new feature**, the frontier question changes from "what stage is next" to "how much planning does this feature deserve." Size it — propose with your reasoning, let the user correct you; they see scope the artifacts don't show:
37
+
38
+ | Size | Looks like | Planning path |
39
+ |---|---|---|
40
+ | **Large** | A new subsystem or cross-cutting change; real unknowns; decisions worth an ADR | discovery *(new tech territory only)* → `launch-wayfinder` → grill → `launch-spec` → design validation → `launch-tickets` |
41
+ | **Semi** | Self-contained feature, some design surface, a handful of tickets | grill → `launch-spec` → design validation *(optional)* → `launch-tickets` |
42
+ | **Small** | Well-understood change, little or no design surface, one or few tickets | grill → `launch-tickets` |
43
+
44
+ Judgment calls: the grill here is feature-scoped (same `launch-grill`, narrower brief); discovery earns a place only when the feature opens genuinely new tech territory — a vendor category or storage engine the project hasn't used; design validation is for real UI surface; a genuine architecture decision gets an ADR before tickets. Between two sizes pick the smaller — it's cheaper to add a stage than to over-plan a small change. `mode` calibrates on top: `spike` may drop `launch-spec` and design validation (record the skip); `high-rigor` bumps one notch. Every size ends at `/launch-implement`.
45
+
46
+ ## Running it
47
+
48
+ 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.
49
+ 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 `mode` permits. `origin: existing` with no real vision → route to `launch-project-alignment`, not a blank vision.
50
+ 3. **Confirm the read.** Say where you think the project is and why — which artifacts you found and which you didn't. Ambiguous signals (template-only vision, several specs) are questions, not guesses.
51
+ 4. **Route.** Invoke the owner by 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.
52
+ 5. **Leave an explained map.** Current stage, the next one with a sentence on what it does and whether it's optional here, then the rest of the arc to the destination — and that any stage is reachable by keyword. A bare stage name reads as a turnstile; explain, don't gate.
53
+
54
+ ## Stage keywords
55
+
56
+ Case-insensitive direct jumps:
57
+
58
+ - `status` / `where` — report the detected stage and stop.
59
+ - `next` — detect the frontier and drive it (the default).
60
+ - `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.
61
+ - `feature` / `size` — size a described feature (recommend a path; route on request).
62
+
63
+ Unrecognized keyword → show this list and ask.
64
+
65
+ ## Mode calibration
66
+
67
+ `mode` calibrates rigor, not stage order: `spike` may skip stages 2–5 and 8 when the vision's non-goals record it (don't nag); `standard-mvp` skips nothing silently; `high-rigor` skips nothing, wants an ADR per stage-6 decision, and design validation covers error and edge states. When a stage looks skipped, check the vision's non-goals before deciding — and if you can't tell, ask.
@@ -0,0 +1,77 @@
1
+ # The Launchrail core workflow
2
+
3
+ How a project moves from idea to verified, released software through committed artifacts. The rail is one complete, self-contained skill set — every stage owner is a Launchrail `launch-*` skill, written to the rail's artifact contract ([ADR-0020](https://github.com/wemuda/launchrail/blob/master/docs/adr/0020-independent-skill-set.md); several absorb methodology from [Matt Pocock's skills](https://github.com/mattpocock/skills), credited in `NOTICE.md`). The stage table below is the contract for which skill owns which stage and what artifact it must leave behind, and the conductor rules further down are the contract for how the `launch` conductor (and any agent working the rail) behaves between stages.
4
+
5
+ ## Running it
6
+
7
+ Two commands cover the whole rail:
8
+
9
+ - **`/launch`** — plan. It detects which stage the project has reached from its committed artifacts and runs or routes to that stage's owner; it takes a stage name (`vision`, `discovery`, `design-validation`, …) to jump straight there, and it sizes each new feature once the foundation exists ([ADR-0009](https://github.com/wemuda/launchrail/blob/master/docs/adr/0009-launch-orchestrator-skill.md), [ADR-0018](https://github.com/wemuda/launchrail/blob/master/docs/adr/0018-implement-front-door.md)).
10
+ - **`/launch-implement`** — build. The single entry point for stage 10: it drives ready tickets to verified merges through the project's selected loop — the whole frontier, a spec's tickets, the next N ("max 5"), or one ticket at a time.
11
+
12
+ ## Prerequisites
13
+
14
+ - 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.
15
+
16
+ ## Stages
17
+
18
+ | # | Stage | Tool | Input | Committed artifact |
19
+ |---|---|---|---|---|
20
+ | 1 | Vision | Launchrail `vision-creation` skill | The idea, the user | `docs/vision.md` |
21
+ | 2 | Visual exploration | Claude Design | Vision | Exploration artifacts (linked from the vision) |
22
+ | 3 | Discovery research | Launchrail `discovery` skill (composes `launch-research`) | Vision + intended stack | Landscape/options map in `docs/research/` (`discovery-*.md`) |
23
+ | 4 | Complexity grill | `launch-grill` | Vision + exploration + discovery | Grill constraints in `docs/research/` |
24
+ | 5 | Technical research | `launch-research` | **Grill constraints** | Research notes in `docs/research/` |
25
+ | 6 | Architecture decisions | ADRs (seeded template) | Research | `docs/adr/NNNN-*.md` |
26
+ | 7 | MVP specification | `launch-wayfinder` / `launch-spec` † | Vision, ADRs, research | `docs/specs/` |
27
+ | 8 | Design validation | Launchrail `design-validation` skill | Spec (+ Claude Design at the top fidelity) | Revised spec with `## Design validation` section |
28
+ | 9 | Tickets | `launch-tickets` † | Validated spec | Tickets in the tracker: `ready-for-agent` label, `Blocked by: #n` edges |
29
+ | 10 | Implementation | `/launch-implement` † → the Ralph loop | Ready tickets | PRs merged and verified; the frontier drained |
30
+ | 11 | Verification | `npx @wemuda/launchrail verify` · Launchrail `browser-smoke` skill | Merged work | The gate green; smoke evidence where behavior is user-facing |
31
+ | 12 | Release | The project's release setup | Verified base | The release cut |
32
+
33
+ † **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.
34
+
35
+ Stage notes:
36
+
37
+ - **Stages 3 → 4 → 5 are one arc** (`deep-research`): discovery *diverges* — it maps the real option space for the vision's hard parts (all the auth vendors, not one) and never picks winners; the grill *converges* — it narrows that landscape into constraints; research de-risks what survives. Don't collapse discovery into the grill outside `spike` mode: a grill with no discovery narrows whatever stack was assumed upstream, the exact failure discovery exists to prevent ([ADR-0015](https://github.com/wemuda/launchrail/blob/master/docs/adr/0015-discovery-research-stage.md)).
38
+ - **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.
39
+ - **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.
40
+ - **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) gating every merge.
41
+
42
+ ## Sizing the work in the delivery loop
43
+
44
+ The stages above take a fresh project to its first release. After that, the delivery loop repeats once per feature, and `launch` sizes each feature so its planning depth matches the work ([ADR-0014](https://github.com/wemuda/launchrail/blob/master/docs/adr/0014-start-feature-conductor.md), folded into `launch` by [ADR-0018](https://github.com/wemuda/launchrail/blob/master/docs/adr/0018-implement-front-door.md)):
45
+
46
+ - **Large feature** — discovery when it opens new tech territory, `launch-wayfinder` to break it down, a grill, `launch-spec`, design validation, then `launch-tickets`.
47
+ - **Semi feature** — a grill, `launch-spec`, optionally design validation, then `launch-tickets`.
48
+ - **Small feature** — a grill straight to `launch-tickets`.
49
+
50
+ Every size ends the same way: `/launch-implement`, gated by `launchrail verify`. Sizing changes *how many* planning stages a feature needs, never *who owns* them.
51
+
52
+ ## Adopting an existing project
53
+
54
+ When `.launchrail.yml` records `origin: existing`, stage 1 is reached through the Launchrail `project-alignment` skill: it inventories what the codebase already has, infers a draft vision from the code, interviews only the gaps, and detects the existing design system as the baseline for stages 2 and 8, then hands to `vision-creation` to commit ([ADR-0013](https://github.com/wemuda/launchrail/blob/master/docs/adr/0013-existing-project-alignment.md)). Alignment is an on-ramp onto the same rail, not a second workflow.
55
+
56
+ ## Conductor rules
57
+
58
+ The contract for `launch`, `/launch-implement`, and any agent driving the rail. The conductors execute these rules; this document owns them.
59
+
60
+ - **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.
61
+ - **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.
62
+ - **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.
63
+ - **The grill feeds research.** Run the grill before technical research and hand research the grill's surviving constraints as its brief.
64
+ - **`ready-for-agent` marks tickets, never specs.** The implementation loop's frontier is every open issue wearing that label, and it cannot tell prose from work — a spec or research note published to the tracker takes a different label (e.g. `spec`), or the loop will dispatch the document as work. Relabel before anyone starts the loop.
65
+ - **Implementation is never started unprompted.** Stage 10 belongs to the user: conductors hand over `/launch-implement` and explain; they do not launch it.
66
+ - **Everything the workflow produces is project-owned.** Vision, research, ADRs, specs, tickets — Launchrail tooling never overwrites them.
67
+ - **Setup gaps are action, not conversation.** Known, additive fixes (commit untracked init output, run `init` when the manifest is missing, `sync` when loop materials are absent) get applied and reported; questions are saved for product artifacts, where intent is genuinely unknowable. Init owns installs — never improvise a dependency install from the web.
68
+
69
+ ## Stage-skipping by project mode
70
+
71
+ The manifest's `mode` calibrates rigor, not stage order:
72
+
73
+ - `spike` — stages 2–5 and 8 may be skipped deliberately; record the skip in the vision's non-goals.
74
+ - `standard-mvp` — the default path; skip nothing silently.
75
+ - `high-rigor` — no skips; ADRs for every stage-6 decision, and design validation covers error and edge states, not just happy paths.
76
+
77
+ When a stage looks skipped, check the vision's non-goals before deciding whether it's deliberate — and if you still can't tell, ask.
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: launch-browser-smoke
3
+ description: Drive the running app through its defined smoke journeys in a real browser and produce a Launchrail evidence bundle. Use when user-facing work needs verification beyond deterministic tests, when the user asks to smoke-test the app, or before declaring user-facing work done in a project with the browser-testing module enabled (.launchrail.yml modules.browser-testing).
4
+ ---
5
+
6
+ # Browser smoke testing
7
+
8
+ Drive the real application through its user journeys in a browser and record evidence. Agentic smoke testing supplements deterministic tests — it never replaces them, and it never substitutes assertion for evidence.
9
+
10
+ ## Preconditions
11
+
12
+ 1. `.launchrail.yml` has `modules.browser-testing: true`. If not, stop and suggest `npx @wemuda/launchrail add browser-testing`.
13
+ 2. Deterministic checks pass first: run `node scripts/verify.mjs`. If verify fails, fix that before smoke testing — smoke runs on top of a green build.
14
+ 3. The app is running. Start it with `node scripts/dev.mjs` (use `--background` in cloud or CI sessions; logs land in `.launchrail/state/dev.log`). In a fresh clone, run `node scripts/setup.mjs` first.
15
+
16
+ ## Run contract
17
+
18
+ 1. **Collect the journeys.** Read `docs/testing/smoke-journeys.md` (sections headed `## Journey:`) plus any journeys defined in the ticket or spec under verification. Each journey has a start point, steps, and verify checks.
19
+ 2. **Scaffold the evidence bundle.** Run `npx @wemuda/launchrail smoke` (add `--url <url>` for a preview environment). It confirms the app responds and creates `artifacts/verification/<run-id>/` containing `meta.json`, a `summary.md` skeleton, and `screenshots/` + `traces/` directories. If it reports the app unreachable, start the app — do not skip the journey.
20
+ 3. **Drive each journey in a real browser** — Playwright MCP, browser tools, or a Playwright script, whichever is available. The browser-testing module seeds a Playwright MCP server (`.mcp.json`); approve it once in Claude Code to drive the browser interactively, or fall back to a Playwright script in headless CI. Follow the steps as a user would: click, type, navigate. Try realistic variations and obvious edge cases, and watch the console and network panel as you go.
21
+ 4. **Capture evidence while testing, not afterwards:**
22
+ - Screenshots of each key state → `screenshots/`
23
+ - Console errors and warnings → `console.log`
24
+ - Failed or unexpected requests → `network-errors.json`
25
+ - Playwright traces where available → `traces/`
26
+ 5. **Apply the standard checks to every journey:**
27
+ - No uncaught console errors
28
+ - No failed API requests
29
+ - The success state is visible
30
+ - Data remains after refresh
31
+
32
+ ## When you find a real bug
33
+
34
+ 1. Record the precise reproduction in the evidence bundle.
35
+ 2. Add or update a deterministic test that fails on the bug.
36
+ 3. Fix the bug.
37
+ 4. Prove the deterministic test passes.
38
+ 5. Re-run the affected journey.
39
+ 6. Keep the trace or screenshot that shows the failure.
40
+
41
+ This turns exploratory findings into permanent regression coverage instead of forgotten discoveries.
42
+
43
+ ## Completing the run
44
+
45
+ - Fill in `summary.md` completely: journey outcomes, standard checks, evidence references, deviations, newly added tests, remaining blockers. Check only boxes you actually verified.
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.
@@ -0,0 +1,89 @@
1
+ ---
2
+ name: launch-code-review
3
+ description: Review the changes since a fixed point (commit, branch, tag, or merge-base) along two axes — Standards (does the code follow this repo's documented coding standards?) and Spec (does the code match what the originating ticket/spec asked for?). Runs both reviews in parallel sub-agents and reports them side by side. The self-review gate inside launch-ralph-implement; also for reviewing a branch, a PR, or work-in-progress changes on request.
4
+ ---
5
+
6
+ <!-- Contains text derived from Matt Pocock's skills (https://github.com/mattpocock/skills), MIT — see ../NOTICE.md -->
7
+
8
+ Two-axis review of the diff between `HEAD` and a fixed point the user supplies:
9
+
10
+ - **Standards** — does the code conform to this repo's documented coding standards?
11
+ - **Spec** — does the code faithfully implement the originating ticket / spec?
12
+
13
+ Both axes run as **parallel sub-agents** so they don't pollute each other's context, then this skill aggregates their findings.
14
+
15
+ The issue tracker configuration lives in `docs/agents/issue-tracker.md`, seeded by `launchrail init` from the manifest — `npx @wemuda/launchrail sync` re-seeds it if it's missing.
16
+
17
+ ## Process
18
+
19
+ ### 1. Pin the fixed point
20
+
21
+ Whatever the user said is the fixed point — a commit SHA, branch name, tag, `main`, `HEAD~5`, etc. Inside a Ralph dispatch the fixed point is the branch's base. If nothing determines one, ask for it.
22
+
23
+ Capture the diff command once: `git diff <fixed-point>...HEAD` (three-dot, so the comparison is against the merge-base). Also note the list of commits via `git log <fixed-point>..HEAD --oneline`.
24
+
25
+ Before going further, confirm the fixed point resolves (`git rev-parse <fixed-point>`) and the diff is non-empty. A bad ref or empty diff should fail here — not inside two parallel sub-agents.
26
+
27
+ ### 2. Identify the spec source
28
+
29
+ Look for the originating spec, in this order:
30
+
31
+ 1. Issue references in the commit messages (`#123`, `Closes #45`, etc.) — fetch via the workflow in `docs/agents/issue-tracker.md`. On the rail this is the normal case: the ticket being implemented, plus whatever it links.
32
+ 2. A path the user passed as an argument.
33
+ 3. A spec under `docs/specs/`, or a file under `.scratch/`, matching the branch name or feature.
34
+ 4. If nothing is found, ask the user where the spec is. If they say there isn't one, the **Spec** sub-agent will skip and report "no spec available".
35
+
36
+ ### 3. Identify the standards sources
37
+
38
+ Anything in the repo that documents how code should be written: `AGENTS.md` and `CLAUDE.md` (the agent contract carries the project's conventions), plus a `CODING_STANDARDS.md` or `CONTRIBUTING.md` where one exists.
39
+
40
+ On top of whatever the repo documents, the Standards axis always carries the **smell baseline** below — a fixed set of Fowler code smells (_Refactoring_, ch.3) that applies even when a repo documents nothing. Two rules bind it:
41
+
42
+ - **The repo overrides.** A documented repo standard always wins; where it endorses something the baseline would flag, suppress the smell.
43
+ - **Always a judgement call.** Each smell is a labelled heuristic ("possible Feature Envy"), never a hard violation — and, like any standard here, skip anything tooling already enforces.
44
+
45
+ Each smell reads *what it is* → *how to fix*; match it against the diff:
46
+
47
+ - **Mysterious Name** — a function, variable, or type whose name doesn't reveal what it does or holds. → rename it; if no honest name comes, the design's murky.
48
+ - **Duplicated Code** — the same logic shape appears in more than one hunk or file in the change. → extract the shared shape, call it from both.
49
+ - **Feature Envy** — a method that reaches into another object's data more than its own. → move the method onto the data it envies.
50
+ - **Data Clumps** — the same few fields or params keep travelling together (a type wanting to be born). → bundle them into one type, pass that.
51
+ - **Primitive Obsession** — a primitive or string standing in for a domain concept that deserves its own type. → give the concept its own small type.
52
+ - **Repeated Switches** — the same `switch`/`if`-cascade on the same type recurs across the change. → replace with polymorphism, or one map both sites share.
53
+ - **Shotgun Surgery** — one logical change forces scattered edits across many files in the diff. → gather what changes together into one module.
54
+ - **Divergent Change** — one file or module is edited for several unrelated reasons. → split so each module changes for one reason.
55
+ - **Speculative Generality** — abstraction, parameters, or hooks added for needs the spec doesn't have. → delete it; inline back until a real need shows.
56
+ - **Message Chains** — long `a.b().c().d()` navigation the caller shouldn't depend on. → hide the walk behind one method on the first object.
57
+ - **Middle Man** — a class or function that mostly just delegates onward. → cut it, call the real target direct.
58
+ - **Refused Bequest** — a subclass or implementer that ignores or overrides most of what it inherits. → drop the inheritance, use composition.
59
+
60
+ ### 4. Spawn both sub-agents in parallel
61
+
62
+ **Standards sub-agent prompt** — include:
63
+
64
+ - The full diff command and commit list.
65
+ - The list of standards-source files you found in step 3, **plus the smell baseline from step 3** pasted in full — the sub-agent has no other access to it.
66
+ - The brief: "Report — per file/hunk where relevant — (a) every place the diff violates a documented standard: cite the standard (file + the rule); and (b) any baseline smell you spot: name it and quote the hunk. Distinguish hard violations from judgement calls — documented-standard breaches can be hard, but baseline smells are always judgement calls, and a documented repo standard overrides the baseline. Skip anything tooling enforces. Under 400 words."
67
+
68
+ **Spec sub-agent prompt** — include:
69
+
70
+ - The diff command and commit list.
71
+ - The path or fetched contents of the spec.
72
+ - The brief: "Report: (a) requirements the spec asked for that are missing or partial; (b) behaviour in the diff that wasn't asked for (scope creep); (c) requirements that look implemented but where the implementation looks wrong. Quote the spec line for each finding. Under 400 words."
73
+
74
+ If the spec is missing, skip the Spec sub-agent and note this in the final report.
75
+
76
+ ### 5. Aggregate
77
+
78
+ Present the two reports under `## Standards` and `## Spec` headings, verbatim or lightly cleaned. Do **not** merge or rerank findings — the two axes are deliberately separate (see _Why two axes_).
79
+
80
+ End with a one-line summary: total findings per axis, and the worst issue _within each axis_ (if any). Don't pick a single winner across axes — that's the reranking the separation exists to prevent.
81
+
82
+ ## Why two axes
83
+
84
+ A change can pass one axis and fail the other:
85
+
86
+ - Code that follows every standard but implements the wrong thing → **Standards pass, Spec fail.**
87
+ - Code that does exactly what the issue asked but breaks the project's conventions → **Spec pass, Standards fail.**
88
+
89
+ Reporting them separately stops one axis from masking the other.
@@ -0,0 +1,44 @@
1
+ ---
2
+ name: launch-design-validation
3
+ description: Validate an approved spec visually before implementation — at a confirmed fidelity level (recorded skip, flow-diagram artifact, screen-mockup artifact, or Claude Design), feed the findings back into a revised spec, and produce a handoff note for ticket creation. Use when a spec in docs/specs/ is drafted and the user wants design validation, a visual review, or pre-implementation sign-off.
4
+ ---
5
+
6
+ # Design validation
7
+
8
+ Coordinate the loop **spec → visual pass at the right fidelity → revised spec → handoff**. The goal is to catch "specified but wrong on screen" before implementation starts: flows that read fine in prose but collapse when a user has to click through them.
9
+
10
+ ## The fidelity ladder
11
+
12
+ The stage runs at one of four levels, chosen per spec ([ADR-0016](https://github.com/wemuda/launchrail/blob/master/docs/adr/0016-design-validation-fidelity-ladder.md)):
13
+
14
+ | Level | What gets made | Made by |
15
+ |---|---|---|
16
+ | 1 · Recorded skip | Nothing driven; the `## Design validation` section records what was assessed and why | this skill |
17
+ | 2 · Flow diagrams | An artifact page of flow/state diagrams describing what is being made — entry points, steps, decision points, end states | this skill, in-session |
18
+ | 3 · Screen mockups | An artifact page showing the designs — mid-fidelity mockups of the key screens and the states the spec claims to handle (empty, loading, error) | this skill, in-session |
19
+ | 4 · Claude Design | High-fidelity designs of entire screens/pages | Claude Design — drive it, or hand off (see below) |
20
+
21
+ Every level answers the same question — does the specified behavior survive contact with a screen? — at increasing cost and resolution. Claude Design is reserved for level 4: full screens properly designed. The diagram and mockup artifacts of levels 2–3 are the session's own work.
22
+
23
+ ## Ground rules
24
+
25
+ - The spec and everything this skill writes are **project-owned** artifacts. Revise the spec in place; never fork a parallel copy that can drift.
26
+ - Validate flows, not pixels. Even at level 4, this stage answers "does the specified behavior survive contact with a screen?", not "is the visual style final?".
27
+ - Every design finding must land in exactly one place: a spec revision, an ADR (if it changes an architecture decision), or an explicitly recorded rejection. Findings that live only in chat are lost.
28
+ - **Evidence is linked, not committed.** Levels 2–4 link their artifact pages / design artifacts from the spec's `## Design validation` section — the same way stage 2's exploration artifacts are linked from the vision. The committed gate stays the spec section itself; because every finding lands in the spec or an ADR anyway, the gate never depends on the links surviving. If the session cannot publish a linkable page, say so and link the most durable render it can produce — never leave the evidence chat-only.
29
+ - Do not start implementation from this skill. The output is a validated spec and a handoff note — tickets come next.
30
+
31
+ ## Process
32
+
33
+ 1. **Locate the spec.** Find the spec under `docs/specs/` (ask if there are several). Read it plus `docs/vision.md` and any grill/research artifacts it references, so validation happens against the product's constraints rather than in a vacuum.
34
+ 2. **Extract the flows to validate.** From the spec, list the user-facing journeys it implies — entry point, steps, decision points, end state. Confirm the list with the user; three to six flows is the useful range for an MVP.
35
+ 3. **Choose the level — recommend, then confirm.** Read the spec's design surface and the manifest's `mode`, recommend one level with a one-line reason, and let the user confirm or override across all four. Mode is **advisory, never a gate**: `spike` leans toward a recorded skip, `high-rigor` leans toward mockups or Claude Design with error and edge states covered — but the user owns the call. Never pick silently.
36
+ 4. **Run the level.**
37
+ - **Recorded skip** — go straight to step 7 and write the section as a recorded skip: date, what was assessed, why nothing needed driving.
38
+ - **Flow diagrams** — build one artifact page of flow/state diagrams covering the confirmed flows, including the decision points and terminal states the spec claims.
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
+ - **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
+ 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.
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
+ 8. **Hand off.** Confirm with the user that the revised spec is approved, commit it (respect the project's commit conventions), and point them at ticket creation as the next stage. See [`workflow.md`](../launch/workflow.md) for the full stage order.
@@ -0,0 +1,33 @@
1
+ ---
2
+ name: launch-discovery
3
+ description: The divergent option-space scan that runs before the complexity grill. Given the vision and the intended stack, it maps the real landscape of libraries, frameworks, vendors, hosted services, and patterns available for the hard parts of the product — enumerating the alternatives with their trade-offs rather than locking onto the first choice — and commits a landscape/options map that becomes the grill's input. Use after the vision (and visual exploration) and before the grill, or when the user asks to explore the tech landscape, survey vendors/libraries, or do discovery research. It composes `launch-research` for depth on any single thread; it does not pick winners — the grill does that.
4
+ ---
5
+
6
+ # Discovery research — map the option space before you narrow it
7
+
8
+ The stage that keeps the grill honest. A complexity grill is a *convergent* tool: it prunes a design tree. But it can only prune the branches already on the tree — so when the stack is assumed upstream (an `EXECUTION.md`, a README, a founder's default), the grill narrows an assumption instead of the real option space, and the technical-research stage that follows only ever de-risks the first guess. Discovery is the **divergent** counterweight: before the grill narrows anything, widen the field. For each hard part of the product, surface the actual alternatives that exist so the grill has real options to choose between.
9
+
10
+ Diverge here; converge in the grill; de-risk in technical research. This stage owns the *diverge*.
11
+
12
+ ## Ground rules
13
+
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
+ - **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 invoke `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
+ - **Everything here is project-owned.** The landscape map is committed to the project under `docs/research/`; Launchrail tooling never overwrites it.
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
+
20
+ ## Process
21
+
22
+ 1. **Read the inputs.** `docs/vision.md` and the intended stack (from the vision, `.launchrail.yml`, an `EXECUTION.md`/README, or by asking). Note the existing design system if one was recorded during alignment — it constrains front-end options.
23
+ 2. **Carve the product into areas of genuine choice.** Not everything needs discovery — most of a stack is settled or obvious. Find the handful of areas where the option space is real *and* the decision is load-bearing: the parts a grill would otherwise narrow blindly. They usually cluster around auth/identity, data storage and access, background/async work, third-party integrations, and whatever the vision's core mechanic demands (session replay, real-time transport, payments, …). Confirm the shortlist with the user — three to six areas is the useful range; don't manufacture choice where there is none.
24
+ 3. **For each area, enumerate the real contenders.** List the actual options that fit this stack — libraries, frameworks, hosted services, vendors, and the roll-your-own baseline. For each: what it is, what it buys you, what it costs (integration effort, lock-in, license, operational burden), and where it breaks down for *this* vision. Include the boring and the build-it-yourself options; a landscape that lists only the trendy pick is not a landscape.
25
+ 4. **Go deep where it's load-bearing.** For the areas where the choice most shapes the architecture, drive `launch-research` on the specific threads — verify real capabilities against the vision's needs, maintenance and community health, license, and concrete integration cost on this stack. Where research agents aren't available in the session, say so and fall back to a clearly-marked best-effort survey — do not silently skip the depth pass.
26
+ 5. **Write the landscape map.** Commit one doc per area (or one grouped doc) under `docs/research/`, named `discovery-<area>.md`. Each area records: the contenders with their trade-offs, what's verified vs. assumed, any options ruled out with the reason, and — most importantly — the **questions this hands to the grill**: the decisions now teed up with real options behind them.
27
+ 6. **Hand to the grill.** This stage does not choose. Route to the complexity grill (`launch-grill`, stage 4), which takes the landscape as input and narrows it into surviving constraints. Tell the user what you surveyed, where the docs are, that the grill is next, and that they can jump straight there.
28
+
29
+ ## What this stage is not
30
+
31
+ - **Not the grill.** It opens options; it doesn't close them. If you find yourself arguing for one choice, stop and hand that argument to the grill.
32
+ - **Not technical research.** Technical research (stage 5) runs *after* the grill and de-risks the decisions it made. Discovery runs *before* the grill and widens the decisions it will make. Same research skill, opposite direction — one diverges, one converges.
33
+ - **Not a stack rewrite.** Options that can't fit the intended stack are noted and set aside, not campaigned for. If discovery surfaces that the intended stack itself is wrong for the vision, that's a finding for the grill and possibly an ADR — raise it, don't act on it here.