Commit Graph

5 Commits

Author SHA1 Message Date
type-two
afb61b2926 Lane C S18: the mid-storm entry seam — a crate is a pure function of its event
The emergency callout arrives at t≈30, which makes a NON-ZERO START a first-class
case for the storm clock. Measured before writing anything, and the debris module
failed two ways that had nothing to do with the callout:

  · the same storm flown twice through one module spawned DIFFERENT crates
    (wildnight height 1.582 m then 1.165 m). main.js builds one debris module at
    boot and clear()s it per phase change; clear() rewound the leaf accumulators
    and not the piece PRNG. Live on main today — night 2 of the seven-night week
    never flew night 1's crates, and no test looked.
  · an entry at t=45, past the wildnight's t=38 event, gave every LATER crate the
    skipped crate's height, spin axis and phase — the stream sat 5 draws behind.
    Skipping history corrupted the future, not just the present.

One cause: a crate's jitter came off a shared stream whose POSITION encoded how
much history had happened. Keyed on the event itself now, so a crate is a pure
function of its event — the move weather.core.js's header already argues for.

debris.enterAt(t0, dt) for the one part that is a genuine path integral: the
ambient leaf layer. A t=0 run has 6 leaves crossing the grass at t=30 and a cold
entry has ZERO, staying becalmed ~7 s while the 2.5 s EMA climbs off zero —
DESIGN.md line 149 makes that moving grass the gust front's tell, and gate 1's
whole premise is that the grass is the only briefing a callout gets. It runs the
ladder rather than skipping it, and the ladder ACCUMULATES: i*dt is the more
accurate ladder and therefore the wrong one (1770 of 1800 steps disagree, first
at step six), because main.js, fixedLoop and sail.js all accumulate.

Pins: +5 (522 -> 527). Wind order-independence broadened to every storm and five
scalar observables plus the exact callout ladder, and a BACKWARDS peak scan
cross-checking what the dispatch will quote. All four mutations went red; the
first draft of the stormStats case could not fail (it memoises per def, so it was
comparing an object to itself) and was rewritten rather than shipped.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 19:21:29 +10:00
m3ultra
b7a069069d debris: delete the dead sail.nodes seam — sail._applyDebris is the one contact model
The SPRINT2-era duck-typed path (if sail.nodes → applyToSail) has been
dead since decision 5 chose option b, and was a double-apply waiting for
the day anyone exposed .nodes. The sail key on step()'s world arg is
accepted and ignored, documented.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 19:03:36 +10:00
type-two
b70699189c Lane C S13 gate 2.3 + D's sliver: ambient leaves from 30 km/h; hail pool hides at zero
Leaves: a pooled handful (cap 7) streaming with the wind from 8.3 m/s — the
same number D keys the player's lean on, so the yard and the body start
telling one story at one speed. Count rides a 2.5 s speed EMA so it doesn't
strobe; own seeded rng (seed ^ 0x1eaf) so the pool never shifts the crate
sequence; bit-identical under identical (dt, t) streams (asserted).
debris.clear() rewinds the layer. dev_skyfx flies the debris layer now and
warms it to the scrub point, so ?t=50 shows the leaves t=50 would have.

D's aftermath sliver, exactly as diagnosed on lane/d: the hail InstancedMesh
at count:0 with frustum culling and depthWrite off still draws instance 0's
identity matrix — a 5 cm always-on-top speck at the origin. mesh.visible now
gates on n > 0, sky.hail joins the public fx object, and a whole-storm assert
demands hidden-at-zero / shown-when-falling in both directions (gated on
floor(1300 x intensity) >= 1: a burst's first frames honestly draw nothing).

THREADS: gate-2 wrap entry — D's judging unblocked, A's M key live.
Selftest 340/0/0 (+2 tests). Mutation-checked: dropped stepLeaves, a 3 m/s
threshold, and an always-visible hail pool all go red.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 11:51:26 +10:00
m3ultra
11f27c493c Fix debris ground friction, cloud seam and yard coords
Three bugs the bench found once it was actually running a storm:

- Debris was glued to the floor. The scrape `v *= 0.86` ran every frame while
  grounded, which is 0.86^60 per second — it pinned a 9 kg crate at 0.7 m/s in
  a 19 m/s wind. Friction now applies on impact, with dt-scaled rolling
  friction while resting. A crate crosses the whole yard at ~6 m/s.
- Debris slid instead of tumbling: wind is horizontal, so once down there was
  no vertical force at all and it skated at constant height. Added tumbling
  lift that flips sign as it rolls — bins hop now.
- The cloud dome had a dead straight seam across the sky. The fbm claimed to
  tile and didn't; now each octave wraps at its own integer period.

Also: shelters and the bench now use Lane A's landed yard coords (t1 -9,2 /
t2 8,-2, gardenBed 1,2) instead of my guesses, so shelter tuning means
something.

Verified in-browser against a real storm: crate crosses the yard and the t=74
bin spawns from storm JSON; sail node shoved 0.32 m; a 14 kg bin at 20 m/s
knocks the player down and a tub drifting at 0.3 m/s correctly does not;
lightning peaks 0.88. Lane A's selftest: 37 pass / 3 skip.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 21:50:41 +10:00
m3ultra
383471d0f5 Add debris, skyfx and the Lane C bench; align to landed contracts
debris.js: hand-rolled kinematic tumble, drag ∝ speed² so the gust that
spikes a corner is the one that launches the neighbour's bin. Ground bounce
via world.heightAt (contracts.js documents it as ours), sphere-vs-player
knockdown reported to Lane D, sphere-vs-sail-node impulse duck-typed so it
lights up when Lane B exposes nodes and stays silent until then.

skyfx.js: instanced rain that wraps around the camera rather than respawning,
storm sky + procedural cloud dome, lightning, and synthesized WebAudio layers
(wind bed, howl, rain, gust whoosh on the telegraph, rope creak off the worst
corner, flog when one blows). It modulates Lane A's lights and hands them back
on dispose() rather than owning them.

weather_demo.html: graybox bench to drive all three before M0 — mock sail,
storm scrub, 4x, throw-a-crate.

Aligned to contracts.js now that it has landed: relative three imports (there
is no importmap), contracts' rng() instead of a local copy, and storm paths
resolved off import.meta.url — server.py serves the repo root, so an absolute
/world/... would have 404'd at integration.

storm_02: fix the southerly change. contracts.js puts north at -Z and the wind
vector blows toward (cos d, sin d), so the old swing to +2.6 blew toward due
south — a northerly wearing a southerly's name. Now slews to -1.35: a SSW
buster off the open side of the yard, into the house.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 21:38:21 +10:00