The 82-line ENEMY_SPECS table and its kind unions are data, not vocabulary --
that is the block you edit to balance the game. Moved to enemies.ts (143).
statusKinds.ts (25) is not cosmetic: enemy specs name the status they inflict
and the survivor carries seconds-remaining per status, so leaving StatusKind
in types.ts would have made types.ts and enemies.ts mutually dependent. It
imports nothing, so the graph is statusKinds <- enemies <- types.
14 files repointed by script rather than by hand, splitting each types import
across the three owning modules by symbol.
The tests cannot catch a mistyped stat -- they assert behaviour, not the
balance table, so a wrong enemy hp passes 160 tests at 100% coverage. Checked
separately: 191 numeric pairs before, 191 after, compared as sorted multisets,
identical. check and build both pass; bundle 210.11 kB, same as baseline.
No reverse_survivors file is over the 250-line cap now.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
Split along actor lines, but not the obvious way. A plain sim/enemies cut
needs makeEnemy and grantXp going out and enemiesStep coming back -- a cycle.
Nothing here would have caught it: no eslint-plugin-import, and tsc and vitest
both pass on cyclic ES modules. It shows up as a TDZ error in the bundle.
So the graph is a tree instead:
simUnit.ts (42) leaf -- geometry, projectile constants, makeEnemy,
enemySpeed; imports only types and vec
simSurvivor.ts (132) createSurvivor, xp/upgrades, survivorStep
simThreats.ts (168) enemiesStep, projectilesStep, and enemy death
sim.ts (69) createInitialState and step, the only module that
reaches all three
Repointing director.ts's makeEnemy at the leaf also removes the sim <->
director cycle that was already there, surviving on const-arrow late binding.
npm run check and npm run build both pass -- 160 tests, coverage identical at
531/159/101/514, 32 modules bundled at 210.09 kB against 210.11 kB before.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
sim.test.ts 698 -> 175 and director.test.ts 315 -> 178, into four new
modules. 160 tests passing before and after.
sim.ts and types.ts are reverted. sim.ts's exported step() calls
survivorStep, which any seam moves out - 63 tests failed with a
ReferenceError while tsc reported only unused imports. types.ts has its
difficulty tables below the type declarations that use them.
Third project now where a TypeScript seam compiles clean and fails at
runtime. In TS, tsc does not tell you a split worked; the test run does.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY