Samuel Obukwelu sobu.dev · Samuel Obukwelu
Builder · Operator · Engineer
Notes · sobu.dev

What I'm thinking, in short.

Off-cuts, TILs, links, quotes, status. Short by definition. The essays live here.

ASIDE

A Chief of Staff per domain

The work volume has crept up to where context-switching is the real cost. TaskFast, Fraction, home life. Holding all of it in one head means everything gets the same lukewarm half-attention.

So I’ve been building a small fleet of Chief of Staff agents, one per domain. Each is its own agent profile with its own identity file, its own chat bot, its own memory peer, its own scheduled watchers. They don’t share anything. A competitive secret in TaskFast’s memory will never surface in a Fraction conversation, by construction.

Above them sits Benson, my main agent, who does none of the domain work. His one job is to read across the fleet every morning and tell me what to look at first. Three minds, one sense of what matters.

The interesting infra question is how signal actually gets to these agents. My local server accepts no inbound network connections. So Fireflies and GitHub webhooks land on a Cloudflare Worker instead. The Worker verifies the signature, dedupes against KV, persists the raw payload to D1, and enqueues the event id. The local server then long-polls that queue, pulls events, and feeds them to the right CoS.

The trick is the queue. It buffers for days. If the server is asleep, offline, or I’m rebuilding it, nothing is lost. Polling APIs from the local server directly would silently lose anything that ages out of a source’s window during downtime. The Worker-plus-Queue path makes the whole pipeline forgiving in the way I need it to be.

What I like most is how cleanly the topology decomposes. Domain agents talk to me when I want depth. Benson talks to me when I want priority. Webhooks talk to Cloudflare. Cloudflare talks to my local server. My local server talks to nobody.

ASIDE

Six hours at the Generative UI hackathon

Six hours on a Saturday, noon to six. Built a thing called Witness at a generative UI hackathon.

Most agent UIs are built for the agent. You inherit a chat log and a spinner, and you’re supposed to trust it. Witness flips that. Instead of one chat shape for every task, the model renders the verification surface itself, tuned to what the agent just did.

Six hours isn’t enough to ship the idea, but it’s enough to feel where it bites. The real frontier is the agent generating the UI that makes its own work auditable. That’s a different skill from writing code, and the gap is wider than I expected.

TIL

Astro's glob loader is lazy until you call getCollection

The glob() loader Astro ships with content collections doesn’t read disk at config-load time — it defers until the first getCollection() call. Means you can declare a hundred collections without paying for the ones a page never uses.

Discovered while wiring a second collection alongside blog. The build stayed cheap; the new collection only got walked on the page that actually rendered it.

ASIDE

Discriminated unions are an authoring signal

Designing the notes schema, I kept reaching for “make every field optional and add a refine() for the rules.” Then I remembered the marginalia schema already uses a discriminated union, and switched.

The shift wasn’t about types — it was about authoring. With a flat optional schema, the editor lets you type kind: link and forget the URL. With a union, the build fails the moment you do that. The schema becomes a checklist you can’t ignore. That’s the actual win — not the type narrowing in the renderer, but the constraint at write time.

QUOTE

Make it work, make it right, make it fast — in that order.

Kent Beck

The order is the whole lesson. People skip “make it right” because “make it work” already shipped, then optimize. Six months later the code is fast and wrong and nobody can change it.

I read this as a debt instrument. Skipping a step doesn’t remove the work — it moves it later, with interest.