feat(bridge): protocol 7 — the Event System's shard half (Phase 16b cutover, 1 of 6) #26
Reference in New Issue
Block a user
No description provided.
Delete Branch "edge"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The Event System cutover, step 1 of 6 (
EVENTS_PLAN.mdPhase 16b).edge→main, a clean fast-forward —mainis 0 ahead.Merge this and
link#40togetherinstaller'sbundle.ymlGate 1 reads the protocol number out of both released artefacts and refuses a pair that disagrees. Whichever of these two merges first releases a component speaking 7 against a sibling still on 5, so the bundle run behind it composes nothing. That is transient and self-healing — the second merge dispatches the job again, and the nightly would catch it regardless — but it means these two are one step, not two.Nothing has been released or bundled from this work at all: everything below has been on
edgesince Phase 11a.What lands (5 commits, protocol 5 → 7)
champ.boss.killedwith its damage table.lease.list; the run-scoped participation ledger — the Bridge's first persisted state; the first handler that defers, which produced the first livebridge.busy.world.spawn/despawn/owned) behind five authorable verbs — and the Bridge's second persisted file, an ownership registry.Spawner/XmlSpawner, the seasonal toggle, the boot self-check, the item grant and the world save. The third persisted file.overlay.tomldeclaresprotocol = 7. It has been bumped in the same PR as its emitters throughout, which is the rule that keeps a bundle composable.The contract this release rests on
Written into
docs/link/v6.mdin Phase 16a, and the reason the refusal fix is safe:Every
Err(reqId, …)call site acrossBridgeWorld,BridgeOneShots,BridgeLeasesandBridgeParticipationwas audited against that rule before the change — each is a pre-mutation guard or follows a failedWritethat left the value alone.Verification
Every phase in here was walked on a real ServUO 57.4 (208k items, 42k mobiles) against a
cargo --releasesidecar, and Phase 16a walked the whole of it once more end to end from artefacts built exactly the way CI builds them: the overlay installed from a tarball into a tree withScripts/Custom/Bridge,Config/Bridge.cfgandSaves/Bridge/deleted first, so it was a first install rather than an upgrade, thenScripts.csprojbuilt offline with the server stopped.All three of Phase 16's deliberate failures pass. A mid-teardown process kill resumed with all 15 steps still at
attempts = 1; a sidecar killed mid-phase left the rundegradedwith its world writes parked atattempts = 0and the shard reconnected on its own; a cap breach answeredrefusedin the author's own words.16b re-verifies this from the released overlay tarball — installer → composed bundle → fresh ServUO copy → boot → one event with a real teardown — which is the leg 16a could not do, since a locally built bundle cannot go through core's host-allowlisted installer.
🤖 Generated with Claude Code
https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
Protocol 6 amended in place. Two mechanisms behind one new default-off gate, `Bridge.EventsEnabled` -- deliberately not `AdminWriteEnabled`, because enabling the admin plane is consenting to staff moderation from a screen a human is looking at, and this is consenting to the world being changed and watched on a schedule, unattended. BridgeLeases: a live config value held for a bounded time, with the deadline honoured on the shard whether or not the website is heard from again, and a compare-and-set restore that reports `drifted` rather than overwriting a GM's deliberate change. Memory-only -- nothing calls Config.Save() -- so a restart is a free restore. BridgeParticipation: presence in a declared area plus kill credit inside it, keyed by character serial, persisted in the world save. The Bridge's first persisted state, because a run spans hours and an in-memory tally would regress every attendee's score after one restart. Its snapshot is also the first handler that DEFERS, which makes `bridge.busy` reachable for the first time. And it immediately found a defect in 11a: BridgeIdempotency.Busy built its frame with Begin("bridge.busy") and then appended a diagnostic `.Str("kind", ...)`, so the object carried two `kind` fields and every JSON parser takes the last. The sidecar answered 200 instead of 425. Renamed `busyKind`. Co-Authored-By: Claude <noreply@anthropic.com>