A Log You Can Ask — What Thirty Notebooks Could Not Show
9 minSomething to state up front. In April 2026 this magazine ran a piece about a thirty-year tomato grower in Oregon, who moved thirty notebooks from a barn onto one screen. It was an interview naming the person, their age and their region.
This is not a specific farm. So we do not republish that interview. Instead we built the same shape from beginning to end ourselves. Every screen and every number below comes from what we built, and it is not any one farm's records.
The reason this distinction sits in the first paragraph is that the original's whole argument is permission — "you can do this too" — and that permission rests on the reality of the case. Repeating the same sentence without having confirmed that reality is not permission, it is advertising.
So what this piece sets out to prove narrows. Not "a farmer did it" but "a tool like this looks like this, and it really does this much".
The heart of the original had nothing real in it
The original's axis was good. Paper stops at writing. Taking things out and comparing them is left to human memory and patience. But stacked in the same slots, a record becomes something you can ask.
We still think that shift in materiality is right. The problem is that the piece never once showed it.
- What he actually said — zero lines of the original request
- What screen definition that speech became — zero lines of definition
- What steps it went through — zero steps of process
- Moving thirty notebooks — only the statement "I'm transferring them bit by bit"
And the piece's best line — "first flower on day eighteen after transplanting" — was the same. It is a claim that only stands once five seasons of data exist, and neither that data nor the screen where it emerged was there.
This time we put three things side by side. What was said → what became a definition → what was actually drawn.
What was said
While building, we wrote the requirement as three sentences. No development vocabulary.
- "Pick a crop and this season's records come up in a row."
- "Recording should work with one hand."
- "Show me what this time last year looked like, next to it."
Three sentences became three tools.
log offers: log.season, log.add, log.compareWhat became a definition
The first sentence became this part of the screen. Not code — a declaration.
{
"type": "list",
"items": "{{season}}",
"emptyMessage": "Nothing recorded this season yet",
"itemTemplate": {
"type": "linear", "direction": "horizontal", "spacing": 12,
"children": [
{ "type": "text", "text": "{{item.date}}" },
{ "type": "text", "text": "{{item.action}}" },
{ "type": "text", "text": "{{item.tempC}}°C" },
{ "type": "text", "text": "{{item.note}}" }
]
}
}The second sentence became one button.
{
"type": "button",
"label": "First flower",
"onTap": {
"type": "tool", "tool": "log.add",
"params": { "crop": "Tomato", "action": "firstFlower", "tempC": 19.5 }
}
}The third sentence produced one more screen. One line of route.
"routes": { "/": "ui://pages/today", "/compare": "ui://pages/compare" }The whole app is four JSON files. No compiler runs.
What was actually drawn
Today's screen. Days since transplanting and the average of past years sit at the top.

Press "First flower" once and one row appears.

And the screen with the years laid over each other.

18.2 days is written down nowhere
This is the most important part of this piece.
The original wrote "eighteen days" as though it were a result. In this sample that number is not a constant. It is computed from the records every time.
/// Days from transplant to first flower, per season.
///
/// This is the whole "eighteen days" claim, and it is arithmetic over the
/// rows — no constant anywhere. A year with no flower recorded yet is left
/// out rather than guessed at.And the verification confirms that directly. If the computed value appears as a string in the source, it fails.
src = open(os.path.join(SERVER, "bin", "server.dart")).read()
assert str(cmp["avgDays"]) not in src, "the average must come from the records, not the source"The passing log.
average 18.2 computed from records, not present in any source file"It emerged from the records" and "somebody typed it in" look identical on screen. So a way to tell them apart went into the pass condition.
The exceptions start to speak
The best observation in the original was not the average but what came after it. Once there is an anchor, the years that depart start to become visible.
The computed table is exactly that.
spans: 2021:22d, 2022:18d, 2023:15d, 2024:18d, 2025:18d, 2026:18d2021 was twenty-two days, and that row's note carries five cold days in early April. 2023 was fifteen days, with warm week before transplanting.
In scattered notes, both twenty-two and fifteen would have drifted past as "a bit different this year". With no baseline to compare against, you do not even know they are exceptions. Only once the average of 18.2 stands do those two years start to speak.
Without the same slots, nothing stacks
There is one condition under which all of this holds. The records have to be the same shape.
/// One entry, in the same six slots every time. The whole argument of the
/// article rests on this being fixed: `plot · crop · action · date · note ·
/// tempC`. Paper let every year invent its own shorthand; slots do not.Six slots. This is what paper could not do — paper allows a different shorthand every year. Whether 2019's "set out" and 2023's "moved" mean the same thing, the notebook does not know.
And one thing was done deliberately about the date.
// The date is the machine's, not the grower's memory. Paper let a row
// be written three days late with no trace; this cannot.The division between judgment and tool
The original's best asset was a five-row table dividing the work. Judging what needs recording is the farmer's; carrying it is the tool's. We keep that table, and this time each row points at something real seen above.
| What | Who | The real thing in this piece |
|---|---|---|
| Deciding what to record | Farmer | Six slots (plot·crop·action·date·note·tempC) |
| Saying how you want to see it | Farmer | Three sentences of requirement |
| Turning that speech into a screen | Tool | Four bundle JSON files |
| Stacking, filtering, computing | Tool | log.season · log.add · log.compare |
| Deciding what to do | Farmer | — (the tool does not judge) |
The last row is the same place as the original's restrained boundary section. That sentence sits verbatim at the bottom of the screen.
A tendency, not an instruction. Read this season on its own terms.
The tool takes an average; it does not tell you to plant. Cross that line and thirty years of judgment go unused.
The range of this sample
There is no farmer. The three requirement sentences in this piece were written by me, and the five seasons of records were made by me. So please do not read this as "a farmer built it this way". What this piece showed reaches "a tool like this looks like this, is this short, and the average really is computed".
And we did not confirm whether a domain expert can handle this format directly. The JSON above is readable, but whether a fifty-eight-year-old grower could edit it themselves is a separate question and this series did not answer it. The conversion the original called "just say it" — the step where a person's words become a definition — was done here by my hands.
Moving thirty notebooks was not addressed either. How much work it really is to move paper into slots was not measured by this sample.
We also note why the UI is in English. The samples in this series use English on screen and in the code. This piece is a construction rather than any one farm's tool, so a reader in any language reads the same capture and the same source.
From writing down to asking
The original closed with "start small and add one slot at a time". We keep that advice.
To it we add one line learned from building. Keeping the slots the same is harder than adding slots. Deciding the six slots took under ten minutes, but those six have to stay the same across five seasons for the final screen to hold. That is exactly where paper failed.
And once it holds, the record changes its nature. From something written down to something you can ask. 18.2 days was not written for us by anybody; it was the answer to a question.
Practice task
Pick one answer from the plant example and name the record it cites. What would the tool do if no record matched?