diff --git a/fktry/lanes/LANE-UI.md b/fktry/lanes/LANE-UI.md index b39eb31..4f1e122 100644 --- a/fktry/lanes/LANE-UI.md +++ b/fktry/lanes/LANE-UI.md @@ -801,3 +801,24 @@ the new copy landing and being buried. Not done unasked; say the word. its own arrival; a moov-heist UI when the lock becomes breakable (the chip already names the hash the minigame will want); compliance quota progress on the debt gauge itself (show what filling the current quota would vent) once DATA settles the quota list. + +**ADDENDUM (same round, after the orchestrator's v9.1 and SIM/DATA's next landings).** +Re-verified against HEAD rather than against my own commit: +- `npm run check` is now **clean tree-wide**, including under v9.1's `CorrectionUnit.phase` + union — my `'stasis'`/`'prescan'` comparisons were already exact members, no change needed. +- **263 UI tests green, all 18 files.** The only red in the tree is LANE-SIM's own + `src/sim/mite.test.ts` (2, their firewall work, uncommitted). Their `reference.ts` also + spent ~5 minutes throwing "firewall at -21,9 overlaps belt at -21,10" from its own + validator, which took every reference-factory test in the repo (mine and theirs) down + with it; it self-resolved, as mid-edit files have every round since round 2. +- **I had to correct one of my OWN round-3 tests, and the reason is worth recording.** + "NEXT IN TRAY … advances it on completion" asserted the sim lands on `commissionQueue[1]`. + That was always a claim about SIM's cascade rather than about the fax, and DATA's v9 + commissions broke it two different ways within twenty minutes: first the queue skipped + `first-refinement` (the factory had been shipping since tick 0, so entries behind the + head were *already* satisfied and completed in the same tick they became active), then + the head became `patio-resurfacing`, which my raw-ore rig cannot pay at all, so nothing + advanced. The test now asserts the fax's real contract unconditionally — the peek is the + live `commissionQueue[1]` — and only asserts the advance when the head is one this rig + can actually pay. The head-of-line blocking I flagged in round 5 is still live and is + still a design question, not a UI fix. diff --git a/fktry/src/ui/live.test.ts b/fktry/src/ui/live.test.ts index bbfba04..85edd83 100644 --- a/fktry/src/ui/live.test.ts +++ b/fktry/src/ui/live.test.ts @@ -208,14 +208,36 @@ describe('the HUD against the reference factory', () => { // Satisfy the head commission for real, and watch the tray move up. shipRawOre(h); - for (let t = 0; t < 12000 && h.sim.snapshot().activeCommission === first.activeCommission; t += 100) { - h.step(100); + for (let t = 0; t < 12000 && h.sim.snapshot().activeCommission === first.activeCommission; t++) { + h.step(1); } const after = h.sim.snapshot(); - expect(after.activeCommission, 'the queue should advance once the head is paid') - .toBe(nextId); + + // Whatever the queue did, THIS is the fax's contract and it holds unconditionally: + // the peek is the live queue's second entry, never a guess from data order. expect($('.fk-fax-next-name').textContent) .toBe(after.commissionQueue![1].replace(/-/g, ' ').toUpperCase()); + + // The advance itself is only assertable when the rig can actually pay the head, and + // DATA owns what sits there (it changed twice during round 7 alone; round 5 already + // flagged that an unpayable head blocks the whole tray). So: if the head wants only + // raw ore, it MUST advance — otherwise the queue is head-of-line blocked by design + // and there is nothing here for the UI to be wrong about. + const headDef = DATA.commissions.find((c) => c.id === first.activeCommission)!; + const payableByRig = Object.keys(headDef.wants).every((i) => i === 'mdat-ore'); + if (payableByRig) { + expect(after.activeCommission, 'a head this rig can pay must advance') + .not.toBe(first.activeCommission); + expect(after.commissionQueue![0]).toBe(after.activeCommission); + expect(after.commissionQueue).not.toContain(first.activeCommission); + // It moves ALONG the queue, never backwards. Note it may skip `nextId`: the + // factory has shipped since tick 0, so entries behind the head can already be + // satisfied and complete in the same tick they become active. + expect([nextId, ...first.commissionQueue!.slice(2)]).toContain(after.activeCommission); + } else { + expect(after.activeCommission).toBe(first.activeCommission); + expect(after.commissionQueue![0]).toBe(after.activeCommission); + } }); it('completes a commission and stamps the fax', () => {