先に明かしておくことがある。 2026年4月にこの雑誌は、江原道華川の30年目のトマト農家が納屋のノート三十冊をひとつの画面に移した話を載せた。実名と年齢と地域まで特定されたインタビューだった。
この現場は特定の農家ではない。 だから元のインタビューをそのまま再掲しない。代わりに同じ形を最初から最後まで自分で作った。 以下のすべての画面と数字はそうやって作ったものから出たものであり、どこか一軒の農家の記録ではない。
この区別を冒頭に置く理由は、元の記事の論旨全体が「あなたにもできる」という許しであり、その許しは事例の実在に乗っているからだ。実在を確認しないまま同じ文を繰り返せば、それは許しではなく広告だ。
だからこの記事が証明しようとするものは狭くなる。「ある農家がやり遂げた」ではなく「こういう道具はこういう姿で、実際にこれだけできる」までだ。
元の記事の心臓に実物がなかった
元の記事の軸は良かった。紙は書くところで止まる。 取り出して照らし合わせる仕事は人の記憶と忍耐に委ねられる。ところが同じ欄で積まれれば、記録は問いかけられるものになる。
その物性の転換は今も正しいと見る。問題はその記事がそれを一度も見せなかったことだ。
- 彼が実際に何を言ったのか — 要求の原文0行
- その言葉がどんな画面定義になったのか — 定義の抜粋0行
- どんな段階を経て作られたのか — 制作過程0段階
- ノート三十冊の移管 — 「合間に移している」という記述だけ
そして記事の白眉である「植えて18日目に最初の花」という発見もそうだった。五年分のデータが積もってはじめて成り立つ主張なのに、そのデータもそれが現れた画面もなかった。
今回は三つを並べて置く。言ったこと → 定義になったこと → 実際に描かれたこと。
言ったこと
作りながら要求を三つの文に書いた。開発用語を使わなかった。
- 「作物を選んだら今年の記録がずらっと出るように。」
- 「記録は片手でできるように。」
- 「去年の今ごろはどうだったかが横に出るように。」
三つの文が三つの道具になった。
log offers: log.season, log.add, log.compare
定義になったこと
最初の文が画面のこの部分になった。コードではなく宣言だ。
{
"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}}" }
]
}
}
二つ目の文はボタンひとつになった。
{
"type": "button",
"label": "First flower",
"onTap": {
"type": "tool", "tool": "log.add",
"params": { "crop": "Tomato", "action": "firstFlower", "tempC": 19.5 }
}
}
三つ目の文で画面がもうひとつ増えた。ルート一行だ。
"routes": { "/": "ui://pages/today", "/compare": "ui://pages/compare" }
アプリ全体がJSON四つだ。 コンパイルは走らない。
実際に描かれたこと
今日の画面。植えてから何日かと例年の平均が上にある。

「First flower」を一度押すと行がひとつ増える。

そして年を重ねて見た画面。

18.2日はどこにも書かれていない
これがこの編で最も重要な部分だ。
元の記事は「18日」を結果のように書いた。このサンプルでその数字は定数ではない。 記録から毎回計算される。
/// 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.
そして検証がそれを直接確認する。計算された値がソースに文字列として入っていれば失敗させる。
AVG=$(grep -o "average from records: [0-9.]*" captures/run.log | awk '{print $4}')
if grep -RIn --exclude-dir=captures -F "$AVG" farm_server/bin farm_log.mbd bundle_host/lib; then
echo " the average $AVG appears literally in the source — it must be computed"
exit 1
fi
通過ログだ。
average 18.2 computed from records, not present in any source file
「記録から現れた」と「そう書いておいた」は画面では同じに見える。 だから見分ける方法を合格条件に入れた。