Round 3 orders, all six. The validator move landed in 4803b6a (swept into
LANE-SCREEN's commit by the shared index); this is the rest.
- heat retune: round 2's numbers were below the sim's always-on cooling, so
nothing could ever warm up. Decoder now 100 gen at 0.0033 heat / 0.001 cool
-> throttles 10.2s, scrams 14.5s, 23.9s cycle, 25.8/s average (1.29x the
ASIC). Verified against LANE-SIM's real sim, not just arithmetic.
- powerGen had to move: the scram/restart hysteresis forces ~30% duty, so at
55 gen the decoder averaged worse than a steady ASIC and nobody would build
one.
- two new tests refuse decorative heat (per-tick and per-craft). They caught a
fresh instance of the same bug in chart-stco-map before it shipped.
- bufferCap 240 -> 300: one tank now covers exactly one decoder scram.
- ASIC COOLER spec'd (aura deferred to M4, no contract field requested yet);
THE MUXER + moov brain sub-lines; reel + broadcast era tech.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
222 lines
12 KiB
Markdown
222 lines
12 KiB
Markdown
# CANON-DELTA — everything in `data/` that isn't in the codex yet
|
||
|
||
LANE-DATA owns this file. `../../docs/FKTRY_LORE.md` is canon; this is the ledger of
|
||
where the data has run ahead of it. The orchestrator absorbs these into the lore doc in
|
||
one pass later. Until then, **this is the single place canon-drift is allowed to live**.
|
||
|
||
Rule for adding an entry: the codex was silent, I invented in its voice, and I wrote
|
||
down *why it is consistent with the codex* — not just what I did. If a future lore pass
|
||
disagrees, the codex wins and the data changes.
|
||
|
||
---
|
||
|
||
## Canonized in round 1 (orchestrator: "CANONIZED", round 2 review)
|
||
|
||
| Thing | Kind | Why it fits |
|
||
|---|---|---|
|
||
| `press-anchor-slab` | recipe (dct-press) | The press run backwards is an IDCT, and an IDCT *is* a complete picture. §4 already runs the field loom and the telecine puller in reverse, so reversibility is established machine behaviour. This is where I-frames come from. |
|
||
| `color-plate` | item | §4 demosaicer literally outputs "a smooth colour sheet"; it needed an id. |
|
||
| `v-hold-roll` | item | §1 Broadcast Shelf has "v-hold faults that make whole regions periodically roll upward". Bottling one gives the ANALOG PACK's "combing + v-hold roll + static" triptych three real ingredients. |
|
||
| `artifact-bottler` | machine | §2 calls the science packs "a bottled artifact triptych" but names no bottling plant. Something has to hold the bottle. |
|
||
| `lane-splitter` | machine | The contract has `kind: 'splitter'` and belts need routing, but §4 only ever calls the DEMUXER "the first splitter" — which is a refinery, not a junction. |
|
||
|
||
## Added in round 2
|
||
|
||
### The container line (unblocks `stream-hex-splicing`)
|
||
|
||
§2 names the CONTAINER PACK's contents ("moov shard + offset ribbon + sync key") and §7
|
||
names the moov brain's parts, but nothing said where they come from. The chain now
|
||
mirrors what the parts actually *are* in a real container:
|
||
|
||
| Thing | Kind | Why it fits |
|
||
|---|---|---|
|
||
| `moov-shard` | item | The index, not the payload. |
|
||
| `offset-ribbon` | item | The stco map — a ribbon of byte offsets. |
|
||
| `sync-key` | item | The stss table lists which frames are keyframes, i.e. I-frames. |
|
||
| `demux-container` | recipe (demuxer) | The demuxer is the machine that separates index from payload. 8 ore → 2 shards: the index is a rounding error next to the mdat, which is the joke and also the truth. |
|
||
| `spool-offset-ribbon` | recipe (gop-assembler) | The assembler is the only machine that knows where each frame starts, because it put them there. |
|
||
| `cut-sync-key` | recipe (artifact-bottler) | Cut from an anchor slab, because stss is a list of anchors. |
|
||
| `bottle-container-pack` | recipe | Assembles the §2 triptych. |
|
||
|
||
Chicken-and-egg check: §4 says the hex splicer "Requires CONTAINER PACK research", so the
|
||
container line deliberately does **not** route through the splicer. It is demuxer →
|
||
assembler → bottler, all machines you already own.
|
||
|
||
### The bloom line
|
||
|
||
§3 sells bloom "by intensity grade; grade-5 bloom visibly tries to escape its canister in
|
||
one direction" — five grades, one item each, `bloom-grade-1..5`.
|
||
|
||
- `bloom-concentrate` is **kept** and redefined as the raw, ungraded draw-off from a loop
|
||
(`tap-bloom`). It was not deleted because LANE-SCREEN hardcodes it in
|
||
`src/screen/corruptionMap.ts:54` and its test — deleting it would have broken another
|
||
lane's suite mid-round. Grading now consumes it.
|
||
- The recipe id `bloom-grade-3` survives from round 1 but now produces the *item*
|
||
`bloom-grade-3`, so the id finally means what it says. `tap-bloom` is the renamed
|
||
round-1 `bloom-grade-3` recipe. **Deprecation notice:** no recipe id was retired, but
|
||
`bloom-grade-3` changed its inputs/outputs entirely. Nothing outside `data/` referenced
|
||
it (checked: only my own `tech.json`).
|
||
- Escalation is in delta wafers, not exotic inputs — a grade-5 canister is 2 raw bloom +
|
||
18 wafers of compounding, which is §4's "contents compound each lap" priced honestly.
|
||
|
||
## Added in round 3
|
||
|
||
### THE MUXER and the moov brain (§7, data-first — mechanics are M4's)
|
||
|
||
§7 names the parts and says each is "its own late-game production line", but never said
|
||
what makes them. Each part is now made by the machine that already owns that knowledge,
|
||
which is the whole joke: the container is assembled by the factory that made the mess.
|
||
|
||
| Thing | Made by | Why that machine |
|
||
|---|---|---|
|
||
| `stsz-ledger` | gop-assembler | The sample-size table. The assembler packed the crates, so it knows how big each one was. |
|
||
| `stco-map` | hex-splicer | The chunk-offset map — byte offsets are the splicer's entire domain. It nudges them for a living; here it writes them down honestly, under protest. |
|
||
| `stts-metronome` | telecine-puller | Time-to-sample is a cadence, and the puller is the cadence machine. Built from judder cams, so the metronome ticks 3:2. |
|
||
| `stss-keyring` | artifact-bottler | The sync-sample table is a list of I-frames, so it is literally forged from anchor slabs. |
|
||
| `ftyp-seal` | artifact-bottler | §7 names the ftyp seal as part of the container; it needed a source. |
|
||
| `moov-brain` | muxer | The four converge. 300 ticks. |
|
||
| `megaglitch` | muxer | `mux-container`: brain + seal + 500 mdat ore + 100 melt, 900 ticks. §7's "colossal composited corruption" priced like one. |
|
||
|
||
`muxer` is `kind: 'crafter'`, not `'shipper'` — it *builds* the megaglitch, and you still
|
||
have to ship the thing. 5×5, the biggest footprint in the game, per "hero structure".
|
||
|
||
### ASIC COOLER (spec'd, deliberately not yet mechanical)
|
||
|
||
§2 HEAT says heat is "Vented by ASIC coolers" — a machine the codex names and never
|
||
specifies. Authored now so the data is ready; **the mechanic is deferred to M4**, when
|
||
SIM builds auras. Gated behind `broadcast-asic-cooling` so it can't appear early.
|
||
|
||
- **Intended mechanic (SIM, when auras exist):** an adjacency aura — every machine whose
|
||
footprint touches the cooler's 2×2 gets the cooler's `coolPerTick` (0.02) instead of
|
||
its own. That turns the software decoder from a 30%-duty throb into something you can
|
||
*engineer around*: ring your decoders with coolers and pay for it in floor space and
|
||
build cost. This needs a contract change (`coolRadius?`, or a `kind: 'cooler'`) —
|
||
**not requesting it until SIM is ready to build it**, since a contract field nobody
|
||
reads is the same decorative trap heat just fell into.
|
||
- **Authored as `kind: 'power'` with `powerGen: 5`** because there is no cooler kind and
|
||
a lie is worse than a stretch: it is an ASIC, ASICs decode, decoding makes bandwidth.
|
||
It vents far more than it earns. If `kind: 'cooler'` ever lands, this moves.
|
||
- Its own `coolPerTick: 0.02` is inert today (nothing heats it) and is there to state the
|
||
intended aura strength in data rather than in prose.
|
||
|
||
---
|
||
|
||
## The numbers, and the arithmetic behind them
|
||
|
||
### The reference M1 chain (measured, not guessed)
|
||
|
||
Computed from `data/*.json` against the machine list in SIM's `meltChain()`
|
||
(`src/sim/sim.test.ts`), with the two recipes that test hand-dials applied:
|
||
|
||
```
|
||
idle draw (every machine's powerDraw) 57 /s
|
||
+ active recipe draw at full tilt 39 /s
|
||
= peak draw 96 /s
|
||
- compression paid back (quantize -6, 4:2:2 -4, 4:2:0 -8) 18 /s
|
||
= net peak demand 78 /s
|
||
```
|
||
|
||
**Units (RULED round 3):** `gen`/`draw` are bandwidth per **second**; `stored` and
|
||
`bufferCap` are bandwidth-**seconds**. My round-2 assumption held.
|
||
|
||
### Round 2's heat was decorative — what went wrong
|
||
|
||
Worth writing down, because it's a trap anyone can fall into. I sized round 2's
|
||
`heatPerTick: 0.0025` against *no* cooling. SIM then implemented heat with cooling shed
|
||
**every tick, active or not** (`HEAT_DISSIPATION = 0.004`). So the decoder shed 0.004 and
|
||
banked 0.0025: net **−0.0015/tick**. It could never warm up. The number looked like a
|
||
mechanic and was a comment.
|
||
|
||
The lesson is now a test (`every heat source out-heats its own cooling`), and it caught a
|
||
second instance immediately: `chart-stco-map` banked 0.06 heat over 90 ticks while the
|
||
splicer shed 0.09 — I'd authored a fresh decorative number in this very round.
|
||
|
||
**Anything with a heat number must beat its own machine's cooling, or it isn't a
|
||
mechanic.** The validator now refuses both forms (per-tick machine heat, per-craft recipe
|
||
heat).
|
||
|
||
### The software decoder: `powerGen` 55 → 100, `heatPerTick` 0.0033, `coolPerTick` 0.001
|
||
|
||
Net while running = 0.0033 − 0.001 = **0.0023/tick**. Against SIM's curve (throttle 0.7,
|
||
scram 1.0, restart 0.5):
|
||
|
||
```
|
||
throttle, from cold 0.7 / 0.0023 / 30 = 10.1 s (target ~10 s)
|
||
scram, from cold 1.0 / 0.0023 / 30 = 14.5 s (target 13-15 s)
|
||
steady cycle, up 0.5 / 0.0023 / 30 = 7.25 s (heat 0.5 -> 1.0)
|
||
steady cycle, down 0.5 / 0.001 / 30 = 16.67 s (cools 1.0 -> restart 0.5)
|
||
period 23.9 s (target ~25 s)
|
||
duty 30.3 %
|
||
```
|
||
|
||
**Why the decoder cools slowly (0.001, vs the sim's 0.004 default):** it is an overclocked
|
||
tower PC held together with zip ties and prayer (§4). It is the worst-cooled object in the
|
||
factory. The ASIC has "a huge heatsink afro" and no heat source at all.
|
||
|
||
**Why powerGen had to nearly double.** SIM's hysteresis (scram at 1.0, restart at 0.5)
|
||
means any machine that throttles at ~10 s spends ~70% of its life cooling. At round 2's
|
||
55 gen that's an average of ~14/s — strictly worse than the ASIC's steady 20, so nobody
|
||
would ever build one and "burst gen" would be a lie. Averaged properly (generation is
|
||
throttled linearly 1.0 → 0.5 across the throttle window, and zero while scrammed):
|
||
|
||
```
|
||
un-throttled 0.2 / 0.0023 = 87.0 ticks at 100/s
|
||
throttled 0.3 / 0.0023 = 130.4 ticks at avg 75/s
|
||
energy per cycle = 100 x (87.0 + 130.4 x 0.75) = 18480 bandwidth-ticks
|
||
average = 18480 / 717 ticks = 25.8 /s
|
||
```
|
||
|
||
| | peak | duty | average | failure mode |
|
||
|---|---|---|---|---|
|
||
| DECODE ASIC | 20 /s | 100% | **20 /s** | none, forever |
|
||
| SOFTWARE DECODER | 100 /s | 30% | **25.8 /s** | total blackout, 16.7 s at a time |
|
||
|
||
Five ASICs at full song, one third of the time, in one 2×2 footprint. 29% more average
|
||
power for a supply that vanishes on a schedule you don't control — a real choice, and the
|
||
answer to "does anyone dare run two side by side" is still *no, not naked*: identical
|
||
decoders heat in lockstep and therefore black out in lockstep.
|
||
|
||
### `bufferCap: 240 → 300`
|
||
|
||
Re-derived against the retuned cycle, since the order was "one tank should cover one
|
||
decoder scram" and the scram window changed:
|
||
|
||
```
|
||
reference chain: peak draw 96 /s, compression pays back 18 /s -> net demand 78 /s
|
||
balanced plant: 3 ASIC (60/s steady) + 1 software decoder (25.8/s avg) = 85.8 /s ✓
|
||
decoder scrams: supply = 60 + 18 = 78 /s vs draw 96 /s -> deficit 18 /s
|
||
18 /s x 16.67 s = 300 bandwidth-seconds
|
||
bufferCap = 300 -> one tank rides out exactly one scram.
|
||
```
|
||
|
||
And it refills in time to do it again: while the decoder is up the plant makes 67/s more
|
||
than it spends, recharging 300 in **4.5 s** of the 7.25 s up-phase. That is the M2
|
||
sentence — **a buffer tank is what makes software decoders survivable** — and it now
|
||
closes.
|
||
|
||
### `heat` on the hex splicer: `coolPerTick 0.001`, 0.08 per splice
|
||
|
||
Net 0.035 per craft after the 45 ticks of cooling → 28.6 crafts → **42.9 s** of continuous
|
||
splicing before it scrams (`chart-stco-map`: 50 s). A lesser fever than the decoder's
|
||
14.5 s, exactly as ordered. §4: "Requires ... a steady buffer feed or it splices *itself*"
|
||
— left running unattended, it stops itself.
|
||
|
||
---
|
||
|
||
## Open / deferred
|
||
|
||
- **The ASIC cooler's aura is spec'd, not built** (above). Until SIM has auras, heat is
|
||
survivable only by duty-cycling or by leaning on ASICs. Deliberate.
|
||
- `cinema-pack`, `mosquito-swarm`, `gibbs-wraith` remain forward canon (no recipe). The
|
||
validator's FORWARD_CANON allowlist is the enforcement, and it has a companion test
|
||
asserting nothing sits on the list once it *is* producible. Round 3 retired
|
||
`container-pack`'s slot (round 2) and added none.
|
||
- Dials-as-recipes (quantizer Q, subsampler grades, GOP cadence) stays, per round-2 review.
|
||
- **The heat constants in `data/validate.test.ts` are mirrored from `src/sim/index.ts`**
|
||
(throttle 0.7, restart 0.5, dissipation default 0.004, 30 tps). They are not exported,
|
||
so my arithmetic tests can't import them. If SIM retunes the curve, my tests go stale
|
||
*silently* — they'd still pass while the feel drifts. Re-check on any heat round. A
|
||
cheap fix if SIM likes: export the constants.
|
||
- The muxer, moov brain and megaglitch are data-only; no lane implements a victory
|
||
condition yet. The tech gate (`fortress-the-muxer`) keeps them out of reach meanwhile.
|