CustomLabs
Delivery record

The Delivery Record.

The Agentic Delivery Playbook says how we run a fleet of coding agents. This page is the receipts.

Every page on customlabs.io was built that way: one task per branch, a fixed stage flow, nothing reaching main except through a merge request. 126 of those tasks merged in 31 days.

Six defects got past the agent that wrote them. Below is each one: what shipped, what caught it, and the check that now fails the build if it comes back. The playbook makes claims. This page shows the working.

Counts as of 2026-08-04, at commit b60b19b.

01: The numbers

Six numbers, each one caveated.

Every tile carries a second line for what it doesn't tell you. Read them together, not alone.

snapshot

126

Distinct tasks merged

134 merge commits from task branches, total.

Doesn't tell you: Fewer than the merge-commit count above it, because some tasks merged into main more than once: 3 as a suffixed follow-up branch after review or verify rejected the first attempt, and 5 as a second merge from the same branch.

snapshot

31 days

Calendar window

2026-07-04 → 2026-08-03.

Doesn't tell you: Says nothing about hours per day or how many agents ran concurrently — a busy day and a quiet one count the same.

snapshot

3

Follow-up branches

Opened after review or verify sent the first attempt back.

Doesn't tell you: A lower bound, not a defect count — this only counts a rejection that needed a whole new branch. Rework inside the same branch, before it ever reached review, is invisible here.

snapshot

24

"Fix …" commits on main

Commit subjects on main starting with the word "Fix".

Doesn't tell you: Counts only commits whose subject literally starts with the word "Fix" — a defect fixed under a different subject line, or folded into a larger commit, doesn't show up in this count.

live

68

Published knowledge entries

Computed live at build time, not from the snapshot below.

Doesn't tell you: Counts insights, case studies, comparisons, patterns, failure modes, glossary terms, and tools — not every page on the site, and not this page either.

curated

7

Build-time invariants added after a break

Named in full below, section 03.

Doesn't tell you: A curated count, not an exhaustive one — only the checks in scripts/verify-seo.mjs and scripts/verify-theme.mjs with a traceable incident behind them are counted, not the rest of the test suite.

02: What the gates caught

Six defects, and what stopped each one.

Every SHA below is evidence text, not a link. The repository is private.

Shipped
Nine product pages published a "what it's built with" stack list — TypeScript, Postgres, Terraform, and so on — for every product. Nothing else in the repo documented the real technology choices behind any of the nine; the lists were inferred, not confirmed.
Caught by
Review stage
Root cause
The claims were checkable, and once checked, they were wrong.
Guard added
`stack` became an optional field on the Product interface and was unset on all nine products; the page now renders a "What it's built with" section only when the field is actually populated, so confirming a real stack later brings the section back with no code change.
Shipped
26 identical, blank Open Graph social cards.
Caught by
Human inspection after deploy
Root cause
renderSvgToPng() passed a fontBuffers option that @resvg/resvg-js@2.6.2 doesn't actually support — documented in the library's README, missing from its type definitions. Options cross the NAPI boundary as one JSON-stringified blob, so the single unknown key silently discarded the whole font object and resvg fell back to system fonts. Invisible on a dev machine with system fonts installed; every line of text dropped on the font-less CI build image.
Guard added
A byte-hash uniqueness check in verify-seo.mjs that fails the build if any two OG images render to identical bytes, plus wiring npm test into the CI build job — it had never actually run there.
Shipped
A new light theme whose focus ring was the lime --accent token, the same value the dark theme uses. Every focusable element on every page was affected, in the theme that had just shipped.
Caught by
Verify stage, after merge
Root cause
Every focusable element on every page drew its focus indicator in the lime --accent token: 17:1 contrast on the dark theme, 1.08:1 on the new paper-colored light theme. Not a weak indicator — no indicator, on every focusable element, on every page, in light mode.
Guard added
A new --focus-ring token (unchanged lime on dark, a darker olive on light tuned to clear 3:1 against every surface); a non-text 3:1 contrast floor plus a grep rejecting var(--accent) inside any :focus rule in verify-theme.mjs — axe-core does not check focus-ring contrast at all.
Shipped
Category filter chips on the failure-modes field guide hid the matching cards but left their category headings behind — filtering to one category could leave five empty, ruled headings on the page. Two strings also shipped literal markdown backticks onto the page and into the emitted HowTo JSON-LD.
Caught by
Review stage
Root cause
The click handler toggled visibility on the cards only, never on the heading wrapper around them; the backticked strings were plain prose Astro renders as literal text, not markdown.
Guard added
The filter logic moved into one applyFilter() function that also hides an empty category heading and runs once on page load, so the default view matches a click on "All"; TopicMember became a discriminated union on kind to restore the compile-time guarantee that date fields are actually present.
Shipped
The header search trigger both navigated to /search/ and opened the command palette on top of the new page — two stacked search surfaces from one click.
Caught by
Browser check after merge
Root cause
Listener ordering, not the anchor. ClientRouter registers a document-level click listener at parse time and only bails if preventDefault() was already called; the palette's own delegated handler registered later, in bubble phase, so ClientRouter ran first and navigated before the palette could stop it.
Guard added
The delegated handler moved to { capture: true }, which always runs before a bubble-phase listener regardless of registration order; verify-seo.mjs now greps the source for that option, and the why is written into README.md.
Shipped
Nine product pages rendered their content sections as styled kicker spans — visually a heading, structurally nothing. Page outline was one h1 and a single h2 from the FAQ component, across nine content sections per page.
Caught by
Review stage
Root cause
The exact failure these pages existed to fix: no heading outline for a screen reader or crawler to navigate by.
Guard added
Every section now pairs its kicker with a real h2, the same way failure-modes/[slug].astro does; outline is now one h1 plus ten h2s per page.
03: Every bug became an invariant

7 checks, each one because something broke.

Named with the file that enforces it, and the exact failure it now makes impossible to reintroduce.

OG image byte-hash uniqueness

scripts/verify-seo.mjs

A social-card render silently collapsing to the same blank PNG for every route — the URL-uniqueness check alone would have passed while every card was byte-identical.

Non-text 3:1 contrast floor on --focus-ring

scripts/verify-theme.mjs

A focus indicator that clears contrast on dark and fails it on light (or any future surface) shipping unnoticed — axe-core has no check for this at all.

Capture-phase listener grep on the search trigger

scripts/verify-seo.mjs

The header search anchor navigating to /search/ and opening the command palette on top of it at the same time — a runtime race with nothing in the built HTML to assert against otherwise.

Text-contrast floor (4.5:1) across every token pair

scripts/verify-theme.mjs

A text color quietly failing WCAG AA against its own surface — the fix for a specific --text-dim-as-text regression (2.85:1), generalized to every text-and-surface pairing in both themes.

Search-index coverage invariant

src/lib/search-index.ts

A published page or entry with no way to find it through site search — the fix for a 39-route hole that had gone unnoticed across case studies, glossary, topics, tools, pricing, and the diagnostic pages.

Inline document-weight ceiling

scripts/verify-seo.mjs

Something large getting inlined into every page again — the search index used to add roughly 47 KB to every single page's HTML before it moved to a static endpoint.

Search-index anchor resolution

scripts/verify-seo.mjs

A search result promising a specific row and landing the reader at the top of the page instead. Every record whose URL carries a "#" must match a real id in the built HTML — the check this page itself was rejected for missing.

04: Before you copy this

What this doesn't prove.

Read this section before the numbers above, not after.

Read the model this evidences

The Agentic Delivery Playbook is the 22-practice operating model behind every task on this page. CodeHerder is the product that runs it day to day.

Questions

05: Before you ask.

What people ask us about publishing this.

01 Did agents write all of it?

Most of the code, yes — plan, code, and several rounds of review and verify run as agent stages. Of the six commits above, three carry the agent's own author name and three carry a human one; the record draws from both.

02 Doesn't this prove agents need heavy supervision?

Yes, and that's the point. Every one of the six incidents on this page was caught by a gate, not by the agent that wrote the code catching its own mistake. Take the gates away and this page is a list of six things that shipped broken instead of a list of six things a check caught.

03 Why publish your own bugs?

Because a claim about how well a delivery model catches defects is only worth something if it names actual defects, not a hypothetical failure rate. Six real incidents, with the real root cause and the real guard that came out of each one, is the strongest evidence we have for the operating model on /agentic-delivery/.

04 Can we see the repo?

No — it's private. The short SHAs on this page are evidence text, not links; nothing here resolves to a URL you can open.

05 Does this transfer to our codebase?

The pattern does; the numbers don't. One task per branch, a fixed stage sequence, and a review stage that actually looks for problems is the transferable part — see the practices this page links out to on /agentic-delivery/. Our own count of merged tasks and follow-up branches is specific to this repository.

navigate select esc close