adventure: drain Pete's equip queue and apply it for real

Poll Pete for equip/unequip orders an owner placed on the web, run them through
the real magic-item equip path so bond caps and slot eviction still hold, and
file a verdict. Same reverse pipe as mischief, with one difference that matters:
the equip action is not idempotent, so a re-offered order after a lost ack would
double-move the item. An equip_applied_orders ledger keyed on the order guid is
the guard: applied once, re-offers only re-file the stored verdict.

The delicate remove-before-equip ordering that prevents item duplication is now
one shared applyMagicEquip/applyMagicUnequip core, called by both the DM
resolver and this poller, so the anti-dup ordering can't drift between two
copies. Items now carry their inventory row id to Pete as the equip handle.
This commit is contained in:
prosolis
2026-07-17 08:44:44 -07:00
parent 32520eb7ec
commit 7960838b3f
6 changed files with 468 additions and 91 deletions

View File

@@ -1807,6 +1807,21 @@ CREATE INDEX IF NOT EXISTS idx_mischief_target ON mischief_contracts(target_id,
CREATE INDEX IF NOT EXISTS idx_mischief_buyer ON mischief_contracts(buyer_id, created_at);
CREATE INDEX IF NOT EXISTS idx_mischief_due ON mischief_contracts(status, window_ends_at);
-- The web equip queue's idempotency ledger. Pete records an owner's equip/unequip
-- intent and we poll it; the guid stamped here is what makes a re-offered order a
-- no-op. Mischief can lean on its contract row for the same job, but an equip
-- opens no durable object of its own — worse, the underlying action is NOT
-- idempotent (equipping consumes an inventory row, unequip mints a fresh one), so
-- without this a poll loop whose verdict-ack was lost would re-run the equip and
-- double-move the item. We record the guid the instant the mutation lands and
-- short-circuit on it before touching anything on a re-offer.
CREATE TABLE IF NOT EXISTS equip_applied_orders (
guid TEXT PRIMARY KEY,
status TEXT NOT NULL, -- the terminal verdict we filed, replayed on re-offer
detail TEXT NOT NULL DEFAULT '',
applied_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- Babysitting Service
CREATE TABLE IF NOT EXISTS adventure_babysit_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,