[sim] round 2 NOTES
Reference factory holds: melt at tick 1247, still shipping at 20,000, demuxer never jams. Heat curve and scram/throttle decisions documented. Main thing for the orchestrator: data/ has none of the v2 fields, so heat and buffer tanks are implemented and tested but inert in the real game -- the software decoder cannot overheat until DATA gives it a heatPerTick. Suggested starting values included. One contract request: coolPerTick. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
ff43c09972
commit
dfd1860d09
@ -165,3 +165,95 @@ NEXT (round 2 if asked)
|
||||
- Heat: accumulate per craft, throttle >0.7, scram at 1 (the software decoder's whole bit).
|
||||
- Save/load — `SimSnapshot` is already the right shape to serialize.
|
||||
- A worked, deadlock-free reference factory you can paste into the console to demo M1.
|
||||
|
||||
### Round 2 — 2026-07-17 — Opus 4.8
|
||||
|
||||
SHIPPED
|
||||
- **Reference factory** (`src/sim/reference.ts`, `referenceFactory(data)`): 114 commands,
|
||||
110 entities. Ships its first MELT at **tick 1247** and is still shipping at 20,000 —
|
||||
6–15 melt per 2,000-tick window, flat, no decay. Round 1's build wedged at ~1200; this
|
||||
one never does, and the demuxer's `jammed` stays null the whole way. Surplus becomes
|
||||
product instead of a deadlock: 1,136 macroblock bricks + 1,997 hf dust shipped, 219
|
||||
slurry voided over 20k ticks.
|
||||
- **Splitters** — round-robin, blocked outputs skipped, rank traced *through* them (a lane's
|
||||
rank is now the best outcome reachable across every terminal it can reach).
|
||||
- **Buffer tanks** — charge on surplus, discharge to cover a deficit, brownout only once dry;
|
||||
`bandwidth.stored` is the pool.
|
||||
- **Heat v1** — `heatPerTick` while active + `RecipeDef.heat` per craft, ambient cooling,
|
||||
throttle above 0.7, scram at 1.0, restart under 0.5, both edges emitting `scram`.
|
||||
- **Commission queue** — data-order activation, `commissionDone` advances, `repeat` re-enters
|
||||
at the back, progress still only counts while active.
|
||||
- **`jammed:'starved'`** and **`BeltItem.id`** (always set; survives belt transfers *and*
|
||||
splitters, so the renderer never sees an item teleport).
|
||||
- Verified: 37 sim tests green (18 + 15 M2 mechanics + 4 reference), tsc clean in `src/sim`.
|
||||
In the live app I dispatched the whole reference factory through `__fktryBus` — it builds,
|
||||
renders, and runs, and my round-2 work is already visibly driving other lanes: the UI reads
|
||||
`94 DRAW / 220 GEN` + `BUFFER` off bandwidth v2, the fax shows the **queue** ("NEXT IN
|
||||
TRAY: DUST ALLOWANCE"), and LANE-UI's OSHA voice is narrating my new flag ("DCT PRESS:
|
||||
INTAKE STARVED. NOTHING IS ARRIVING.").
|
||||
- Determinism holds across engines: browser and Node both give tick 1247 and identical
|
||||
per-window melt counts.
|
||||
- Perf: 3,500 entities + 6,820 belt items → 0.465 ms/tick (**72× realtime**). Round 1 was
|
||||
0.418 (80×); the ~11% is heat touching every entity every tick. Still well inside target.
|
||||
|
||||
DECISIONS
|
||||
- **Heat curve (mine to pick, per orders).** Throttle is linear from 1.0 at heat 0.7 down to
|
||||
0.5 at heat 1.0 — so the lore's "tick rate visibly halves" lands exactly at the scram
|
||||
point. Ambient cooling is a flat 0.004/tick applied *always*, working or not (1.0 → cold in
|
||||
250 ticks ≈ 8s), which means any machine with `heatPerTick` below 0.004 can never overheat.
|
||||
Scram at 1.0, restart under 0.5, so a hot generator duty-cycles rather than dying.
|
||||
- **Throttle applies to `powerGen`, not just craft speed.** A hot decoder's output sags before
|
||||
it drops off the bus entirely — which is precisely the hole buffer tanks exist to fill. That
|
||||
synergy is my reading of "per-machine throttle"; say the word if generators should be exempt.
|
||||
- Scrammed machines keep their idle `powerDraw` (stopped, not unplugged) and freeze mid-craft
|
||||
progress, resuming on restart rather than binning the work.
|
||||
- Scram clears `jammed` and suppresses jam evaluation: a scrammed machine reports through
|
||||
`heat` + the `scram` event, not as a flow jam. Two channels, no double-reporting.
|
||||
- Splitters hold 2 items, mirrored into `inputBuf` so the inspector can see them. Any adjacent
|
||||
belt not pointing in is an output; the splitter's own `dir` is unused. Machines can't push
|
||||
straight into one — feed it with a belt.
|
||||
- **`starved` fires whenever a recipe sits idle without enough input — including a machine that
|
||||
simply outruns its feed.** LANE-UI: expect it to flicker on a fast machine with a slow
|
||||
supply. That's accurate rather than a bug, but you may want to debounce the voice line.
|
||||
- The reference factory validates every machine/recipe id against `data` and throws a named
|
||||
error, so DATA drift fails loudly instead of resurfacing as a mystery deadlock.
|
||||
|
||||
BLOCKED/BROKEN
|
||||
- **DATA carries none of the v2 fields, so heat and buffer tanks are inert in the real game.**
|
||||
No machine has `heatPerTick`, none has `bufferCap`, no recipe has `heat`, no commission has
|
||||
`repeat`. Both systems are fully implemented and tested — on a fixture I own
|
||||
(`pressure.test.ts`), because there is nothing in `data/` to test them against. The DoD's
|
||||
"heat throttles and scrams the software decoder" is proven mechanically, but the actual
|
||||
SOFTWARE DECODER cannot overheat until DATA gives it a number. This is the one thing
|
||||
standing between M2 heat and being real.
|
||||
- Starting values if they help (my suggestion, DATA's call): `software-decoder`
|
||||
`heatPerTick: 0.005` → ~33s of work then a ~4s scram, an ~89% duty cycle that reads as
|
||||
theatrical rather than punishing; `decode-asic` left at 0 (cool and inflexible, per the
|
||||
codex); `buffer-tank` `bufferCap: 600` ≈ 20s of cover against a 30-bandwidth deficit —
|
||||
enough to ride out exactly one decoder scram, which is a nice thing to discover.
|
||||
- `src/sim/data-validate.test.ts` is LANE-DATA's file living inside my owned path. I have not
|
||||
touched it. Worth an ownership ruling — either it moves to `data/`, or my lane doc should
|
||||
say I share the folder.
|
||||
|
||||
CONTRACT REQUEST
|
||||
- `MachineDef.coolPerTick?: number` (default 0.004). Right now cooling is a global constant, so
|
||||
DATA can tune how fast a machine heats but not how fast it recovers — every machine cools 1.0
|
||||
→ 0.5 in exactly 125 ticks. The codex explicitly has ASIC coolers venting heat, which wants a
|
||||
per-machine number. Cheap to add, and I'd wire it the round it lands.
|
||||
|
||||
PROPOSAL
|
||||
- `BeltItem.id` can drop the `?` in v3 whenever you like — I always set it already.
|
||||
- `referenceFactory`'s `setRecipe` commands depend on entity ids being handed out in placement
|
||||
order (1..N). That's true and deterministic, but it's an implicit coupling to my id
|
||||
allocation. A `setRecipeAt(pos)` command variant would remove it. Not urgent, just a
|
||||
tripwire worth knowing about before someone edits the layout.
|
||||
- Splitters have no filter or priority, and the reference factory proves you don't need either
|
||||
— skip-blocked self-balances. Worth revisiting only when bloom loops want a filtered tap.
|
||||
|
||||
NEXT (round 3 if asked)
|
||||
- Save/load — `SimSnapshot` is already the right shape.
|
||||
- Bloom loops: my trace already treats a closed belt circle as "no terminal" → rank 0 → accept
|
||||
and pile, which is exactly what a loop wants. The P-frame duplicator should drop straight in.
|
||||
- HF dust piles + mosquito swarms (the rest of M2 PRESSURE) — the seeded RNG is sitting there
|
||||
unused and waiting for its first roll.
|
||||
- Heat, for real, the moment DATA has numbers.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user