Design of record for the bump, plus the reference updates it obliges.
Engagement Phase 10, as built.
link/v5.md is new. Three enrichments in one bump, because a bump costs a sidecar
release, a republished bundle and an operator update on every shard — a field left
out costs a whole second round of that, not a follow-up commit.
a. house.decay gains ownerName and a nested `schedule`. estimatedCollapse is
present ONLY where it is exact: under dynamic decay each stage's duration is
drawn at random on entry, so collapse is knowable only once the house is
already at IDOC; under static decay it is exact at every stage. Omitted
rather than approximated — an absent field is honest where a wrong date
becomes a dated promise in a player's mail.
b. vendor.listing gains ownerAcct — a character name identifies nobody, only the
game account joins to shard_account_links — and a `fees` block resolving
PlayerVendor.PayTimer's dismissal rule into a dismissalAt instant. There is
deliberately no daysRemaining: a pay period is a UO day on an old-system
shard, so the name would be wrong by a factor of twelve.
c. account.login.result is a NEW kind. account.login.attempt fires from a veto
hook that runs before the auth decision and constructs with Accepted = true,
so it fires on successful logins too and cannot carry a verdict.
INTEGRATION.md: the version banner to 5, the Housing and Market field tables and
examples, and the new kind beside the attempt — with the attempt's own row
corrected to say why it is not a failure signal.
PLAN.md: 5.1's "failed-login signals" row was wrong about what AccountLogin can
tell you; 5.3 and 5.4 gain the two new signals; 5.4's dynamic-decay model gets the
consequence for publishing a collapse time, and the CanDecay rule gets its testing
trap. 7's frames are marked as 1.0's design sketch rather than the shipped wire,
which they have not been for four versions.
ENGAGEMENT.md: Phase 10 as built. Two decisions taken during the build (both field
groups nested, so one admin rule governs each and a future field inherits the gate;
no daysRemaining), the three visibility classifications, and the pin improvement —
the schema test now asserts the declarations AGREE rather than that they all say a
literal, which is the protocol-4 bug seen from the other side.
Co-Authored-By: Claude <noreply@anthropic.com>
Two scope decisions taken by the org lead on 2026-08-31, before any Phase 10 code,
plus the three factual corrections that finding them out produced.
Phase 10 — the protocol bump now carries three enrichments, not one. The argument is
specific to this phase: a bump costs a sidecar release, a republished bundle and an
operator update on every shard, so a field left out does not cost a follow-up commit,
it costs a second bump with the same lead time and a split operator population. The
two additions:
* player-vendor fee state on vendor.listing (ownerAcct, holdGold, chargePerDay,
daysRemaining), because uo.vendor.expiring is the same "owned asset at risk with
a deadline" shape as the flagship and today has neither an address nor a deadline;
* a post-decision account.login.result, because EventSink.AccountLogin is a veto
hook that fires BEFORE the auth decision.
Moving vendor.sale out of the opt-in patch tier was explicitly declined.
Phase 11 — ships every checked row of 8.6 rather than a single rule, carving out
uo.market.item_listed (a saved search; no per-user query store exists). ~23 triggers
grouped by the audience kind each family exercises, since exercising the ceiling
lattice at scale is the point rather than volume of mail. Every rule still ships
enabled = 0 per Q3. Notes that the phase will likely want an 11a/11b split on the
4a/4b precedent, to confirm at its start.
Three corrections to 8.6, each verified against the emitters rather than the table:
* uo.vendor.sale is real and does carry ownerAcct, but lives in servuo-plugins/
patches/ (opt-in, verified only against ServUO 57.4) — dormant, not broken, on a
shard that declined the tier;
* uo.vendor.expiring had no data at all, not merely no mapper — vendor.listing
carries ownerSerial/ownerName and nothing carries held gold or daily charge;
* uo.account.login_attempt could not have been built as described — it would have
mailed "someone tried to log into your account" on every successful login.
Renamed uo.account.login_failed so the id cannot be misread again.
Also amended: the status header, scope decision 3, and 6.0b's documentation
assignment for rows 10 and 11 (v5.md now earned; the patch-tier caveat is an
operator-facing doc obligation; runicgateway.com's capability claim changes when
"one rule" becomes "the catalogue").
Co-Authored-By: Claude <noreply@anthropic.com>