docs(link): protocol 6 part b — leases, participation, and what the walk found #220

Merged
whitlocktech merged 1 commits from feature/events-p11b-leases-participation into edge 2026-09-05 04:10:03 +00:00
Member

The docs half of servuo-plugins#22 + link#37 + website#193 + Module-uo#30. Six files.

link/v6.md gains §§7–10

§7 stops saying "what 11b will add" and becomes one version, two halves — with the warning it already carried kept and sharpened: an overlay and a sidecar both declaring 6 are only interchangeable within one side of the 11b merge, which is tolerable exactly because nothing is released from edge.

§8, the lease plane. The two mechanisms EVENTS.md names, and three shapes where the obvious alternative is subtly wrong — holdMs over untilMs because a deadline is measured against two clocks; text on the wire and parsed comparison because a formatted-number diff would report drift on a value nobody touched; refuse-don't-clamp because a clamp leaves the two halves disagreeing about when the world comes back.

§9, the participation ledger, including why it is the Bridge's first persisted state and why presence accrues in seconds rather than sample counts.

§10, verification, with the four claims the phase was written to prove and two subsections that are the interesting part.

Three things the repos disproved

Phase 11b is FIVE repos, and the plan was wrong in the opposite direction from 11a. 11a dropped installer because nothing there hardcodes a protocol version. 11b adds website, because a lease's ledger row had no reconcile path anywhere: cleanup.js resolves a resource to the action of the step that made it, and for a lease that action is core.lease — core's own, on a path a module cannot register anything on.

§D's "two patterns" is nearer 95/5. Measured on 57.4: of the 158 non-Bridge Config.Get call sites in Scripts/, roughly eight are read live. The allowlist is not a curated subset of a large pool; it is nearly the whole of what exists, and the catalog Phase 12 inherits will be short for reasons no care can change. §D now carries the measurement.

Config.Set has exactly one caller in the entire tree (Server/ScriptCompiler.cs). No in-game command, gump or console verb writes a config key, so on a stock shard a GM cannot drift a configuration lease even deliberately. The compare-and-set is still required — Phase 12's object-property leases are trivially driftable — but the config half of it is proved with scaffolding, not by a GM. Recorded in §D beside the first measurement, because it decides how drifted gets tested at all.

Two §G rows close

  • Participation attribution, which §G called "the largest remaining piece of new UO work" — that sentence is now past tense with the design that replaced it.
  • Lease a live config value → built, one key, with the measurement above attached so nobody reads the row as "and the rest are easy".

§10.1 — the defect the phase's own deferral found in 11a's shipped code

bridge.busy came back 200, not 425, the first time anything produced it. BridgeIdempotency.Busy built its frame with Begin("bridge.busy") and then appended a diagnostic .Str("kind", prior.Kind)two kind fields, and every JSON parser takes the last. The sidecar read participation.snapshot, matched nothing, and answered a 200 whose body said nothing had happened, which is the worst of the three possible answers because a retry loop reads it as success.

Unreachable in 11a by construction, and the sidecar test covering the mapping was correctly feeding it a hand-built frame. This is 11a's own sentence — "11b's leases are the first thing that can actually produce it, and proving it belongs in that walk" — collected, and it is the argument for the phase ordering stated as a fact rather than a hope.

§10.2 / §10.3 — what could not be driven, and two traps

Presence needs a connected client. The sweep credits online players (NetState != null), which is the correct test and not one a probe should loosen — a character parked in Britain and logged out for eight hours did not attend anything. Kill credit needs none, so accrual, persistence, chunking and replay were all driven; the one unexercised line is named rather than assumed.

  • Core.Kill does not save the world, so the first restart test reloaded an empty Participation.bin and looked exactly like a persistence bug.
  • A probe meaning to produce two damagers must not kill with the first blow — 40 damage on a Mongbat killed it outright, and a correctly-working ledger read as one that credits only the killer.

The other five files

  • INTEGRATION.md — §2 gains v6's event plane; §6 gains "The event plane — leases" and "— participation" with the five and six things a third-party caller actually needs; §7 gains a 403 row, because an operator's refusal is not a malformed request.
  • PLAN.md — a new §7 subsection recording the two ServUO facts that shaped both halves, plus the persistence mechanism and why its hooks attach in Configure() rather than Initialize().
  • EVENTS.md — §D's measurement, the two §G rows, and §F's inForce() beside the three callables with the reason it is not read() plus a comparison.
  • EVENTS_PLAN.md — Phase 11b as built: the five-repo correction, the ten decisions, and every finding above.
  • MODULE_API.mdinForce() in the lease shape, the signature index and the 1.10.0 rule list. Amended in place at 1.10.0, by the same rule §7 states for the protocol.

Notes

docs has no CI. Every relative link in the six files was resolved by hand (0 broken). CRLF preserved throughoutgit diff --numstat reports 313/91/35/34/60/13 against real content diffs rather than whole-file rewrites, and the tree holds no bare LF and no \r\r\n.

  • AI-assisted: Claude Code (Opus 5).

Plugin: RunicGateway/servuo-plugins#22 · Sidecar: RunicGateway/link#37 · Core: RunicGateway/website#193 · Module: RunicGateway/Module-uo#30

🤖 Generated with Claude Code

The docs half of `servuo-plugins#22` + `link#37` + `website#193` + `Module-uo#30`. Six files. ## `link/v6.md` gains §§7–10 §7 stops saying *"what 11b **will** add"* and becomes **one version, two halves** — with the warning it already carried kept and sharpened: an overlay and a sidecar both declaring `6` are only interchangeable within one side of the 11b merge, which is tolerable exactly because nothing is released from `edge`. **§8, the lease plane.** The two mechanisms `EVENTS.md` names, and three shapes where the obvious alternative is subtly wrong — `holdMs` over `untilMs` because a deadline is measured against two clocks; text on the wire and parsed comparison because a formatted-number diff would report drift on a value nobody touched; refuse-don't-clamp because a clamp leaves the two halves disagreeing about when the world comes back. **§9, the participation ledger**, including why it is the Bridge's first persisted state and why presence accrues in seconds rather than sample counts. **§10, verification**, with the four claims the phase was written to prove and two subsections that are the interesting part. ## Three things the repos disproved **Phase 11b is FIVE repos, and the plan was wrong in the opposite direction from 11a.** 11a dropped `installer` because nothing there hardcodes a protocol version. 11b adds `website`, because a lease's ledger row had no reconcile path anywhere: `cleanup.js` resolves a resource to the action of the step that made it, and for a lease that action is `core.lease` — core's own, on a path a module cannot register anything on. **§D's "two patterns" is nearer 95/5.** Measured on 57.4: of the **158** non-Bridge `Config.Get` call sites in `Scripts/`, roughly **eight** are read live. The allowlist is not a curated subset of a large pool; it is nearly the whole of what exists, and the catalog Phase 12 inherits will be short for reasons no care can change. §D now carries the measurement. **`Config.Set` has exactly one caller in the entire tree** (`Server/ScriptCompiler.cs`). No in-game command, gump or console verb writes a config key, so on a stock shard **a GM cannot drift a configuration lease even deliberately**. The compare-and-set is still required — Phase 12's object-property leases are trivially driftable — but the config half of it is proved with scaffolding, not by a GM. Recorded in §D beside the first measurement, because it decides how `drifted` gets tested at all. ## Two §G rows close - **Participation attribution**, which §G called *"the largest remaining piece of new UO work"* — that sentence is now past tense with the design that replaced it. - **Lease a live config value** → built, one key, with the measurement above attached so nobody reads the row as "and the rest are easy". ## §10.1 — the defect the phase's own deferral found in 11a's shipped code `bridge.busy` came back **200**, not 425, the first time anything produced it. `BridgeIdempotency.Busy` built its frame with `Begin("bridge.busy")` and then appended a diagnostic `.Str("kind", prior.Kind)` — **two `kind` fields, and every JSON parser takes the last.** The sidecar read `participation.snapshot`, matched nothing, and answered a 200 whose body said nothing had happened, which is the worst of the three possible answers because a retry loop reads it as success. Unreachable in 11a by construction, and the sidecar test covering the mapping was correctly feeding it a hand-built frame. This is 11a's own sentence — *"11b's leases are the first thing that can actually produce it, and proving it belongs in that walk"* — collected, and it is the argument for the phase ordering stated as a fact rather than a hope. ## §10.2 / §10.3 — what could not be driven, and two traps **Presence needs a connected client.** The sweep credits online players (`NetState != null`), which is the correct test and not one a probe should loosen — a character parked in Britain and logged out for eight hours did not attend anything. Kill credit needs none, so accrual, persistence, chunking and replay were all driven; the one unexercised line is named rather than assumed. - **`Core.Kill` does not save the world**, so the first restart test reloaded an empty `Participation.bin` and looked exactly like a persistence bug. - **A probe meaning to produce two damagers must not kill with the first blow** — 40 damage on a Mongbat killed it outright, and a correctly-working ledger read as one that credits only the killer. ## The other five files - **`INTEGRATION.md`** — §2 gains v6's event plane; §6 gains *"The event plane — leases"* and *"— participation"* with the five and six things a third-party caller actually needs; §7 gains a **403** row, because an operator's refusal is not a malformed request. - **`PLAN.md`** — a new §7 subsection recording the two ServUO facts that shaped both halves, plus the persistence mechanism and why its hooks attach in `Configure()` rather than `Initialize()`. - **`EVENTS.md`** — §D's measurement, the two §G rows, and §F's `inForce()` beside the three callables with the reason it is not `read()` plus a comparison. - **`EVENTS_PLAN.md`** — Phase 11b as built: the five-repo correction, the ten decisions, and every finding above. - **`MODULE_API.md`** — `inForce()` in the lease shape, the signature index and the 1.10.0 rule list. **Amended in place at 1.10.0**, by the same rule §7 states for the protocol. ## Notes `docs` has no CI. Every relative link in the six files was resolved by hand (0 broken). **CRLF preserved throughout** — `git diff --numstat` reports 313/91/35/34/60/13 against real content diffs rather than whole-file rewrites, and the tree holds no bare LF and no `\r\r\n`. - [x] AI-assisted: Claude Code (Opus 5). Plugin: RunicGateway/servuo-plugins#22 · Sidecar: RunicGateway/link#37 · Core: RunicGateway/website#193 · Module: RunicGateway/Module-uo#30 🤖 Generated with [Claude Code](https://claude.com/claude-code)
wtclaude added 1 commit 2026-09-05 04:08:06 +00:00
Six files. `v6.md` gains sections 7-10: one version with two halves, the lease
plane, the participation ledger, and 11b's verification.

Three corrections to what the plan and the design of record assumed.

Phase 11b is FIVE repos, not four, and in the opposite direction from 11a's
correction: a lease's ledger row had no reconcile path anywhere, because the step
that made it names `core.lease` and that is core's own action. `website` joins.

EVENTS.md's §D frames the 258 `Config.Get` call sites as splitting into two
patterns. Measured on 57.4: of the 158 non-Bridge sites in `Scripts/`, roughly
eight are read live. The allowlist is not a curated subset of a large pool, it is
nearly the whole of what exists. And `Config.Set` has exactly one caller in the
entire tree, so on a stock shard a GM cannot drift a configuration lease even
deliberately -- which is why proving `drifted` needed a scaffolding verb.

§G's "participation attribution is now the largest piece of new UO work" closes,
and the live-config-lease row goes to built-with-one-key.

§10.1 records the defect the phase's own deferral found in 11a's shipped code:
`bridge.busy` answered 200 instead of 425 because the frame carried two `kind`
fields and parsers take the last. Unreachable in 11a by construction; produced on
the first collision here.

Co-Authored-By: Claude <noreply@anthropic.com>
whitlocktech merged commit 5fe4305502 into edge 2026-09-05 04:10:03 +00:00
whitlocktech deleted branch feature/events-p11b-leases-participation 2026-09-05 04:10:04 +00:00
Sign in to join this conversation.
No description provided.