Skip to content

Run the gates against the thing people download - #167

Merged
CaYatur merged 1 commit into
mainfrom
fix/packaged-smoke-visibility
Aug 6, 2026
Merged

Run the gates against the thing people download#167
CaYatur merged 1 commit into
mainfrom
fix/packaged-smoke-visibility

Conversation

@CaYatur

@CaYatur CaYatur commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Closes #166. MSMS_SMOKE_WORLDS had been failing against every packaged build since at least v0.2.5 — the released v0.2.5 binary fails it too — and nobody knew, for two compounding reasons.

Nothing could be read

A packaged app is built for the Windows GUI subsystem: no console is attached, so every console.log goes nowhere. A packaged gate could only ever report 1 — no assertion name, no context, nothing to act on.

The transcript now also goes to msms-data/logs/smoke.log, truncated per run. That alone turned an opaque exit code into the actual defect on the first run:

WORLDS-SMOKE: FAIL - exception Error: ENOENT: no such file or directory,
  open C:\Users\...\Temp\MSMS-0.3.0\src\shared\ipc.ts

Everything below is downstream of being able to see that.

Four gates read the repository at runtime

They assert things about the code rather than about a running process:

check reads
every declared IPC channel has a handler src/shared/ipc.ts, register.ts, preload/index.ts
the bundled bridge jar matches what it was built from bridge/src/main/resources/plugin.yml (x2)
every route in the router appears in the documented surface src/main/web/server.ts
the checked-in spec is current writes docs/openapi.json

None of that exists in a packaged app — it is an asar of built JavaScript extracted to a temp folder with no src in it. So they threw ENOENT and took their whole gate down, after having already passed everything they could genuinely test. The failure was 100% test harness and 0% product, which is exactly why it survived so long: the app was fine.

They now skip when there is no source tree, and say so in the transcript rather than vanishing.

The guard is itself guarded

"Skip when the file is missing" is one careless edit from "skip always", and a check that silently stops running is the failure this project keeps finding (#157 had a fixture that made a real assertion vacuous). So:

  • skipNoSource refuses to skip when a source tree IS present and fails the gate instead. That catches an inverted or unconditional guard.
  • sourceRoot fails the gate when it is standing in the repository and the file it probes for has moved, rather than answering "packaged" and disabling every source-derived check at once.

Proved failable — renaming the probe target fails a dev run:

SMOKE: FAIL - this is the repository but src/shared/ipc.ts is missing,
  so the source-tree probe would disable every source-derived check

A release step, not a one-off

npm run gates and npm run gates:packaged run all eleven and print the transcript of anything that fails, so the packaged binary gets checked from now on instead of being assumed.

dev build         11/11 pass
packaged binary   11/11 pass    (was 2 failing: WORLDS and WEB)

Found while verifying the v0.3.0 artifacts; the product code is untouched by this PR.

Closes #166. MSMS_SMOKE_WORLDS had been failing against every packaged
build since at least v0.2.5 — the released v0.2.5 binary fails it too — and
nobody knew, for two compounding reasons.

**Nothing could be read.** A packaged app is built for the Windows GUI
subsystem, so it has no console attached and every console.log goes nowhere.
A packaged gate could only ever say "1": no assertion name, no context.
The transcript now goes to `msms-data/logs/smoke.log` as well, truncated per
run. That alone turned an opaque exit code into the actual defect in one
run, and it is why the rest of this commit exists.

**Four gates read the repository at runtime.** They assert things about the
CODE rather than about a running process — every declared IPC channel has a
handler, the bundled bridge jar matches the plugin.yml it was built from,
every route in the router appears in the documented surface, the checked-in
openapi.json is current. None of that exists in a packaged app: it is an
asar of built JavaScript, extracted to a temp folder with no `src` in it. So
they threw ENOENT and took their whole gate down, after having already
passed everything they could genuinely test.

They now skip when there is no source tree, and SAY SO in the transcript.

The guard is itself guarded, because "skip when the file is missing" is one
careless edit away from "skip always", and a check that silently stops
running is what this project keeps finding:

- `skipNoSource` refuses to skip when a source tree IS present, and fails
  the gate instead. That catches an inverted or unconditional guard.
- `sourceRoot` fails the gate when it is standing in the repository and the
  file it probes for has moved, rather than reporting "packaged" and
  disabling every source-derived check at once.

Both proved failable: renaming the probe target fails a dev run with "this
is the repository but src/shared/ipc.ts is missing, so the source-tree probe
would disable every source-derived check".

`npm run gates` and `npm run gates:packaged` run all eleven, so this is a
release step rather than something done by hand once.

  dev build         11/11 pass
  packaged binary   11/11 pass   (was 2 failing: WORLDS and WEB)
@CaYatur

CaYatur commented Aug 6, 2026

Copy link
Copy Markdown
Owner Author

Self review

The first fix was in the wrong place, and the gate told me

I first installed the transcript tee at module scope, so it would also capture the single-instance-lock failure. It wrote nothing in a packaged run while msms.log from the same process wrote fine — the packaged app started, logged, and produced no transcript. Rather than keep guessing at why module-scope file writes behave differently there, I moved the call inside whenReady(), next to the log.info that demonstrably works, and it worked immediately.

That leaves the lock failure uncovered by the transcript, so that one message goes through log.error instead of console.log — it lands in msms.log, which is the file that works at that point.

I do not have a root cause for the module-scope write failing, and I am not claiming one. What I have is a working placement and a reason to prefer it. If it matters later, the reproduction is in the issue.

The silent catch nearly cost another hour

teeSmokeOutput swallowed its own failure — a tee that quietly does nothing, which is precisely the shape of bug this PR is about. Adding one log.warn to that catch is what made the next step obvious. Kept.

Running all eleven gates found a second instance of the same bug

I fixed the IPC cross-check, confirmed WORLDS passed, and could easily have stopped. Running the whole set against the packaged binary immediately turned up WEB failing on docs/openapi.json — same class, different gate. A sweep for process.cwd() then found two more (a second plugin.yml read, and the router source), neither of which any gate had reached yet in packaged form. Four sites total; one would have been a false fix.

Deliberately not done

  • The --packaged runner is not wired into npm run dist. Building and then testing the artifact is a decision with a two-to-three minute cost, and folding it silently into the build command would make dist mysteriously slow. It is one command, documented in the PR body and the issue.
  • The unpacked build (release/win-unpacked) passes these gates even unfixed, because it sits inside the repository and resolves process.cwd() to it. Only the portable exe, which extracts to %TEMP%, exposes the bug. Anyone testing "the packaged build" via win-unpacked from the repo root would have seen green — worth knowing, because that is the easier thing to reach for.
  • I did not try to make the source-derived checks work packaged by shipping src/. They are repository assertions; shipping source to satisfy a test would be the tail wagging the dog.

Scope

No product code changes in this PR — smoke.ts, a new smokeLog.ts, the index.ts wiring, and a script. The v0.3.0 app binary behaves identically; what changed is that its gates can now be run and read.

@CaYatur
CaYatur merged commit 6415ec8 into main Aug 6, 2026
1 check passed
@CaYatur
CaYatur deleted the fix/packaged-smoke-visibility branch August 6, 2026 00:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MSMS_SMOKE_WORLDS fails against a packaged build, and has since at least v0.2.5

1 participant