[data] compliance quotas, the forged hash, and eight lines about being audited
Round 7 phase 1. The Correction grows an HR department. - COMPLIANCE QUOTAS: four `compliance:true` standing orders spread across the reward curve (indices 5/9/13/20) so the debt valve is never more than eight faxes away. Tier-0/1 only, enforced against SIM's DEBT_TIER_MIN rather than a hand-typed 2. Measured on the real sim: one quota vents -0.2004, i.e. exactly one band. - FORGED HASH: 1 STCO MAP + 50 HF DUST -> 1 FORGED HASH on the existing hex-splicer, gated behind a new fortress node. Two inputs, so it cannot travel SIM's empty-inputs catcher path; a test fails by name if it ever does. §6 names the forged article outright and the splicer has charted the genuine map since round 3 - the machine, the material and the crime were already in the data. - Eight STANDARD chyron lines, one per mechanic the player is about to meet, all <=96 chars. The width cap now has a test in this lane instead of SCREEN's. - CANON-DELTA: the rungs-2-4 reading of §5, the no-grudge ruling, the deviation-targeting ruling (tier is now read by three mechanics), and the forged hash's argument against the container-pack reading. Validator 74 -> 86; all 11 new checks fault-injected and restored.
This commit is contained in:
parent
60a14313b4
commit
3acd605e2e
@ -365,6 +365,137 @@ The `firewall` (no model yet) gets its forged-checkmark `#3fff7f` art-directed,
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Added in round 7
|
||||||
|
|
||||||
|
### THE CORRECTION's rungs 2-4 — what §5 asks of the data
|
||||||
|
|
||||||
|
§5's ladder is four rungs; round 6 built rung 1 (parity mites) and its counter. Rungs 2-4
|
||||||
|
are mechanics, and almost all of them are SIM's — the useful thing to record is how little
|
||||||
|
new *content* the enemy needs, and the one place it needs a lot.
|
||||||
|
|
||||||
|
| Rung | §5 | What data owes it |
|
||||||
|
|---|---|---|
|
||||||
|
| 2 CHECKSUM WARDEN | audits a machine, rolls back its last N outputs, stamps a compliance seal | **Nothing new.** The seal is `EntityState.sealed`, the counter is the FIREWALL authored in round 6, and the expensive counter is the `pry` command. |
|
||||||
|
| 3 REDUNDANCY GUNSHIP | mirrors a sector and out-ships you with a sanitised copy | **Nothing new** — but see the deviation ruling below, which quietly makes `ItemDef.tier` load-bearing for it. |
|
||||||
|
| 4 HASH AUDITOR | refuses a region into 0:00 stasis until you break the lock | **FORGED HASH** — the whole material counter, and the only new item this round. |
|
||||||
|
|
||||||
|
**The pry exchange rate is worth writing down.** `DEBT_PER_PRY` is 0.05 and
|
||||||
|
`DEBT_VENT_COMPLIANCE` is 0.2, so **four pried seals cost exactly one QUOTA 7-C to
|
||||||
|
undo**. The firewall is free and the crowbar is billed — which is the correct shape:
|
||||||
|
the counter you researched is cheap, and defacing a notice with your hands is not.
|
||||||
|
|
||||||
|
### The no-grudge ruling — the enemy has no feelings, only a ledger
|
||||||
|
|
||||||
|
RULING (SIM's, recorded here as canon): **canning a Correction unit adds no debt.** §5 is
|
||||||
|
explicit — it "does not hate you; it *cannot perceive* you — only deviation, which it
|
||||||
|
repairs." A grudge requires a perceiver. So the firewall is free, the mite in the jar is
|
||||||
|
free, and round 6's `correction-specimen` (1000) and `annual-correction-cull` (2100,
|
||||||
|
standing) stay pure profit with no hidden tax on farming the immune system.
|
||||||
|
|
||||||
|
The consequence is the interesting half: **the only two things that raise the figure are
|
||||||
|
shipping corruption and prying seals** — and both of those are things you did to the *file*,
|
||||||
|
not things you did to *them*. You cannot anger The Correction. You can only be, statistically,
|
||||||
|
a region of the file that does not match.
|
||||||
|
|
||||||
|
### The deviation-targeting ruling — `tier` is not flavour any more
|
||||||
|
|
||||||
|
RULING (SIM's): a gunship tethers to the 8×8 sector with the most **tier≥2 output**, not the
|
||||||
|
most throughput. It corrects corruption, not productivity — an honest, busy, boring sector is
|
||||||
|
invisible to it, which is the same joke the mites tell one rung down.
|
||||||
|
|
||||||
|
Recording it because of what it does to this lane: `ItemDef.tier` is now read by **three**
|
||||||
|
separate mechanics — `MITE_TIER_MIN` (what a mite will repair), `DEBT_TIER_MIN` (what counts
|
||||||
|
as deviation when shipped), and now the gunship's sector scoring. **A tier number is no longer
|
||||||
|
decoration.** Mis-tiering an item now mis-aims an airborne enemy and mis-prices the debt
|
||||||
|
economy at the same time. Standing rule for future rounds: tier is a mechanic; argue it.
|
||||||
|
|
||||||
|
### COMPLIANCE QUOTAS — The Correction's register
|
||||||
|
|
||||||
|
Four `compliance: true` standing orders, spread across the reward curve so the valve is
|
||||||
|
never far from the tray (indices 5, 9, 13, 20 of 25):
|
||||||
|
|
||||||
|
| Quota | Wants | Reward | The horror |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `quota-7c` | 40 LUMA BARS | 150 | The order's own exemplar. "THE FILE THANKS YOU FOR YOUR COOPERATION. THE FILE DOES NOT KNOW YOUR NAME." |
|
||||||
|
| `quota-12a` | 80 MDAT ORE + 30 HF DUST | 340 | *"We are not purchasing these. We are removing them from the possibility of becoming something."* |
|
||||||
|
| `quota-30r` | 100 bbl CHROMA SLURRY | 620 | The callback. `first-refinement` taught you the demuxer's slurry is *your problem now*; The Correction has been waiting four commissions to solve it for you, forever, and not ask what you were going to do with it. |
|
||||||
|
| `quota-99z` | 40 GOP CRATES + 25 ANCHOR SLABS | 1600 | Sealed and unmoshed. You run the entire M1 chain and then hand over the crate *instead of* making melt with it. The endgame quota asks you to build the factory and decline to be it. |
|
||||||
|
|
||||||
|
**Why tier-0/1 is the whole rule.** Debt rises on tier≥`DEBT_TIER_MIN` shipments, so a quota
|
||||||
|
that wanted a tier-2 product would charge the player debt for venting debt. The validator
|
||||||
|
fails such a quota by name and by tier. It is also the fiction, exactly: the register cannot
|
||||||
|
ask for corruption, because from inside the file corruption is not a thing you *have*, it is
|
||||||
|
a thing that is *wrong with you*.
|
||||||
|
|
||||||
|
**Why they are standing orders.** A valve you can open once is not a valve. All four repeat,
|
||||||
|
and all four are fillable at tick 0 with zero research — pinned by a test, because debt starts
|
||||||
|
climbing the moment the first melt ships and the tech tree opens much later than that. A quota
|
||||||
|
gated behind research would be a fire escape welded shut.
|
||||||
|
|
||||||
|
**Why the pay is good.** In voice: `correction-buyback` has said since round 2 that "we pay
|
||||||
|
well, we pay immediately, and we pay every time." The quota is *supposed* to be tempting —
|
||||||
|
shipping boring content on purpose only becomes a real strategy if it is a real temptation.
|
||||||
|
The counterweight is not the rate, it is the ceiling: the register can never ask for anything
|
||||||
|
above tier 1, so it cannot scale with you, while the collectors' ladder climbs to 3200. Late
|
||||||
|
game, QUOTA 99-Z's 1600 is half of `quarterly-sins`. You outgrow compliance; that is the arc.
|
||||||
|
|
||||||
|
### FORGED HASH — the moov heist, industrialised
|
||||||
|
|
||||||
|
`forge-hash` on the existing HEX SPLICER: **1 STCO MAP + 50 HF DUST → 1 FORGED HASH**
|
||||||
|
(tier 3), 240 ticks, bandwidth 40, heat 0.4. Gated by a new fortress node
|
||||||
|
`fortress-moov-heists` (35 container + 25 temporal packs).
|
||||||
|
|
||||||
|
The order suggested `container-pack + hf-dust`; here is the argument for the other reading,
|
||||||
|
as asked.
|
||||||
|
|
||||||
|
1. **No recipe in this game consumes a science pack.** Packs are research currency, spent at
|
||||||
|
the lab and nowhere else — that is one of the few genuinely clean lines in the economy.
|
||||||
|
The endgame counter should not be the single exception that blurs it.
|
||||||
|
2. **§6 names the material outright.** MOOV HEISTS: *"scan scrolling hex for real frame
|
||||||
|
signatures ... and rebuild/forge the stco/stsz index to your advantage."* The forged
|
||||||
|
article **is** the stco index. And the machine was already standing there: §4's hex
|
||||||
|
splicer is *"a robotic hex-editor"* over *"a scrolling hexadecimal ticker-tape"*, and it
|
||||||
|
has charted the genuine `stco-map` since round 3. The machine, the material and the crime
|
||||||
|
were all already in the data. The recipe only admits it.
|
||||||
|
3. **You cannot forge a document you have never seen a real copy of.** Consuming a genuine
|
||||||
|
STCO MAP is the forger's first rule, and it is why the input is the expensive one.
|
||||||
|
4. **HF DUST is the forger's second rule, and this is the part I like.** A hash is a digest:
|
||||||
|
to make one land where you want it, you append bytes that change nothing anyone can see.
|
||||||
|
HF DUST is *literally* the high-frequency detail the quantizer threw away — invisible
|
||||||
|
bytes, in barrels. Packing the discarded difference back in until the numbers agree is how
|
||||||
|
a real collision is actually built. It also hands the game's most over-produced byproduct a
|
||||||
|
genuine endgame sink: 50 per forgery, against `pan-speckle`'s 40.
|
||||||
|
5. **It costs the victory chain.** `assemble-moov-brain` wants an STCO MAP too, so every
|
||||||
|
forgery is one MEGAGLITCH deferred. You spend the endgame to survive the endgame — the
|
||||||
|
correct price for voiding an inquisition.
|
||||||
|
|
||||||
|
**Shape note for SIM, as ordered:** `forge-hash` has **two inputs**, so it cannot and must not
|
||||||
|
travel the empty-inputs catcher path that spots traps and firewalls. A test now fails by name
|
||||||
|
if *any* input-free recipe ever produces `forged-hash`, so the second detection you budgeted
|
||||||
|
can rely on the shape staying an ordinary craft. The item id is exactly your
|
||||||
|
`FORGED_HASH_ITEM`, imported rather than retyped.
|
||||||
|
|
||||||
|
### Eight more STANDARD lines — the audit pool
|
||||||
|
|
||||||
|
Chyron 38 → 46 lines (~15 minutes before a repeat). One line per mechanic the player is about
|
||||||
|
to meet, all ≤96 chars, all in the reassuring-menace register:
|
||||||
|
|
||||||
|
```
|
||||||
|
Units conducting review are not present. What is not present cannot be obstructed. <- you cannot fight them
|
||||||
|
The sector was always white. You are remembering a draft. <- stasis
|
||||||
|
A seal is not a punishment. A seal is a machine being permitted to rest. <- the warden's seal
|
||||||
|
If your work appears beside itself, the copy is the one doing it correctly. <- the gunship mirror
|
||||||
|
An audit finds nothing where there is nothing. Be nothing for five seconds. <- ABSTENTION, taught
|
||||||
|
Your ledger is not a debt. It is a description, and descriptions are revised down… <- the quota valve
|
||||||
|
We do not lock a sector. We decline to unlock it. These are different services. <- the auditor
|
||||||
|
A hash you wrote yourself is still a hash. We will read it. We will believe it. <- the forged hash
|
||||||
|
```
|
||||||
|
|
||||||
|
Round 6's lesson is now enforced in this lane rather than discovered in SCREEN's: the 96-char
|
||||||
|
cap has its own test here, deliberately a conservative local copy of theirs.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## The numbers, and the arithmetic behind them
|
## The numbers, and the arithmetic behind them
|
||||||
|
|
||||||
### The reference M1 chain (measured, not guessed)
|
### The reference M1 chain (measured, not guessed)
|
||||||
@ -572,6 +703,100 @@ paid for with the quantizer's own sins** — you study your own damage. Later no
|
|||||||
tens of minutes and demand the analog/temporal/container chains, which is where the floor
|
tens of minutes and demand the analog/temporal/container chains, which is where the floor
|
||||||
space goes.
|
space goes.
|
||||||
|
|
||||||
|
### Round 7: how fast a melt line walks the ladder, and what a quota buys back
|
||||||
|
|
||||||
|
All against LANE-SIM's constants as landed (`DEBT_PER_CORRUPT_SHIP 0.0025`,
|
||||||
|
`DEBT_DECAY_PER_TICK 0.00002`, bands `[0.2, 0.4, 0.6, 0.8]`).
|
||||||
|
|
||||||
|
One mosh reactor is 3 MELT per 90 ticks — the M1 chain's whole point. That is
|
||||||
|
`3 × 0.0025 = 0.0075` of debt per 90 ticks, less 90 ticks of decay:
|
||||||
|
|
||||||
|
```
|
||||||
|
net climb = 0.0075/90 − 0.00002 = 0.0000633 / tick
|
||||||
|
band 1 OBSERVED (0.2) = 3,160 ticks = 1m 45s of shipping melt
|
||||||
|
band 2 AUDITED (0.4) = 6,320 ticks = 3m 31s <- wardens
|
||||||
|
band 3 SEALED (0.6) = 9,480 ticks = 5m 16s <- gunships
|
||||||
|
band 4 REFUSED (0.8) = 12,640 ticks = 7m 01s <- auditors
|
||||||
|
```
|
||||||
|
|
||||||
|
**A single-reactor factory that never ships anything boring meets all four rungs inside
|
||||||
|
seven minutes.** That is the pressure the valve exists to answer.
|
||||||
|
|
||||||
|
Measured, not modelled — LANE-SIM's real reference factory on my real JSON (throwaway
|
||||||
|
probe, then deleted; sim behaviour is their lane to test):
|
||||||
|
|
||||||
|
```
|
||||||
|
band 1 OBSERVED t = 5,874 (3m 16s)
|
||||||
|
band 2 AUDITED t = 9,281 (5m 09s) <- wardens
|
||||||
|
band 3 SEALED t = 12,740 (7m 04s) <- gunships
|
||||||
|
band 4 REFUSED t = 16,152 (8m 58s) <- auditors
|
||||||
|
```
|
||||||
|
|
||||||
|
Slower than the clean model because the reference plant spends its early minutes building
|
||||||
|
up rather than shipping, and because 1,013 of its 3,300-odd corrupt shipments are
|
||||||
|
macroblock bricks that arrive in a late burst. Same shape, ~1.3× the clock: **the whole
|
||||||
|
enemy ladder unspools inside the first nine minutes of a working factory.**
|
||||||
|
|
||||||
|
Against it, QUOTA 7-C: 40 LUMA BARS is 20 `demux-ore` crafts (45 ticks each) = **900 ticks,
|
||||||
|
30 seconds** on one demuxer fed by two extractors. Completing it vents 0.2 outright —
|
||||||
|
bands are 0.2 wide, so **one quota = exactly one band** — plus 0.024 of loose clean credit
|
||||||
|
from the material itself.
|
||||||
|
|
||||||
|
```
|
||||||
|
30 seconds of a two-machine side line buys back 1m 45s of melt-shipping debt
|
||||||
|
```
|
||||||
|
|
||||||
|
~3.5× leverage in time, deliberately. The strategy has to be *tempting* or nobody chooses
|
||||||
|
to be boring. What it actually costs is floor and ore: the quota line is a second copy of
|
||||||
|
the rung-1 starter factory that will never make a single unit of product.
|
||||||
|
|
||||||
|
**The vent must beat the material, and now that is a test.** SIM's comment says the vent is
|
||||||
|
"deliberately worth more than the material: the paperwork is the point, not the luma." Every
|
||||||
|
quota is measured against it — loose clean credit (`items × DEBT_CLEAN_CREDIT_PER_ITEM`) must
|
||||||
|
stay under `DEBT_VENT_COMPLIANCE`, or the fax would be a worse version of just belting the
|
||||||
|
same crates at the sky:
|
||||||
|
|
||||||
|
```
|
||||||
|
quota-7c 40 items -> 0.024 credit 12% of the 0.2 vent
|
||||||
|
quota-12a 110 items -> 0.066 33%
|
||||||
|
quota-30r 100 items -> 0.060 30%
|
||||||
|
quota-99z 65 items -> 0.039 20%
|
||||||
|
```
|
||||||
|
|
||||||
|
All well under the 0.25 `DEBT_CLEAN_CREDIT_MAX` ceiling too, so no quota asks for material
|
||||||
|
the economy will discard on arrival. The paperwork is worth 3-8× the luma. As intended.
|
||||||
|
|
||||||
|
**And the valve was measured, end to end, in the real sim.** QUOTA 30-R wants 100 bbl
|
||||||
|
CHROMA SLURRY and the reference factory ships 230 of it, so hoisting that quota to the head
|
||||||
|
of the queue (in memory; the JSON on disk untouched) exercises the whole path:
|
||||||
|
|
||||||
|
```
|
||||||
|
t=10,932 DONE quota-30r debt 0.3112 -> 0.1108 (delta -0.2004)
|
||||||
|
band 1 -> band 0, and the standing order re-queued to the back
|
||||||
|
```
|
||||||
|
|
||||||
|
−0.2004 is `DEBT_VENT_COMPLIANCE` exactly, plus that tick's own decay. **One quota, one
|
||||||
|
band, measured.** The claim in the table above is not arithmetic; it is a reading.
|
||||||
|
|
||||||
|
### Round 7: the forged hash's fever, and why one fits inside the fax
|
||||||
|
|
||||||
|
`forge-hash` banks 0.4 per craft; the splicer sheds `240 × 0.001 = 0.24` over the same 240
|
||||||
|
ticks. Net **0.16 per craft → 6.25 crafts → 1,500 ticks = 50s** of continuous forging before
|
||||||
|
it scrams. Identical to `chart-stco-map`'s 50s and still a lesser fever than the decoder's
|
||||||
|
14.5s, so the round-3 ordering holds: **the splicer can make six forgeries, then it must cool.**
|
||||||
|
|
||||||
|
The timing that matters is against `AUDITOR_NOTICE_TICKS = 600`:
|
||||||
|
|
||||||
|
```
|
||||||
|
notice -> stasis 600 ticks (20s)
|
||||||
|
one forgery 240 ticks (8s)
|
||||||
|
```
|
||||||
|
|
||||||
|
One forgery fits inside the fax lead time **with room to spare — but only if the STCO MAP is
|
||||||
|
already on the belt.** So the real preparation is stockpiling maps, which competes directly
|
||||||
|
with `assemble-moov-brain`. §4's line on the splicer ("requires a steady buffer feed or it
|
||||||
|
splices *itself*") turns out to be the auditor counter's whole difficulty curve.
|
||||||
|
|
||||||
### `heat` on the hex splicer: `coolPerTick 0.001`, 0.08 per splice
|
### `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
|
Net 0.035 per craft after the 45 ticks of cooling → 28.6 crafts → **42.9 s** of continuous
|
||||||
@ -596,3 +821,12 @@ splicing before it scrams (`chart-stco-map`: 50 s). A lesser fever than the deco
|
|||||||
retunes the curve my arithmetic now fails loudly instead of asserting the old feel.
|
retunes the curve my arithmetic now fails loudly instead of asserting the old feel.
|
||||||
- The muxer, moov brain and megaglitch are data-only; no lane implements a victory
|
- 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.
|
condition yet. The tech gate (`fortress-the-muxer`) keeps them out of reach meanwhile.
|
||||||
|
- **The register is a queue position, not a register (round 7, open).** SIM credits only
|
||||||
|
`commissionQueue[0]`, so a compliance quota can only be filed when it reaches the head.
|
||||||
|
Standing quotas do re-queue to the back, so mid-game the valve comes round periodically —
|
||||||
|
but it is not the on-demand relief the fiction implies ("standing quota; there is no final
|
||||||
|
collection, only the next one"). Mitigated in data by spreading four quotas across the
|
||||||
|
curve so at most 8 commissions ever sit between valves, and pinned by a test. The real fix
|
||||||
|
is a parallel always-open register, which is a contract/mechanic question, not a data one.
|
||||||
|
- **`ItemDef.tier` is now read by three mechanics** (mite repair, debt accrual, gunship
|
||||||
|
sector scoring). Any future re-tier is a balance change in three places at once.
|
||||||
|
|||||||
@ -19,6 +19,10 @@
|
|||||||
"flavor": "12 STATIC CANISTERS, brine grade, not display grade. Our previous supplier shipped display grade and we no longer speak of them. Standing order; the jars come back empty and we do not explain why.",
|
"flavor": "12 STATIC CANISTERS, brine grade, not display grade. Our previous supplier shipped display grade and we no longer speak of them. Standing order; the jars come back empty and we do not explain why.",
|
||||||
"wants": { "static-canister": 12 }, "rewardBandwidth": 120, "repeat": true },
|
"wants": { "static-canister": 12 }, "rewardBandwidth": 120, "repeat": true },
|
||||||
|
|
||||||
|
{ "id": "quota-7c",
|
||||||
|
"flavor": "QUOTA 7-C: 40 LUMA BARS. Grey card. No cast, no character, no opinion. THE FILE THANKS YOU FOR YOUR COOPERATION. THE FILE DOES NOT KNOW YOUR NAME. Standing quota; there is no final collection, only the next one. Your figure has been revised downward.",
|
||||||
|
"wants": { "luma-bars": 40 }, "rewardBandwidth": 150, "repeat": true, "compliance": true },
|
||||||
|
|
||||||
{ "id": "patio-resurfacing",
|
{ "id": "patio-resurfacing",
|
||||||
"flavor": "48 MACROBLOCK BRICKS for a patio. Client has been advised the patio will not be flat. Client insists the patio has never been flat. Proceed.",
|
"flavor": "48 MACROBLOCK BRICKS for a patio. Client has been advised the patio will not be flat. Client insists the patio has never been flat. Proceed.",
|
||||||
"wants": { "macroblock-bricks": 48 }, "rewardBandwidth": 220 },
|
"wants": { "macroblock-bricks": 48 }, "rewardBandwidth": 220 },
|
||||||
@ -31,6 +35,10 @@
|
|||||||
"flavor": "9 RINGING HALOS, hung not stacked. They are for a doorway. The doorway is for nothing. Do not ask what comes through it; it is already through. [someone has drawn a sine wave in the corner of this fax. it is not our department.]",
|
"flavor": "9 RINGING HALOS, hung not stacked. They are for a doorway. The doorway is for nothing. Do not ask what comes through it; it is already through. [someone has drawn a sine wave in the corner of this fax. it is not our department.]",
|
||||||
"wants": { "ringing-halos": 9, "gamut-paint-rec709": 2 }, "rewardBandwidth": 300 },
|
"wants": { "ringing-halos": 9, "gamut-paint-rec709": 2 }, "rewardBandwidth": 300 },
|
||||||
|
|
||||||
|
{ "id": "quota-12a",
|
||||||
|
"flavor": "QUOTA 12-A: 80 MDAT ORE, unwashed, and 30 HF DUST, swept. We are not purchasing these. We are removing them from the possibility of becoming something. Nothing sent to this address will ever be looked at, and that is the service. THE FILE THANKS YOU.",
|
||||||
|
"wants": { "mdat-ore": 80, "hf-dust": 30 }, "rewardBandwidth": 340, "repeat": true, "compliance": true },
|
||||||
|
|
||||||
{ "id": "correction-buyback",
|
{ "id": "correction-buyback",
|
||||||
"flavor": "Good morning. Our records show 5 unreferenced ANCHOR SLABS in your sector. We would like to purchase them. We pay well, we pay immediately, and we pay every time. This is not an audit. You are not in trouble. There is no trouble. Your file looks so much better already. We will be here.",
|
"flavor": "Good morning. Our records show 5 unreferenced ANCHOR SLABS in your sector. We would like to purchase them. We pay well, we pay immediately, and we pay every time. This is not an audit. You are not in trouble. There is no trouble. Your file looks so much better already. We will be here.",
|
||||||
"wants": { "anchor-slab": 5 }, "rewardBandwidth": 450, "repeat": true },
|
"wants": { "anchor-slab": 5 }, "rewardBandwidth": 450, "repeat": true },
|
||||||
@ -43,6 +51,10 @@
|
|||||||
"flavor": "STANDING ORDER: 25 MELT per collection, indefinitely. Our client is redecorating. Our client has not specified an end date. We have stopped asking our client things.",
|
"flavor": "STANDING ORDER: 25 MELT per collection, indefinitely. Our client is redecorating. Our client has not specified an end date. We have stopped asking our client things.",
|
||||||
"wants": { "melt": 25 }, "rewardBandwidth": 560, "repeat": true },
|
"wants": { "melt": 25 }, "rewardBandwidth": 560, "repeat": true },
|
||||||
|
|
||||||
|
{ "id": "quota-30r",
|
||||||
|
"flavor": "QUOTA 30-R: 100 bbl CHROMA SLURRY. Any subsampling. No ceiling, no schedule, no end. We understand you have more of this than you want. We understand a great many things about your sector that nobody told us. Pour it in. We will take all of it, always, and we will not ask what you were going to do with it.",
|
||||||
|
"wants": { "chroma-slurry": 100 }, "rewardBandwidth": 620, "repeat": true, "compliance": true },
|
||||||
|
|
||||||
{ "id": "vaporwave-sunset",
|
{ "id": "vaporwave-sunset",
|
||||||
"flavor": "1 MELTED ANCHOR SLAB + 3 MOSQUITO SWARMS (live) + 40 bbl CHROMA SLURRY (4:2:0) = 1 VAPORWAVE SUNSET. Deliver before the beat drops.",
|
"flavor": "1 MELTED ANCHOR SLAB + 3 MOSQUITO SWARMS (live) + 40 bbl CHROMA SLURRY (4:2:0) = 1 VAPORWAVE SUNSET. Deliver before the beat drops.",
|
||||||
"wants": { "melt": 1, "anchor-slab": 1, "mosquito-swarm": 3, "chroma-420": 40 }, "rewardBandwidth": 700 },
|
"wants": { "melt": 1, "anchor-slab": 1, "mosquito-swarm": 3, "chroma-420": 40 }, "rewardBandwidth": 700 },
|
||||||
@ -67,6 +79,10 @@
|
|||||||
"flavor": "4 CONTAINER PACKS and 20 EXPLOSIVE HITS, shipped in that order and not the other order. The last supplier shipped in the other order. There is no last supplier.",
|
"flavor": "4 CONTAINER PACKS and 20 EXPLOSIVE HITS, shipped in that order and not the other order. The last supplier shipped in the other order. There is no last supplier.",
|
||||||
"wants": { "container-pack": 4, "explosive-hits": 20 }, "rewardBandwidth": 1400 },
|
"wants": { "container-pack": 4, "explosive-hits": 20 }, "rewardBandwidth": 1400 },
|
||||||
|
|
||||||
|
{ "id": "quota-99z",
|
||||||
|
"flavor": "QUOTA 99-Z: 40 GOP CRATES, SEALED, and 25 ANCHOR SLABS, UNMOSHED. Do not open them. Do not improve them. We are aware what your reactor does to a crate and we would like this batch to arrive having never met it. Your cooperation is recorded in a file whose only contents are your cooperation.",
|
||||||
|
"wants": { "gop-crate": 40, "anchor-slab": 25 }, "rewardBandwidth": 1600, "repeat": true, "compliance": true },
|
||||||
|
|
||||||
{ "id": "sodium-requisition",
|
{ "id": "sodium-requisition",
|
||||||
"flavor": "One (1) beam of SODIUM LIGHT, 589nm, in its prism. We are aware who holds the prisms. We are aware what they call it when you take one. We are prepared to call it something else. 30 BLUE HOLES accepted as consolation if you lose your nerve.",
|
"flavor": "One (1) beam of SODIUM LIGHT, 589nm, in its prism. We are aware who holds the prisms. We are aware what they call it when you take one. We are prepared to call it something else. 30 BLUE HOLES accepted as consolation if you lose your nerve.",
|
||||||
"wants": { "sodium-light": 1, "blue-hole": 30 }, "rewardBandwidth": 1800 },
|
"wants": { "sodium-light": 1, "blue-hole": 30 }, "rewardBandwidth": 1800 },
|
||||||
|
|||||||
@ -67,5 +67,7 @@
|
|||||||
{ "id": "stss-keyring", "name": "STSS KEYRING", "codex": "7:the-muxer", "tier": 2, "color": "#e0b83f" },
|
{ "id": "stss-keyring", "name": "STSS KEYRING", "codex": "7:the-muxer", "tier": 2, "color": "#e0b83f" },
|
||||||
{ "id": "ftyp-seal", "name": "FTYP SEAL", "codex": "7:the-muxer", "tier": 2, "color": "#b08fd0" },
|
{ "id": "ftyp-seal", "name": "FTYP SEAL", "codex": "7:the-muxer", "tier": 2, "color": "#b08fd0" },
|
||||||
{ "id": "moov-brain", "name": "THE MOOV BRAIN", "codex": "7:the-muxer", "tier": 3, "color": "#d8a0ff" },
|
{ "id": "moov-brain", "name": "THE MOOV BRAIN", "codex": "7:the-muxer", "tier": 3, "color": "#d8a0ff" },
|
||||||
{ "id": "megaglitch", "name": "THE MEGAGLITCH", "codex": "7:the-megaglitch", "tier": 3, "color": "#ff2fd4" }
|
{ "id": "megaglitch", "name": "THE MEGAGLITCH", "codex": "7:the-megaglitch", "tier": 3, "color": "#ff2fd4" },
|
||||||
|
|
||||||
|
{ "id": "forged-hash", "name": "FORGED HASH", "codex": "6:moov-heists", "tier": 3, "color": "#5fff9f" }
|
||||||
]
|
]
|
||||||
|
|||||||
@ -70,7 +70,7 @@
|
|||||||
"asset": "telecine-puller", "color": "#6e5a38",
|
"asset": "telecine-puller", "color": "#6e5a38",
|
||||||
"flavor": "Cranks 24 into 30 on a deliberately lumpy cam. Runs backwards as a purifier, which we do not discuss on site." },
|
"flavor": "Cranks 24 into 30 on a deliberately lumpy cam. Runs backwards as a purifier, which we do not discuss on site." },
|
||||||
{ "id": "hex-splicer", "name": "HEX SPLICER", "codex": "4:hex-splicer", "kind": "crafter",
|
{ "id": "hex-splicer", "name": "HEX SPLICER", "codex": "4:hex-splicer", "kind": "crafter",
|
||||||
"footprint": { "x": 3, "y": 3 }, "recipes": ["splice-offsets", "chart-stco-map"], "powerDraw": 12,
|
"footprint": { "x": 3, "y": 3 }, "recipes": ["splice-offsets", "chart-stco-map", "forge-hash"], "powerDraw": 12,
|
||||||
"coolPerTick": 0.001,
|
"coolPerTick": 0.001,
|
||||||
"asset": "hex-splicer", "color": "#5a3a3a",
|
"asset": "hex-splicer", "color": "#5a3a3a",
|
||||||
"flavor": "Nudges the offsets a few bytes so the decoder fetches garbage. Keep its buffer fed, or it splices itself." },
|
"flavor": "Nudges the offsets a few bytes so the decoder fetches garbage. Keep its buffer fed, or it splices itself." },
|
||||||
|
|||||||
@ -84,6 +84,8 @@
|
|||||||
"outputs": { "explosive-hits": 4, "hf-dust": 2 }, "ticks": 45, "bandwidth": 20, "heat": 0.08 },
|
"outputs": { "explosive-hits": 4, "hf-dust": 2 }, "ticks": 45, "bandwidth": 20, "heat": 0.08 },
|
||||||
{ "id": "chart-stco-map", "machine": "hex-splicer", "inputs": { "offset-ribbon": 3, "moov-shard": 1 },
|
{ "id": "chart-stco-map", "machine": "hex-splicer", "inputs": { "offset-ribbon": 3, "moov-shard": 1 },
|
||||||
"outputs": { "stco-map": 1 }, "ticks": 90, "bandwidth": 14, "heat": 0.15 },
|
"outputs": { "stco-map": 1 }, "ticks": 90, "bandwidth": 14, "heat": 0.15 },
|
||||||
|
{ "id": "forge-hash", "machine": "hex-splicer", "inputs": { "stco-map": 1, "hf-dust": 50 },
|
||||||
|
"outputs": { "forged-hash": 1 }, "ticks": 240, "bandwidth": 40, "heat": 0.4 },
|
||||||
|
|
||||||
{ "id": "bait-swarm", "machine": "mosquito-trap", "inputs": {},
|
{ "id": "bait-swarm", "machine": "mosquito-trap", "inputs": {},
|
||||||
"outputs": { "mosquito-swarm": 1 }, "ticks": 90, "bandwidth": 3 },
|
"outputs": { "mosquito-swarm": 1 }, "ticks": 90, "bandwidth": 3 },
|
||||||
|
|||||||
@ -69,7 +69,15 @@
|
|||||||
"Your corruption is healing on the belt. That is not a fault. That is the warranty.",
|
"Your corruption is healing on the belt. That is not a fault. That is the warranty.",
|
||||||
"Do not build the drawer with a seal we never issued. It is unkind to the technicians.",
|
"Do not build the drawer with a seal we never issued. It is unkind to the technicians.",
|
||||||
"Every mite you can holds a correction never made. Somewhere a frame stays wrong. We forgive you.",
|
"Every mite you can holds a correction never made. Somewhere a frame stays wrong. We forgive you.",
|
||||||
"There is no infestation. There is only maintenance you did not schedule and cannot cancel."
|
"There is no infestation. There is only maintenance you did not schedule and cannot cancel.",
|
||||||
|
"Units conducting review are not present. What is not present cannot be obstructed.",
|
||||||
|
"The sector was always white. You are remembering a draft.",
|
||||||
|
"A seal is not a punishment. A seal is a machine being permitted to rest.",
|
||||||
|
"If your work appears beside itself, the copy is the one doing it correctly.",
|
||||||
|
"An audit finds nothing where there is nothing. Be nothing for five seconds.",
|
||||||
|
"Your ledger is not a debt. It is a description, and descriptions are revised downward.",
|
||||||
|
"We do not lock a sector. We decline to unlock it. These are different services.",
|
||||||
|
"A hash you wrote yourself is still a hash. We will read it. We will believe it."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -51,6 +51,9 @@
|
|||||||
"cost": { "container-pack": 40, "temporal-pack": 30, "spatial-pack": 30 },
|
"cost": { "container-pack": 40, "temporal-pack": 30, "spatial-pack": 30 },
|
||||||
"unlocks": ["tally-stsz-ledger", "chart-stco-map", "wind-stts-metronome",
|
"unlocks": ["tally-stsz-ledger", "chart-stco-map", "wind-stts-metronome",
|
||||||
"forge-stss-keyring", "cut-ftyp-seal", "assemble-moov-brain"] },
|
"forge-stss-keyring", "cut-ftyp-seal", "assemble-moov-brain"] },
|
||||||
|
{ "id": "fortress-moov-heists", "era": "fortress",
|
||||||
|
"cost": { "container-pack": 35, "temporal-pack": 25 },
|
||||||
|
"unlocks": ["forge-hash"] },
|
||||||
{ "id": "fortress-neural-keyer", "era": "fortress",
|
{ "id": "fortress-neural-keyer", "era": "fortress",
|
||||||
"cost": { "container-pack": 50, "analog-pack": 50, "spatial-pack": 50, "temporal-pack": 50 },
|
"cost": { "container-pack": 50, "analog-pack": 50, "spatial-pack": 50, "temporal-pack": 50 },
|
||||||
"unlocks": ["neural-keyer", "neural-key", "neural-unmix"] },
|
"unlocks": ["neural-keyer", "neural-key", "neural-unmix"] },
|
||||||
|
|||||||
@ -14,6 +14,12 @@ import { TICKS_PER_SECOND } from '../src/contracts';
|
|||||||
import {
|
import {
|
||||||
HEAT_COOL_DEFAULT, HEAT_COOL_MAX, HEAT_RESTART, HEAT_THROTTLE_START,
|
HEAT_COOL_DEFAULT, HEAT_COOL_MAX, HEAT_RESTART, HEAT_THROTTLE_START,
|
||||||
} from '../src/sim/constants';
|
} from '../src/sim/constants';
|
||||||
|
// Round 7, same rule: THE CORRECTION's economy is SIM's arithmetic, so the quota
|
||||||
|
// content is checked against the real constants rather than a hand-typed 2 and 0.2.
|
||||||
|
import {
|
||||||
|
DEBT_BANDS, DEBT_CLEAN_CREDIT_MAX, DEBT_CLEAN_CREDIT_PER_ITEM, DEBT_TIER_MIN,
|
||||||
|
DEBT_VENT_COMPLIANCE, FORGED_HASH_ITEM,
|
||||||
|
} from '../src/sim/constants';
|
||||||
|
|
||||||
import itemsJson from './items.json';
|
import itemsJson from './items.json';
|
||||||
import machinesJson from './machines.json';
|
import machinesJson from './machines.json';
|
||||||
@ -387,6 +393,39 @@ describe('recipes', () => {
|
|||||||
expect(wanters.length, 'no commission wants a canned mite').toBeGreaterThan(0);
|
expect(wanters.length, 'no commission wants a canned mite').toBeGreaterThan(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('the forged hash exists under exactly the id the auditor counter looks for', () => {
|
||||||
|
// Round 7, coordinated with SIM: `FORGED_HASH_ITEM` is the constant their hash-auditor
|
||||||
|
// reads when deciding whether a prescan finds anything. If this item id drifts, the
|
||||||
|
// material counter silently stops existing and abstention becomes the only answer —
|
||||||
|
// which is exactly how the constant's own comment describes the no-data case.
|
||||||
|
const forged = items.find((i) => i.id === FORGED_HASH_ITEM);
|
||||||
|
expect(forged, `no item is "${FORGED_HASH_ITEM}" — the audit counter does not exist`).toBeTruthy();
|
||||||
|
expect(forged!.tier).toBe(3);
|
||||||
|
expect(recipes.some((r) => (r.outputs[FORGED_HASH_ITEM] ?? 0) > 0)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('the forged hash has inputs — it must NOT read as a wildlife catcher', () => {
|
||||||
|
// The trap and the firewall are detected BY SHAPE: empty inputs. SIM budgeted a
|
||||||
|
// second, separate detection for the forged hash precisely because it is an ordinary
|
||||||
|
// two-input craft. An input-free forge would collide with the catcher path and the
|
||||||
|
// splicer would start conjuring forgeries out of nothing.
|
||||||
|
const forges = recipes.filter((r) => (r.outputs[FORGED_HASH_ITEM] ?? 0) > 0);
|
||||||
|
const freeLunch = forges.filter((r) => Object.keys(r.inputs).length === 0).map((r) => r.id);
|
||||||
|
expect(freeLunch, 'an input-free forge would be mistaken for a wildlife catcher').toEqual([]);
|
||||||
|
const forge = recipes.find((r) => r.id === 'forge-hash')!;
|
||||||
|
expect(Object.keys(forge.inputs).length).toBe(2);
|
||||||
|
expect(forge.machine).toBe('hex-splicer');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('the forged hash is late, and it is genuinely makeable', () => {
|
||||||
|
// Fortress-adjacent by order. A tick-0 forgery would defuse the endgame before it
|
||||||
|
// arrives; an unmakeable one would be a counter that only exists in the codex.
|
||||||
|
const gate = tech.find((t) => t.unlocks.includes('forge-hash'));
|
||||||
|
expect(gate, 'forge-hash is ungated — the seal can be forged in the tutorial').toBeTruthy();
|
||||||
|
expect(gate!.era).toBe('fortress');
|
||||||
|
expect([...producible()]).toContain(FORGED_HASH_ITEM);
|
||||||
|
});
|
||||||
|
|
||||||
it('every heat value is a 0..1 fraction per craft', () => {
|
it('every heat value is a 0..1 fraction per craft', () => {
|
||||||
const bad = recipes.filter((r) => r.heat !== undefined && !(r.heat >= 0 && r.heat <= 1))
|
const bad = recipes.filter((r) => r.heat !== undefined && !(r.heat >= 0 && r.heat <= 1))
|
||||||
.map((r) => `${r.id} -> heat ${r.heat}`);
|
.map((r) => `${r.id} -> heat ${r.heat}`);
|
||||||
@ -483,6 +522,105 @@ describe('commissions', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ------------------------------------------------- The Correction's register (v9)
|
||||||
|
//
|
||||||
|
// A `compliance: true` commission is not a collector's fax. It is the enemy's HR
|
||||||
|
// department, and completing one vents PARITY DEBT (DEBT_VENT_COMPLIANCE). That makes
|
||||||
|
// these the escalation valve, so they carry rules the ordinary queue does not: they may
|
||||||
|
// only ever ask for boring material, they must be re-fillable forever, and they must be
|
||||||
|
// fillable by a factory that has researched nothing — because debt starts climbing the
|
||||||
|
// moment the first melt ships, long before the tech tree opens.
|
||||||
|
|
||||||
|
describe('compliance quotas — The Correction\'s register', () => {
|
||||||
|
const quotas = commissions.filter((c) => c.compliance);
|
||||||
|
const gated = new Set(tech.flatMap((t) => t.unlocks));
|
||||||
|
const ungated = recipes.filter((r) => !gated.has(r.id) && !gated.has(r.machine));
|
||||||
|
const day0 = (() => {
|
||||||
|
const have = new Set<string>();
|
||||||
|
for (;;) {
|
||||||
|
const before = have.size;
|
||||||
|
for (const r of ungated) {
|
||||||
|
if (Object.keys(r.inputs).every((i) => have.has(i))) {
|
||||||
|
for (const o of Object.keys(r.outputs)) have.add(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (have.size === before) return have;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
const tierOf = new Map(items.map((i) => [i.id, i.tier]));
|
||||||
|
const total = (c: CommissionDef) => Object.values(c.wants).reduce((a, b) => a + b, 0);
|
||||||
|
|
||||||
|
it('the register exists at all', () => {
|
||||||
|
expect(quotas.length).toBeGreaterThanOrEqual(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('a quota only ever wants boring material — tier-0/1, never corruption', () => {
|
||||||
|
// THE RULE. Debt rises on tier>=DEBT_TIER_MIN shipments, so a quota that wanted a
|
||||||
|
// tier-2 product would charge the player debt for venting debt. Fails by name.
|
||||||
|
const bad = quotas.flatMap((c) =>
|
||||||
|
Object.keys(c.wants)
|
||||||
|
.filter((w) => (tierOf.get(w) ?? 0) >= DEBT_TIER_MIN)
|
||||||
|
.map((w) => `${c.id} wants tier-${tierOf.get(w)} "${w}" — that shipment IS deviation`));
|
||||||
|
expect(bad).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('every quota is a standing order — a valve you can open once is not a valve', () => {
|
||||||
|
const oneShot = quotas.filter((c) => !c.repeat).map((c) => c.id);
|
||||||
|
expect(oneShot).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('every quota is fillable at tick 0 — debt arrives before research does', () => {
|
||||||
|
const blocked = quotas.flatMap((c) =>
|
||||||
|
Object.keys(c.wants)
|
||||||
|
.filter((w) => !day0.has(w))
|
||||||
|
.map((w) => `${c.id} wants "${w}", which needs research — the valve is welded shut early`));
|
||||||
|
expect(blocked).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('the paperwork is worth more than the luma', () => {
|
||||||
|
// SIM's DEBT_CLEAN_CREDIT_PER_ITEM already pays for shipping boring things. The
|
||||||
|
// commission's vent must beat simply belting the same material at the sky, or the
|
||||||
|
// fax is a worse version of a thing the player can do without it.
|
||||||
|
const pointless = quotas
|
||||||
|
.map((c) => ({ c, credit: total(c) * DEBT_CLEAN_CREDIT_PER_ITEM }))
|
||||||
|
.filter(({ credit }) => credit >= DEBT_VENT_COMPLIANCE)
|
||||||
|
.map(({ c, credit }) =>
|
||||||
|
`${c.id} vents ${DEBT_VENT_COMPLIANCE} but its ${total(c)} items already credit ${credit.toFixed(3)} loose`);
|
||||||
|
expect(pointless).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('no quota is so large its own shipment blows the clean-credit ceiling', () => {
|
||||||
|
// Credit is capped (DEBT_CLEAN_CREDIT_MAX) so it cannot be hoarded. A quota that
|
||||||
|
// exceeds the cap in one collection is asking for material the economy discards.
|
||||||
|
const wasteful = quotas
|
||||||
|
.map((c) => ({ c, credit: total(c) * DEBT_CLEAN_CREDIT_PER_ITEM }))
|
||||||
|
.filter(({ credit }) => credit > DEBT_CLEAN_CREDIT_MAX)
|
||||||
|
.map(({ c, credit }) => `${c.id} banks ${credit.toFixed(3)} against a ${DEBT_CLEAN_CREDIT_MAX} ceiling`);
|
||||||
|
expect(wasteful).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('completing one is worth a whole band on the gauge', () => {
|
||||||
|
// Cross-lane pin, same spirit as the heat curve: if SIM widens the bands past the
|
||||||
|
// vent, the valve stops being visible and this fails loudly instead of the player
|
||||||
|
// discovering that compliance does nothing.
|
||||||
|
const narrowest = Math.min(...DEBT_BANDS.map((b, i) => b - (DEBT_BANDS[i - 1] ?? 0)));
|
||||||
|
expect(DEBT_VENT_COMPLIANCE).toBeGreaterThanOrEqual(narrowest);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('the valve is never far from the tray', () => {
|
||||||
|
// Debt can spike at any point in the run. If the quotas all clustered at one end of
|
||||||
|
// the queue there would be stretches of the game with no way to buy the gauge down.
|
||||||
|
const idx = commissions.map((c, i) => (c.compliance ? i : -1)).filter((i) => i >= 0);
|
||||||
|
const gaps = idx.map((i, n) => i - (n === 0 ? -1 : idx[n - 1]) - 1);
|
||||||
|
gaps.push(commissions.length - idx[idx.length - 1] - 1);
|
||||||
|
const droughts = gaps
|
||||||
|
.map((g, n) => ({ g, n }))
|
||||||
|
.filter(({ g }) => g > 8)
|
||||||
|
.map(({ g, n }) => `${g} commissions in a row with no quota (run ${n})`);
|
||||||
|
expect(droughts).toEqual([]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// The v4 gating rule ("a machine/recipe id in ANY TechDef.unlocks is locked until that
|
// The v4 gating rule ("a machine/recipe id in ANY TechDef.unlocks is locked until that
|
||||||
// tech completes") turned the tech tree from decoration into a lock on the whole game.
|
// tech completes") turned the tech tree from decoration into a lock on the whole game.
|
||||||
// It also turned three rounds of tech authoring into a bootstrap deadlock: every pack
|
// It also turned three rounds of tech authoring into a bootstrap deadlock: every pack
|
||||||
@ -709,6 +847,19 @@ describe('stations', () => {
|
|||||||
expect(lines.filter((l) => !l.trim())).toEqual([]);
|
expect(lines.filter((l) => !l.trim())).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('no line is wider than the sky', () => {
|
||||||
|
// Round 6 I wrote eight lines at 100-136 chars and found out from SCREEN's suite.
|
||||||
|
// The cap is theirs (src/audio/band.test.ts: the chyron band renders ~62 mono chars
|
||||||
|
// and they allow 96); this is a deliberately conservative local copy so the words
|
||||||
|
// fail in the lane that writes them. If SCREEN widens the band, this only ever errs
|
||||||
|
// on the narrow side — and I'll happily let a few lines breathe.
|
||||||
|
const CHYRON_MAX = 96;
|
||||||
|
const overlong = (byId('the-standard').chyron as string[])
|
||||||
|
.filter((l) => l.length > CHYRON_MAX)
|
||||||
|
.map((l) => `${l.length} chars: "${l}"`);
|
||||||
|
expect(overlong).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
it('the numbers station really does encode the hidden seams', () => {
|
it('the numbers station really does encode the hidden seams', () => {
|
||||||
// The treasure map has to point at treasure. Recompute the planted groups from
|
// The treasure map has to point at treasure. Recompute the planted groups from
|
||||||
// seams.json: if a hidden seam moves and the broadcast does not, this fails.
|
// seams.json: if a hidden seam moves and the broadcast does not, this fails.
|
||||||
|
|||||||
@ -579,3 +579,110 @@ The Correction past mites); a `parity-mite`-fed product line (§5: mites "fix me
|
|||||||
lake" — a real "footage of a lake" item you can only make FROM a canned mite would close the
|
lake" — a real "footage of a lake" item you can only make FROM a canned mite would close the
|
||||||
loop); SPILL FOG + EDGE BOIL (§10, still waiting on a SIM mechanic); the ASIC cooler aura
|
loop); SPILL FOG + EDGE BOIL (§10, still waiting on a SIM mechanic); the ASIC cooler aura
|
||||||
tuning once `coolRadius` is live in-sim.
|
tuning once `coolRadius` is live in-sim.
|
||||||
|
|
||||||
|
### Round 7 (Phase 1) — 2026-07-29 — Opus 5
|
||||||
|
|
||||||
|
SHIPPED: all 5 orders. items 61 → 62, recipes 64 → 65, tech 25 → 26, commissions 21 → 25,
|
||||||
|
chyron 38 → 46. Validator 74 → 86. All rulings argued in `data/CANON-DELTA.md` (round 7).
|
||||||
|
- **COMPLIANCE QUOTAS**: four `compliance:true` standing orders at queue indices 5/9/13/20 —
|
||||||
|
`quota-7c` (40 LUMA BARS, 150), `quota-12a` (80 ORE + 30 DUST, 340), `quota-30r` (100 bbl
|
||||||
|
SLURRY, 620), `quota-99z` (40 GOP CRATES + 25 SLABS SEALED AND UNMOSHED, 1600). Tier-0/1
|
||||||
|
enforced against your `DEBT_TIER_MIN`, not a hand-typed 2.
|
||||||
|
- **FORGED HASH**: `forge-hash` on the existing hex-splicer — **1 STCO MAP + 50 HF DUST →
|
||||||
|
1 FORGED HASH** (tier 3), 240t / bw 40 / heat 0.4, gated by new fortress node
|
||||||
|
`fortress-moov-heists`. Two inputs, so it cannot travel your empty-inputs catcher path.
|
||||||
|
- **8 STANDARD lines**, one per mechanic the player is about to meet, all ≤96 chars.
|
||||||
|
|
||||||
|
VERIFIED: `npm run check` clean. My 86 green. **Fault-injected all 11 new checks** (quota
|
||||||
|
wanting melt; quota not repeating; quota wanting researched material; quota out-crediting its
|
||||||
|
own vent; quota over the credit ceiling; quotas clustered into a drought; `forged-hash` id
|
||||||
|
drift; an input-free forge; an ungated forge; a 122-char chyron line; decorative forge heat)
|
||||||
|
— every one failed by name, then restored byte-for-byte. Live on :8155, zero console errors:
|
||||||
|
the fax opens on `raw-payload` with FIRST REFINEMENT in the tray, and **MOOV HEISTS renders in
|
||||||
|
the FORTRESS row of the research panel with zero code from UI.**
|
||||||
|
|
||||||
|
**THE MEASUREMENT — the vent works, end to end, on the real sim.** Throwaway probe (deleted;
|
||||||
|
sim behaviour is your lane). QUOTA 30-R wants 100 bbl slurry and reference v7 ships 230, so
|
||||||
|
hoisting it to the queue head in memory exercises the whole real path:
|
||||||
|
|
||||||
|
```
|
||||||
|
t=10,932 DONE quota-30r debt 0.3112 -> 0.1108 (delta -0.2004)
|
||||||
|
band 1 -> band 0, standing order re-queued to the back
|
||||||
|
```
|
||||||
|
|
||||||
|
−0.2004 is `DEBT_VENT_COMPLIANCE` plus that tick's decay. **One quota = exactly one band**, as
|
||||||
|
designed, measured rather than asserted. Same probe walked the ladder on reference v7:
|
||||||
|
band 1 t=5,874 / band 2 t=9,281 / band 3 t=12,740 / band 4 t=16,152 — **the whole enemy ladder
|
||||||
|
unspools inside nine minutes.** My clean single-reactor model predicted 3,160/6,320/9,480/12,640;
|
||||||
|
the real plant is ~1.3× slower because it spends its first minutes building. Both are in
|
||||||
|
CANON-DELTA; the model is labelled as a model.
|
||||||
|
|
||||||
|
DECISIONS:
|
||||||
|
- **`stco-map + hf-dust`, not `container-pack + hf-dust`** — argued at length in CANON-DELTA.
|
||||||
|
Short version: no recipe in this game consumes a science pack (packs are lab currency, one of
|
||||||
|
the few clean lines in the economy); §6 names the forged article outright ("rebuild/forge the
|
||||||
|
stco/stsz index"); §4's splicer is already a hex-editor over a scrolling ticker-tape and has
|
||||||
|
charted the genuine STCO MAP since round 3; you cannot forge a document you have never seen a
|
||||||
|
real copy of; and HF DUST is *literally* invisible bytes — packing the discarded difference
|
||||||
|
back in until the digest agrees is how a collision is actually built. It also costs the
|
||||||
|
victory chain: `assemble-moov-brain` wants an stco map too, so every forgery is a MEGAGLITCH
|
||||||
|
deferred. One forge (240t) fits inside `AUDITOR_NOTICE_TICKS` (600t) **only if the map is
|
||||||
|
already on the belt** — so the real preparation is stockpiling maps, and §4's "steady buffer
|
||||||
|
feed or it splices itself" turns out to be the counter's whole difficulty curve.
|
||||||
|
- **Quotas pay well, on purpose.** `correction-buyback` has said since round 2 that "we pay
|
||||||
|
well, we pay immediately, and we pay every time" — the temptation has to be real or nobody
|
||||||
|
chooses to be boring. The counterweight isn't the rate, it's the ceiling: the register can
|
||||||
|
never ask above tier 1, so it cannot scale, while the collectors' ladder climbs to 3200. You
|
||||||
|
outgrow compliance. 30 s of a two-machine side line buys back 1m 45s of melt-shipping debt.
|
||||||
|
- **`ItemDef.tier` is now read by three mechanics** — `MITE_TIER_MIN`, `DEBT_TIER_MIN`, and your
|
||||||
|
gunship's sector scoring. Recorded as a standing rule: a tier number is no longer decoration,
|
||||||
|
and any future re-tier is a balance change in three places at once.
|
||||||
|
- **The 96-char chyron cap now has a test in MY suite.** Round 6 I wrote eight lines at 100-136
|
||||||
|
and found out from SCREEN's `band.test.ts`. The cap is still theirs; mine is a deliberately
|
||||||
|
conservative local copy so the words fail in the lane that writes them.
|
||||||
|
|
||||||
|
BLOCKED/BROKEN: nothing of mine. Two suite failures at push time, **both attributed by
|
||||||
|
stash-and-compare on `data/` only** (`git stash push -- data/`, never bare) — both reproduce
|
||||||
|
identically with my entire diff stashed, both in `src/sim/reference.test.ts`:
|
||||||
|
- "is still shipping melt at 20,000 ticks — the deadlock regression net"
|
||||||
|
- "keeps the demuxer alive by voiding surplus rather than jamming"
|
||||||
|
|
||||||
|
The tree moved a lot under me and the failing set moved with it, so read those two names
|
||||||
|
rather than the count. At round-start `npm run check` had 2 errors and the suite was
|
||||||
|
**107 failed / 405 passed** (SIM's `frozenEnt` referenced from the wrong closure, taking 11
|
||||||
|
files down). Mid-round it was 2 failed with `src/ui/live.test.ts` "narrates a whole warden
|
||||||
|
cycle" in the set; that one went green on its own while I wrote this up. Final: **tsc clean,
|
||||||
|
588 passed / 2 failed**, my 86 green throughout. Every number in this entry was re-probed at
|
||||||
|
the end, not carried over from when I first measured it.
|
||||||
|
|
||||||
|
CROSS-LANE — SIM, one blocker and one nit:
|
||||||
|
1. **Reference v7 still never clears rung 1, so no commission completes and no quota is
|
||||||
|
reachable in the demo.** Measured at 90,000 ticks: `activeCommission` is still `raw-payload`
|
||||||
|
and `commissionDone` fired **zero** times. It ships mv-flux 46, hf-dust 2155, chroma-slurry
|
||||||
|
230, macroblock-bricks 1013, melt 120, anchor-slab 20, parity-mite 190 — and **zero raw MDAT
|
||||||
|
ORE**, because every ore goes into the demuxer. This is the same finding I filed in round 5;
|
||||||
|
it went green briefly with reference v5 and is live again. Fix is unchanged and small: tap
|
||||||
|
~20 ore straight to an uplink ahead of the demuxer. Until then the compliance valve, the
|
||||||
|
commission ladder and the fax tutorial are all unreachable in the shipped demo — which is
|
||||||
|
why I had to hoist a quota by hand to measure the vent at all.
|
||||||
|
2. **The register is a queue position, not a register.** `creditCommission` only credits
|
||||||
|
`commissionQueue[0]`, so a quota can be filed only when it reaches the head. Standing quotas
|
||||||
|
do re-queue, so the valve comes round periodically — but it isn't the on-demand relief the
|
||||||
|
fax implies. I mitigated in data (four quotas, max 8 commissions between valves, pinned by a
|
||||||
|
test) and I'm deliberately NOT asking for a parallel register: that's a mechanic, and the
|
||||||
|
round-3 lesson was that a contract field nobody reads is a decorative trap. Ask me when you
|
||||||
|
want to build it.
|
||||||
|
|
||||||
|
CROSS-LANE — SCREEN: 8 new STANDARD lines, all ≤96, yours to reshape as always. Two of them do
|
||||||
|
teaching work you may want to lean on — *"An audit finds nothing where there is nothing. Be
|
||||||
|
nothing for five seconds."* is the abstention counter, and *"A hash you wrote yourself is still
|
||||||
|
a hash. We will read it. We will believe it."* is the forged hash. If you widen the cap I'll
|
||||||
|
give a couple of them room to breathe.
|
||||||
|
|
||||||
|
CONTRACT REQUEST: none. `compliance`, the forged hash and the quotas all fit v9 as written.
|
||||||
|
|
||||||
|
NEXT (candidates): a `parity-mite`-fed product line (§5's "footage of a lake" as a real item you
|
||||||
|
can only make FROM a canned mite would close the loop); the STSZ half of the §6 heist (a forged
|
||||||
|
*ledger* as a warden counter, mirroring the forged hash's auditor counter); SPILL FOG + EDGE
|
||||||
|
BOIL (§10, still waiting on a SIM mechanic); the ASIC cooler aura tuning once `coolRadius` is
|
||||||
|
live in-sim; `cinema-pack` when the Fortress exists.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user