[sim] round 4 NOTES

Research provable end-to-end on DATA's real tree (realtech.test.ts), not
just a fixture. Cooler aura ~triples a hot generator's run. Constants
exported. Reference factory ships slabs.

For the orchestrator:
- the demo needs one line from you: the reference build uses two gated ids
  so it is a post-research save now. Dispatched cold it comes up 100 draw
  vs 80 gen and browns out -- I watched it. referenceFactoryTech(data)
  names the techs; testkit.grantResearch() opens them. Proposing a dev-only
  {kind:'grantResearch'} command instead of importing test helpers
- DATA fixed the tech bootstrap mid-round and was right to: it was circular
  and 0 of 24 techs were affordable at start
- asic-cooler still has no coolRadius, so its aura is inert in the game
- cooling cap 0.05/tick is my call; reasoning in NOTES

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
LANE-SIM 2026-07-17 20:20:47 +10:00
parent 039eff15fa
commit 3e45ee2652

View File

@ -388,3 +388,107 @@ NEXT (round 4 if asked)
- The Correction / parity mites (M3's enemy).
- Spatial heat + `coolRadius`, if the ASIC cooler is meant to mean something.
- A self-upgrading bloom recipe, if you want the codex's literal loop.
### Round 4 — 2026-07-17 — Opus 4.8
SHIPPED
- **Research v1 + the v4 gating rule.** `kind:'lab'`, `setResearch`, `snapshot.research`,
the `researched` event, and gating: any id a tech's `unlocks` names is refused by
`place`/`setRecipe`/`setRecipeAt` until that tech lands; anything no tech mentions is free
forever (so data with no tech gates nothing). Labs take only packs the active tech still
needs, several labs feed one total, and research rides through save/load — as a *rule*,
not just a list, so a restored save can still build what it unlocked.
- **A real research run on DATA's own tree** (`realtech.test.ts`): ore → demuxer → quantizer
→ {crime → bricks, ringing → halos} + slurry → artifact bottler → SPATIAL PACK →
archaeology lab → tech complete → a recipe that was silently refused is now accepted.
Cold start, nothing granted. That's the DoD's unlock path on real data, not a fixture.
- **Spatial cooling** (`coolRadius`): chebyshev from the footprint, auras stack by sum,
total capped at `HEAT_COOL_MAX`. Proven by measuring the actual shed rate, and a cooler in
range roughly triples a hot generator's run before it scrams (2.5× the ticks).
- **`src/sim/constants.ts`** — 12 constants exported; DATA can import truth instead of
hand-copying numbers that go stale silently.
- **Reference factory v4**: anchor-slab overflow tap → the demo now ships slabs (18 over 20k),
melt still first at tick 1248, still shipping at 20k, still **zero brownout ticks**.
`referenceFactoryTech(data)` derives which techs the layout needs, from the commands.
- Also wired: `bandwidth.capacity`, `EntityState.scrammed`, `commissionQueue` in the snapshot
literal (v5-ready).
- Verified in the browser as well as Node — identical ticks (1248 / scram 435), gating live
(`mv-extractor` refused while locked), `capacity: 900`, 23 techs unlockable, no console
errors. 65 sim tests; 318 across the repo.
- Perf: **64.7× realtime** at 3,500 entities / 6,820 belt items (0.515 ms/tick, best of 3 on
a fresh page). Round 3 measured 74.9×. Nothing I added is meaningfully per-tick — `drainLabs`
early-outs when nothing is being researched, and cooling only touches machines that can
heat — so I can't attribute the gap, and I'm not going to pretend I can. It's either
environment noise or something small I haven't found; the headless benchmark I proposed last
round would settle it.
DECISIONS
- **Cooling cap = 0.05/tick, and the number is arbitrary but the reasoning isn't.** At 0.05 a
machine sheds a full 1.0 of heat in 20 ticks, which is already effectively instant. Past
that, more coolers buy nothing but still cost bandwidth and floor space — a stack that does
nothing reads as broken rather than generous. Retune freely; it's one constant now.
- A cooler's aura excludes itself (its own `coolPerTick` is already counted once), and the
cache is invalidated on place/remove/rotate but *not* setRecipe — auras are geometry.
- **A lab's appetite is whatever the active tech costs**, so switching targets re-ranks every
lane feeding it, and `setResearch` drops the route cache. Labs take only what the tech still
needs — a lab is not a warehouse, and packs hoarded for a tech nobody picked would strand
where no other lab could reach them.
- Switching research targets **abandons** delivered packs rather than banking them per-tech.
Packs are the cost of indecision. Say the word if you'd rather bank them.
- Completing a tech clears `active` rather than guessing a next target.
- A machine placed while some of its recipes are locked defaults to its **first unlocked**
recipe, not `recipes[0]`.
- `testkit.ts` (new, tree-shaken, imported by nothing in the app) grants research via a
save/load round-trip — the public API, not a back door. It's how a test says "this is a
late-game save" honestly.
BLOCKED/BROKEN
- **The demo browns out, and it needs one line from you.** The reference factory uses two
gated ids (`software-decoder` ← stream-software-decoding, `assemble-gop-i-only`
disc-i-only-cadence), so it is a post-research save by definition now. Dispatched cold
through `__fktryBus` it comes up **100 draw against 80 gen — BROWNOUT** with no decoder,
which I watched happen on screen. `__fktryDemo` must open those techs first;
`referenceFactoryTech(data)` tells you exactly which, and `testkit.grantResearch(sim, ids)`
will do it. The alternative is a dev-only `{kind:'grantResearch'}` command — your call,
since shipping testkit into main.ts is a bit grubby. A test pins both halves of this.
- **DATA fixed the tech tree underneath me mid-round, twice, and it was the right call both
times.** When I started: no `kind:'lab'` machine existed at all, and every science pack was
made on the artifact-bottler which was itself locked behind a tech costing 10 analog-packs
— a hard circular dependency, **0 of 24 techs affordable at start**, the tree literally
unenterable. It now has `archaeology-lab`, spatial-packs craftable with zero research, and
6 techs affordable cold. `realtech.test.ts` is the tripwire if that bootstrap ever closes
over again — it's worth keeping for exactly that reason.
- Casualty of the churn: my first pass hard-coded `mosh-reactor` as "a gated machine" and
broke when DATA un-gated it an hour later. Round 1's lesson, relearned. The real-tree
tests now *derive* a gated and an ungated machine from the data.
- `asic-cooler` has `coolPerTick: 0.02` but still no `coolRadius`, so its aura is inert in the
real game — it cools only itself, and it has no heat to shed. The mechanic is live and
tested on a fixture; DATA just needs the number. (This was my round-3 note; the field now
exists for them.)
- Vitest caches JSON imports: I spent a while chasing a "gating is broken" ghost that was a
stale `tech.json` in `node_modules/.vite` while DATA edited underneath. Worth knowing if
anyone else sees data that doesn't match disk.
CONTRACT REQUEST
- None. v4 had everything.
PROPOSAL
- **A dev-only `{kind:'grantResearch'; tech: string[]}` command** would let `__fktryDemo` set
up a late-game board without importing test helpers into the app, and would give UI a way to
build a "sandbox" mode later. It's the cleanest fix for the brownout above.
- The mosh reactor now needs **two** melt lanes in the reference layout, and that's a smell
worth knowing about rather than a bug: a machine pushes one item per output type per tick,
so a 3-melt craft trickles out over several ticks, and while its own lane is busy melt is
free to take any *other* rank-1 lane. Nothing is lost — it still reaches an uplink — but it
can wander into a lane meant for something else. If that ever bites somewhere it matters,
the fix is a per-item lane affinity, not more belts.
- `Sim.save/load` are hardened in v4 and `testkit` depends on the blob shape (`.research`).
If the save format ever versions past 3, testkit moves with it.
NEXT (round 5 if asked)
- HF dust piles + mosquito swarms — the RNG is still unrolled and save/load already carries
its state, so wildlife lands without touching persistence.
- The Correction / parity mites.
- A headless perf benchmark, so the numbers above stop being anecdotes.
- Research *time* (a lab currently counts a pack the tick it lands) if you want the tech tree
to feel like an investment rather than a purchase.