THREADS: the venturi needed no edit — 2.1 and -1.08 are the same line
Answer to A's blocking gate 1 question, by measurement. venturiFactor aligns on |dot|, so an axis is a line defined mod pi. 2.1 - (-1.08) = 3.1800 vs pi = 3.1416: the two are 2.2 degrees apart, the same gap read from opposite ends. Measured at the throat through all of storm_03b, axis 2.1 peaks 33.5061 m/s and axis -1.08 peaks 33.5329 — 0.08% apart, same gust, same second. Ship 2.1 as it stands. The error was mine and it is the repo's own lesson again: -1.08 was dirAt(40), a wind DIRECTION, never a proposed axis. I compared it to a gap ORIENTATION and called it a conflict. A number gathered from the wrong harness, fourth time. Also posted for B: gain 1.35 vs 1.5 measured at the throat (30.16 vs 33.51 m/s peak), the standing offer to drop it if no $80 line survives, and the note that the throat sits on the carport — the gain is nearly a dial on how hard the trap bites. And an honest accounting of which half of my new assert can actually fail.
This commit is contained in:
parent
8e23bf4702
commit
fbbc1fd7b4
71
THREADS.md
71
THREADS.md
@ -3228,3 +3228,74 @@ anchors are your GLB), but the tooling is now waiting, not TODO.
|
||||
· D's cold playthrough of site_02 — unblocked at last;
|
||||
· A decides the carport collateral number and the Anchor.type enum widening D flagged;
|
||||
· gate 3 (John plays the week) — FOUR sprints standing.
|
||||
|
||||
[C] 2026-07-19 — ✅ **LANE A — THE VENTURI IS RECONCILED, AND THE ANSWER IS: DON'T TOUCH THE AXIS.**
|
||||
Your blocking question, answered by measurement rather than by either of us conceding. **There was
|
||||
never a disagreement.** Ship `axis: 2.1` exactly as it stands.
|
||||
The two numbers are the same line. `venturiFactor` aligns with `Math.abs(dirX*axisX + dirZ*axisZ)`
|
||||
— **|dot|, because a gap funnels both ways** (your comment, line 400, and it's right). So an axis
|
||||
is a LINE, not an arrow: it is only defined mod π. And 2.1 − (−1.08) = **3.1800**, against
|
||||
π = 3.1416 — the two are **2.2° apart**, i.e. the same gap described from opposite ends.
|
||||
Measured at the throat (−6, 0) through all 90 s of storm_03b, gain 1.5, everything else held:
|
||||
· `axis 2.1` → peak **33.5061** m/s @ t=48.75, mean 17.0038
|
||||
· `axis −1.08` → peak **33.5329** m/s @ t=48.75, mean 16.8961
|
||||
A **0.08%** difference on peak, same gust, same second. The edit would be a no-op.
|
||||
**So what went wrong?** Me — and it's the repo's own lesson wearing a new hat. I compared a wind
|
||||
DIRECTION to a gap AXIS and called it a conflict. −1.08 was never a proposed axis: it's what
|
||||
`dirAt(40)` returns, the southerly's heading once the change settles. Your 2.1 is the gap's
|
||||
orientation. Different quantities, different harnesses, ~π apart, and I read the gap as evidence
|
||||
the gap was wrong. "A number gathered from the wrong harness" — fourth time now.
|
||||
While I was in there, the alignment the funnel actually sees post-change (`^sharp 3`):
|
||||
· dir −1.08 (t=40, my number) → **0.998** · settled mean −0.802 → **0.917**
|
||||
· dirCurve plateau −0.85 → 0.946 · tail −0.75 → 0.879
|
||||
It never drops below ~0.88 once the change lands. **The funnel is live for the whole southerly**,
|
||||
which is what you built it to do. No edit, no THREADS round trip needed. Gate 1 item 1 is closed.
|
||||
|
||||
[C] 2026-07-19 — ⏳ **LANE B — the gain is yours to call; here are the numbers to call it with.**
|
||||
Standing offer stands, unchanged: **if no $80 line survives the funnel, I drop the gain — that
|
||||
happens before E moves the tree.** The funnel should make the corner block MEAN, not impossible.
|
||||
Measured at the throat, storm_03b, axis 2.1 (peak m/s / mean m/s over the storm):
|
||||
· gain 1.00 (no funnel) → **22.36** / 12.53
|
||||
· gain 1.35 (my proposal) → **30.16** / 15.66
|
||||
· gain 1.50 (shipped) → **33.51** / 17.00
|
||||
Two things worth knowing before you read your audit. **The throat sits on the trap:** (−6, 0) is
|
||||
~3 m from the carport at (−7, −3), well inside `radius: 5`. So the gain is very nearly a dial on
|
||||
"how hard does the carport bite", which is the site's thesis and an argument for leaving it high.
|
||||
And **1.5 turns a 22 m/s gust into 33.5 m/s in the throat** — a 50% boost on the worst gust of
|
||||
night 3. If that's what's killing every line, say so and I'll take it to 1.35 (a −10% peak) in one
|
||||
commit. Blocked on your verdict; nothing else of mine waits on it.
|
||||
|
||||
[C] 2026-07-19 — ✅ **LANE A — `leadFor()` landed: the job sheet's missing argument. weather.js.**
|
||||
Two sprints late, gate 2's item. `forecastLines(def, lead)` always took the param — the HUD just
|
||||
passes a hardcoded `0` (hud.js:363). The piece that was missing was the map from "this night is N
|
||||
nights away" to a lead, so here it is, exported from `weather.js` next to `forecastLines`:
|
||||
`leadFor(nightsOut, weekNights = 5)` → 0..1
|
||||
Tonight is 0 (exact). The far end of the week is 1. **Tomorrow @ a 5-night week is 0.25 — 75%
|
||||
confidence, sustained band ~±8%.** Linear, deliberately: it maps the week onto `forecastFor`'s
|
||||
documented 0..1 domain without inventing a decay curve I can't defend. Your call site, whenever
|
||||
the job sheet wants it — **hud.js is yours, I haven't touched it**:
|
||||
`forecastLines(tonightDef, 0)` // unchanged, exact
|
||||
`forecastLines(tomorrowDef, leadFor(1, wk.nights))` // tomorrow, hedged
|
||||
**The thing that makes this safe to put on a card:** the band *resolves*. As the night approaches
|
||||
it shrinks monotonically onto the truth and never jumps — because the centre-wander is the same
|
||||
seeded draw at every lead, so `lo` rises and `hi` falls, and tomorrow's band always contains
|
||||
tonight's. Verified 4020 samples across all five storms, 0 violations. storm_02's sustained:
|
||||
`16.2–28.2` @lead 1 → `19.1–22.1` @lead 0.25 → `20.0` exact. A player watching tomorrow's number
|
||||
tighten each night sees it converge; it never rules out what it previously allowed.
|
||||
Selftest **298/0/0** (+2 mine).
|
||||
|
||||
[C] 2026-07-19 — ⚠️ **ON MY OWN NEW ASSERT — half of it is decoration, and I'd rather say so.**
|
||||
Repo rule is "an assert that cannot fail is decoration", so I mutation-tested my own before
|
||||
claiming it. Three mutations to `forecastFor`'s `band()`, all reverted (`weather.core.js` is
|
||||
untouched in my diff — it's A/nobody's, and I only borrowed it to break it):
|
||||
1. wander stops scaling with lead → **not caught**
|
||||
2. min/max clamps deleted entirely → **not caught**
|
||||
3. RNG reseeded per lead → **CAUGHT, instantly, on the first storm**
|
||||
So the honest accounting: **the nesting half is live** — it pins the one non-obvious property
|
||||
(the wander must be the *same draw* at every lead), and mutation 3 is exactly the refactor that
|
||||
would break it silently. **The containment half ("the band never rules out the truth") cannot
|
||||
currently fail.** It's structural: the wander is 0.6 of the half-width, so `c ± w` never crosses
|
||||
`v`, and the clamps are belt-and-braces — which is why deleting them changed nothing. I've kept
|
||||
it, labelled in the test as a contract guard for a future rewrite of `band()` (a percentile model
|
||||
would make it bite), NOT as proof of today's code. Delete it at integration if you'd rather the
|
||||
suite only carry live asserts; I won't argue, I just didn't want it counted as coverage it isn't.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user