@wemuda/launchrail 1.15.1 → 1.17.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 +4 -2
- package/assets/agents-docs/domain.md +1 -1
- package/assets/skills/launchrail/launch/SKILL.md +1 -1
- package/assets/skills/launchrail/launch/workflow.md +1 -1
- package/assets/skills/launchrail/launch-browser-smoke/SKILL.md +18 -11
- package/assets/skills/launchrail/launch-browser-smoke/composed-stack.md +46 -0
- package/assets/skills/launchrail/launch-grill/domain-modeling.md +2 -2
- package/assets/skills/launchrail/launch-loop-readiness/SKILL.md +1 -0
- package/dist/commands/add.js +3 -3
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/adr.d.ts +18 -0
- package/dist/commands/adr.js +35 -0
- package/dist/commands/adr.js.map +1 -0
- package/dist/commands/dev.d.ts +35 -0
- package/dist/commands/dev.js +158 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/doctor.js +38 -16
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.js +3 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/verify.js +7 -0
- package/dist/commands/verify.js.map +1 -1
- package/dist/index.js +36 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/adr.d.ts +46 -8
- package/dist/lib/adr.js +209 -37
- package/dist/lib/adr.js.map +1 -1
- package/dist/lib/browser-testing.d.ts +2 -3
- package/dist/lib/browser-testing.js +9 -59
- package/dist/lib/browser-testing.js.map +1 -1
- package/dist/lib/manifest.d.ts +14 -0
- package/dist/lib/manifest.js +29 -1
- package/dist/lib/manifest.js.map +1 -1
- package/dist/lib/seeds.js +7 -6
- package/dist/lib/seeds.js.map +1 -1
- package/dist/lib/stack.d.ts +77 -0
- package/dist/lib/stack.js +210 -0
- package/dist/lib/stack.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -60,7 +60,7 @@ 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 the running app in a real browser to see a just-built change working — one-off, from the shell with `agent-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` against a stack `launchrail dev` started, 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), [ADR-0036](https://github.com/wemuda/launchrail/blob/master/docs/adr/0036-cli-owned-stack-start.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
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
|
|
@@ -74,7 +74,9 @@ npx @wemuda/launchrail sync # apply managed updates + run migra
|
|
|
74
74
|
npx @wemuda/launchrail add browser-testing # enable a module
|
|
75
75
|
npx @wemuda/launchrail doctor # repository and environment checks
|
|
76
76
|
npx @wemuda/launchrail verify # deterministic verification gate
|
|
77
|
+
npx @wemuda/launchrail dev --background # start the smokeable stack from the manifest; --check proves the contract
|
|
77
78
|
npx @wemuda/launchrail eject <module|file> # opt out of management (vendor mode: --all)
|
|
79
|
+
npx @wemuda/launchrail adr index # regenerate the ADR registry's index table from the records (--check for CI)
|
|
78
80
|
```
|
|
79
81
|
|
|
80
82
|
Initialized projects carry two files: `.launchrail.yml` (configuration) and `.launchrail-lock.json` (versions, checksums, applied migrations; committed to the repo). Full walkthrough: [docs/getting-started.md](https://github.com/wemuda/launchrail/blob/master/docs/getting-started.md). Committed, unedited example of what `init` produces: [examples/hello-launchrail](https://github.com/wemuda/launchrail/tree/master/examples/hello-launchrail).
|
|
@@ -147,7 +149,7 @@ The toolchain is stable and versioned. The full surface — `init`/`doctor`, the
|
|
|
147
149
|
See [CONTRIBUTING.md](https://github.com/wemuda/launchrail/blob/master/CONTRIBUTING.md). The short version:
|
|
148
150
|
|
|
149
151
|
- Commits follow [Conventional Commits](https://www.conventionalcommits.org/) (`type(scope): summary`); see [ADR-0002](https://github.com/wemuda/launchrail/blob/master/docs/adr/0002-conventional-commits.md). Releases and the changelog are generated from them ([docs/releasing.md](https://github.com/wemuda/launchrail/blob/master/docs/releasing.md)).
|
|
150
|
-
- Meaningful decisions are recorded as ADRs in [docs/adr/](https://github.com/wemuda/launchrail/tree/master/docs/adr/); the registry index [docs/adr/README.md](https://github.com/wemuda/launchrail/blob/master/docs/adr/README.md) says which are live.
|
|
152
|
+
- Meaningful decisions are recorded as ADRs in [docs/adr/](https://github.com/wemuda/launchrail/tree/master/docs/adr/), named by decision date and slug; the registry index [docs/adr/README.md](https://github.com/wemuda/launchrail/blob/master/docs/adr/README.md) says which are live, and `launchrail adr index` regenerates it.
|
|
151
153
|
- The agent operating contract lives in [AGENTS.md](https://github.com/wemuda/launchrail/blob/master/AGENTS.md).
|
|
152
154
|
- Security issues go through [SECURITY.md](https://github.com/wemuda/launchrail/blob/master/SECURITY.md), not public issues.
|
|
153
155
|
|
|
@@ -44,7 +44,7 @@ Multi-context repo (presence of `CONTEXT-MAP.md` at the root):
|
|
|
44
44
|
└── docs/adr/
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
ADRs use the project's own format — copy `docs/adr/0000-template.md
|
|
47
|
+
ADRs use the project's own format — copy `docs/adr/0000-template.md` to `YYYY-MM-DD-short-slug.md` (the decision date, then a slug unique in the directory; no sequence number to claim), declare in its `## Status` what it amends or supersedes, and regenerate the registry index (`launchrail adr index`, writing `docs/adr/README.md`) in the same commit.
|
|
48
48
|
|
|
49
49
|
## Use the glossary's vocabulary
|
|
50
50
|
|
|
@@ -21,7 +21,7 @@ Read `.launchrail.yml` (`origin`, `modules`, `issueTracker`) first — it is the
|
|
|
21
21
|
| 3 | Discovery | `launch-discovery` | Landscape map committed under `docs/research/` (`discovery-*.md`) |
|
|
22
22
|
| 4 | Complexity grill | `launch-grill` | Grill constraints committed under `docs/research/` |
|
|
23
23
|
| 5 | Technical research | `launch-research`, fed the grill constraints | Research notes committed under `docs/research/` |
|
|
24
|
-
| 6 | Architecture decisions | ADRs (`docs/adr/0000-template.md`) | `docs/adr/
|
|
24
|
+
| 6 | Architecture decisions | ADRs (`docs/adr/0000-template.md`) | `docs/adr/YYYY-MM-DD-*.md` beyond the template |
|
|
25
25
|
| 7 | MVP specification | `launch-wayfinder` / `launch-spec` † | A spec exists — a `spec`-labeled issue on the tracker, or a `docs/specs/` file in local mode (read `docs/agents/issue-tracker.md`) |
|
|
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 |
|
|
@@ -62,7 +62,7 @@ A planning session (a grill, a wayfinder ticket, an interview) closes with the b
|
|
|
62
62
|
| 3 | Discovery research | Launchrail `discovery` skill (composes `launch-research`) | Vision + intended stack | Landscape/options map in `docs/research/` (`discovery-*.md`) |
|
|
63
63
|
| 4 | Complexity grill | `launch-grill` | Vision + exploration + discovery | Grill constraints in `docs/research/` |
|
|
64
64
|
| 5 | Technical research | `launch-research` | **Grill constraints** | Research notes in `docs/research/` |
|
|
65
|
-
| 6 | Architecture decisions | ADRs (seeded template) | Research | `docs/adr/
|
|
65
|
+
| 6 | Architecture decisions | ADRs (seeded template) | Research | `docs/adr/YYYY-MM-DD-*.md` |
|
|
66
66
|
| 7 | MVP specification | `launch-wayfinder` / `launch-spec` † | Vision, ADRs, research | A `spec`-labeled issue on the tracker (or `docs/specs/` in local mode) ‡ |
|
|
67
67
|
| 8 | Design validation | Launchrail `design-validation` skill | Spec (+ Claude Design at the top fidelity) | Revised spec with `## Design validation` section |
|
|
68
68
|
| 9 | Tickets | `launch-tickets` † | Validated spec | Tickets in the tracker: `ready-for-agent` label, `Blocked by: #n` edges |
|
|
@@ -7,23 +7,30 @@ description: Drive the running app in a real browser to see a just-built change
|
|
|
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
|
+
The stack you drive starts through the CLI, never through a hand-adapted script ([ADR-0036](https://github.com/wemuda/launchrail/blob/master/docs/adr/0036-cli-owned-stack-start.md)): `launchrail dev` owns the start command, the readiness wait, the state files and the driver's browser, so what this skill relies on is the same in every project.
|
|
11
|
+
|
|
12
|
+
## Step zero — a fresh clone has nothing installed
|
|
13
|
+
|
|
14
|
+
A hosted session (`CLAUDE_CODE_REMOTE=true`) is always a fresh clone, and a missing `node_modules` fails every later step with a misleading error. Run `node scripts/setup.mjs` first, unconditionally, in any hosted session and whenever `node_modules` is missing. It installs dependencies, Playwright's Chromium, and `agent-browser`.
|
|
15
|
+
|
|
10
16
|
## Preconditions
|
|
11
17
|
|
|
12
18
|
1. `.launchrail.yml` has `modules.browser-testing: true`. If not, stop and suggest `npx @wemuda/launchrail add browser-testing`.
|
|
13
|
-
2. The
|
|
14
|
-
3.
|
|
15
|
-
4.
|
|
19
|
+
2. **The gate, proportionate.** If `testing.checkCommand` is set, run `npx @wemuda/launchrail verify --fast` and fix red before smoking. If it is not set, do **not** run the full suite as a stand-in; say in your handoff that no fast gate is configured and the smoke ran without one (`launch-loop-readiness` sets it). Inside a Ralph dispatch the fast gate already ran before this step.
|
|
20
|
+
3. **Start the stack from the manifest:** `npx @wemuda/launchrail dev --background` (add `--port <n>` with a port nobody else uses when other builders share the machine). It runs `smoke.start`, else `testing.devCommand`, waits until every origin answers, and writes `.launchrail/state/stack.json` (origins, pid, log — plus whatever a composed start command adds: keys, fixture ids, a mailbox path), `dev.url`, `dev.pid`, and `browser.env`. Read your URLs from `stack.json`; never assume `testing.appUrl`.
|
|
21
|
+
4. **If the stack cannot start from the manifest, the smoke is blocked — do not rebuild the stack by hand inside a ticket.** Frontends that come up without their backend, a start command that needs Docker, a page that says "not configured": these mean the project has no `smoke.start` for its composed stack. Report the smoke as blocked with the exact gap, and point at [composed-stack.md](composed-stack.md) — the fix is a start command plus a manifest entry, proven once with `launchrail dev --check`, not fifteen tool calls of archaeology in every smoke.
|
|
22
|
+
5. **The driver.** `set -a; . .launchrail/state/browser.env; set +a` before the first `agent-browser` command: it points the driver at Playwright's Chromium and, in a root container, turns the sandbox off. Then `npx agent-browser --version` must answer. Sharp edge: the env vars are the reliable form — `--executable-path` is ignored once a daemon is running and only warns, so a first `open` can look fine and the next `snapshot` fail with "Chrome not found". Change the browser only after `npx agent-browser close`. If no Chromium resolves at all, `npx agent-browser install` fetches its own; if the driver still cannot run, use the fallback at the end.
|
|
16
23
|
|
|
17
24
|
## The run
|
|
18
25
|
|
|
19
26
|
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
27
|
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
|
|
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.
|
|
28
|
+
- `npx agent-browser open <url>` — start on the origin the change lives on, from `stack.json`.
|
|
29
|
+
- `npx agent-browser snapshot -i` — the interactive elements with refs (`@e1`, `@e2`, …). **Refs die with navigation:** re-snapshot after every `open`, reload, or route change before clicking anything.
|
|
30
|
+
- `npx agent-browser click @e3`, `fill @e5 "text"`, `type`, `press Enter` — act as a user would. Prefer refs, or role-based finds, over text finds: a text find for a word that appears in a menu can open the menu instead of the control you meant.
|
|
31
|
+
- `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. **Success toasts auto-dismiss:** a `wait --text` on one can time out on a success that did happen, so confirm the outcome through `network requests` (the request and its status) or the resulting state, not the toast alone.
|
|
25
32
|
- `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.
|
|
33
|
+
- `npx agent-browser errors`, `console`, `network requests` — after each step, not only at the end. `errors` is uncaught exceptions only; `console` carries the page's own error logs.
|
|
27
34
|
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
35
|
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
36
|
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.
|
|
@@ -36,10 +43,10 @@ A browser smoke is you driving the real stack in a real browser to check that wh
|
|
|
36
43
|
|
|
37
44
|
## Done
|
|
38
45
|
|
|
39
|
-
- `npx agent-browser close`,
|
|
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.
|
|
46
|
+
- `npx agent-browser close`, then `npx @wemuda/launchrail dev --stop`.
|
|
47
|
+
- 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. Everything you wrote lives under `.launchrail/state/`, which ignores itself in git.
|
|
41
48
|
- A smoke you could not drive is a failure, not a pass. Never report one you did not run.
|
|
42
49
|
|
|
43
50
|
## Fallback — no driver
|
|
44
51
|
|
|
45
|
-
If `agent-browser` cannot
|
|
52
|
+
If `agent-browser` cannot run here even after `browser.env` and `install`, write a throwaway `playwright-core` script under `.launchrail/state/` 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.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Starting a composed stack for the browser smoke
|
|
2
|
+
|
|
3
|
+
`launchrail dev` needs one command that brings up everything the smoke drives, and a list of the origins that must answer. For a single-process app that is `testing.devCommand` and `testing.appUrl`, and nothing else is needed. This page is for the other kind: a customer page running an SDK, an API, a dashboard on a third origin, a worker, fixtures — where "start the dev server" starts five frontends and no backend, and the backend's own start needs Docker that a hosted session does not have.
|
|
4
|
+
|
|
5
|
+
## The contract
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
# .launchrail.yml
|
|
9
|
+
smoke:
|
|
10
|
+
start: node scripts/smoke-stack.mjs # boots the whole smokeable stack, in-process where it can
|
|
11
|
+
origins: # every one must answer HTTP before the stack is "ready"
|
|
12
|
+
dashboard: http://localhost:5173
|
|
13
|
+
demo: http://localhost:4173
|
|
14
|
+
api: http://localhost:3001/health
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`launchrail dev --background` runs `start`, polls the origins, and writes `.launchrail/state/stack.json`. The start command **merges** anything the smoke will need into that same file — read it, add your keys, write it back; never replace it, the CLI merges too:
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"origins": { "dashboard": "http://localhost:5173", "demo": "http://localhost:4173" },
|
|
22
|
+
"pid": 41337,
|
|
23
|
+
"fixtures": { "orgId": "org_test", "projectId": "prj_test", "publishableKey": "pk_test_…" },
|
|
24
|
+
"mailbox": ".launchrail/state/mail/"
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`launchrail dev --check` proves the contract once — start, wait, assert the files, tear down — at adoption and whenever the stack changes. Nothing in a smoke should discover the stack; the smoke reads `stack.json` and drives.
|
|
29
|
+
|
|
30
|
+
## The pattern that works without Docker
|
|
31
|
+
|
|
32
|
+
Every platform arrives at the same shape once it needs to run in a fresh container:
|
|
33
|
+
|
|
34
|
+
1. **Boot the real backend in-process** against an in-process database (Postgres-in-WASM, SQLite, an embedded engine) — the real app module, not a mock server. Migrate and seed on start.
|
|
35
|
+
2. **Stub only the outbound seams:** mail to a captured sender, object storage to memory, queues to a synchronous stub, third-party APIs to recorded responses. Everything the user's click touches stays real.
|
|
36
|
+
3. **Seed fixtures directly**, through the backend's own services or repository layer, not through the UI: a member, an org, a project, a publishable key, an allowlisted origin. Write their ids and keys into `stack.json`.
|
|
37
|
+
4. **Run the real frontend dev servers** on their real origins, so CORS, cookies across ports, and credentialed requests are exercised for real. Point them at the in-process API through their normal env vars.
|
|
38
|
+
5. **Solve auth for the driver.** Every product has one of these. Magic-link sign-in: the captured mail sender writes each message to `mailbox`, and the smoke reads the link from the newest file and opens it. Password or session sign-in: seed the credential and put it in `fixtures`. Never bypass auth with a test-only backdoor in the app — the smoke should sign in the way a user does.
|
|
39
|
+
6. **Write the customer-facing page** the SDK runs on as a small static host (a demo page) that reads the publishable key from `stack.json` or an env var, so it comes up configured, not "not configured".
|
|
40
|
+
7. **Exit cleanly on SIGTERM** so `launchrail dev --stop` tears everything down: one process group, child servers closed in a handler.
|
|
41
|
+
|
|
42
|
+
A project that already has such a harness for its own full-stack tests is one script away: wrap the harness in `scripts/smoke-stack.mjs`, keep it running instead of exiting after a test, and merge the URLs and fixtures into `stack.json`.
|
|
43
|
+
|
|
44
|
+
## What the smoke then does
|
|
45
|
+
|
|
46
|
+
`set -a; . .launchrail/state/browser.env; set +a`, read `stack.json`, `agent-browser open` the origin the ticket touches, sign in via the `mailbox` or `fixtures`, and drive the change. Nothing here is written back to the repository; `.launchrail/state/` ignores itself.
|
|
@@ -42,6 +42,6 @@ Only offer to create an ADR when all three are true:
|
|
|
42
42
|
2. **Surprising without context** — a future reader will wonder "why did they do it this way?"
|
|
43
43
|
3. **The result of a real trade-off** — there were genuine alternatives and you picked one for specific reasons
|
|
44
44
|
|
|
45
|
-
If any of the three is missing, skip the ADR — an implementation choice that fails the bar lives in the spec or the ticket, not `docs/adr/`. And when the decision refines one an existing ADR already owns, amend that ADR
|
|
45
|
+
If any of the three is missing, skip the ADR — an implementation choice that fails the bar lives in the spec or the ticket, not `docs/adr/`. And when the decision refines one an existing ADR already owns, amend that ADR — a new record that declares `amends` it in its `## Status`, or a revision of the record itself — instead of minting an unrelated sibling; a corpus of revisions reads worse than a decision with a history.
|
|
46
46
|
|
|
47
|
-
ADRs use the **project's own format**: copy `docs/adr/0000-template.md` (seeded by `launchrail init`)
|
|
47
|
+
ADRs use the **project's own format**: copy `docs/adr/0000-template.md` (seeded by `launchrail init`) to `YYYY-MM-DD-short-slug.md` — the decision date, then a slug unique in `docs/adr/`; there is no number to claim, so parallel sessions never collide — and regenerate the registry index with `launchrail adr index` **in the same commit** (its table is generated from the records; never hand-edit the rows). A project whose records still follow an older `NNNN-` scheme keeps those names; only new records take dates. One format per project; do not introduce a second.
|
|
@@ -26,6 +26,7 @@ It is advice, never a gate: `/launch-implement` runs whether or not this skill e
|
|
|
26
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
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
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
|
+
8. With the browser-testing module on: `npx @wemuda/launchrail dev --check` — starts the smokeable stack from the manifest, waits for every origin, asserts the state files, tears down. A failure here is a readiness finding: the project needs `testing.devCommand`, or `smoke.start` plus `smoke.origins` for a composed stack (`.claude/skills/launch-browser-smoke/composed-stack.md`) — fix it in this pass, so no smoke ever discovers the stack by hand.
|
|
29
30
|
|
|
30
31
|
## Step 2 — Measure
|
|
31
32
|
|
package/dist/commands/add.js
CHANGED
|
@@ -65,12 +65,12 @@ function planBrowserTesting(parsed, detection, answers) {
|
|
|
65
65
|
notes.push(`Existing ${detection.playwrightConfigFile} detected — keeping it; no config or baseline spec seeded.`);
|
|
66
66
|
}
|
|
67
67
|
const nextSteps = [
|
|
68
|
-
`Run \`node scripts/setup.mjs\` — installs @playwright/test, ${BROWSER_DRIVER_PACKAGE} (the browser smoke's driver
|
|
68
|
+
`Run \`node scripts/setup.mjs\` — installs @playwright/test, its Chromium, and ${BROWSER_DRIVER_PACKAGE} (the browser smoke's driver, which reuses that Chromium).`,
|
|
69
69
|
];
|
|
70
70
|
if (!answers.devCommand) {
|
|
71
|
-
nextSteps.push("Set the
|
|
71
|
+
nextSteps.push("Set the start command: testing.devCommand in .launchrail.yml — or, for a composed stack (several origins, an in-process backend, fixtures), smoke.start plus smoke.origins; see .claude/skills/launch-browser-smoke/composed-stack.md.");
|
|
72
72
|
}
|
|
73
|
-
nextSteps.push("Review the seeded files — they are yours: playwright config, tests/e2e/baseline.spec.ts, scripts
|
|
73
|
+
nextSteps.push("Prove the start contract: `npx @wemuda/launchrail dev --check` starts the stack, waits for every origin, asserts the state files, and tears down. Do this now, not inside someone's smoke.", "Review the seeded files — they are yours: playwright config, tests/e2e/baseline.spec.ts, scripts/ (dev/verify/doctor delegate to the CLI).", "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).");
|
|
74
74
|
return {
|
|
75
75
|
manifest,
|
|
76
76
|
testing: { ...answers },
|
package/dist/commands/add.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface AdrIndexOptions {
|
|
2
|
+
cwd: string;
|
|
3
|
+
/** Report whether the index is current without writing; exit 1 when it is not. */
|
|
4
|
+
check: boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface AdrIndexOutcome {
|
|
7
|
+
code: number;
|
|
8
|
+
/** "current" | "updated" | "stale" (check mode) | "missing" (no registry / no index section). */
|
|
9
|
+
result: "current" | "updated" | "stale" | "missing";
|
|
10
|
+
records: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* `launchrail adr index` — regenerate the registry's index table from the
|
|
14
|
+
* records on disk. The registry is project-owned; only the rows between the
|
|
15
|
+
* markers are touched, and only here (never by sync), so the project keeps
|
|
16
|
+
* every other line and parallel branches merge by re-running the command.
|
|
17
|
+
*/
|
|
18
|
+
export declare function runAdrIndex(options: AdrIndexOptions): AdrIndexOutcome;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { ADR_REGISTRY_PATH, scanAdrs, withRegeneratedIndex } from "../lib/adr.js";
|
|
4
|
+
/**
|
|
5
|
+
* `launchrail adr index` — regenerate the registry's index table from the
|
|
6
|
+
* records on disk. The registry is project-owned; only the rows between the
|
|
7
|
+
* markers are touched, and only here (never by sync), so the project keeps
|
|
8
|
+
* every other line and parallel branches merge by re-running the command.
|
|
9
|
+
*/
|
|
10
|
+
export function runAdrIndex(options) {
|
|
11
|
+
const registryPath = join(options.cwd, ADR_REGISTRY_PATH);
|
|
12
|
+
const entries = scanAdrs(options.cwd);
|
|
13
|
+
if (!existsSync(registryPath)) {
|
|
14
|
+
console.error(`launchrail: ${ADR_REGISTRY_PATH} not found — run \`launchrail sync\` to seed the registry first`);
|
|
15
|
+
return { code: 1, result: "missing", records: entries.length };
|
|
16
|
+
}
|
|
17
|
+
const source = readFileSync(registryPath, "utf8");
|
|
18
|
+
const next = withRegeneratedIndex(source, entries);
|
|
19
|
+
if (next === null) {
|
|
20
|
+
console.error(`launchrail: ${ADR_REGISTRY_PATH} has no index to regenerate — add a \`## Index\` heading with a table (or the adr-index markers) and re-run`);
|
|
21
|
+
return { code: 1, result: "missing", records: entries.length };
|
|
22
|
+
}
|
|
23
|
+
if (next === source) {
|
|
24
|
+
console.log(`adr index: current (${entries.length} record(s))`);
|
|
25
|
+
return { code: 0, result: "current", records: entries.length };
|
|
26
|
+
}
|
|
27
|
+
if (options.check) {
|
|
28
|
+
console.error(`adr index: out of date — run \`launchrail adr index\` and commit ${ADR_REGISTRY_PATH}`);
|
|
29
|
+
return { code: 1, result: "stale", records: entries.length };
|
|
30
|
+
}
|
|
31
|
+
writeFileSync(registryPath, next);
|
|
32
|
+
console.log(`adr index: updated ${ADR_REGISTRY_PATH} (${entries.length} record(s))`);
|
|
33
|
+
return { code: 0, result: "updated", records: entries.length };
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=adr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adr.js","sourceRoot":"","sources":["../../src/commands/adr.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAelF;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,OAAwB;IAClD,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,OAAO,CAAC,KAAK,CAAC,eAAe,iBAAiB,iEAAiE,CAAC,CAAC;QACjH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;IACjE,CAAC;IACD,MAAM,MAAM,GAAG,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAClD,MAAM,IAAI,GAAG,oBAAoB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnD,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CACX,eAAe,iBAAiB,6GAA6G,CAC9I,CAAC;QACF,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;IACjE,CAAC;IACD,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,uBAAuB,OAAO,CAAC,MAAM,aAAa,CAAC,CAAC;QAChE,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;IACjE,CAAC;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,oEAAoE,iBAAiB,EAAE,CAAC,CAAC;QACvG,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;IAC/D,CAAC;IACD,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAClC,OAAO,CAAC,GAAG,CAAC,sBAAsB,iBAAiB,KAAK,OAAO,CAAC,MAAM,aAAa,CAAC,CAAC;IACrF,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;AACjE,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type OriginStatus } from "../lib/stack.js";
|
|
2
|
+
export interface DevOptions {
|
|
3
|
+
cwd: string;
|
|
4
|
+
/** Start detached, log to .launchrail/state/dev.log, wait for readiness, leave it running. */
|
|
5
|
+
background: boolean;
|
|
6
|
+
/** Re-address the single derived origin and expose PORT to the start command. */
|
|
7
|
+
port: string | null;
|
|
8
|
+
/** Stop the background stack recorded in dev.pid. */
|
|
9
|
+
stop: boolean;
|
|
10
|
+
/** Start, wait for every origin, assert the state files, tear down — the adoption-time proof. */
|
|
11
|
+
check: boolean;
|
|
12
|
+
/** Readiness deadline for --background and --check. */
|
|
13
|
+
timeoutMs?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface DevOutcome {
|
|
16
|
+
code: number;
|
|
17
|
+
origins: Record<string, string>;
|
|
18
|
+
/** Per-origin readiness after the wait (background/check only). */
|
|
19
|
+
ready: Record<string, OriginStatus>;
|
|
20
|
+
pid: number | null;
|
|
21
|
+
}
|
|
22
|
+
/** Stop the detached stack: the whole process group when the platform has one, the pid otherwise. */
|
|
23
|
+
export declare function stopStack(cwd: string): Promise<{
|
|
24
|
+
code: number;
|
|
25
|
+
pid: number | null;
|
|
26
|
+
}>;
|
|
27
|
+
/**
|
|
28
|
+
* Start the smokeable stack from the manifest and own its state (ADR-0036):
|
|
29
|
+
* `.launchrail/state/stack.json` (origins, pid, log — merged with whatever a
|
|
30
|
+
* composed start command writes there), `dev.url`/`dev.pid` for shells, and
|
|
31
|
+
* `browser.env` for the smoke's driver. The seeded `scripts/dev.mjs` delegates
|
|
32
|
+
* here, so adapted copies in older projects can no longer drift away from the
|
|
33
|
+
* contract the `launch-browser-smoke` skill relies on.
|
|
34
|
+
*/
|
|
35
|
+
export declare function runDev(opts: DevOptions): Promise<DevOutcome>;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
2
|
+
import { existsSync, openSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { MANIFEST_FILENAME, parseManifest } from "../lib/manifest.js";
|
|
5
|
+
import { BROWSER_ENV_FILE, DEV_LOG_FILE, DEV_PID_FILE, DEV_URL_FILE, ensureStateDir, INSTALL_HINT, mergeStackState, missingDependencies, readStackState, resolveStackStart, STACK_STATE_FILE, waitForOrigins, writeBrowserEnv, } from "../lib/stack.js";
|
|
6
|
+
const NONE = { code: 1, origins: {}, ready: {}, pid: null };
|
|
7
|
+
const DEFAULT_TIMEOUT_MS = 120_000;
|
|
8
|
+
function loadManifest(cwd) {
|
|
9
|
+
const path = join(cwd, MANIFEST_FILENAME);
|
|
10
|
+
if (!existsSync(path)) {
|
|
11
|
+
console.error(`launchrail: ${MANIFEST_FILENAME} not found — run \`launchrail init\` first.`);
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
const parsed = parseManifest(readFileSync(path, "utf8"));
|
|
15
|
+
if (!parsed.manifest) {
|
|
16
|
+
console.error(`launchrail: ${MANIFEST_FILENAME} is invalid:`);
|
|
17
|
+
for (const error of parsed.errors)
|
|
18
|
+
console.error(` - ${error}`);
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
return parsed.manifest;
|
|
22
|
+
}
|
|
23
|
+
function readPid(cwd) {
|
|
24
|
+
const path = join(cwd, DEV_PID_FILE);
|
|
25
|
+
if (!existsSync(path))
|
|
26
|
+
return readStackState(cwd)?.pid ?? null;
|
|
27
|
+
const pid = Number.parseInt(readFileSync(path, "utf8").trim(), 10);
|
|
28
|
+
return Number.isFinite(pid) ? pid : null;
|
|
29
|
+
}
|
|
30
|
+
function alive(pid) {
|
|
31
|
+
try {
|
|
32
|
+
process.kill(pid, 0);
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** Stop the detached stack: the whole process group when the platform has one, the pid otherwise. */
|
|
40
|
+
export async function stopStack(cwd) {
|
|
41
|
+
const pid = readPid(cwd);
|
|
42
|
+
if (pid === null) {
|
|
43
|
+
console.log("No background stack recorded (no .launchrail/state/dev.pid) — nothing to stop.");
|
|
44
|
+
return { code: 0, pid: null };
|
|
45
|
+
}
|
|
46
|
+
for (const signal of ["SIGTERM", "SIGKILL"]) {
|
|
47
|
+
try {
|
|
48
|
+
process.kill(-pid, signal);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
try {
|
|
52
|
+
process.kill(pid, signal);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
// Already gone.
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
for (let i = 0; i < 20 && alive(pid); i += 1)
|
|
59
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
60
|
+
if (!alive(pid))
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
rmSync(join(cwd, DEV_PID_FILE), { force: true });
|
|
64
|
+
mergeStackState(cwd, { pid: null });
|
|
65
|
+
console.log(alive(pid) ? `launchrail: pid ${pid} did not exit.` : `Stopped the background stack (pid ${pid}).`);
|
|
66
|
+
return { code: alive(pid) ? 1 : 0, pid };
|
|
67
|
+
}
|
|
68
|
+
function printReadiness(origins, ready) {
|
|
69
|
+
for (const [name, url] of Object.entries(origins)) {
|
|
70
|
+
const status = ready[name];
|
|
71
|
+
console.log(` ${status ? "✓" : "✗"} ${name}: ${url}${status ? ` (${status})` : " — not answering"}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Start the smokeable stack from the manifest and own its state (ADR-0036):
|
|
76
|
+
* `.launchrail/state/stack.json` (origins, pid, log — merged with whatever a
|
|
77
|
+
* composed start command writes there), `dev.url`/`dev.pid` for shells, and
|
|
78
|
+
* `browser.env` for the smoke's driver. The seeded `scripts/dev.mjs` delegates
|
|
79
|
+
* here, so adapted copies in older projects can no longer drift away from the
|
|
80
|
+
* contract the `launch-browser-smoke` skill relies on.
|
|
81
|
+
*/
|
|
82
|
+
export async function runDev(opts) {
|
|
83
|
+
const manifest = loadManifest(opts.cwd);
|
|
84
|
+
if (!manifest)
|
|
85
|
+
return NONE;
|
|
86
|
+
if (opts.stop) {
|
|
87
|
+
const stopped = await stopStack(opts.cwd);
|
|
88
|
+
return { ...NONE, code: stopped.code, pid: stopped.pid };
|
|
89
|
+
}
|
|
90
|
+
if (missingDependencies(opts.cwd)) {
|
|
91
|
+
console.error(`launchrail: dependencies are not installed (no node_modules) — ${INSTALL_HINT}.`);
|
|
92
|
+
return NONE;
|
|
93
|
+
}
|
|
94
|
+
const stack = resolveStackStart(manifest, opts.port);
|
|
95
|
+
if (!stack.command) {
|
|
96
|
+
console.error(`launchrail: no start command — set testing.devCommand in ${MANIFEST_FILENAME}, or smoke.start (with smoke.origins) for a composed stack.`);
|
|
97
|
+
return NONE;
|
|
98
|
+
}
|
|
99
|
+
ensureStateDir(opts.cwd);
|
|
100
|
+
const browser = writeBrowserEnv(opts.cwd);
|
|
101
|
+
const env = opts.port ? { ...process.env, PORT: opts.port } : { ...process.env };
|
|
102
|
+
const primary = Object.values(stack.origins)[0] ?? null;
|
|
103
|
+
const detached = opts.background || opts.check;
|
|
104
|
+
console.log(`Starting the stack via ${stack.source}: ${stack.command}`);
|
|
105
|
+
if (stack.composed && opts.port) {
|
|
106
|
+
console.log(" --port is passed through as PORT; a composed stack's origins are the declared ones.");
|
|
107
|
+
}
|
|
108
|
+
if (!detached) {
|
|
109
|
+
mergeStackState(opts.cwd, { command: stack.command, origins: stack.origins, pid: null, log: null, startedAt: new Date().toISOString() });
|
|
110
|
+
if (primary)
|
|
111
|
+
writeFileSync(join(opts.cwd, DEV_URL_FILE), primary + "\n", "utf8");
|
|
112
|
+
const result = spawnSync(stack.command, { cwd: opts.cwd, shell: true, stdio: "inherit", env });
|
|
113
|
+
return { code: result.status ?? 0, origins: stack.origins, ready: {}, pid: null };
|
|
114
|
+
}
|
|
115
|
+
const log = openSync(join(opts.cwd, DEV_LOG_FILE), "a");
|
|
116
|
+
const child = spawn(stack.command, { cwd: opts.cwd, shell: true, detached: true, stdio: ["ignore", log, log], env });
|
|
117
|
+
child.unref();
|
|
118
|
+
const pid = child.pid ?? null;
|
|
119
|
+
if (pid !== null)
|
|
120
|
+
writeFileSync(join(opts.cwd, DEV_PID_FILE), String(pid) + "\n", "utf8");
|
|
121
|
+
if (primary)
|
|
122
|
+
writeFileSync(join(opts.cwd, DEV_URL_FILE), primary + "\n", "utf8");
|
|
123
|
+
mergeStackState(opts.cwd, {
|
|
124
|
+
command: stack.command,
|
|
125
|
+
origins: stack.origins,
|
|
126
|
+
pid,
|
|
127
|
+
log: DEV_LOG_FILE,
|
|
128
|
+
startedAt: new Date().toISOString(),
|
|
129
|
+
});
|
|
130
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
131
|
+
console.log(` pid ${pid ?? "?"} · log ${DEV_LOG_FILE} · waiting up to ${Math.round(timeoutMs / 1000)}s for ${Object.keys(stack.origins).length} origin(s)`);
|
|
132
|
+
const ready = await waitForOrigins(stack.origins, timeoutMs);
|
|
133
|
+
printReadiness(stack.origins, ready);
|
|
134
|
+
const allReady = Object.values(ready).every((s) => s !== null);
|
|
135
|
+
// A composed start command may have merged its real origins/keys into stack.json meanwhile.
|
|
136
|
+
const state = readStackState(opts.cwd);
|
|
137
|
+
console.log(` state: ${STACK_STATE_FILE}${state && Object.keys(state).some((k) => !["schemaVersion", "command", "origins", "pid", "log", "startedAt"].includes(k)) ? " (the start command added fields)" : ""}` +
|
|
138
|
+
` · ${DEV_URL_FILE} · ${DEV_PID_FILE}`);
|
|
139
|
+
console.log(` browser: ${browser.executablePath ? `${browser.executablePath} (${browser.source})` : "no Playwright Chromium found — agent-browser will use its own (npx agent-browser install)"}` +
|
|
140
|
+
`${browser.args ? ` · args ${browser.args}` : ""} → ${BROWSER_ENV_FILE}`);
|
|
141
|
+
if (opts.check) {
|
|
142
|
+
const filesOk = [STACK_STATE_FILE, DEV_URL_FILE, DEV_PID_FILE, BROWSER_ENV_FILE].every((f) => existsSync(join(opts.cwd, f)));
|
|
143
|
+
await stopStack(opts.cwd);
|
|
144
|
+
if (allReady && filesOk) {
|
|
145
|
+
console.log("\nStack check passed: every origin answered and the state files were written.");
|
|
146
|
+
return { code: 0, origins: stack.origins, ready, pid };
|
|
147
|
+
}
|
|
148
|
+
console.error(`\nStack check failed: ${allReady ? "state files missing" : "not every origin answered before the deadline"} — see ${DEV_LOG_FILE}.`);
|
|
149
|
+
return { code: 1, origins: stack.origins, ready, pid };
|
|
150
|
+
}
|
|
151
|
+
if (!allReady) {
|
|
152
|
+
console.error(`\nlaunchrail: the stack did not answer on every origin within ${Math.round(timeoutMs / 1000)}s — it is still running; read ${DEV_LOG_FILE}, or stop it with \`launchrail dev --stop\`.`);
|
|
153
|
+
return { code: 1, origins: stack.origins, ready, pid };
|
|
154
|
+
}
|
|
155
|
+
console.log(`\nStack ready. Stop it with \`launchrail dev --stop\`.`);
|
|
156
|
+
return { code: 0, origins: stack.origins, ready, pid };
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=dev.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"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"}
|