fix(bridge): make the market sweep notice a vendor running out of gold #19
Reference in New Issue
Block a user
No description provided.
Delete Branch "fix/vendor-fee-signature"
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?
Found by engagement Phase 11b's live acceptance walk. Pairs with website#179, Module-uo#24 and docs#.
The defect
BridgeMarket.Signature()diffs shop name, owner, map, coordinates and the item/price list — the things a listing is made of. Protocol 5 added afeesblock to the frame and the change detector never learned about it.So a vendor quietly running down its gold alters nothing the sweep compares, emits no frame, and
uo.vendor.expiring— the notification whose entire subject is a vendor running out of gold — can fire only by coincidence: when somebody happens to reprice an item on a shop that is already broke. Which is the one shop nobody is restocking.Proved on the rig by setting a vendor's held gold to zero and watching nothing follow:
…and after the fix, the same knob, with no price or stock change anywhere:
The fix, and why the derived values
The signature carries
exemptandperiodsRemaining, notholdGold/bankAccount/nextPayAt.periodsRemainingis an integer division, so it moves only when the shard's own answer to "is this vendor in danger" moves — near-zero extra frame volume.HoldGoldchanges on every sale andNextPayTimeon every pay tick, and keying on either would re-emit a fat listing frame for a shop whose listings had not changed.AppendFeeSignaturesits directly besideAppendFeesand mirrors its branches (commission → exempt;charge <= 0→ free), with a comment saying so, because the failure mode of the two drifting apart is exactly this bug again.Emit cadence, not frame shape. No field added,
PROTOCOL_VERSIONuntouched,overlay.tomlunchanged, sidecar unaffected. The general form is worth carrying to the next enrichment and is now recorded indocs/link/v5.md: a sweep-based kind has a change detector, and a field added to the frame but not to the detector ships correct and arrives never.Also:
tools/scaffolding/BridgeRigDriver.csThe walk needed the shard driven from outside the game, one verb per line in a file the driver polls and truncates. Every other probe here runs a fixed script at boot or from an in-game client, and both are the wrong shape: a walk asserts what happened between two steps ("one mail, then nothing for a day"), so the steps have to be separated by the observer rather than by a hard-coded delay — and ServUO's console reads a fixed verb set (
Scripts/Misc/ConsoleCommands.cs), so[p5probecannot be typed at a headless shard at all.decaylist·decay·vendorlist·vendorfunds·citylist·governor·election·activate·password·save·shutdown. FlagRigDriverEnabled, absent fromoverlay/Config/Bridge.cfglike every other scaffolding flag, so a server whose config lacks the key never runs it. Never deployed —deploy.ps1copies onlyoverlay/.The README gains the two ServUO facts the walk cost a rebuild each to learn:
RefreshDecay()returns false outright forDecayType.Condemned, and on a seeded world every house that can decay is Condemned — the seeder backdates accounts pastAccount.InactiveDurationprecisely to make them decay. The rescue then reportsAgelessfor the owner's newest house andLikeNewfor an older one, and a consumer watching only forLikeNewmisses the common case.Stop-Processdrops the socket and the shard says nothing, so a killed shard is indistinguishable from a wedged one andserver.shutdownnever reaches the sidecar. Hence the driver'sshutdownverb (Core.Kill).Verification
dotnet build Scripts.csproj -c Releaseclean (ServUO compiles the plugin at boot; there is no CI build).deploy.ps1 -Verifyclean before,add=0 change=2after./historyon a live shard.uo.vendor.expiringthen fired once to the linked owner on both channels, and the second crossing inside the day was cooled — the rung this unblocks.AI-assisted: written with Claude Code.
🤖 Generated with Claude Code