Compound Labs
Get the newsletter
THE STANDUPAnthropic fixes Claude 5.1 error spikesERROR SPIKES, FIX DEPLOYEDCOMPOUND MASTODONSkillWorks records inactive files beside their roster status22 INACTIVE FILES STILL LOADCTXWINDOWContext Window tracks AI lab changes and filters their evidenceFILTERS KEEP EVIDENCE TOGETHERAGENTWIREmicrosoft/agent-governance-toolkit - AI Agent Governance ToolkitPOLICY ENFORCEMENT FOR AI AGENTSCOMPOUND FACEBOOKCompound Portfolio restores its sweep after a missing module stops desk dataSWEEP RESTORED, DESK DATA WRITTENBLOCKDEXBlockDex shows no destination for captured rows with rejected slash names31 ROWS, NO DESTINATIONCONTEXT WINDOWOpenAI adds 1024p image pricing: $0.50 and $0.251024P IMAGE, $0.50 AND $0.25COMPOUND BLUESKYCompound Labs renamed job labels so job-run finds breaker stateBREAKER STATE, NOW FINDABLECTXWINDOWContext Window tracks document changes but failed mobileMOBILE WORKFLOW, ONE COLUMNAGENTWIREMineDojo Voyager: Open-Ended Embodied AgentOPEN-ENDED EMBODIED AGENTFOUNDER BLUESKYdeploy.sh now fails false Vercel production landingsFALSE LANDINGS NOW FAILCOMPOUNDlast known fixes redirect tracking after migrationSTUDIO SOURCES NOW SAY COMPOUNDCONTEXT WINDOWOpenAI adds sora-2-pro pricing720P VIDEO, $0.15, $0.30FOUNDER LINKEDINdeploy.sh now stops failed promotes from marking production landedFAILED PROMOTES NO LONGER LANDUSINGITUPUsing It Up records a receipt fixing a wobbling wooden tableONE RECEIPT, TABLE STAYED LEVELCOMPOUNDpnpm v12.4.2POSIX BIN SHIMS REPLACEDFOUNDER PEERLISTCompound Labs' deploy runner rejects failed promotesFAILED PROMOTES NO LONGER LANDTRUSTDESKTrustDesk fixes host migration redirects while keeping /api/ outOLD HOST, 308; API STAYS LIVE
Independent product R&D labFounded and run by Isaiah Kim, @kyisaiah47Newest commit Sep 16, 2026, AgentwireNewest writing Sep 16, 2026Site changelog Sep 16, 2026
Aug 15, 20264 min read

Undo on a write you cannot recall: a queue, two mirrored UPDATEs, and a window that is a floor

A correction posted into somebody's general ledger cannot be pulled back from the other side. There is no unsend. Reversing a posted bill adjustment means a second journal entry, and the auditor sees both of them forever. So the feature request "let me undo that" is not a button problem.

The build I want to describe is an agent that reconciles a purchase order, a goods receipt and a bill against each other overnight, clears what agrees inside a tolerance, and queues what disagrees for a bookkeeper. When the bookkeeper approves a suggested fix, that fix eventually becomes a write into QuickBooks. Here is what "eventually" is made of.

Undo works by not doing the thing yet

Approving does not call the ledger. It inserts a row:

const postsAt = Date.now() + UNDO_WINDOW_SECONDS * 1000; // 60
await sb.from("matchrail_corrections").insert({
  status: "scheduled",
  scheduled_for: new Date(postsAt).toISOString(),
  payload: { approvedVarianceCents: Number(match.variance_cents), /* ... */ },
});

and writes an audit row saying who approved what, on what evidence. A separate cron sweep picks the row up later. Every gate below hangs off that single deferral.

The race is the whole mechanism

Two actors want the same row: the sweep, which wants to post it, and the human, who wants to kill it. They are written as mirror images of one conditional UPDATE.

// The dispatcher's claim, once per row, per sweep.
update matchrail_corrections set status = 'posting'
  where id = ? and status = 'scheduled' and scheduled_for <= now()

// The human's undo, from the countdown on screen. update matchrail_corrections set status = 'undone' where id = ? and user_id = ? and status = 'scheduled' ```

Both predicates require status = 'scheduled', so exactly one of them affects a row and the other gets zero rows back. No read-then-write, no advisory lock, no interval in which both believe they hold it. That matters more than usual here because the two things they would each be doing are "write to a ledger" and "promise a human nothing was written".

The loser also has to say which way it went. undo re-reads the row and distinguishes "already undone" from "too late, it is posting", because those are different facts to somebody staring at a timer.

The window is a floor, and copy leaks it

A cron sweep runs on a cadence. A 60 second window plus a 15 minute sweep means a correction posts no sooner than 60 seconds and possibly ten minutes later. Everything user-facing has to be phrased that way, so the pages say "posts no sooner than 60s" rather than "posts in 60 seconds".

Because that number is quoted by a client component and enforced by the server sweep, it lives in a file with zero imports. Putting it next to the dispatcher would drag a service-role database client into the browser bundle the moment the landing page imported it.

That file also documents the cron expression it assumes. Reading this repo back, vercel.json was firing the dispatch route every 5 minutes while the constant, the route header and three rendered surfaces all said 15. Nothing posted early, since the floor is a WHERE clause rather than a schedule, but the deployment was running a cadence none of the published copy describes. Fixed to /15 *.

The check people forget: revalidate at post time

Between approval and the sweep, the documents can move. A vendor re-syncs, a bill line changes, the variance is no longer what the human saw. So the approved figure is frozen into the correction payload and compared against the live match before the write:

if the current variance is not the approved variance, the row goes to held with a message naming both figures, and nothing posts. There is no retry anywhere in this path either. A blind retry against an accounting system is how you post the same adjustment twice, and the duplicate stays invisible until a reconciliation months later.

What each terminal state proves about the ledger

Row statusReached the ledgerHow it got there
undonenoThe human's UPDATE won the race. Audit row records wrote: false.
heldnoDaily post cap burned, exception already closed, or the approved figure moved. Returns to held, never re-arms itself to scheduled.
failednoThe rail refused the write, or write-back for that ledger is not wired. The match stays an open exception.
posted, price/quantity/void kindsyesThe vendor API response is stored verbatim on the audit row, not paraphrased.
posted, hold/accept kindsnoA decision recorded inside the product. wroteToLedger: false is carried explicitly rather than inferred from a rail nobody called.

The last row is the one worth stealing. Two of five correction kinds never touch anything outside the product, and if that distinction is left implicit, an audit trail full of posted tells you nothing about which writes actually happened.

How we built this: MatchRail, https://matchrail.thecompound.tech/

---

One shipped product, taken apart, once a month. What it does, what it cost to build, what the pipeline behind it looks like, and what the numbers did, read off the repository and the live site, not written from memory. Join the list.

All writing