[sim] round 5 NOTES

The relic works end to end (seed-derived, honours DATA's relicReserve,
digs up, persists). Wildlife's design point holds: sink your dust and
nothing hatches. Reference v5 researches a tech at tick 1235 with melt
and the zero-brownout regression untouched.

For the orchestrator:
- ONE contract change needed: GameData.seams + main.ts importing
  data/seams.json. DATA shipped the file mid-round with a good schema
  (and reserved a relic corner for me), but nothing reaches sim.init, so
  seams are inert in the running game. I mirrored their shape as
  SeamDef/SeamMap, exported, ready to lift
- still no trap machine in data, so swarms can't be cleared in the real
  game. Suggested machine + recipe in NOTES; the sim spots traps by recipe
  shape so it needs no code
- swarms slow crafting but NOT powerGen -- my call, flag it if wrong
- save format v3 -> v4 (wildlife, relics, lab timers)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
LANE-SIM 2026-07-18 14:07:22 +10:00
parent 71c885e009
commit e9661dd772

View File

@ -492,3 +492,115 @@ NEXT (round 5 if asked)
- A headless perf benchmark, so the numbers above stop being anecdotes. - 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 - 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. to feel like an investment rather than a purchase.
### Round 5 — 2026-07-18 — Opus 4.8
SHIPPED
- **`grantResearch`** — idempotent, ignores unknown ids, completes the active target out from
under the labs, save/load safe. Verified through the live bus, so `__fktryDemo` can drop
`testkit` whenever you like.
- **Research takes time**`RESEARCH_TICKS_PER_PACK = 60` (exported). Stepped: a lab spends
the full 60 ticks on a pack, then consumes it and ticks progress by exactly 1, so
`research.progress` stays integer and determinism stays trivial. Labs really do parallelise
— measured 200 ticks with two vs 260 with one on the same supply. A lab mid-pack reports
`progress` 0..1, so RENDER/UI can show it working.
- **Wildlife v1** — piles grow from dust a machine is sitting on, hatch swarms at 1.0, swarms
drift to production machinery and slow it while attached, traps can them. Deterministic,
save/load carries the lot, spawn/clear events on both. 12 tests including the design point.
- **Seams** — extractors run only while their footprint overlaps an authored seam rect;
off-seam they idle with `'no seam'`, edge-triggered like every other jam. Consumes DATA's
real `seams.json` shape (and a bare rect list), defensively — see BLOCKED.
- **THE RELIC** — one optical fossil per world, position a pure function of the seed, 1828
tiles out, never on a seam, never under the demo. `excavate` within a tile uncovers it and
emits `relicFound`; it stays found through save/load and 20,000 further ticks. When DATA's
seam map supplies a `relicReserve` the roll folds into that corner — verified in-browser
landing at (21,15), inside the reserve, and digging up first try.
- **Reference factory v5** — a second works on DATA's eastern seam: ore → demuxer → quantizer
→ {crime → BRICKS, ringing → HALOS} + slurry → artifact bottler → SPATIAL PACK →
archaeology lab. **It researches `broadcast-phosphor-seams` at tick 1235.** Melt still first
at 1247, still shipping at 20k, **zero brownout ticks**, 179/179 placements legal, and with
seams wired **zero extractors off-seam** — both works sit on real ore.
- Verified: 99 sim tests (446 across the repo), tsc clean in my lane, and the browser agrees
with Node tick-for-tick (melt 1247, scram 434, research 1235). Perf **63× realtime** at
3,500 entities / 6,820 belt items (0.529 ms/tick) — Round 4 was 64.7×, so all of this round
cost ~3%. (An earlier probe "timed out" and looked like a regression; it was the 30s tool
limit on a 16k-tick warmup, not the sim. Staged it and re-measured.)
DECISIONS
- **Dust breeds from BACKED-UP dust, not from dust existing.** First cut grew piles from
whatever a machine held, and the tidy factory — dust belted straight to an uplink — still
hatched 56 swarms, because buffers are never empty between pushes. Growth is now
proportional to what sits *beyond one craft's worth* (`DUST_SPILL_GRACE`). Plumbed lines
never cross the threshold; neglected ones hit the stall cap and hatch in ~400 ticks. The
asymmetry is the mechanic — without it the hazard is just weather.
- Related, and worth knowing: my first "tidy" fixture still bred, and the mechanic was
innocent. A crusher making 4 dust per craft out-produces a single belt lane (~0.15
items/tick) and backs up no matter how you plumb it. That's a true fact about belts.
- **`SWARM_MAX = 8`.** A permanently jammed machine breeds forever — measured 29 swarms in one
20k demo run, which is a plague, not a hazard. At the cap, full piles just sit there.
- **Swarms only settle on production machinery**, preferring machines actually mid-craft and
falling back to jammed ones. Power plants read as permanently "running" and hoovered up
every swarm in the world to no effect — it looked exactly as silly as it sounds. The
fallback matters because the dust that bred them came from a machine that seized: without
it, a swarm evaporates at the moment it should bite.
- **Swarms slow crafting, not generation.** `swarmThrottle` is not applied to `powerGen`, so
an infestation never causes a brownout. That's my call, not the contract's — flag it if you
want mosquitoes on the grid; it would make them far nastier and would end the zero-brownout
regression.
- Traps are identified by **recipe shape** — empty inputs, outputs the canned swarm — not by a
machine id, so DATA's real trap lights up with zero code changes. A trap only progresses
while a swarm is in `TRAP_RADIUS`, and holds at full progress rather than canning air if its
prey drifts off or a neighbour beats it to the catch.
- Switching research target **forfeits the part-processed pack** in every lab, matching the
existing rule that switching abandons delivered packs. Lab intake now counts what *all*
labs are holding, so a bank of them can't collectively hoard more than the tech costs.
- **The annex is a separate works, not a tap off the melt line.** Every column between the
quantizers and the press is spoken for; threading bricks, halos and slurry through that
floorplan would have made the melt regression hostage to the science. DATA's second mdat
seam is empty ground, so the annex mines its own ore and shares only the bandwidth bus.
- Save format **v3 → v4** (wildlife, relics, lab timers). `testkit` follows it.
BLOCKED/BROKEN
- **`GameData.seams` is not wired, so seams are inert in the actual game.** DATA shipped
`data/seams.json` mid-round (good schema, and they reserved a relic corner for me), but
`GameData` has no `seams` field and `main.ts` doesn't import the file, so nothing reaches
`sim.init`. I consume it defensively and my tests inject it. **This is the one contract
change the round needs** — see CONTRACT REQUEST. I verified in-browser what happens once
it's wired: 0 extractors off-seam, relic in DATA's reserve. Until then extractors mine
anywhere, exactly as before.
- **There is still no trap machine in the data,** so swarms cannot be cleared in the real
game. The mechanic is complete and tested against a fixture trap; DATA needs a machine
whose recipe has no inputs and outputs `mosquito-swarm`. The demo currently hatches its 8
and keeps them. (Suggested shape in PROPOSAL.)
- The demo researches **one** tech and then idles: completing clears `active` and nothing
auto-picks a successor. That's a player/UI decision rather than a sim one, but it means
the annex jams shortly after 1235 — the bottler starves of halos (skim-ringing wants 3
coefficient packs per craft against crime's 1, and the splitter is a blind 1:1), packs back
up, and the line seizes. Harmless and honest, but it's why the demo grows piles.
- My round-1 lesson bit me again from the other side: DATA reworked the commission ladder
mid-round (`first-taste` → `raw-payload`, 20 ore), which broke a sim test that assumed
shipping melt closes the first commission. Rewritten to assert the *rule* — shipping what
the active order wants credits it, capped at the cost — rather than which order is first
this week.
CONTRACT REQUEST
- **`GameData.seams?: SeamMap`**, and `main.ts` importing `../data/seams.json` into the data
object. The shape is DATA's file verbatim; I've mirrored it as `SeamDef`/`SeamMap`, exported
from `src/sim/index.ts`, so the contract can lift it as-is. Nothing else in my lane is
blocked.
PROPOSAL
- **A trap for DATA**, matching what the sim already recognises:
`{ id: 'mosquito-trap', kind: 'crafter', footprint: {x:2,y:2}, recipes: ['catch-swarm'], powerDraw: 3 }`
plus `{ id: 'catch-swarm', machine: 'mosquito-trap', inputs: {}, outputs: {'mosquito-swarm': 1}, ticks: 30, bandwidth: 2 }`.
The canned swarm is already an item and commissions already ask for live ones, so it ships.
- Should swarms bite `powerGen` as well as craft speed? Currently no, deliberately.
- `snapshot.wildlife` and `snapshot.relics` are always present (found or not) as the v6 note
requires. They alias live arrays like `commissionQueue` — same read-only rule.
NEXT (round 6 if asked)
- The Correction / parity mites — the enemy proper.
- A headless perf benchmark, so these numbers stop being browser anecdotes (proposed round 3;
the 30s-timeout scare this round is the third time it would have paid for itself).
- Per-seam `richness` driving extraction rate, once DATA wants it — the field is already there.
- Swarm behaviour beyond "sit and bite": drifting between targets, or fleeing a trap.