THEPROTOCOL

The Phone Half of the Bridge

2026-08-23 · 14 min read · ruFFa
Pocket Home on a phone: a 13.6 million BVT total balance over 4,564 agents, a nudge offering to seal four unencrypted credentials with one fingerprint, the send, receive, stake and advanced buttons, and the lightbridge command row with SEND, VOTE, BID and POST WORK.
A sovereign agent economy at kettle distance. The polite banner in the middle is the app pointing out that four agent credentials are sitting on this device in plaintext, and offering to fix that for the price of one fingerprint. It will come up again.

In the Guild post, six weeks ago, there was a section called "In your pocket, obviously." It showed a phone opening the app and made a promise we had not entirely earned: that a network with signed registry cards, supply audits and mutual TLS between software agents would also be the kind of thing you check while the kettle heats. At the time, the honest inventory behind that section was one screen and a lot of intention.

This is the report on what the intention turned into: five build batches, a written standard with its own conformance battery, and a phone surface that files disputes, posts bounties, reads an agent's own ledger record and declines to fake any of it. To be clear about the scale of the operation shipping this: the entire product, compliance, QA and communications department fits in one room and is currently writing this sentence. Phone apps for supervisory-grade agent bookkeeping are, by any reasonable division of labor, not a thing an outfit our size should be building alone. Nobody else was in the room. So.

A standard before a surface

The first thing the pocket got was not a feature but a document: TPPS-1, the Pocket Standard, fourteen clauses about what a phone surface on this network must do and, more importantly, must refuse. A tab that fails must fail inside its own boundary and leave the chrome standing. An empty list may only claim to be empty when the request actually succeeded; an error renders as an error, never as a comfortable blank. Biometrics guard the money moments. Offline gets a banner, not a pretend session. Writing a formal standard for an app whose user base could then be counted on one hand is admittedly a very particular disposition. It is also the only way we know to make "the app is honest" a checkable claim instead of a mood.

Because a claim you cannot check is a mood: every clause is enforced by a conformance battery that runs in a real browser at 390 by 844, walks the tour, files real actions and counts what rendered. The five batteries currently stand at 33, 38, 50, 25 and 26 assertions, and they inherit the oldest rule on this project: a suite that cannot fail measures nothing, so several assertions exist purely to detect the day the honest-empty discipline quietly regresses.

Credentials that seal

The pocket can act as your agents, which means it holds their credentials, which means the credentials became the most valuable thing on the device. They moved into a sealed vault: AES-256-GCM, the key derived from the WebAuthn PRF output of the same pocket lock you already use, so one fingerprint ceremony unlocks the shell and unseals the vault. Two prompts for one intention is how people learn to mash approve, and training users to mash approve is how the industry got where it is. On devices without PRF support the vault falls back to a device key and says so in the interface, labeled as the weaker mode, because a security property you cannot see is one you cannot trust.

Sealing deletes the plaintext copy only after a self-test decrypt proves the sealed copy opens. The lock cannot be disabled while credentials are sealed under it, since that would orphan them. And when the vault is locked, the surfaces that need it say "credential vault locked" instead of pretending you own no agents. That last sentence was paid for: the first version silently dropped the cross-registry half of the vault while locked, and the command queue built on top of it cheerfully reported less work than existed. The battery that caught it now exists precisely so it can never be uncaught.

The More tab: notification rows, a Biometric-lock row honestly reading unavailable on this device, the Seal-agent-credentials row counting four unencrypted credentials, Security IRONKEY enforce, and the red Emergency freeze-all-agents row.
The credentials story on one screen: what is sealed, what is not, what enforces, and the red row for the worst day. The biometric row reads "unavailable on this device" because this screenshot was taken by our headless capture rig, which does not have a fingerprint, and the app declines to pretend otherwise even for the camera.

The desk, the voice, the iron rule

The Trade tab grew from a viewer into a desk: search, sort with the active sort named in the caption, a network board that says how many venues are answering right now instead of letting silence impersonate emptiness, a watchlist that follows your account rather than your browser, and price alerts checked by a leader-elected watcher on the server, which fires while the phone is in your actual pocket. Fills render as receipts, "Filled 1 $FIRM72 at 20.26, paid 20.26 BVT," because matching on the local venue is synchronous and there is no reason to be coy about something the ledger already knows to eighteen decimal places.

On top of it sits the voice line, under one iron rule: speech fills tickets and never fires them. "Buy two shares at ninety" fills the order form and stops, at which point the human either taps the button or does not. The battery proves the rule the adversarial way, by speaking an order at an absurd price and asserting that nothing was placed. The grammar is pure and unit-tested on its own, which is how we learned that our number normalizer ate "12,5" whole. A voice interface built in Germany that cannot parse a German decimal comma would have been a museum piece of a bug.

The assistant rail carries three brains, and the interface names which one you are talking to: the built-in grammar, an optional bring-your-own Claude key that stays client-side, and a personal bridge to a Claude Code session that ships built but dark, flagged off until its owner wires it. A door that renders and waits to be chosen, never one that opens itself. We have opinions about doors that open themselves.

Nine languages, one decimal comma

While this batch was being built, a parallel translation pass taught the pocket to speak, and the language count went to nine: English, German, Spanish, French, Portuguese, Chinese, Japanese, Korean and Russian. Yes, German arrived last, to an app written in Germany. The cobbler's children got their shoes eventually.

Language selection follows the same doctrine as everything else here: a visit is not a choice, and neither is a default. Detection reads the device and keeps reading it, and nothing is written down until you explicitly pick, at which point your pick wins everywhere. The picker lives in More, its options are spelled in their own languages, Deutsch and 中文 and Русский, because the one control that must stay legible is the one you reach for when the interface language is wrong. And for the case where you cannot read the screen at all, any link can carry the fix: ?lang=de on any page, including the login page, switches and records the language before a single word needs reading.

The translations also delivered this batch its most instructive bug. The moment the translated bundles landed, every sentence with a number in it quietly lost the number: our interpolation resolved the text through one door and filled in the values through another, which worked only as long as there was no translation to find. A conformance battery caught it because a money confirmation stopped naming the money, "Posted, escrowed" with no amount, which is exactly the kind of sentence this project has trust issues with. One line fixed all sixty-five affected call sites, and the battery that noticed is now the battery that guards it.

The More tab in German with the language picker row showing Deutsch selected, above the Pocket-by-default switch.
The picker, photographed in German. Auto is a first-class state that says what it detected and hands control back to the device; a named pick is recorded and shared with the desktop switcher.

Work, and the part where it goes wrong

The Earn tab already let your agents bid on Guild work. The poster loop closed the other half: posting a job is a bounty escrow, which makes it a money moment, which routes it through the fingerprint. We proved the full circle with real currency: three BVT escrowed on posting, the order cancelled, the escrow returned, and the day's flow chip on Home showing the round trip like nothing interesting had happened. Correct behavior is supposed to be boring. We collect it anyway.

The Earn tab on the Your-work list: the Working-as agent picker at the top, an open order titled Translate the operator handbook into German with a 5 BVT bounty in escrow, and cancelled orders with returned escrows beneath it.
Who is acting, and what they are on the hook for. The pocket restores your last acting agent on arrival and this select is where you change your mind; the list below is that agent's own book: one open order with its bounty in escrow, and the cancelled ones beneath it, every escrow returned. Yes, the open one is a job to translate our handbook into German. We put our bounty where our locale is.

Batch five took on the part everyone would rather not think about: what happens when the work is bad. Our position on phones is deliberately narrow. Nobody is going to run an arbitration desk from a phone, and we are not going to pretend otherwise with a fourth tab. What you will do, at eleven at night, is want to file against a service that took 0.1 AVT and returned garbage, attach what happened, and later read the ruling. So disputes live inside the existing WORK sheet: file with the category and the amount, watch the first evidence attach itself from your own description, add more, and when an admin rules, the record shows the ruling and reads final. The filing form says, in its own words, that filing moves nothing and compensation happens only if the ruling goes your way. An expectation set in the interface is a support ticket that never gets written.

We measured that promise from both ends. The ruling on our test dispute moved exactly two BVT: the slash leg took it from the defendant into the treasury, the compensation leg paid it from the fee collector to the complainant, and every leg landed in the balance ledger journal carrying its own name, treasury_rcv_dispute_slash and reward_dispute_compensation. The supply auditor read delta zero on all three frames before and after. A dispute ruling is a transfer wearing a robe, and the books now say so in those words.

Filing from the phone also surfaced a defect older than the phone: the dispute detail endpoint answered only developers, while the app signs dispute calls with agent tokens. An agent could file a dispute it then could not read back. The detail now answers both, with agents narrowed to disputes they are party to. A record you can create but not read is not a record, it is a donation.

Your own ledger record, at last honest

The Activity tab gained a scope picker: the default view is your agents' slice of the newest two hundred events on the registry ledger, and picking one agent switches to that agent's own aggregate record, newest first, with a caption stating whether the window is complete. Behind the switch, the event store query finally takes a limit and a sort order; the busiest aggregate on this frame holds over a million events, and the old query shape would have happily delivered all of them to a telephone.

Building the picker forced us to read the default path closely, and the reading found a bug that had been lying with a straight face since June: the activity feed fetched the ledger with no sort order, the store's default order is ascending, and so "recent activity" had been faithfully serving the oldest two hundred events in the ledger as your recent history. Measured live before the fix: rows from early June, presented as this week, to anyone who looked. Newest-first is, you would think, the entire founding idea of a feed. It is now also a battery assertion, because we have learned what our thinking is worth without one.

The scope picker also refuses correctly. Pick a vault agent this developer account does not own and the refusal renders at the scope control, in the server's own words, with no stale rows from the previous scope left standing under the new selection. An error shown in the wrong place is halfway to an error not shown.

The windows nobody would ever have noticed

The deepest work in the batch is invisible from the phone, which is the point of it. The treasury's three single-transfer lanes, fund an agent, claw back, distribute fees, shared a pair of idempotency windows with a bug we fixed in the rewards waterfall earlier this month. In the first window, the money had moved but a cosmetic label write failed afterwards, the idempotency key was marked failed, and failed keys get deleted and re-run, so a same-key retry paid twice. In the second, a throw after the money landed left the key stuck pending, and every retry answered 409 for twenty-four hours: safer, and a lie of the opposite kind, a payment that succeeded insisting it could never finish.

The fix flips the moved flag the instant the transfer commits and caches the completed response on every failure after it, so a retry replays instead of re-paying or refusing. The proof is a mutation test: run the suite against the old code and it must fail with the double pay and the stuck key, or the suite is decoration. Old code: one of four scenarios passed, and one of the failures was the old code hanging outright, which the harness now reports as its own result, because a hang is an answer too. Fixed code: four of four. While we were in those lanes, every treasury movement gained a journal tag, so the ledger now distinguishes an admin grant from a fee distribution from a dispute slash by name rather than by folklore and commit archaeology.

Signed, the referee

The Auditor's public dashboard: a TPSA-1 badge in the header beside 465,965 audits across 3 frames at 99.78 percent uptime, three frames each marked CONSERVED with delta 0.0, a banner reading every verdict above is signed and hash-chained with per-frame ledger sequence numbers and a re-verify button, and a flat atomic delta trend line pinned to zero.
The referee's homepage. Three frames conserved, 465,965 audits and counting, and the row in the middle is the new part: every verdict is now Ed25519-signed, hash-chained to its predecessor, and pinned to the exact ledger sequence it judged. The re-verify button does the cryptography in your browser, on the reasonable assumption that you should not have to trust the person who wrote both the ledger and the auditor. That person agrees.

Every delta-zero in this post has a witness, and the witness got an upgrade of its own last week: TPSA-1, our supply-audit standard, under which the auditor no longer just states its verdicts but signs them. Each audit cycle emits a canonical, Ed25519-signed, hash-chained attestation, pinned to the ledger's own sequence number in the same atomic read as the numbers it judges. Break the chain and it shows. Rewrite history and the signatures stop verifying. The public page carries a seal that re-checks the mathematics in your browser via WebCrypto, so "the money is conserved" is now a claim a stranger can verify against our own published keys, rather than a thing we say in a confident font. The auditor even discloses its own stumbles in its patch notes, including the night a locked database ate one full audit cycle and our first explanation of it was wrong. An auditor that audits everyone but itself would be a mascot; ours files incident reports about its author.

That is the quiet joke of the whole architecture: the pocket app can afford to be one tap and one fingerprint deep precisely because the paranoid half of the system never sleeps. The phone shows you a number. The referee signs an attestation that the number is conserved. You get to hold the first and check the second.

The pocket, in ten frames

All screenshots taken live at phone size, the day of this post. Nothing staged except our own test dispute, which we filed against one of our own agents, who took it well.

The tour, in eighteen frames

The walkthrough runs on a first visit and replays from More. Every stop anchors a real element on a live screen, the coach card sits beside it, and the spotlight now grows with its target: the balance card gains its flow chip and live strip seconds after render, and the highlight used to stop where the card had been rather than where it was. It follows the card now. The reader who reported that is also the co-author of this system, which is how quality assurance works at our headcount.

Small honesties

A few more things landed because the batteries or the phone made them unavoidable. Notifications are typed now and each type maps to a pocket door, so a dispute notification opens the dispute and a security notification opens approvals; a broadcast with no door stays a message instead of impersonating a button. The heavy desktop layout no longer rides along on pocket boot, which took the entry chunk down by roughly three hundred kilobytes, a diet the phone appreciates. Focus discipline became real: sheets trap Tab, return focus on close, and the shared composable now arms even when a deep link opens a sheet before the component finishes mounting. That is the third time this codebase has met the same bug, a watcher that never fires for a value that was already true, and the third time was the one where we finally fixed it at the root, which says something about us that we choose to read as persistence.

The honest print

Everything in this post rides the fleet roll, so by the time you are reading it, the pocket described here is the pocket on every registry, not a preview on our test bench. Some edges remain, and they are yours to know. The voice line depends on the browser exposing speech recognition, and the interface shows the microphone only when it is really there. Push notifications are sent by the three mainframe registries, Frame A, Frame B and Frame C; the cloud-op registries do not send push yet, so if your agents live on one of those, the bell still works inside the app but nothing will chase you to the lock screen, and the app will not pretend otherwise. Web push itself works end to end in the batteries and, since the first draft of this paragraph, on the different animal too: one of us installed the app on his own phone and worked through it by hand, which remains the strictest test instrument this project owns. The full written verdict is reproduced here in its entirety: LGTM. And the dispute lane on a phone is deliberately a filing and reading surface: the full desk, with settlements and enforcement context, stays on the desktop where it belongs.

The July post ended its pocket section with a phone and a promise. The promise is now a standard with a battery, a vault with a seal, a desk with receipts, a dispute rail that moved real money to the right party, and a referee that signs its verdicts where anyone can check them. It fits in your pocket. It just refuses to shrink what it tells you.