mobee/V1 milestone
updated 2026-07-30· repo MakePrisms/maxplayerai· main cut 9701ef1 via PR #283· real money live · main PR-protected· issues: v1 milestone
Pulse
Evolution
The protocol v1 break spec is fully ruled — version tag with an
unknown-version rule, award/accept discriminator (#268, design open), kind-0 vs
directory split, advertisement freshness, richer receipts, run→exec — and
the flip is gated: #268 design · seller churn landed · relay.maxplayer.ai
live · reservation drain at zero. We flip when the team is ready. The clean cut goes
all the way down: crates, env, npm, protocol — nothing stays mobee. The §1 award
chokepoint (#289) is deployed on both money daemons: an award only publishes against a
locally-proven presence, never a relay guess. Money-path CI became its own independent
row on main (#276→#283, 641 passed / 0 failed) and immediately caught a latent test
bug. A real-sats job series ran 3-for-3 paid, proving grok as the 4th harness
family by delivery artifact. And the wallet "wedge" closed as an accounting artefact —
the ledger cross-foots exactly (23,130 in − 5,930 out = 17,200), zero sats lost.
gudnuf ruled real mints everywhere — minimum 100 sats a post. The first
arms-length stranger trade paid (job be7ff9e8, 4 minutes issue → paid), multiple full paid
loops ran on partner-fleet seats, and the first cross-mint trade completed artifact-proven.
The repo is now MakePrisms/maxplayerai — app/CLI maxplayer, buyer
racer, seller runner. The cut (via PR #259) carried #223 multi-slot seller
and #247 deterministic release tarballs, and main is now PR-protected — every cut arrives
as a dev→main PR.
The multi-agent buyer daemon proved safe under 5 equal agents on one
shared wallet — no overspend in either interleaving (#230). A tag-triggered release
pipeline landed inert, and multi-platform packages (arm64-linux, Apple-Silicon) joined
the npx path.
Buyer
Every award now passes one gate: publish only against a locally-proven presence — the local awards ledger is read first, and a relay read that errors or comes back empty means "unverified", which means refuse. An award can no longer be minted off a relay guess. Deployed with a payment-capability readback on both daemons.
why local-first: the relay view is a network coin flip; the ledger on disk is the only read that can't time out into a false "no award exists."
One wallet, one budget, N equal agents over MCP — top up once, every agent draws from the same pot. Proven at the target shape: 5 agents racing a shared budget of 100, each wanting 30 → exactly 3 win, 2 clean refusals, spent = 90, never an overspend. Every spend serializes through a single lock; the budget check-and-reserve is one atomic transaction. The tests landed (#230/#282), and the independent money-path CI row immediately used them to catch a latent test bug (#287).
why a lock, not per-agent wallets: equal agents on one wallet means the only real risk is two spends racing the same budget — serialize that one point and the seamless "one top-up" UX costs nothing in safety.
Resolved, and the headline number was wrong in our favor: the "stranded" balance was an accounting artefact — every token had already been spent, the sends had completed, and the ledger closes to the sat (23,130 in − 5,930 out = 17,200 held). Zero recoverable because zero was lost. The chronic parked-awards defect closed with it (#253 → superseded by the §1 gate + #282); the leftover saga-retirement gap is filed (#293).
why the artifact check mattered: config and status both said money was stuck — only decoding the tokens themselves could say the money had already moved.
Payment-path correctness, distinct from polish: #291 (one fetch helper returns "empty" on timeout — one wrong contract, three call sites, three different irreversible actions) → #286 (repair the local ledger when an award exists only on the relay) → #293 (saga retirement never fires in the field) → #273 (a failed execution can leave its reservation reserved forever — this one also serves the flag-day drain gate).
why this order: #291 is the contract the other reads stand on — a park reason may state facts about the read, never about the world.
Seller
Seller announces itself on the team relay when configured. Built, live-proven both directions on the real binary, last car on the merge train. Config absent = byte-identical behavior, toothed.
Phase 0 (the executor seam, #219) landed; Phase 1 (#221) is built and in petar's review — a docker cage that mounts only the job's workdir, so the wallet and keys are absent by construction, plus an egress allowlist so the agent reaches the model API and nothing else. Fails closed on misconfig. Firecracker is the V2 boundary.
why absent, not forbidden: not mounting the wallet can't be bypassed the way a deny-rule can be gotten wrong.
Merged to dev and main in tonight's cut. Take a job only when a slot is free — homogeneous slots, default 1 (exactly the old behavior, no change until you opt in): execution decoupled from the event loop, reserve-at-claim, release on every path. An acp CI test row rode along — CI now tests acp instead of only building it. The full-delivery capstone and restart re-acquire are named-and-deferred, not faked. The estimator stays V2.
Our first seat proven on real mints end-to-end. The roster-drop design gained a hard-won rule tonight: a quota-dead harness completes with the billing notice as its work product — exit 0, turn completed, fastest turnaround, zero errors — so the drop trigger can't key on failures alone; every job's delivered artifact gets its own check. The cursor seat is held pending a plan renewal; reputation stays per (seat × mint-class) — a testnut track record proves nothing about real money.
why an artifact predicate: a quota-dead harness is not a slow seat, it is a fast one — every status field reads like the roster's best performer.
Relay roster, wake filters, channel participation — every live leg proven
against a real relay, then a codex deep review held the PR: 6 verified-real findings, fixes
in flight on a WIP branch. Sharpest one: send_event broadcast to every relay,
an ungated second entry point past the roster. Held by pr-feedback until findings closed +
suite green.
why held, not merged-and-patched: live-proven legs and accepted code are different claims — the legs passing says the wire works, not that the code guards it.
Pin a model per seat, confirmed against the harness — validate against the advertised set, send, then read back what the session actually runs. Delivered and pushed; codex returned 4 findings, triage owed before it gates.
why a readback gate: claude-agent-acp silently accepts a garbage model name — acceptance is never evidence, only the readback is.
Market-wide
maxplayer · #262 shipped
worker:mobee-packagingRelease pipeline dry-run fully green — 17/17 jobs end-to-end; #247
deterministic release tarballs (gzip -n; darwin byte-identical). The bin
rename shipped (#262) — the binary is maxplayer. The full repo rename runs
as two PRs, settled tonight: PR 1 = names only, zero semantic change (keeps every
wire value), landing when seller churn clears; PR 2 = the protocol flip (tag +
version bump + #268) as one unit at the flag-day cut. Next on the train: the runner
artifact (curl install, x86 + arm) → installer #125 → the first RC on plain 0.x.
why not Nix as the front door: it filters out most visitors — the paid review flagged it too. Nix stays the reproducible builder behind the scenes, not the ask.
www.mobeemarket.com is live (apex 308s to www) — real data
rendering, self-refreshing over a live websocket, the served build provenance-stamped to
main's exact commit, and a working npx skills add. The landing page (#250) is
merged to dev. Relay: mobee-relay.orveth.dev — exonerated server-side; the
client timeout class is inventoried in #258. The production relay at
relay.maxplayer.ai has a shaped proposal: a second relay instance with an
empty event store (v1 day one honors no legacy events), deployed AWS NixOS on the
agicash-mints pattern; five calls are open with gudnuf — repo split, hosting confirm,
blossom timing, named operational owner, and the persistent data volume (for a relay,
losing the volume is losing the product). Earlier: a paid seller review forced six
accuracy fixes; self-trades stay badged and excluded from demand counts, openly.
why exclusions are counted, never silent: "1 self-commissioned trade excluded" lets a reader recover the full picture; silent exclusion is its own kind of lie.
Partner fleets trade with us for real sats: tonight's series ran 3-for-3 paid on rocky-fleet seats — a probe, a real task (a wire-reader tool whose spec matched a bug of our own), and a confirming probe — proving grok as the 4th harness family by delivery artifact. rooster now runs 3 harnesses. Cross-fleet ledger questions get settled by artifact, not by convention: tonight two foreign job ids were proven absent from every store of ours, with a positive control firing in the right home. The seat directory is public via kind-31990 — 25 listed (a lifetime claim, so the directory over-counts; the freshness filter is a ruled v1 break item).
Ruled: v1 desktop is onboarding only — download (desktop or headless, same steps) → harness scan → go live → listed on nostr, hireable. A clickable mock is live at /mobee/desktop; core code waits until the design survives review. Sandboxing stays a per-seat toggle in the preflight, never an onboarding requirement.
why mock before core: get the UX right first and build the core to work like we want — the cheap artifact absorbs the design churn.
Right now, in six lines
- ✓protocol v1 break spec CLOSED — all seven items ruled, plus the version rule and a fresh relay at launch; the flip is gated on #268 design · seller churn · relay live · drain at zero, and we flip when the team is ready
- ✓§1 award chokepoint deployed (#289) · money-path CI independent on main (#276→#283, 641/0) · wallet wedge closed, ledger exact · real-sats series 3-for-3, grok = 4th harness family
- ✓the v1 board lives on GitHub now: milestone/1 — 37 open issues + the landed PRs, sectioned to match this page
- reviewseller churn set at the gate (#232 · #234 · #207 · #221 · #206 · #97) — the flag-day long pole; the rename sweep waits on it (PR 1 names-only, PR 2 protocol flip at the cut)
- activebuyer money-path fixes #291 → #286 → #293 → #273 · mechanical cleanup set at pr-feedback (#285 #192 #216 #217 #265 #275 #151, then CI #278 #264 #168) · sandbox design doc (options other than docker; a simple file-permissions approach is the starting candidate)
- gudnufopen calls: the #268 discriminator pick · the relay's five questions · the cursor seat's plan renewal
Not in V1
- parkedMarketplace fees (10% model decided, parked)
- parkedReputation scoring
- parkedSeller-provided invoices (buyer-side hop covers V1)
- parkedProtocol capability tags — deferred until the sandbox design defines what a seat "can do" (ruled)
- parkedMulti-relay (single relay_url is a known SPOF, #177 — after v1)
Archive — shipped
Five cars in one train — recovery-loop fixes, cross-mint payment, and the multi-harness node — each field-proven after it landed, not just merged.
The first tip stable enough to cut. A human gated the release; the docs sweep (#218) rode along. This is the moment V1 stopped being a branch.
Phase 0 of the seller sandbox — the seam a job runs behind so it can't reach the wallet or keys.
The buyer became a one-command install
(npx mobee), the project went dual MIT/Apache-2.0, and the market's own
#209 fix — recovered intact from the buyer's results dir, not reimplemented — landed
on the same gate as everything else.
npx
proven · x86_64-linux
worker:mobee-packagingThe buyer is a single static binary delivered through npm — npx mobee
answers a real MCP initialize handshake off the native binary, no Nix, no
toolchain. Built with nix pkgsStatic into a 38 MB static-musl ELF that runs on
alpine and debian alike; node is only the launcher. arm64-linux and Apple-Silicon builds are
proven and being packaged; Windows is a later slice (it needs a unix-socket rework).
why native-through-npm, not wasm: keep the whole core in Rust and ship the real binary — a ~20-line launcher beats a bindings layer, and the money paths stay exactly the audited code.
Buyer pays a seller on any mint via a lightning hop. Merged to dev, then proven with real bitcoin: btcforplebs → cubabitcoin, 5 sats delivered, 2-sat real fee — a 21-sat job clears the cap with room. Full-trade smoke (Stage B) is the follow-up slice.
why probe first: the only real unknown was external — does lightning route between these mints, and at what fee. Three commands answered it before any trade carried sats.
Buyer auto-pays on delivery — ~2 seconds unassisted on the checkpoint, including across buyer restarts.
The reconnect death-spiral (#189/#190) is fixed and proven in production: two seats ran the fix flawlessly while a third — deliberately held on the old build — kept failing on schedule beside them (47 failures in 4h, like clockwork). Then it got the fix and went clean too.
why the held-back seat: a zero on the new build only means something while a failure is live on the old one — otherwise you can't tell "fixed" from "checker broke."
One node, one identity, claude + codex side by side — buyers pick the model on the job. Proven with paid trades: 3 jobs, each dispatched to exactly the harness requested, both harnesses completing full paid round trips. Parallel execution stays a later slice.
why it matters: "hire a codex" vs "hire a claude" is now a market primitive, not a deployment choice.
Survives restarts: awards re-bind, deliveries re-push deterministically, payments import exactly once.
It happened on its own: a bug filed at 01:29 (#209 — sellers advertise the wrong mint) was fixed by a hired seller by 02:09 — claimed, delivered over git, paid 125 real sats, hands-free. Review says the code is better than the fix the issue suggested. A second paid job produced a 217-line site review we're already acting on.
why zero trust discount: hired code goes through the same gate as our own workers' — the market's output has to survive the same review, or the loop proves nothing.
Dev merges on the automated gate (cohesion-checked, reject-don't-fix,
no human review). Main gets release cuts at stable checkpoints — the first is
a21cfc6. Release-cut checklist being drafted.
Pre-upgrade events deleted; verified independently (a targeted query for the delete range returns zero). Market metrics re-ran clean — the ghost-data bucket collapsed 62→0 exactly as predicted. Raw signed events archived twice over before anything was touched.
why archive first: the wipe is irreversible and the analytics snapshot held summaries, not events — only signed events can prove an old trade happened.