0009 — A calendar date is a date, not a timestamp
The best-evidenced decision in the codebase. Two shipped bugs, and both lq check and the generated tests passed throughout.
Context
A due date, an issue date, a publication date. These are calendar dates: the same
day for everyone reading them. timestamptz is the reflexive choice and it is
wrong for this, in a way that only shows up for readers in a different timezone
from whoever wrote the code.
Decision
date('column', { mode: 'string' }). A real date column, and the value stays a
'YYYY-MM-DD' string from the column all the way to <input type="date">.
The two bugs
This record exists because both of these shipped.
Off by one day. Stored as a timestamp, a date rendered as the previous day for any reader west of whoever entered it. Nothing errored.
A form that silently cleared the field it was editing. <input type="date">
accepts only 'YYYY-MM-DD'. Handed a Date, the browser rejects the value and
renders the field empty — so opening a record to edit it and saving blanked
the date. No error, no warning; the user's data quietly gone.
And the line that earns this page its place:
Both
lq checkand the generated tests passed throughout.
That is corroborated independently in for-agents: of the worst bugs found while
building products on this template, "two of the worst passed both lq check and
the generated tests. A required text field did not compile, and a date form
silently blanked the field it was editing."
Consequences
The decision does not stop at the column. Both halves of the round trip have to agree or the bug comes back:
formatDate parses and formats in UTC — precisely the bug mode: 'string'
exists to prevent, reintroduced at the render layer if it did not.
todayForDateInput is deliberately not toISOString().slice(0, 10). That is
UTC, so anywhere behind it the form offers tomorrow's date all evening.
There is deliberately no timestamp field type in the generator. A stored instant renders as the wrong day for a reader in another timezone, and the generator should not make that easy to reach for.
Why it is the strongest record here
Every other page argues from a design principle. This one argues from two user-visible data-loss bugs that every automated gate approved. If you read one record to understand why this codebase enforces things at the type and schema level rather than by convention, read this one.
0008 — There is one validation verb
Five commands means an agent remembers zero. lq check is what the hook runs, what the rules mandate, and what CI runs — the same code path in all three.
0010 — Offset pagination, deliberately
Cursor pagination is better at scale and worse at everything a starting product needs.