docs(rust): the step-2 player walk, and D186-D187

PLAYER_WALK's step-2 rows 3-9 walked with the org lead in the game on
both rigs (2026-09-27). Records the results, corrects four rows (the
helper is unloaded, not deleted; no enter message can show; sleepers do
not score; ZoneManager's own entry counted the player anyway), and adds
D186 (a link code's second pass skips servers known down) and D187 (no
permission sync to a server the poll saw go away) with F6, F7 and F12's
as-walked notes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
2026-09-27 03:18:40 -05:00
parent 9aba725ca2
commit 1891f4f6fd
2 changed files with 34 additions and 8 deletions

View File

@@ -70,6 +70,8 @@ Taken by the org lead during and straight after the walk.
| **D183** | **F14's expiry is core's to record: the resource ledger gains an `expired` status, and a module reports one with `ctx.events.expired({ kind, ref })`.** `expired` is terminal like `reverted` — teardown never tries to take it back — and the run log says `resource.expired`. It is a MODULE_API minor (1.10.0 → 1.11.0), and it must not disturb Module-uo, which is already built against 1.10.0: additions only, no existing status changes meaning. Rejected: asking core to reconcile, which files an expected expiry as `orphaned` (a fault, and still claimable for a revert); and core marking rows expired from `lease_until` on its own clock. |
| **D184** | **F8's signal is `plugin.loaded` / `plugin.unloaded`, carrying the permissions that plugin added or removed.** The plugin diffs the registered permission list around each load and unload, emits only once the world is ready (a boot is the restart sync's), and the site marks the permission sync dirty when the list is not empty. The same list is §4.1's first evidence of which plugin owns a permission. Rejected: every load, names only. |
| **D185** | **F2 is the site's: NPC attackers are labelled by the killfeed**, which trims a prefab's variant digits (`wolf2` → wolf) and names the NPC families that read badly otherwise (scientists, bandits, animals). No wire change. Rejected: the plugin sending a display name Rust may not have. |
| **D186** | **F6, as walked: a link code's second pass skips the servers the site already knows are down.** Asking the non-issuers in parallel was not enough: while any server was down, a code no issuer held — every made-up one — still waited out that server's whole timeout (12 s on both rigs, the step-2 walk). A server the board poll last saw without a connected game is not an issuer, so it cannot hold the code: it counts as offline without the wait. Issuers are asked whatever their state, so a good code on a down server still answers "unsure". Rejected: dropping the second pass (a code typed before its mint is ingested would be refused once); a short timeout on it (still a wait, and a guess at the number). |
| **D187** | **F7, as walked: no permission sync goes to a server the poll saw go away until a fresh hello says its world is ready.** The `worldReady` hold reads the stored hello, which is the old boot's until the poll reads the new one — and on Carbon a due audit went out in that gap, 80 s before "Server startup complete". The poll already writes `online: 0` the moment a server goes away, so the hold reads that too (titles already did). A human's "sync now" is still not held. |
## 2. Fixes
@@ -118,6 +120,11 @@ to, that is D168's case (a helper), or the tally measures distance itself for zo
Carbon too. Settled by D181 and D182: ZoneManager has no public way (its `UpdatePlayerZones` is private and
runs only for a connecting player), so a helper patches `Zone.InitializeZone` with Harmony; without the helper the
bridge scores its own zones by `IsPositionInZone`.
*As walked, 2026-09-27, both rigs:* narrower than it reads. Without the helper, ZoneManager 3.1.14 counted the
player every time we tried — a zone opened around them, a zone re-created by a ZoneManager reload, and a rejoin
after a restart (its `UpdatePlayerZones` runs on connect) — only late: with the helper in, its sweep one tick after
`InitializeZone` found the player not yet counted. So the helper makes entry immediate, and its flags apply at
once; the score never depended on it. What the first walk saw may need a busier server than one player to recur.
**F13 — the `world.expired` frame leaves with its kind overwritten.** *(Rust-Plugins, protocol)*
Three zones expired in the game exactly on time; all three frames were filed as `kind: "zone"`. Line ~7310
@@ -149,6 +156,8 @@ issued a code in the last five minutes, and answer "unsure" only when one of *th
**F6 — redeeming a code waits on every dead server in turn.** *(Module-Rust)* About 21 seconds, four per dead
server; the rig sorts last, so a successful link waited too. F5's fix usually leaves one server to ask; failing
that, ask in parallel with a short timeout.
*As walked, 2026-09-27:* the parallel fleet still took 12 s for a made-up code whenever a server was down —
one whole timeout on the second pass. Settled by D186; 338 ms after it, 360 ms with a rig stopped as well.
**F8 — loading a missing plugin does not re-sync permissions.** *(Rust-Plugins, Module-Rust)* PopupNotifications
came back at about 18:44; the grant that had been unresolved landed at 18:57, on the fifteen-minute audit. The
@@ -168,6 +177,8 @@ deliberately wiped, the site restored its group, membership and grant — R2's c
restart sync ran 35 s before "Server startup complete", timed out with no warning in the log (the titles push
at the same moment did log one), and the retry 2.5 minutes later recorded "0 applied", so nothing says what the
restart restored. *Fix:* hold the restart sync until the hello says `worldReady: true`; log a failed sync.
*As walked, 2026-09-27:* the restart sync waited on both rigs, but on Carbon a due *audit* went out the moment
the sidecar reconnected — the stored hello was still the old boot's. Settled by D187.
**F2 — NPC killers are named by prefab.** *(Rust-Plugins or Module-Rust)* "killed by `wolf2`". Send a display name,
or map prefab to label on the site — whichever the killfeed page already expects. The site's, by D185.
@@ -405,9 +416,15 @@ in Rust-Plugins, Rust-Link and Module-Rust, and the three cut over to `main` tog
a 3-minute zone expired into `expired` with `resource.expired` and teardown never touched it (F13, F14)
— which found a run left `pending` for ever when its last resource expires while it runs, fixed in
website#209; a restart's sync waited for `worldReady` and went after it (F7); and `ZZZZZZ` with five
servers down answered "unknown or has expired", once, in one timeout (F5, F6). Still to walk: the rows
of [`PLAYER_WALK.md`](../../rust-link/PLAYER_WALK.md)'s step-2 section that need somebody in the game
(3–9).
servers down answered "unknown or has expired", once, in one timeout (F5, F6). The rows of
[`PLAYER_WALK.md`](../../rust-link/PLAYER_WALK.md)'s step-2 section that need somebody in the game (3–9)
were walked with the org lead in the game on 2026-09-27, on Oxide and then Carbon, and all passed but row 8's timing: the gather
tally matched the inventory to the unit, a player's own wall was not a raid, a zone scored a player who stood
still through its opening, a restart and a ZoneManager reload, with the helper and without it, and the killfeed
read Bear, Wolf, Boar and Scientist. The walk found two gaps, both fixed in Module-Rust on `edge` and walked on
the walk core: a made-up code still waited one timeout on a dead server (D186), and a due audit went to a
restarting Carbon before its hello was read (D187). F12 turned out narrower than written (see F12). Not walked:
a player killed by another player — there was no second player.
3. **The redesigns**, each planned in detail before code and walked on both frameworks: the permission manager
(§4.1), the event step editor with the kit-weekend template (§4.2, §4.3), zones and domes (§4.4), the map's
marker types (§4.5), the chat title conditions (§4.6), and the NPC research (§4.7).