All work
Systems DesignSolution ArchitecturePrototype

Terra

A Field Console for a Smallholding That Kept Failing Silently

A solution architecture and working prototype for managing a rehabilitating smallholding — 53 plants, two irrigation controllers, and a decade of accumulated guesses. Every failure on the property had the same shape: two kinds of truth drifting apart with nothing comparing them. Terra is built around reconciling them, and around rendering 'I don't know' as a first-class answer instead of a plausible default.

terra.app
Terra
Terra screenshot

The Problem

An emitter labelled 2 GPH was actually delivering 0.65. Sixteen trees were under-watered for an unknown length of time, and nothing in any tool anyone uses would have caught it, because the label and the reality were never compared. Meanwhile a chlorotic lemon had been treated repeatedly without anyone ever establishing whether the diagnosis was right — apply chelated iron, feel productive, and three seasons later the plant is still yellow.

Research & Discovery

1

The weekly capture flow is shaped by the actual constraint: one person, one hand, twenty minutes, no signal. The route is generated by physical position rather than plant ID so there's one circuit and no backtracking, and photos carry a ghost overlay of the previous image so framing matches

2

Health is assessed as component sliders with prompts rather than one vague number, and trend is surfaced more prominently than value — a plant at 60 and rising is fine; a plant at 78 that was 90 last month is the one to look at

3

Every scheduled task carries its rationale, because 'prune the apricot in late summer' is forgettable and 'prune the apricot in late summer because Eutypa enters through wet-weather wounds' is not. Two rules that are destructive rather than merely suboptimal get blocking treatment

Strategy

Three Truths

Intent, Configuration, and Reality drift apart silently. Three pairs, three reconcilers — that's the entire architecture.

Anchored Numbers

Every derived figure traces to an independently-stated requirement. A number with no anchor cannot be checked, and it will drift.

Uncertainty Propagates

'I don't know' is a first-class state. A plausible default is worse than a blank, because a blank prompts investigation.

Cost of Delay

Attention ranked by severity × time sensitivity × irreversibility ÷ effort — which surfaces the five-minute job that prevents a dead tree.

Key Decisions

1

Made the drift warning obstructive rather than informative. Above 30% deviation it is not dismissable — you can act or you can revert, but you cannot acknowledge and move on. The original failure was invisible for an unknown period, so making it visible isn't enough

2

Made the follow-up date a mandatory field on every treatment. You cannot log an intervention without committing to check whether it worked, and the system generates that task and asks a specific question. Without it the loop never closes

3

Treated map coordinates as an editable working guess rather than a survey, because they were hand-placed from a verbal description. Eight plant identifications are recorded as unknown rather than guessed at

4

Kept the delivery calculator as pure functions with no I/O, database, or framework, because it had already failed twice on arithmetic a five-line unit test would have caught

5

Drew hard boundaries: the system doesn't decide, doesn't identify plants from photos, doesn't control hardware, and doesn't gamify. Automated writes to an irrigation controller with a drift bug is a way to kill sixteen trees overnight

Results & Impact

53

Plants Tracked

3

Kinds of Truth Reconciled

36

Facts Flagged Unverified

  • Wrote a full solution architecture that deliberately excludes schema, API routes, and UI markup — five layers (Record, Reconcile, Observe, Compress, Surface), each depending only on the layers beneath it, so the build order falls out of the structure rather than out of preference
  • Built a working single-file prototype: aerial site map with plant placement, a daily view that answers 'what fits in the time you have', a region-by-region tend view, a walk route, and a gaps view — all driven by the same ranked model
  • Made provenance cross-cutting rather than decorative. Every fact carries a confidence, a source, and a verification timestamp, and an assumed value propagates its uncertainty to every number derived from it — visible wherever that number appears, not just at the source field
  • Designed an attention ranking on cost of delay rather than severity: priority = severity × time sensitivity × irreversibility ÷ effort. The archetype it surfaces is a wire coil against a young trunk — a plant that looks fine today, five minutes of work, and death if ignored. No severity-sorted list finds it
  • Made the diagnosis module store the entire differential, not just the chosen cause, so when a treatment fails the operator returns to hypothesis two instead of restarting the reasoning

Tech Stack

JavaScriptHTML/CSSClaude Code