6 — What may import what
Written: 2026-08-15 · Established by: extracting every cross-directory from '../…' import
across src/ outside src/__tests__/ at commit 93a9a67, then reading each edge that ran against
the layering.
This describes the dependency direction that exists, not one that is enforced. No lint rule
constrains imports between directories — eslint.config.js restricts only node:* builtins. So this
diagram is a measurement, and the four edges called out below are the ones the measurement found
going the wrong way.
Three layers, and one dotted arrow that should not be there.
The solid arrows are the layering: React reads the store, the store drives the engine, and the engine reaches neither back. The dotted pair is the exception, and it is the whole finding — four engine-layer directories reach up into the render layer for geometry that was never render-specific.
| Directory | Depends on | Notes |
|---|---|---|
src/parser |
src/types |
The bottom of the graph |
src/types |
src/parser |
Type-only; see below |
src/checks |
src/parser, src/transforms, src/utils, src/types |
|
src/transforms |
src/parser, src/utils, src/types |
Pure core; its dialogs are React |
src/sim |
src/parser, src/utils, src/types, src/viewer |
|
src/utils |
src/parser, src/types, src/viewer |
|
src/workers |
src/sim, src/parser, src/utils, src/types |
|
src/corpus |
src/parser, src/utils, src/types |
|
src/store |
src/parser, src/sim, src/transforms, src/utils, src/viewer |
|
src/viewer |
src/store, src/sim, src/transforms, src/parser, src/utils |
|
src/sidebar |
src/store and most of the rest |
The widest importer |
src/codemirror |
src/sidebar, src/types |
One symbol; see below |
src/export |
src/store, src/transforms, src/codemirror |
|
src/playback |
src/store, src/viewer, src/parser |
|
src/commands |
src/viewer, src/utils |
|
src/compare |
src/store, src/export, src/transforms |
|
src/bug-report |
src/store, src/parser, src/utils |
|
src/components |
src/utils |
Leaf |
src/dev |
src/store, src/sim, src/viewer |
Dev-only |
src/__tests__ |
everything | pure, dom, scene, scripts |
The four edges that run against the layering
src/sim, src/utils, src/store and src/transforms all import src/viewer/utils.ts. Nine
files outside src/viewer/ import it, and between them they take ten symbols: arcGeometry,
arcLength, arcSegmentCount, arcExtremePoints, chordTolerance, computeBounds, unionBounds,
buildAllSegmentPositions, buildTransitionMarkers and the TransitionMarker type. The first seven
are arc geometry and bounds with nothing to do with rendering, sitting in the render layer because
that is where they were first needed. Issue #80 is open against exactly this and proposes one geometry
layer below the viewer.
src/types/gcode.ts imports six types from src/parser. So src/parser is the bottom of the
graph, not src/types: the shared vocabulary is defined where each construct is detected — Units,
SubprogramInfo, CannedCycleInfo, WcsAlignmentResult, ToolTableEntry, G10Offset — and
gcode.ts re-exports them. These are type-only imports and cost nothing at runtime.
src/checks/fixes/ imports src/transforms. Two symbols only, applyEdits and the Edit type.
A guided fix produces the same edit shape a cleanup tool does, so this is reuse of the splice
machinery rather than a check reaching into the transform UI.
src/codemirror/check-marks.ts imports src/sidebar/severity.ts. One symbol, SEVERITY_LABEL.
The editor's gutter marks and the checks panel have to name a severity the same way.
Where the store is genuinely absent
The engine subgraph reaches no React and no store, and that is what makes src/__tests__/pure/ the
project most of the suite lives in — it runs in a node environment with no jsdom setup, in roughly
a quarter of the whole suite's time. src/transforms straddles the line: its .ts core is pure, and
its *Dialog.tsx components import the store. Only useDeferredTransform.ts does so among the
.ts files, and it is a React hook.
What this map does not tell you
It is directory-level, so it hides the shape inside each box. src/viewer alone holds 33 plain .ts
modules next to its scene components. It also draws every edge at equal weight, which is why
the load path, the write path and the simulation pipeline get their own diagrams rather than being
read off this one.