Build to Think: A Mid-Year Audit
The year-to-date audit, through the lens of Build to Think — the sixteenth edition since March, regenerated with /audit on Fable and Opus 5, this one 2026-08-05. One ink, one accent, short on purpose.
A golf trip needed a live scoreboard, so one got built in an evening — and by Sunday the repo’s closing commit read Seal the record: Amar wins Doppler XII on the first playoff hole. That weekend is the year in miniature: 1,055 commits before work and after dinner around a day job at Google, eighteen products anyone can open in a browser, no servers to babysit and almost nothing to log into.
This week the portfolio grew a repo that quotes the others. Over one weekend, a mapped history of every golf course ever played and a shot ledger for a launch monitor arrived as two live products from one repo — and inside it, four earlier projects are cited by name: a data-staleness guard ported from the golf sim (it caught a lying mirror on its first run), a validator pattern from the archetypes build, a provenance schema from the SF atlas, and this audit itself, quoted in the spec as the reason not to build an integration. The notes stopped being notes. They compile now.
Lesson 1 — Projects die between sessions, not during them
Nothing here died of a hard problem. Things died of the cold start — sitting back down and not knowing where you left off. Every project that matured left itself a note; every one that stalled, stalled in the gap. The evidence is uncomfortably literal: one version’s final commit reads fix: resolve 27+ TypeScript build errors; another died finished, on branches nobody pushed.
The pattern held everywhere: doppler seeded its NEXT.md the day of git init and matured; golf keeps a DECISIONS.md of forks taken with reasons; bass and archetypes v1 ended sessions mid-mess and never came back.
The new repo ran the experiment again and got the same result. Its append-only DECISIONS.md shipped on day one — 728 lines, 23 entries, the first project born with the convention instead of converging on it — and it reads true. Its mutable NEXT.md still lists “Deploy.” as an open task, four days after the deploy, in a file whose neighboring README prints the live URL. Golf’s log grew to 1,320 lines and stayed honest; golf’s note fixed last edition’s lie and then went stale again within hours. The difference is structural, not a matter of discipline. Old entries in an append-only log are supposed to be old, so it cannot go stale. A handoff note is one claim about right now, so it rots the moment you stop editing it. Put the reasoning in the log; keep the note to the one thing you’d forget — and watch the tooling too: this week the automation that writes the session stubs misfired into the wrong directory, and the repair commit documented the misfire instead of deleting it, which is the whole ethic in one diff.
The living log · how a project survives the gap
The transfer: give every project one living file — part lesson log, part spec: decisions with reasons, what’s next, what changed your mind. Update it before you stop. Resuming beats restarting, and it scales: a team that records why it chose something stops relitigating the choice every quarter.
Lesson 2 — Everything you build wants to become a game
Look at where each exploration ended up: an atlas of San Francisco became a drivable city. A launch-planning idea became a deckbuilder. Golf-course data became a sim you can lose at. A friend’s life became an RPG; even the habit tracker is a rat you keep alive. The AI underneath is indifferent. The pull toward play comes from the person: a general capability has no handles, and giving it rules, feedback and stakes is how a mind gets a grip on it. Play isn’t the reward for understanding. It’s the instrument of it.
By late July it had a direction — golf in five repos, including a mod inside Minecraft at 2am — and the repos had begun sharing a cast: Mickey C, the tournament site’s four-time champion, walked next door to become the sim’s protagonist. This week the cast grew to four — Sal, Kyle and Conor joined, one file each, and the type system holds the ensemble together: adding a game event fails to compile until all four have something to say about it. And then the pattern inverted. The sixth golf repo is not a game — it’s a lab: the same obsession that produced a 16-bit sim on real courses now measures every course played and every range shot hit, with sources. Even its name came out of the cluster’s own data — Alister MacKenzie, whose Meadow Club sits third on the list the map is built from, a fact that entered the portfolio months ago as a row in the SF atlas. Play built the appetite; the appetite built an instrument.
The transfer: when an idea isn’t landing — a pricing model, a roadmap — build a toy version people can lose at. Losing teaches faster than reading. Then watch what the play makes you curious about: the questions a game leaves you asking are a better roadmap for the serious tool than the requirements you’d have written up front.
Lesson 3 — Build the memory first, then chisel the product out of the rest
Building to think works like sculpture: early versions pile up material — code, dead ends, notes — and the product is what’s left after you cut the rest away. The cutting is only safe if the design lives somewhere outside the code. That’s why the memory comes first.
The Dopamine Rat proves it. Built four times; dependencies per version ran 2 → 7 → 10 → 3. The version that shipped is the smallest, and the only one that started from a written record of what the first three got wrong. Doppler applied the rule on day one instead of attempt four: two dependencies, no backend, and 264 CI data invariants — the key one “asserts the tournament record agrees with itself.” If a number can be derived, derive it; anything hand-set is labeled as opinion. The same move works on whole repos: the SF atlas deleted the driving game growing inside it — copied out first, so the deletion stayed reversible — and the Minecraft mod was deleted and rebuilt in ~100 minutes because its design already lived in a spec.
The new repo is the rule’s most extreme statement yet. The course map’s package.json has no dependency section at all — 4,000 lines of site and pipeline on zero installed packages, the map library loaded from a CDN. The shot ledger runs four runtime dependencies and 268 tests. A database was in the original design and got deleted before it shipped, with the reasoning on file: two years of range sessions is 1.5 MB of JSON, “Postgres was solving no problem here” — and the table that existed so parser fixes could be replayed over history was replaced by the observation that git already does that, with real diffs and better provenance. The same discipline held at stems in July: ~5,000 lines of video export, a hand-written FFT and a full Winamp skin, zero new dependencies, guarded by an eleven-item list of things that look like dead weight and aren’t, each ending don’t “simplify” it back.
The memory half got its sharpest artifact yet: the ledger’s bag file. Every number on the page is derived from a recorded shot — and that’s the flaw, because a club with no shots renders as nothing to report when the truth is never measured. On the real data that hid four of thirteen clubs. So the bag is asserted by hand and committed: the one fact the record structurally cannot derive is the one fact that gets written down — and writing it down is scored honestly as opening a question, not closing one; every asserted loft ships marked unverified.
One repo, three homes · the July extraction
Maturity as separation of concerns you can survive: give each exploration its own address, and keep — don't destroy — what it grew out of.
Lesson 4 — AI compressed implementation. It did not compress judgment
The cold start is how projects die; whether the thing deserved to exist is why you never come back. bass is the year’s honest failure: ten commits of supply for a demand that never existed — one practice ever logged. The code was fine. The decision was wrong, and every added feature compounded it. Rat v3 made the same mistake with more ceremony — Garmin OAuth before daily use was proven — and died finished. film died in a day, zero photos.
The successes were decisions too: delete 19,963 lines from the atlas, cap doppler’s dependencies on day one, let the renderer admit what the map doesn’t know. Implementation got cheap this year — an evening buys what a quarter used to. Judgment didn’t, and it’s the skill this portfolio was actually training.
This week’s evidence is a run of refusals aimed at the instrument itself. The launch monitor wrote the carry distance into the total-distance column, verbatim, on 51 of 255 shots — “that is not a ball that stopped where it landed” — and the ledger reads those totals as absent, taking the cost in the open: three clubs go dark on total, because a club measured only by shots with no rollout information has not been measured. A score sitting in the wrong column gets flagged, never edited — “silently doubling them would invent data.” A low carry isn’t a mishit if the swing was soft on purpose: a partial is not a mishit, and no shot is ever excluded for a metric the monitor failed to record. Even the column names aren’t trusted: a firmware update could swap two columns and every sentence would stay plausible while being wrong, so the physics that ties them together — curvature to spin axis, start line to club face — is asserted in tests, and a relabelled column now fails the suite.
The transfer: when something you built isn’t being used, don’t add features — read the verdict. Non-adoption is data about the decision, not the polish. And when a dashboard’s number looks clean, ask what the instrument would show you if it were lying: the dangerous defaults are the ones that produce a plausible value instead of an error, and the fix is an assertion that fails loudly, not a correction that hides the doubt.
The stack — whatever you don’t have to log into wins
The monthly infrastructure bill is $0 — but the money is the least of it. Sort the portfolio by what each project depends on and a pattern falls out: everything that survived runs on things you can hit without logging in — OpenStreetMap, MapLibre, git, localStorage, a static host’s free tier — and everything that rotted, rotted at an auth boundary: an OAuth flow, an expiring token, a service key. Not because open tools are better, but because they’re still there at 5am, on a phone, from a golf course. The path of least friction wins, and a login screen is friction.
Keyless → still running
- OSM + Overpass — two golf projects' course geometry; cost: an attribution line
- MapLibre — real maps, no API key
- Open-Meteo — live microclimates for the atlas’s weather-chase mode; no key
- git + a CDN — doppler's whole "backend"; scoring is a commit
- localStorage — the rat's database; the flagship's job queue
- Jekyll + GitHub Pages — twelve years; its one death is opposite →
- NRCan HRDEM — 1 m LiDAR terrain for the Niagara courses; an unauthenticated search, no key
- Nominatim + Esri imagery — the new course map's geocoding and basemap; every source in its spec lists Auth: none
- Demucs, local — stems: no cloud, no accounts, no uploads; the price: only a demo lives at a URL
Auth-walled → where things rotted
- Garmin OAuth — built before daily use was proven; rat v3 died finished
- a Supabase anon key — five months of public writes on the flagship
- Universal Analytics — the site's one death in twelve years
- cron secrets & DNS aliases — the rat simplified; the failures moved here
- a stale Overpass mirror — the one that answers looks healthy; three courses baked from May data. Sequel: the guard written after that caught a second mirror lying 50 days deep — in a different repo, on its first run
Tournament weekend was the field test. Thursday, July 23: git init at 3pm, a live tournament site by 11:31pm. Then every update, all weekend, came from a phone between rounds — 22 commits of scorecards entered hole by hole from the course in Ontario. Nothing on the board was ever set by hand: standings, odds and the champion badge all derive from the committed scorecards. No admin panel, no login. That’s the bar — run it from a golf course, on a phone, between shots — and any OAuth screen in that path kills the live board by Saturday.
The thesis has a control arm: a fresh problem went to a different agent — OpenAI Codex — and came back as a golf-course digital twin, which on day two added a Supabase tier with logins, the stack’s first new keys in months. Two editions later the pattern is data: the twin’s one commit since was a 29,000-line test fixture and a rendering split — real work — while its auth tier went untouched, and its API surface now answers 404 from outside. Nothing rotted loudly. Auth-walled things don’t; they just stop being checkable.
But keyless is not the same as trustworthy. The free endpoint that asks nothing of you can still hand you two-month-old data with a straight face — which is exactly what happened below. Open beats auth-walled on survival; neither one buys you correctness. The fix isn’t a key, it’s a freshness check.
The transfer: count the credentials before you count the features — every key is a place the project can die while you’re not looking. Then go back and ask each keyless source how you’d know if it started lying. The ones that ask nothing of you also promise nothing to you.
What building on top found
Seven courses went into the golf sim in one evening. That meant leaning on parts of the pipeline nobody had leaned on, and three things fell out — each of them shipping silently since the day it was written.
- The parser had been dropping data. OpenStreetMap describes a shape as either a single way or a multi-part relation. The code asked for both, then skipped every relation. The query looked healthy; it returned rows. Torrey Pines South had been shipping with zero fairways.
- The map mirrors had been serving months-old data. The primary endpoint was rate-limited, the script failed over exactly as designed, and the backup answered with a June 1 snapshot. Nothing in the response said so. Three of eighteen courses baked from stale data in one run.
- Five messages had never once appeared on screen.
SPLASH,OUT OF BOUNDS,CLONK,BEACHED,ON IN n— set, then overwritten in the same tick by the line after. Found only because the new character needed the same channel to speak through.
The sequel landed five days later, in a repo that didn’t exist when those bugs were found. The staleness guard written after the mirror incident was ported into the new course map — and on its first run it refused a mirror serving 50-day-old data. That’s the difference between a lesson learned and a lesson installed: one lives in your head, the other fires in a repo you haven’t started yet.
The transfer: when you inherit a pipeline you didn’t write, don’t audit it — extend it. Tests check the paths you thought of; the next feature walks into the ones you didn’t, and it’s free, because you were going to build it anyway. The same trick works on a system you inherited at work: the fastest audit of code nobody remembers is the next thing somebody needs from it.
The year in one line
The shape of the year · commits per week, in three acts
Two quiet months, a detonation, then a tail that keeps accelerating. July’s real final number is 267 commits — the year’s #3 month, and fifteen more than the last edition printed, because that edition was generated at noon on July 31 and the day kept going; its own publishing commits are part of the difference. A census is an intervention, and this one says so. March-and-April’s share is down to 56.3%, eroding every edition without a single spring commit changing. Neither dip in the middle is a stall: the mid-May flatline is Google I/O, the sprint before the keynote taking the same pre-dawn margins; the June trough is a move across the country, New York to San Francisco. Building happens at 5am and after 8pm, almost never during the workday — the two peaks still exactly level at 95 commits each. August’s first anomaly: the new repo was built in daylight, mid-morning and evening across a weekend. The 5am clock was never a preference; it was the shape of the free time.
The portfolio
This round’s deltas — MACKENZIE + Yardages · MUNI golf · course renderer · the site
Shipped & steady — The Doppler XII · bookmarks · archetypes · SF · Flow Slays IO · inference · stems · Level Atlas · Minecraft mods · kareemrpg · prompts-mcp
Bench & footnotes — SF Rush · the Dopamine Rat · bass · the bench
MACKENZIE + Yardages
Every course ever played, mapped with sources — 84 facilities, zero dependencies — and a shot ledger that reads a launch monitor's exports with open distrust: 255 shots, 74 excluded with stated reasons, 268 tests, and a generated profile where every finding names what would falsify it. Built in a weekend on four other repos' written-down lessons.

The Doppler XII
Built in one evening, operated from the tournament, sealed by Sunday. Live scoring was literally git: commit a scorecard, the field’s phones update. Two runtime dependencies, no backend, 264 data invariants in CI. After the seal came “The 36th”: the playoff hole resurveyed from OpenStreetMap, shot by shot, with witness corrections amending the record. Its roster file turned out to be a casting file — the champion is now the playable character in the golf sim next door.

SF Rush
Don't read the commit count — the game was built across sf's spring sprints, then copied out whole on Jul 12: 18k lines, six vehicles, real LiDAR terrain. The chart shows the full lineage; its default level is now the Harbor Links golf course.

Flow Slays IO
A Slay-the-Spire deckbuilder about shipping a GenMedia model. The truest mechanic: the PM classes cannot deal damage — the whole kit is leverage on other people’s cards. July’s retheme added pixel-art combat and an honest balance simulator — launch-week runs were near-unwinnable; now 30–70%.

Prompts · the flagship
X bookmarks → a curated gen-media prompt dataset a Google PM actually uses. Best artifact: a prebuild gate where a hallucinated fact becomes a failing build. July closed a 5-month-open public-write hole in one migration.

Archetypes
v1 was built entirely on a phone. v2 rebuilt the problem statement: 87 archetypes, 170 graded mappings, every objection attacked on schedule and the survivors published.

Course renderer
A golf-course digital twin on MapLibre + OpenStreetMap — refuses to invent geometry the map doesn’t know. The keyless thesis's control arm: this round it gained a 29,000-line Olympic Club stress fixture while its auth tier sat untouched — not broken, just no longer checkable from outside.

Stems
A local-first Demucs stem splitter whose demo renders music videos in your browser — ten styles, four generative sketches drawn from a hand-written FFT — and then, in twenty-three minutes, became a working Winamp: bevels, a real spectrum analyser, a ten-band EQ wired as actual audio. Its dependency list hasn’t moved since July 28.

Level Atlas
An atlas of level design in which the repo is the database: eight levels, thirteen techniques, every entry a JSON file checked at build time, so a dangling reference fails the build instead of the page. Day two it deleted its placeholder map and built a space-graph engine instead — one vocabulary that draws a 1985 side-scroller and a 2016 immersive sim from the same data.

The SF atlas
An atlas built to answer a real question: where in SF to live. Its weather-chase mode colors 189 neighborhoods by live sun, wind, and warmth and ranks the best ones within reach — microclimates as a decision tool for the move. It also grew a driving game, then gave it up: −19,963 lines in six reversible minutes.

LabsCraft v2 · minecraft-mods
An LLM-driven NPC mod deleted (−10.5k lines) and rebuilt (+12.5k) in ~100 minutes by 7 parallel agents — safe because the design was extracted into a spec first. On Jul 28 agents added a third mod in 21 minutes: SportsCraft, golf inside Minecraft — PR open, honest that no one has run it yet.

Inference
Gen-AI unit economics, cited and interactive. Its 34-commit launch day exposed the missing source of truth; the fix made July’s refresh one commit instead of thirty.

MICKEY'S MUNIS · golf
A 16-bit sim on real course geometry — 342 holes, from Augusta to a Toronto par 3, still two runtime dependencies. This round every hole got a shareable address (one prerendered page each, hand-rolled router), the cast grew to four characters the type system keeps in voice, Kamloops arrived via real data archaeology — the club had renumbered its nines after the course was mapped — and courses 19 and 20 were baked and merged by a cloud agent on the CI runner.

The site
The workshop’s logbook — and this audit’s publisher. Survived twelve years by having nothing that could rot. As of this edition it is also cited by the work it measures: the newest repo quotes the audit as the reason to skip an integration.
The Dopamine Rat
Dependency count per version: 2 → 7 → 10 → 3. v4 wins by deleting the other three and building its continuity doc before any feature.

kareemrpg
A friend’s life as a walkable RPG. The tutorial folder quietly became the product — bias toward extending what works.
prompts-mcp
Learned MCP by implementing all four primitives and both transports over his own dataset. The bugs were the curriculum.
The bench
film died in a day with zero photos; two repos never reached a first commit. Cold-start deaths, cheapest form.
The cadence
The bimodal builder · commits by hour of day (Pacific)
Every day of 2026 · Daily commits, week by week
Hover any day for its count and which repos moved. The dense block is the March–April detonation; the warm cell is the single busiest day (Apr 12, the inference launch).
The verdict
The portfolio isn’t a list of products; it’s a thinking log with a URL for each thought. The constraint was never ideas or energy — it was continuity, and for seven months the system built against it was defensive: leave a note, keep a decision log, so the next session doesn’t start cold.
This edition the logs went on offense. A guard written after one repo’s data went stale fired in a repo that didn’t exist yet. A validator pattern, a provenance schema and an auth post-mortem crossed repo boundaries as working parts, not anecdotes. The write-up turned out not to be overhead — it’s the part that ships twice. Even the audit’s own error this round fits: July’s “final” count was off by fifteen because the report was published into the middle of the day it was counting, and its own publication was part of the difference.
What none of this has been tested on is other people. Every citation in that grid is one person quoting themselves — the decision log is never disputed, the campfire convention is never someone else’s, and no one has ever argued that the flagged data should be corrected after all. Solo, the system compounds. Whether it transfers to work where the log has co-authors is the question a solo portfolio structurally cannot answer, and the back half of the year still owes an experiment on it.
Build to think; then write it down, because the note you leave is the only part of a build that can show up early for the next one.
Sixteenth dated edition since 2026-03-29. Census through 2026-08-05. Regenerated with /audit on Fable and Opus 5 across the run — this one on Fable. The long-form master report lives at ~/CodeProj/PROJECT_AUDIT.md.
