Problem
npm run smoke completes in under a minute, and the reason is that only one of the six smokes is deep. The TUI and web smokes are boot/first-paint checks, and every browser-driving script pins Chromium — so a regression in a real TUI interaction, or in a connected web tab other than Apps, or in a non-Chromium engine, passes npm run smoke cleanly.
Where the coverage actually sits today
| Smoke |
Depth |
What it asserts |
smoke:launcher (79 ln) |
Dispatch only |
--help, --cli --help, --tui --help exit 0 with each mode's banner. No connect. |
smoke:cli (500 ln) |
Deep |
10 numbered cases — real tools/list over stdio through the launcher, catalog/config resolution and seeding rules, --server selection, --header merge, an HTTP-transport case with config-file headers lifted onto the wire, the JSON error envelope, and the exit-3 no_stored_token code. |
smoke:tui (267 ln) |
Boot only |
Waits for MCP Servers in the first frame, then SIGTERM. Self-skips when CI is set (needs a real TTY). |
smoke:web (70 ln) |
HTTP only |
GET / → 200 with the injected __INSPECTOR_API_TOKEN__. Never executes the bundle. |
smoke:web:browser (216 ln) |
First paint |
Prod bundle in headless Chromium; "Add Servers" renders with no uncaught error. Never connects. |
smoke:web:app (358 ln) |
One real flow |
Deep-link connect → open app → data-app-status="ready". |
So the launcher → CLI → core → transport path is genuinely covered end to end, and the TUI/web are not.
Gaps to close
1. TUI is effectively unsmoked. Boot-and-render locally, and nothing at all in CI. No keypress, no connect, no tool call. The self-skip is justified (Ink needs raw mode), but it means the entire TUI ships on unit tests alone in CI. Worth evaluating a pty (node-pty) so the CI skip can be lifted, then driving at least: select a server → connect → tools/list renders → run a tool → result renders.
2. Web has exactly one connected flow, and it is the Apps tab. Nothing smokes Tools / Resources / Prompts / Network / Protocol / Logs / Tasks against a live server through the real prod bundle. Those surfaces are carried entirely by unit tests, Storybook play functions, and the integration project — all of which mock or bypass the prod server. smoke:web:app already shows the shape to copy (deep-link connect + a data-* readiness contract); the composable test servers under test-servers/configs/ supply the servers.
3. Chromium only. No Firefox, no WebKit anywhere:
scripts/smoke-web-browser.mjs:107 and scripts/smoke-web-app.mjs:208 both loadChromium().
package.json:72-73 — npx playwright install chromium.
clients/web/vite.config.ts:378 — Storybook browser: "chromium"; package.json:42 installs only chromium.
.github/workflows/main.yml:89 — npx playwright install --with-deps chromium.
Both smoke scripts already share scripts/lib/prod-web-server.mjs, so parameterizing them over a browser list needs no server-side work. Note Playwright's WebKit is not Safari proper — it approximates the engine, not the browser — so this buys engine coverage, not Safari-bug coverage. Also weigh the CI cost: three engines installed and three runs of each browser smoke against a gate that is already several minutes.
Suggested scope
Reasonable to split into sub-issues once sized:
Out of scope
Tarball-level coverage — that is pack:verify's dimension, tracked separately (#2003).
Problem
npm run smokecompletes in under a minute, and the reason is that only one of the six smokes is deep. The TUI and web smokes are boot/first-paint checks, and every browser-driving script pins Chromium — so a regression in a real TUI interaction, or in a connected web tab other than Apps, or in a non-Chromium engine, passesnpm run smokecleanly.Where the coverage actually sits today
smoke:launcher(79 ln)--help,--cli --help,--tui --helpexit 0 with each mode's banner. No connect.smoke:cli(500 ln)tools/listover stdio through the launcher, catalog/config resolution and seeding rules,--serverselection,--headermerge, an HTTP-transport case with config-fileheaderslifted onto the wire, the JSON error envelope, and the exit-3no_stored_tokencode.smoke:tui(267 ln)MCP Serversin the first frame, then SIGTERM. Self-skips whenCIis set (needs a real TTY).smoke:web(70 ln)GET /→ 200 with the injected__INSPECTOR_API_TOKEN__. Never executes the bundle.smoke:web:browser(216 ln)smoke:web:app(358 ln)data-app-status="ready".So the launcher → CLI → core → transport path is genuinely covered end to end, and the TUI/web are not.
Gaps to close
1. TUI is effectively unsmoked. Boot-and-render locally, and nothing at all in CI. No keypress, no connect, no tool call. The self-skip is justified (Ink needs raw mode), but it means the entire TUI ships on unit tests alone in CI. Worth evaluating a pty (
node-pty) so the CI skip can be lifted, then driving at least: select a server → connect →tools/listrenders → run a tool → result renders.2. Web has exactly one connected flow, and it is the Apps tab. Nothing smokes Tools / Resources / Prompts / Network / Protocol / Logs / Tasks against a live server through the real prod bundle. Those surfaces are carried entirely by unit tests, Storybook play functions, and the integration project — all of which mock or bypass the prod server.
smoke:web:appalready shows the shape to copy (deep-link connect + adata-*readiness contract); the composable test servers undertest-servers/configs/supply the servers.3. Chromium only. No Firefox, no WebKit anywhere:
scripts/smoke-web-browser.mjs:107andscripts/smoke-web-app.mjs:208bothloadChromium().package.json:72-73—npx playwright install chromium.clients/web/vite.config.ts:378— Storybookbrowser: "chromium";package.json:42installs only chromium..github/workflows/main.yml:89—npx playwright install --with-deps chromium.Both smoke scripts already share
scripts/lib/prod-web-server.mjs, so parameterizing them over a browser list needs no server-side work. Note Playwright's WebKit is not Safari proper — it approximates the engine, not the browser — so this buys engine coverage, not Safari-bug coverage. Also weigh the CI cost: three engines installed and three runs of each browser smoke against a gate that is already several minutes.Suggested scope
Reasonable to split into sub-issues once sized:
Out of scope
Tarball-level coverage — that is
pack:verify's dimension, tracked separately (#2003).