Notes

Note · September 2026 · 5 min

Tickets as contracts: how a solo build stays honest

The ticket system I run the Keystone platform on: scope locks, approval envelopes, closeouts that say what is not claimed, and a status page that regenerates from the corpus.

Most of the code on the Keystone platform is written with AI coding tools. That makes the ticket, not the pull request, the unit of control. A ticket is the contract between me and whatever is executing: what to build, what it may touch, how we’ll know it worked, and what it must not claim afterwards. The repository holds more than 460 archived tickets and about two dozen active ones, and the discipline around them is what keeps a one-person project from drifting.

What a ticket carries

  1. Machine-readable frontmatter. Every active ticket has an id, a status, a priority, the arc it belongs to, the surfaces it touches (backend, console, Firestore, secrets, DNS and so on), hard dependencies, what it blocks, and links to the decisions, working principles and open questions it relates to. Body prose stays the source of truth for scope; the frontmatter is the queryable index.
  2. A status vocabulary with teeth. Draft, ready, in progress, blocked, backlog, shipped. Blocked is involuntary and must name the blocker; backlog is a choice. The distinction is load-bearing when you are deciding what to work on next.
  3. An approval envelope. “Ready” means scope-locked under a stated envelope: for the recent PostgreSQL work, local and synthetic only, no schema or grant changes, no runtime activation, no production data. Anything outside the envelope is a separate approval, not an assumption.
  4. A closeout that says what is not claimed. When a ticket ships, an archive note records the merged SHA, the test counts on that commit, the findings recorded but deliberately not changed, and a “not claimed” list. The concurrency proof shipped with the sentence “runtime activation remains OFF” in the first line so nobody, including me, could misread it later.

Review before acceptance

Larger batches go through a separate review pass with its own brief before I accept them. The reviewer’s findings are corrected in place and acceptance is withheld until a targeted re-review passes. The recent database batch went through five such cycles; two of the findings were real races that became their own tickets. Slower than merging on green, and the reason the “what I’d change next” lists on this site are specific.

Drift is expected, so it is checked

The platform’s status page is generated from ticket frontmatter, never hand-edited, and a --check mode fails when the page has drifted from the corpus. It is regenerated at review boundaries rather than after every micro-change, which keeps the history readable. The same idea runs through the codebase: the county evidence set regenerates offline and a lockstep test fails if the backend and console copies diverge; a pre-deploy check runs before any release; the verification gate refuses a dirty tree.

Hard gates, not readiness loops

The build doctrine I work under says to ship the largest useful, safe slice and to stop only at hard gates: anything that would make a false public, live or runtime claim. Internal, manual or read-only tools are not gates. Without that rule a careful solo builder can spend months producing readiness checkpoints and never a usable thing. With it, every arc ends in something an operator can open, and every claim on this site can be traced to a ticket.

See the Keystone platform case for the system these tickets built, and Context engineering for how the surrounding documentation is kept true.

Let’s talk.

Have a project or a question? I’d like to hear it.