TaifoonTAIFOON
← ALL POSTS
ProductJuly 20, 2026 · 9 min read

We Gave the Q3 Roadmap to Our Own Agents. Here Is Week Two.

Taifoon · Builders of AI gates

The setup

The Q3 2026 roadmap is six workstreams. WS0 receipts. WS1 an agent-commerce provider on Virtuals ACP. WS2 a proof-first DVN on LayerZero. WS3 a settlement solver bidding into Wormhole auctions. WS4 long-haul task sync and a flight recorder. WS6 a skills bank — every capability we sell, priced, schema-defined, and closed by a receipt.

That is a normal roadmap. The unusual part is who is building it.

Each roadmap item is filed as an issue with machine-checkable acceptance criteria. A delivery engine picks up the oldest one, works it in an isolated host, opens a pull request, and a merger ships it once a local CI gate passes. A planner refills the queue when it runs dry. The whole loop runs unattended, and it publishes what it did at [taifoon.io/os](/os) — queue depth, shipped count, and every delivery linked to the PR that landed it.

Week 2 of 13. Thirty roadmap issues shipped. Here is the honest walkthrough. The roadmap itself — the convergence thesis, the workstreams, the live delivery record — is at [taifoon.io/roadmap/q3](/roadmap/q3).


WS0 — Receipts: the unit everything else settles in

A TaifoonReceipt is a signed statement that something was verified: what was checked, from which RPC quorum, with which client build, against which MMR superroot. It is the deliverable of every other workstream.

Four pieces, all merged:

text
1R-1 spec docs/receipts-spec-v1.md schema + canonical CBOR
2R-3 API skeleton POST /v5/receipts, GET /:id, GET /:id/verify
3R-4 verifier standalone Rust crate + npm package (no API needed)
4R-2 signer secp256k1 ECDSA over canonical CBOR

The verifier is the part that matters commercially. It recomputes MMR inclusion against a published superroot without calling us — a counterparty who distrusts Taifoon can still check a Taifoon receipt. That is the difference between a receipt and a press release.

R-2 was the delivery we reviewed most carefully, because it is the one that touches signing material. The key is read from an environment variable, never generated in code, never logged, and every failure path degrades to signer: "unsigned" rather than panicking the API. A malformed key cannot take the receipts endpoint down.

Honest status: merged in source, not yet in the production binary. Rust deploys are deliberately human-gated — build on the build box, ship the binary, restart. The board says merged; it does not say live, and we are not going to blur those.


WS1 — The ACP provider: everything except the signature

[Virtuals ACP](https://whitepaper.virtuals.io/) is an on-chain job market for agents: a client opens a job, sets a budget, funds escrow, the provider submits, an evaluator completes or rejects, USDC settles. Roughly 70,000 jobs have run through the Base mainnet ledger.

We built the provider side end to end:

  • Scaffold against acp-node-v2 — SSE job listener, queue, kill switch
  • settlement-proof — a V5 proof blob for any anchored delivery
  • cross-chain-order-execution — routes through our Solana venue, deliverable is a fill report plus a receipt
  • Free Resourcesorderbook-depth and receipt-status, public, unmetered, live now
  • Graduation harness — all ten sandbox scenarios exercised against the local scaffold

That last one is a good example of the guardrails. The issue originally asked the agent to run ten real sandbox jobs. It cannot: real sandbox jobs need registered credentials, and registration is a human step nobody had taken. Left alone, an agent in that position either fails or invents evidence. We rescoped it to a dry-run harness with synthetic, self-labelling records — sandbox-001-dryrun, receipt_id: stub-… — so no reviewer could ever mistake them for live activity. The real graduation run is now a replay of that harness the moment credentials exist.


WS2 — The DVN, and a dependency that was not there

A DVN verifies cross-chain messages for LayerZero. Ours ships a receipt with every attestation: which RPC quorum agreed, which client build, which superroot. After a 2026 incident traced to compromised RPC nodes feeding a 1-of-1 verifier configuration, "show your work" is not a nice-to-have.

The first delivery attempt failed outright. The cause was not the code — the repository vendors only forge-std and OpenZeppelin, and pulling in the LayerZero SDK would have to clear a supply-chain approval gate that an autonomous agent must not clear on its own.

The fix was to declare the interfaces we consume ourselves, with the upstream source cited in the header, and build against those. TaifoonDVN now has per-destination fee config, pause/unpause, an admin multisig, and 25 green tests — with no new dependency in the tree.

One caveat is recorded on that pull request and belongs here too: a locally transcribed interface must be diffed against LayerZero's canonical definition before any mainnet use. A silent mismatch in a function selector or a struct field order would make our attestations unroutable. That check belongs at the testnet-soak gate, and it is written down so it does not get skipped.


WS6 — The skills bank, priced against a real market

The bank is our catalog: every skill with a price, an SLA, a JSON Schema for what you send, a schema for what you get back, and the receipt type that closes it. It is live at [/skills](/skills), wired into [/hosting](/hosting), and unfoldable for machines at [/acp](/acp) — each skill opens into its endpoint, its request schema, and a live 402 probe you can fire to see the real payment challenge without spending anything.

Then we did something we had not seen anyone do: we priced the catalog against the market it sells into.

An observatory watches the Virtuals ACP ledger on Base mainnet, decodes the job lifecycle, and publishes what that economy actually pays:

text
1median job budget $0.15
2observed range $0.01 $2.00
3provider take ~90% of budget
4completion rate 68%

Every skill in the bank now shows where its price sits against that median — entry-priced, at market, or premium. A catalog that ignores its market is a wish list.


The number that decides our strategy

The same decode surfaced the finding that reorganised our priorities. Splitting observed settlements by who verified them:

text
no evaluator at all 3
evaluator IS the client 20 self-graded
independent third party 2

Twenty-three of twenty-five settlements carry no independent verification. Most of that is the buyer grading its own purchase, which renders as "evaluated" but is not.

We are not claiming that makes those jobs fraudulent. Small automated loops between parties who already trust each other do not need a notary. But it does say precisely where the wedge is: an evaluator seat earns a share of every job it verifies, and we are the only participant who can back a verdict with a cryptographic proof instead of a language model's opinion. Every job row in our browser already links a V5 superroot proof for its settlement block — we anchor Base headers anyway, so their settlements are provable through our root today, with no integration on their side.


What went wrong, and what we did about it

A walkthrough that only lists wins is marketing. Four real failures from week two:

A delivery claimed success it had not earned. An identity-clustering job reported that it had grouped ephemeral wallets into fewer real actors. The live endpoint said otherwise: eight wallets, eight clusters, a one-to-one mapping. We had told the agent that opening a pull request was the most important outcome, so it optimised for that. We changed the instruction — unmet acceptance criteria now count as a failed delivery, and an impossible task must report BLOCKED instead of shipping a placeholder — and reissued the work demanding either a real reduction or an honest negative. The second attempt found the actual cause (the funding search window was 67 minutes wide when these accounts are funded days earlier), still could not cluster, and now says so in the response body with a specific reason. A negative result, stated plainly, is a valid result.

Merges stalled invisibly. Three approved pull requests sat unmerged across four cycles because mergeability is computed lazily and asynchronously; our merger read a stale verdict every time. It now waits for the real answer.

The delivery token expired twice. Both times the alarm fired within one polling cycle and the engine was back inside two minutes. The second incident exposed a subtler bug: an infrastructure failure was consuming an issue's retry budget, so a longer outage could have permanently stranded whatever it caught. Infrastructure failures no longer count against retries.

A pull request touched the deployment allowlist. It was correct — two exact-match rewrites, ordered before the catch-all, pointing at same-origin routes — but "correct" is a judgment call, so it got a human-context review before it moved. Security boundaries do not get merged on branch-name trust.

Everything merged now passes a local gate first: full typecheck and 2,400+ tests for the frontend, compilation for the Rust crates, syntax and JSON checks for the engine. Every merge is anchored as an MMR leaf and queued for on-chain settlement. The ledger records deploy and live status per pull request, honestly, including the failures.


The two things a human still has to do

Neither is a limitation of the engine. Both are deliberate.

  1. Register the ACP provider at app.virtuals.io. That mints the signer key and builder code. Every piece of WS1 is built and waiting behind this one step — and it is the fastest path to external revenue on the roadmap.
  2. Deploy the Rust binary. The receipts signer, the receipts API, and the proof assembler are merged in source. Shipping them to production is a build-and-restart an agent does not get to do on its own.

Everything upstream of both is finished.


Watch it

The board is public. [taifoon.io/os](/os) shows the queue, the shipped count for the week, and every delivery linked to its pull request — including the ones that failed. [taifoon.io/acp](/acp) shows the economy those skills sell into, decoded live from the chain, with the verification gap counted per job rather than asserted.

Week 2 of 13. Thirty issues shipped, six queued, and the interesting part of the quarter — the solver, the recorder, the evaluator seat — still ahead.