[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:
parent
039eff15fa
commit
3e45ee2652
@ -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.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user