Source docs: docs/runbooks/deploy.md, docs/runbooks/uma-adapter.md — this day executes their staging-deploy + re-seed path after PR #15 (UMA/LMSR/docs branch) merged to main.
claude/fix-deploy-pnpm (PR #16) and re-dispatched from that branch — deployed code
identical to main, only CI plumbing differs.version: 9 from pnpm/action-setup — it hard-fails when
package.json also carries packageManager; (2) checkout submodules: recursive + Foundry
install + forge build before sync-abis — ABIs are generated, not committed; (3)
sync-abis.mjs now falls back to version-suffixed forge artifacts (Name.0.8.15.json):
sources compiled under two solc versions get no plain Name.json, and local runs only worked
because an old single-version build had left one behind (ABI verified identical across
versions); (4) gcloud builds submit --async + a builds describe poll loop — log
streaming needs project Viewer, which the WIF service account lacks, so the CLI exited 1
while the build itself ran to SUCCESS.roles/viewer) was attempted but blocked by the permission classifier — left for jay to
decide; the async-poll fix makes it optional. PR #16 holds all four commits, unmerged.scripts/deploy.sh runs under jay’s local owner credentials, so none of the
CI permission issues apply; it also migrates + seeds in the same pass, which staging needed
anyway for the UMA market. CI run 5 was cancelled first so the two paths couldn’t race on
gcloud run deploy../scripts/deploy.sh (target staging) end to end: migrate → real seed
against Sepolia (staging data wiped and recreated, as planned) → API image via Cloud Build →
verex-api + verex-web to Cloud Run./health ok; /config returns umaAvailable: true,
adapter 0x1B45…00AC (matches the manifest); uma-eth-above-6k-2026 present, oracleType:
"UMA", OPEN. Staging is ready for jay’s propose → 1h liveness → resolve test.
Web: https://verex-web-q6qvjcw5ma-du.a.run.appb = 250), but the re-posted ladder still showed the full-inventory weights — 333.33 /
266.67 — after the operator had sold 772 of its 1,000 tokens.postLadders() was already reading live inventory via balanceOf, so the
bug was not “sizing from config”. The read is just too early: book.ts calls the
after-fill hook (→ postLadders) at line 506, before SETTLE_MATCH is enqueued at 524
and long before it mines. A fresh chain read therefore returns the PRE-trade balance —
a read-your-own-writes race across the off-chain/on-chain boundary. Considered deferring
the re-quote until settlement confirms; rejected because the quote would then lag every
trade by a block, which is exactly what LMSR is supposed to avoid. Netting out
in-flight sales keeps the re-quote instant and the size honest.packages/api/src/mm.ts — new unsettledOperatorSold(marketId) sums
operator-maker Trade rows still at settlement = 'PENDING', grouped by outcome;
postLadders subtracts that from the chain balance before capping at
MAX_LADDER_TOKENS. Clamped to only ever reduce (max(0, …)), so unsettled operator
purchases can’t inflate the quote either. PENDING only — CONFIRMED is already in
balanceOf, and FAILED never moved tokens, so a failed settlement releases the
reservation on its own.e¹/(e¹+e⁰). Operator inventory was 999/outcome (not the 1,000 assumed when predicting),
so the ladder should read 749: observed 249.67 / 199.73 / 149.8 / 99.87 / 49.93 — all five
levels exact for 749 × [5,4,3,2,1]/15, against 333.33 / 266.67 / 200 / 133.33 / 66.67
before the fix. Because the pre-settlement number (999 − 250 pending) equals the
post-settlement one (749 on-chain − 0 pending), the ladder no longer changes when
SETTLE_MATCH lands — that stability is the actual invariant, not just the smaller size.
A first attempt showed no change at all: tsx watch had not restarted its child since
the edit, so the server was serving pre-fix code. Two related
findings left open on purpose: (1) TradePanel.tsx:42-47 estimates tokens as
amount / outcome.price — the center, not a ladder walk — so “Est. tokens” overstates
what a multi-level order gets and can’t see when depth runs out; (2) b = 250 let a
single $400 trade move a market 50¢ → 96¢, which is a tuning question (b ≈ 1900 would
hold that trade inside 50¢ → 60¢, at ~$1,386 max subsidy instead of $173) rather than a
bug. Branch claude/lmsr-ladder-inventory, uncommitted.BookPanel.tsx gains a footnote under the ladder — prices come from LMSR, the
operator’s whole ladder is cancelled and re-posted after each trade, your own resting
orders are never cancelled — linking to /docs/hybrid-amm-clob#does-the-book-change. That
section only covered “the centre now tracks exposure”, so it gained three paragraphs (EN +
KO) actually answering the question the link promises: the levels are cancelled not filled,
order vs. quote, and the two things it does not touch (user orders survive; depth is not
additive across time).tsc --noEmit clean on @verex/web. Copy is English-only in the panel, matching
the rest of /market/[slug]; the doc itself is bilingual like its neighbours. Branch
claude/lmsr-ladder-inventory, uncommitted, alongside the ladder-inventory fix.