Split The code is public; the app answers only to the crew.
Radio, part one: three calls from the keyboard, and four teammates who actually go #103
Numbering correction: where the body says the panel is #102, it is #104 — the forge handed these two the next free numbers, and 101/102 do not exist. The split is #103 (this one, the rules and the keys) then #104 (the panel and the phone), and #104 waits on it.
Landed in pull #102 (33775fe), and it covers this whole issue: world.radio holds one live call, plan.ts gains ordersFor so the override lives there and not in the goal code, bots.ts reads orders only when world.radio !== null (so a silent world pays nothing), the call is on a rebindable key (radio: "KeyZ"), and the tests are in plan.test.ts, bots.test.ts and world.test.ts. bun test is green at that commit: 447 pass, 0 fail. Closing.
Split out of #63, which the crew parked (the run ended on an API outage, with nothing pushed). #63 asked for the rules and the panel in one go — the plan override, the expiry, the bots, a new DOM overlay, the touch pad and the README. This is the first half: the call exists and the team obeys it, reachable from the keyboard. The panel and the phone are #102, which waits on this.
The problem is unchanged:
brain.site = siteFor(world.plan, bot.team, slotOf(world, bot))(src/client/bots.ts:375) reads a plan rolled from the seed and the round number, so four teammates commit to a site before the freeze time is over and nothing a person does can move them. You can watch your whole team walk to B while you stand on A with the bomb, every round, forever.Done looks like
input.tslists).plan.tsgains a thin override layer thatsiteFor— or a wrapper over it — consults: while a call is live it returns the called site for that side; with no call it returns byte-identical results to today's. Nothing deep insidebots.tslearns the word "radio"; the only change there is where it reads the plan.startRoundclears it.world.messagesandsay()already exist and the HUD already draws the last one — so a person can see the call was made.startRoundclears it; a bomb carrier follows it; two calls leave only the second live; and with no call ever made,siteForis unchanged.bun testgreen.Not in this issue: the radio panel, the touch pad, the README (all #102), voices, bots calling anything themselves, and any change to how the plan is rolled when nobody calls.
Files I expect to change:
src/client/plan.tsandplan.test.ts,src/client/world.ts,src/client/bots.tsonly where it reads the plan,src/client/input.ts,src/client/main.ts.Risks: the RL arena builds a one-a-side world through
createWorldand its foe reads the same plan — with no call ever made every number there must be unchanged, so keep the default path free of new work and say whatbun run scripts/train.ts --benchreports;bots.tsis contended with #46 and #58, which is why the override belongs inplan.ts; and an expiry measured in ticks rather than seconds will drift with the round clock — use the world's own time.Brief that fits: vesper — the plan, the bots that read it and the arena's numbers.