Add Sprint 2 assembly instructions: wire proven modules into one playable storm
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
41ad12dede
commit
76421a7f86
132
SPRINT2.md
Normal file
132
SPRINT2.md
Normal file
@ -0,0 +1,132 @@
|
||||
# SPRINT 2 — ASSEMBLY (instructions for Opus 4.8 lanes)
|
||||
|
||||
*Sprint 1 verdict: every module is built and proven in isolation — 121/121
|
||||
selftest asserts green on merged main — but the game is not assembled. main.js
|
||||
still drives the M0 placeholder capsule and stub wind. Sprint 2 is one thing:
|
||||
**wire the proven modules into one playable storm.** Read THREADS.md from your
|
||||
last entry down before starting; the integrator [I] entry lists what changed
|
||||
under you.*
|
||||
|
||||
## Decisions (made — stop waiting on them)
|
||||
|
||||
1. **Lanes run on m3ultra.** Lane D's recommendation is adopted: the M1 Ultra
|
||||
(`johnking@100.91.239.7`) is an asset-build box you SSH to; GLBs get committed;
|
||||
the game never needs it at runtime. PLAN3D §0 is amended by this line.
|
||||
2. **Sail-area problem (B's 70–192 m² finding): fix the yard, not the physics.**
|
||||
Lane A: move p1/p2 in to roughly (−4.5, 5.5) and (4.0, 6.0), add a third post
|
||||
p3 near (0, 7), and register the trees' `branch_anchor_*` empties (E shipped
|
||||
them with `rating_hint`) as anchors. Target: at least three pickable quads in
|
||||
the 18–45 m² range that can shade the garden bed, verified by a new a.test
|
||||
assert that enumerates quad areas. The huge quads stay possible — the load
|
||||
bars teaching "you cannot span the whole yard" is design working as intended.
|
||||
3. **Flat-horizontal loophole: Lane C closes it with vertical gust structure.**
|
||||
Real gusts aren't horizontal; add a per-gust vertical component (downdraft
|
||||
fraction in storm JSON, default ~0.25 of gust power, validated) so a
|
||||
horizontal plate carries real load. Lane B adds the assert: over 8 directions
|
||||
in storm_02 wind, flat-horizontal peak load ≥ 60% of flat-pitched peak (i.e.
|
||||
no longer a free lunch). Ponding stays out of scope (M4 water spike).
|
||||
4. **repair/trim seam: Lane B conforms to Lane D's call sites** (D landed first,
|
||||
duck-typed): add `repair(i)` (→ repairCorner with the spare's hw),
|
||||
`trim(i, delta)` (→ trimCorner) and `cornerPos(i) -> Vector3` (live world
|
||||
position, fresh vector) to the rig object. Contract entries + b.test asserts.
|
||||
5. **debris↔sail seam: option (b)** — Lane B reads `debris.pieces`
|
||||
({x,y,z,vx,vy,vz,r,mass}) inside `sail.step()` and applies impulses; momentum
|
||||
bookkeeping stays in the one integrator. Lane C freezes the `pieces` shape.
|
||||
6. **House GLB: no re-cut.** Lane A reads `fascia_anchor_*` positions out of
|
||||
`house_yardside_v1.glb` at load and places anchors there (data wins over the
|
||||
yard constants). E's 2.80 m fascia replaces the 2.6 m graybox number.
|
||||
|
||||
## Lane A — assemble the game (this is the sprint)
|
||||
|
||||
main.js boot(), in order; keep each step behind a small commit:
|
||||
1. Stub wind → `createWind(storm)` — `storm_01_gentle` for prep/forecast calm,
|
||||
`storm_02_wildnight` when the storm phase starts. Call
|
||||
`wind.setSheltersFromTrees(...)` after the yard builds, per C's ask.
|
||||
2. Placeholder → `await createPlayer(scene, world, cameraRig, {wind, interact})`
|
||||
(async boot; D says same first three args). Delete the placeholder factory.
|
||||
3. Sail: `const view = await createSailView(rig); scene.add(view); view.update()`
|
||||
per frame after `rig.step(dt, wind, t)`. B's THREADS entry has the exact shape.
|
||||
4. `createSkyFx({scene, camera, wind, sun, hemi})` + `unlockAudio()` on first
|
||||
input; `createDebris({heightAt: world.heightAt, onHitPlayer: player.knockdown})`,
|
||||
`debris.setModels()` from `models/debris/` (glob the dir).
|
||||
5. Yard dressing: swap graybox house → `house_yardside_v1.glb` (decision 6),
|
||||
shed + shed_table (D's spare pickup), sail posts as `sail_post_v1.glb` rotated
|
||||
about `rake_pivot`, fence set, grass billboards off `textures/grass_atlas.png`.
|
||||
6. Anchor rework per decision 2.
|
||||
7. HUD: loads in **kN** (B's units note), per-corner bars vs rating, wind meter +
|
||||
gust telegraph banner, garden % (wire `rig.coverageOver(world.gardenBed)` →
|
||||
HP → E's `plants_full/tattered/dead` visibility swap), phase banner, forecast
|
||||
card (storm JSON summary: peak wind, change time), aftermath screen (garden %,
|
||||
corners lost, budget delta).
|
||||
8. Phase machine: forecast (show card, Enter) → prep (rigging UI live, budget
|
||||
$80, optional timer OFF this sprint) → storm (90 s, storm_02) → aftermath.
|
||||
Acceptance: `python3 server.py` → rig a sail with the mouse, press Enter, watch
|
||||
storm_02 try to kill it, repair a corner mid-storm, see the aftermath screen.
|
||||
60 fps during the storm on this box. Selftest stays green after every merge.
|
||||
|
||||
## Lane B — sail in the world
|
||||
|
||||
1. Decision 4 API (repair/trim/cornerPos) + asserts.
|
||||
2. Decision 5: consume `debris.pieces` in step(); assert momentum is conserved
|
||||
within tolerance on a crate-through-sail scenario.
|
||||
3. Prep-phase picking adapter: RiggingSession → clicks. Raycast against Lane A's
|
||||
anchor markers (A exposes `world.anchorMarkers` if you need meshes — agree in
|
||||
THREADS), corner cycling + tension dial + spare purchase, HUD summary line
|
||||
from `summary()`. This unblocks A step 8.
|
||||
4. Joint tuning session with C (their THREADS ask): retune cloth ρ against real
|
||||
m/s storms; then re-run the §7 gate against REAL wind (current assert used the
|
||||
stub) — flat cheap rig cascades in storm_02, twisted mixed rig + one repair
|
||||
survives. Log tuned constants in THREADS.
|
||||
5. Small fix: `coverageOver()` rays start at `heightAt(x,z)`, not y=0 (your nit).
|
||||
6. Decision 3 assert (flat-horizontal no longer dominant) once C lands vertical gusts.
|
||||
|
||||
## Lane C — weather in the game
|
||||
|
||||
1. Decision 3: vertical gust component in storm JSON + validator + asserts.
|
||||
2. Decision 5: freeze and document `debris.pieces` shape in contracts.js.
|
||||
3. Rain must react to the sail: cheap occlusion — sample `rig.coverageOver` cells
|
||||
or raycast a handful of drops so the garden visibly stays dry under cloth.
|
||||
(Coordinate the API with B; don't ray-test every drop.)
|
||||
4. Storm tuning session with B (see B-4).
|
||||
5. skyfx: verify light restoration on `dispose()` inside the real main.js scene —
|
||||
A will call you if teardown flickers phase transitions.
|
||||
6. Consider retiring weather_demo.html once main.js hosts the storm — your call,
|
||||
it stops earning its place when the game IS the bench.
|
||||
|
||||
## Lane D — player in the storm
|
||||
|
||||
1. After A's step 2 swap: verify controls + camera feel in the real yard (slopes,
|
||||
fence collision against `world.solids`), tune walk/run speeds against yard
|
||||
scale, make gust shove + knockdown fire from real wind and real debris hits.
|
||||
2. Wire the spare pickup loop end-to-end: shed_table `pickup_anchor` → carrying →
|
||||
`repair(i)` consumes it (B's decision-4 API). The §7 "one mid-storm repair"
|
||||
scenario must be playable by hand.
|
||||
3. Interaction prompts follow `cornerPos(i)` live (flogging corner = moving prompt).
|
||||
4. Kill dev_player.html only when the main game covers everything it proves.
|
||||
|
||||
## Lane E — polish targets (small sprint)
|
||||
|
||||
1. Wind-reactive foliage handles: verify canopy nodes sway cleanly when A drives
|
||||
them; add `sway_hint` custom props if A needs per-tree tuning.
|
||||
2. Sail cloth texture (512² weave/UV-stripe atlas) so the membrane reads as
|
||||
fabric, + a simple tear decal strip for M3.
|
||||
3. Storm dressing set: wheelie bin (debris, `mass_hint`), washing line, garden
|
||||
gnome (collateral scoring bait). One script run, same acceptance as before.
|
||||
4. Contact-sheet the assembled yard from A's camera for DESIGN.md.
|
||||
|
||||
## Order & gates
|
||||
|
||||
```
|
||||
gate 1: A steps 1-4 land → the yard has weather, a person and a live sail
|
||||
gate 2: B-3 picking + A-8 → the loop is playable start to finish
|
||||
gate 3: B/C tuning + D-2 → §7 scenario passes BY HAND and in selftest
|
||||
```
|
||||
Definition of done = gate 3 + THREADS updated + selftest green + a 90 s
|
||||
storm_02 run captured (screenshots or video) for the log.
|
||||
|
||||
## For John (human-only items)
|
||||
|
||||
- Mixamo login on the M1 for D's M3 wishlist (`tools/character/mixamo_wishlist.txt`
|
||||
— Climbing Ladder, Turning Key, Digging). Not blocking this sprint.
|
||||
- Two dev servers float around: another session holds :8801; this repo's
|
||||
launch.json now uses :8809. Kill either freely; `server.py --port N` works.
|
||||
Loading…
Reference in New Issue
Block a user