Skip to content

import-graph-check.mjs

Proves that the live client cannot reach the design world, by walking the import graph rather than trusting a grep.

Contributor toolingimport-graph-check.mjs

What it does

Walks the import graph outward from the live entry app/src/game/main.jsx, following static imports and any dynamic import() edges it can resolve. It then asks which design-world modules that walk reached, and compares that set against a recorded baseline. A design-world module reachable from the live entry and absent from the baseline fails the run; so does a baseline entry the walk no longer reaches.

The design-world modules are named in the tool's own STRIP_LIST: the mock data source, the world populator, fleet motion, the highscore mock, and the simulation overrides. ADR-0010 abolishes the practice of filling live state with invented values. This check holds that line while the strip lands. The baseline is the list of crossings that still exist, and it is meant to shrink to nothing.

Usage

Run through its npm run alias:

bash
npm run imports:check

Or directly:

bash
node tools/import-graph-check.mjs

Options

FlagValueWhat it doesDefault
--baselinepathReads the recorded crossings from this file instead of the default, resolved against the current working directory. The file must hold a JSON array of repository-relative module paths.tools/import-graph-baseline.json.

Inputs and outputs

Reads app/src/game/main.jsx and every module reachable from it with an .mjs, .jsx, .js, .ts or .tsx extension, staying inside app/src. Reads the baseline JSON. Writes nothing.

On success it exits 0 and prints one line naming how many design-world modules are recorded and confirming they all match the baseline. When the walk followed dynamic import() edges it lists each one first, as those are the edges a reader is least likely to have predicted.

On failure it exits 1. For a module that is reachable but unrecorded it prints the module and a witness: the chain of imports from the live entry that reaches it. The crossing is then found without re-deriving the path by hand. For a baseline entry that is no longer reachable it prints the module alone; that case means the strip has advanced and the baseline should lose a line. A closing line counts both kinds.

Examples

Run the check as the gate runs it, before a commit that touches client data plumbing:

bash
npm run imports:check

Check a proposed baseline without moving the tracked one, which is how you confirm a strip slice removed exactly the crossings you meant it to:

bash
node tools/import-graph-check.mjs --baseline /tmp/proposed-baseline.json

Notes

The walk blanks comments before scanning for import statements, so a JSDoc type reference such as import('./mock.mjs').GameData is not mistaken for a real edge. That matters here more than it would elsewhere: this codebase writes type casts inline, mid-statement, and a naive scan would report a crossing that does not exist at runtime.

A dynamic import() whose specifier is not a literal cannot be resolved and is not walked. The check is therefore a lower bound on reachability — it proves a crossing exists, never that none does. A computed import into the design world would pass, which is a reason to keep specifiers literal in client code.

The baseline records crossings that are known and tolerated, not crossings that are approved. Adding a line to it to make a red run green reverses the tool's purpose; the fix is to sever the import, and ADR-0010 is the record that says so.

Source

tools/import-graph-check.mjs — part of Contributor tooling