diff --git a/BUILD-RECORD.md b/BUILD-RECORD.md
index de7696f..318ad1d 100644
--- a/BUILD-RECORD.md
+++ b/BUILD-RECORD.md
@@ -377,10 +377,10 @@ python3 -m http.server 8000 # then open http://localhost:8000/
# or open index.html directly in a browser
# verify (both arms):
-node --check js/core.js js/renderer.js js/main.js js/levels.js
node test/sim.test.mjs # 15/15 — physics, rules, DOM wiring, rest, framing, clearability
node test/page.test.mjs # 7/7 — page boot, click session, direction, release
-# or: npm test (runs both, in order)
+node test/balance.test.mjs# 5/5 — balance spec (material break + enemy kill budgets)
+# or: npm test (runs all, in order)
```
## 8. Known limitations (honest list)
@@ -406,3 +406,27 @@ designs are original. The game is named **Isle Slingers**.
See the repository commit SHA recorded in the RC completion payload.
Working tree at commit time contains exactly the files listed in §3.
+
+## 11. Addendum — RC-375D84 S-2 modularization (2026-09-28)
+
+The flat `js/{core,levels,audio,renderer,main}.js` files described in §3 no
+longer exist. The tree was restructured (behavior-neutral, proven by a
+golden-step hash — identical scripted playthroughs through the original
+monolith and the split build produce byte-identical state hashes — and by
+27/27 green with the old files DELETED, so the new paths are the only load
+path):
+
+- `js/physics/` — the engine, split into 9 submodules (constants, state,
+ aim, abilities, damage, step, collision, rules, camera) that install into
+ ONE shared scope `P`; `js/physics/index.js` aggregates and exports the
+ unchanged 20-key `ISLE_CORE` API.
+- `js/levels/` — `helpers/` (constructors + SLING) + `data/level-1..5.js`
+ into shared scope `L`; `index.js` exports the unchanged `{LEVELS, SLING}`.
+- `js/audio/`, `js/render/`, `js/app/` — the former audio.js / renderer.js /
+ main.js, moved into module folders (content unchanged at S-2 time).
+- Every module and submodule carries an `agents.md`; the master list is
+ `MODULES.md`; the runtime model and load-order contract is `architecture.md`.
+- The test suites were re-pointed to the new paths (`sim.test.mjs` now walks
+ the whole `js/` tree; `page.test.mjs` loads the 19-script browser order).
+
+See `architecture.md` before touching any of these.
diff --git a/MODULES.md b/MODULES.md
new file mode 100644
index 0000000..4acaf4c
--- /dev/null
+++ b/MODULES.md
@@ -0,0 +1,58 @@
+# Isle Slingers — MODULES.md (master module list)
+
+RC-375D84 S-2. Folders = modules, subfolders = submodules. Every module and
+submodule carries an `agents.md` describing its surface and invariants.
+Load contract (order is load-bearing) is in `architecture.md` and encoded in
+`index.html` + `test/page.test.mjs`.
+
+| # | Module | Submodules | Public global | Role |
+|---|--------|-----------|---------------|------|
+| 1 | `js/physics/` | constants, state, aim, abilities, damage, step, collision, topple, rules, camera | `ISLE_CORE` (via `js/physics/index.js`) | Deterministic DOM-free physics engine (shared scope `P`) |
+| 2 | `js/levels/` | helpers, data (level-1..5) | `ISLE_LEVELS` `{LEVELS, SLING}` (via `js/levels/index.js`) | Level geometry + enemy/bird layouts (shared scope `L`) |
+| 3 | `js/audio/` | — (single file) | `ISLE_AUDIO` `{AudioEngine}` | Synthesized WebAudio SFX (no assets) |
+| 4 | `js/render/` | — (single file) | `ISLE_RENDERER` `{Renderer, VIEW_W, VIEW_H}` | Canvas drawing of the state object |
+| 5 | `js/app/` | — (single file) | page state on `window` | Input, screens/HUD, fixed-timestep main loop |
+
+## physics submodules (shared scope `P`)
+
+| Submodule | Installs (into `P`) | Consumes from `P` |
+|-----------|--------------------|--------------------|
+| constants | WORLD, VIEW, MATERIALS, BIRD_TYPES, ENEMY_TYPES, GRAVITY, LAUNCH_POWER, MAX_PULL, MIN_PULL, AIR_DRAG, BIRD_BOUNCE, BIRD_GROUND_FRICTION, REST_SPEED, SETTLE_TIME, BIRD_MAX_AGE, ABILITY_CD, BIRD_BONUS | — |
+| state | createGame, makeBird, activeBird | WORLD, MATERIALS, BIRD_TYPES, ENEMY_TYPES, makeBird |
+| aim | aimVector, trajectory | LAUNCH_POWER, GRAVITY, AIR_DRAG, BIRD_BOUNCE, WORLD, BIRD_GROUND_FRICTION |
+| abilities | launch, triggerAbility | activeBird, aimVector, MATERIALS, BIRD_TYPES |
+| damage | damageBlock, damageEnemy | MATERIALS, ENEMY_TYPES |
+| step | step, stepPhysics, spendBird | (nearly all — the physics hub) |
+| collision | crushCircleVsBox, collideBirdWorld, collideBirdBlocks, collideBirdEnemies, REST_VEL_CLAMP, resolveBoxPair | MATERIALS, WORLD, damageBlock, damageEnemy |
+| topple | toppleBlocks, blockSupportSpan, beginTopple, integrateTopple, landTopple, topplePathDamage, settleBack, supportStillAlive | WORLD, GRAVITY, MATERIALS, REST_SPEED, damageBlock, damageEnemy, ENEMY_TYPES |
+| rules | checkEndStates, birdsRemaining, starsFor | — |
+| camera | updatePopups, updateCameraTarget, decayCamera | WORLD, VIEW |
+
+## levels submodules (shared scope `L`)
+
+| Submodule | Installs (into `L`) | Consumes from `L` |
+|-----------|--------------------|--------------------|
+| helpers | wood, ice, stone, mogg, grum, king, SLING | — |
+| data/level-N | one level object each (returns it) | wood/ice/stone/mogg/grum/king, SLING |
+
+## Physics notes (S-3/S-4/S-5, RC-375D84 — landed 2026-09-29)
+- **topple** (S-3): blocks carry a rotational DOF (`ang`, `angVel`, `pivoting`).
+ A resting block whose COM is past its support span pivots about the
+ support-edge corner (full continuous rotation, Q1) and either lands on the
+ ground (impact damage via `topplePathDamage`) or, if the pivot is too high to
+ reach the ground, swings back and settles flat (`settleBack`, anti-livelock).
+- **collision** (S-4): crush is velocity-direction-aware (`boxAlong > 30` —
+ falling boxes crush enemies from above or the side), per-enemy crush cooldown
+ (0.12 s, one landing = one crush), and stacked block contact is mass-weighted
+ so heavy blocks drive light planks (chain-crush).
+- **step** (S-5): a settled bird with another bird in play becomes `landed`
+ (a live body under real gravity, no lifetime timer) and is integrated with
+ the blocks; the last bird still spends (win/lose unchanged). `rules` must not
+ declare `lost` while a landed bird is in the world.
+- **state** (S-3/S-5): block records carry `ang`/`angVel`/`pivoting`; bird
+ records gain the `landed` state (queued | aiming | flying | landed | spent).
+
+## Invariants (see architecture.md)
+- `ISLE_CORE` and `ISLE_LEVELS` public API surfaces are key-for-key stable.
+- Deterministic core: `createGame` + `step` are DOM-free and headless-safe.
+- Fixed timestep 1/120 s. Game is fully offline; no new runtime deps.
diff --git a/architecture.md b/architecture.md
new file mode 100644
index 0000000..c8037a2
--- /dev/null
+++ b/architecture.md
@@ -0,0 +1,154 @@
+# Isle Slingers — Architecture
+
+Original architecture for a fully offline, canvas-rendered slingshot game.
+No frameworks, no build step, no external assets. As of RC-375D84 (S-2) the
+JavaScript is a **modularized tree**: folders are modules, subfolders are
+submodules, and every module/submodule carries its own `agents.md`.
+
+## Runtime model (plain `
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+