[ui] round 7 addendum: NEXT IN TRAY asserts the fax's contract, not SIM's cascade

My own round-3 test claimed the sim advances to commissionQueue[1]. DATA's v9
commissions falsified that twice in twenty minutes — first by cascading (entries
behind the head were already satisfied and completed on arrival), then by putting
an unpayable head in front of the rig. The peek assertion — NEXT IN TRAY is always
the live queue's second entry — is unconditional again; the advance is only
asserted when the head is one the test rig can actually pay.

263 UI tests green, tsc clean tree-wide under contracts v9.1.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
type-two 2026-07-29 12:49:12 +10:00
parent b002e68b5a
commit 0508910f27
2 changed files with 47 additions and 4 deletions

View File

@ -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.

View File

@ -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', () => {