Skip to content

Three paths that stopped being true when the packages split - #280

Merged
dhobi merged 1 commit into
masterfrom
fix/stale-paths-after-the-split
Aug 23, 2026
Merged

Three paths that stopped being true when the packages split#280
dhobi merged 1 commit into
masterfrom
fix/stale-paths-after-the-split

Conversation

@dhobi

@dhobi dhobi commented Aug 23, 2026

Copy link
Copy Markdown
Owner

Follow-up to #279, which documented these rather than changing them. Each is a default that was correct when there was one root, and that the move to four packages made wrong. All three fail silently — none is on a path CI takes, which is why they survived.

taoot/tests/browser/driver.ts pointed at the front door

APP_URL falls back to a local dev server, and the fallback stayed 5173 when Titanic's page moved to its own Vite root on 5174. A bare npx tsx taoot/tests/browser/playthrough.ts asked the site for a play/ it does not serve and got the sibling signpost — a 404 page explaining which server to start, which is a puzzling thing for a suite to try to boot a game out of.

CI never saw it: browser.yml passes APP_URL explicitly, which is also why the default could rot without a red tick anywhere.

Verified by running menu-movie.ts with the variable unset — it boots, plays menu.mov and clicks its regions:

movie: menu.mov (7 frames, interactive)
movie click (460,350) frame 1 -> type 2 "frame2"
movie: nightdive.mov segment 2/2 (3 frames, interactive)

taoot/tools/flowmap.ts looked beside the wrong directory — twice

rootDir defaulted to the bare string "gamefiles", resolved against the working directory, naming a path that no longer exists from the repository root. It now goes through gamefilesRoot(), which resolves from the file and honours TAOOT_GAMEFILES — as everything else in that directory already did.

The second one matters more. The publish step computed the repository root as one level up from taoot/tools/, from when the tool lived in tools/. So docs/public was looked for at taoot/docs/public, and the whole publish sits behind existsSync — a wrong path is indistinguishable from "you have no docs checkout", the run still reports success for everything else it wrote, and the interactive flow map quietly stopped being regenerated at the move. git log on docs/public/flow-map/ shows one commit, the initial import.

Same bug for node_modules: a workspace package's own directory holds its symlinks and none of the hoisted dependencies, so the vendor copy could not have found cytoscape either.

Before / after, same command:

(docs/public not found — skipped publishing the interactive map)
published interactive map -> docs/public/flow-map/index.html

tools/dumpscripts.ts assumed a rip at the root

It is a shared tool — it works on any rip because it takes one as an argument — so it may not import a game to find one. The default is discovered instead: the two environment variables the runner sets, then each game's gamefiles/ resolved from this file, and a named error rather than a stack trace when there is none.

invocation result
from the repo root, no args 2,927 files, 17,111 scripts
from taoot/, no args identical
explicit dust/gamefiles 326 files, 423 scripts
both rips absent no rip found: pass one as the first argument, or set TAOOT_GAMEFILES / DUST_GAMEFILES., exit 1

Docs

#279 described all three as known-stale and told the reader to work around them (export APP_URL=…, spelling out taoot/gamefiles in every example). Those passages now describe what the code does. ci.md's "the dev server does not get port 5173" is now 5174, which is the port the runner actually has to stay off.

Not included, deliberately

Running the two tools rewrites taoot/tests/playthrough/nav/shipgraph.gen.ts and the flow map's DATA, and both come out different here — 271 → 326 trips — because this machine has seven trees installed where whoever last generated them had fewer. demo in particular is a different cut of the game, not a translation, so it contributes genuinely different scripts.

That makes regeneration a real change to what the playthrough navigator reads, and it depends on which editions the generating machine happens to have. It should be its own commit, made on purpose, rather than a side effect of fixing a path. Both files are reverted here.

Verified

npm test 534/534 · npm run test:playthrough 30/30 · tsc --noEmit clean · VitePress build clean · all three tools exercised from two working directories each.

🤖 Generated with Claude Code

Each is a default that was correct when there was one root, and that the move
to four packages made wrong. All three fail SILENTLY, which is why they
survived: none of them is on a path CI takes.

**`browser/driver.ts` pointed at the front door.** `APP_URL` falls back to a
local dev server, and the fallback stayed 5173 when Titanic's page moved to its
own root on 5174. A bare `npx tsx taoot/tests/browser/playthrough.ts` therefore
asked the site for a `play/` it does not serve and got the sibling signpost — a
404 page explaining which server to start, which is a puzzling thing for a suite
to try to boot a game out of. CI never saw it, because `browser.yml` passes
`APP_URL` explicitly. Now 5174, and verified by running `menu-movie.ts` with the
variable unset: it boots, plays `menu.mov` and clicks its regions.

**`flowmap.ts` looked for `gamefiles` beside the wrong directory** — twice, and
the second one matters more than the first. `rootDir` defaulted to the bare
string, which is resolved against the WORKING DIRECTORY and named a path that no
longer exists from the repository root; it now goes through `gamefilesRoot()`,
which resolves from the file and honours `TAOOT_GAMEFILES` the way everything
else in that directory already did.

The second is that the publish step computed the repository root as ONE level up
from `taoot/tools/`, from when the tool lived in `tools/`. So `docs/public` was
looked for at `taoot/docs/public`, and the whole publish sits behind
`existsSync` — a wrong path is indistinguishable from "you have no docs
checkout", the run reports success for everything else it wrote, and the
interactive flow map quietly stopped being regenerated at the move. Same for
`node_modules`: a workspace package's own directory holds its symlinks and none
of the hoisted dependencies, so the vendor copy could not have found cytoscape
either.

**`dumpscripts.ts` assumed a rip at the root.** It is a shared tool, so it may
not import a game to find one — the default is discovered instead: the two
environment variables the runner sets, then each game's `gamefiles/` resolved
from this file, and a named error rather than a stack trace when there is none.
It answers the same from any working directory now, and reads Dust's disc as
happily as Titanic's.

The docs written last week described these as known-stale and told the reader to
work around them; those passages are updated to describe what the code does
instead.

Not included, deliberately: running the two tools rewrites
`shipgraph.gen.ts` and the flow map's `DATA`, and both come out different here
because this machine has seven trees installed where whoever last generated them
had fewer — `demo` in particular is a different cut of the game and not a
translation. Regenerating them is a real change to what the navigator reads, and
it should be its own commit made on purpose rather than a side effect of fixing
a path.

Verified: `npm test` 534/534, `npm run test:playthrough` 30/30, `tsc --noEmit`
clean, the VitePress build clean, and the three tools exercised from two working
directories each.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@dhobi
dhobi merged commit bb648a4 into master Aug 23, 2026
2 checks passed
@dhobi
dhobi deleted the fix/stale-paths-after-the-split branch August 23, 2026 12:11
dhobi added a commit that referenced this pull request Aug 23, 2026
…ne edition (#281)

Two things, and the second is the one with a decision in it.

## The comments

A source comment naming a path is documentation, and it rots the same way — so
this is the same sweep #279 did for `docs/`, run over the code. Not by memory:
a scan pulled every path-shaped token out of every comment in the four packages
and `tools/`, resolved each against the filesystem, and only what failed to
resolve was touched. Most of what it found was idiomatic shorthand and correct
(`df/savegame.ts`, `nav/dials.ts`, a served `editors/tracks.html`); what was
left was one shape, in twenty-odd places.

`engine/<x>.ts` used to name the runtime directory. `engine/` is the whole
package now, so every one of those reads as a file that is not there. Inside the
package they are `runtime/<x>.ts`, matching the `df/<x>.ts` shorthand already
used beside them; outside it they are spelled out. The same move sent
`bug-report.ts` to `site/`, `mklangstg.ts` into `taoot/tools/`, the editors into
`site/editors/`, and `masks.ts` out of the playthrough and into the runtime —
where `session.ts` was still pointing at its old home, which is now a reference
from the engine into a game's test directory for a file that sits next to it.

Two that were not path drift:

  - `tools/gif.ts` credited `tools/mkintromov.ts`, which was renamed and moved
    to `taoot/tools/mknightdive.ts`;
  - `proptrace.ts` explained what it replaced by naming
    `taoot/tests/browser/iface.ts`, which is in no commit — a throwaway probe
    that was never checked in. The account is worth keeping and the path is not.

And `dust/src/main.ts` opened by saying the page has "no engine, no interpreter,
no editions, no saves" while importing `GameHost`, the save browser and two
audio sinks. That was true of the experiment and stopped being true as the
experiment worked: it boots off the disc through the same host Titanic uses,
plays the intro films through the engine's own `MoviePlayer`, and saves `.rtd`
through the shared browser. What is left of the original is the standalone set
walker, which `start()` keeps as the FALLBACK for a boot that cannot produce a
viewer — so the "every frame decoded up front" section now says which half of
the page it is about, because the game does not pay that cost.

## The flow map reads one tree, and says which

`flowmap.ts` emits two things that are COMMITTED: `shipgraph.gen.ts`, which the
playthrough navigator walks, and the interactive map under `docs/public/`. Its
input was the whole rip, so its output was a function of which editions the
person running it had installed. On a seven-tree install that is 326 trips
against `en`'s 271 — scripts are deduplicated by content, but the trees are not
all the same game, and `demo` is a different CUT that contributes trips the full
game has not got.

So the default is one tree now, via `activeLanguage()`: `TAOOT_LANG` when set,
`en` when not, a path argument to override, and the generated header records
which tree it read so the next regeneration is comparable to this one.

Regenerated deliberately on that footing, and the result is the reassuring one:
**the graph data is byte-identical to what was committed** — 271 trips, 214
fully understood, the header line the only diff — and the flow map's own output
does not change at all. The committed artifacts were always `en`; nothing had
drifted, and there was no way to reproduce them until #280 fixed the publish
path. Now there is, and it is pinned.

Verified: `npm test` 534/534, `npm run test:playthrough` 30/30, `tsc --noEmit`
clean, `build:dust` clean, `dust/tests/browser/built-layout.ts` good across four
viewports.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

1 participant