Build to Think: A Mid-Year Audit
The year-to-date audit, through the lens of Build to Think — the seventeenth edition since March, regenerated with /audit on Fable and Opus 5, this one 2026-08-17. 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,072 commits before work and after dinner around a day job at Google, seventeen products anyone can open in a browser, no servers to babysit and almost nothing to log into.
Yes, seventeen — the count went down this round, and not from rot. The newest repo merged its two products into one site, retired one of its own URLs on purpose, and wrote the reversal into its decision log under the sentence that earns this edition: “the decision’s own premise expired.” The Aug 2 decision to run two deploys was overturned by its author, in public, with a clause most logs never have — what was kept from the old decision. In the same twelve minutes it deleted 15,685 lines, closed a hole that had been serving 26 MB of personal golf history to anyone who asked, and deployed the result. What it didn’t do is push: production is now running an architecture that exists on one laptop, on a branch GitHub has never seen.
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.
This round the two kinds of memory diverged as far as they ever have. The append-only log did its job under the hardest test yet: it recorded its own reversal — the entry that overturns an earlier entry begins by naming it, ends by itemizing what survives, and neither version gets erased. The mutable note managed to be wrong in both directions at once: it carried “State as of Aug 2” for eleven days of restructuring, was rewritten honest inside the merge commit — and the rewrite says a DNS record is “still pending” on a morning when that exact domain was already serving the new site. It missed the deploy it was updated to describe. 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 — this round it rotted before the commit landed. One more exhibit, because nothing checks the log itself: the merge commit replaced an earlier entry’s heading instead of inserting above it, so the log now holds one entry’s body silently welded inside another’s. The convention that guards every data file in that repo does not yet guard the file the conventions live in.
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 then the pattern inverted: the sixth golf repo is not a game, it’s a lab, measuring every course played and every range shot hit, with sources. This round the lab closed its loop on the player. A one-click browser extension captured the entire five-year scoring record — 166 rounds, 93 courses — and the instrument’s verdict runs like a game loop: a finding flagged a wedge bias, the next session was logged specifically to settle it, and it cleared; the finding rewrote itself because the player did what it asked. The new front page knows the handicap fell from 23.9 to 12.9 and roasts the achievement anyway — “you did not learn to score, you learned to lose by the same amount at harder courses” — and a page called /scratch draws the road to zero with five gaps ranked by cost, where the cheapest listed fix is simply: play. Play built the appetite; the appetite built an instrument; the instrument now hands out quests.
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.
Last edition the new repo deleted its database before shipping (“Postgres was solving no problem here” — git already replays history, with real diffs). This edition it subtracted a whole architecture: the merge deleted 15,685 lines in one commit. The seam between its two halves — two ingest scripts and their committed output copies — had existed for exactly one sentence of rationale, that one app couldn’t see the other’s data at build time. One deploy root made the sentence false, so the seam dissolved into two pure functions and nine tests, with the safety proof written where the reviewer lives: “every number in the profile is unchanged; only its provenance sentences moved.” The deploy config went from 17 lines to 4, taking last edition’s dead-config archaeology with it. The cost is priced in the open too: the repo as a whole gave up its zero-dependency claim to the merge, while the course map inside it kept its discipline — still zero-build, plain script tags, CDN map library — and the decision entry says exactly which half of the old rule survived. 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’s sharpest artifact, the ledger’s bag file, passed this round’s quietest test: the merge moved it and changed not one byte. 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. 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 two weeks on, every asserted loft still ships marked unverified, because writing it down opened a question and nobody has taken the clubs to a gauge. The open question is being kept open on purpose, which is the assertion working.
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 round’s evidence is a run of judgment calls about a person’s own data. The plan for capturing the scoring record required a monthly HAR export — rejected because a HAR carries the session cookie, “a file that must never be committed sitting one git add from being committed”; the replacement extension “never reads document.cookie and records no headers, so the artifact is committable by construction.” Not a promise to be careful — a design with no path to the mistake. The captured record arrives as two arrays with mismatched row counts, and the tempting positional join is refused in one sentence: “a guessed join is invented data.” The extension shipped without its parser, on purpose — “the parser must be written against a real bundle, and none exists until the first run; guessing DOM shapes is inventing data” — supply refusing to outrun evidence, which is exactly the discipline bass lacked. And the honesty cut both ways: for three days the full 26 MB capture sat publicly fetchable in a statically-served directory, until the merge’s data split closed it and the commit admitted it out loud. The keyless stack’s bill arrived — no auth also means no door — and it was paid in the open.
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 for anything sensitive, prefer designs where the failure can’t be constructed over rules about being careful: the artifact that structurally cannot contain the credential beats the reviewer who promises to catch it.
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. Three 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 — and this round added the mirror-image lesson: keyless is not the same as private either. A statically-served directory holds no login screen for your own data any more than for anyone else’s, which is how a 26 MB personal export spent three days publicly fetchable. Open beats auth-walled on survival; it buys you neither correctness nor a door. The fixes aren’t keys — they’re a freshness check and a published/private split.
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 with a hole in it: eight days of total silence, Aug 6–13 — the year’s longest gap since the June move — then fifteen commits in four bursts from a single repo. The corrections column runs again, twice. March was 279, not the 278 every prior edition printed: replaying the old census against today’s tree reproduces every per-repo count exactly, so no commit moved — the histogram was simply printed one short, and the “not a single spring commit changed” boast sat on the misprint. And the count moved while being counted, for the third edition straight: the newest repo’s fifteenth commit landed mid-sweep, minutes into this audit. A census is an intervention; this one watched itself intervene. March-and-April’s share is down to 55.5%. The mid-May flatline is Google I/O; the June trough is the move, New York to San Francisco. And after a year exactly level, the clock’s tie broke: 9pm now leads 5am, 97 to 95 — the margin is one Friday night of building, which also settles last edition’s anomaly. The repo that arrived “in daylight” kept daylight hours for exactly one weekend; its second week ran Friday-night-to-midnight, weekend evenings, and 7:30am before work. The margins are the habit.
The portfolio
This round’s deltas — MACKENZIE · the site
Shipped & steady — The Doppler XII · bookmarks · archetypes · SF · MUNI golf · Flow Slays IO · inference · stems · Level Atlas · Minecraft mods · course renderer · kareemrpg · prompts-mcp
Bench & footnotes — SF Rush · the Dopamine Rat · bass · the bench
MACKENZIE
Every course ever played and every range shot hit, merged this round into one site under one wordmark — the two-deploy decision reversed in its own log because "the decision's own premise expired." A one-click extension captured the five-year scoring record (166 rounds, 93 courses, cookie-proof by construction), the profile took the front page, and the handicap's fall from 23.9 to 12.9 got both a finding and a roast. Production runs it; GitHub hasn't seen it.

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. Cited by the work it measures, correcting its own prior editions on the record — this round it caught a one-commit misprint that three editions had carried as a boast.
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. For months the logs were defensive (don’t start cold), then offensive (guards and schemas crossing repo boundaries). This edition they did the hardest thing a written decision can do: get overturned in public, by their own author, with the surviving parts itemized. “The decision’s own premise expired” is a sentence that can only be written because the premise was written down while it was still true. And in the same twelve minutes, the same log silently ate one of its own headings, because nothing checks the log itself. The convention that guards every data file in that repo does not yet guard the file the conventions live in.
The counterweight is eight commits that never left the laptop. The architecture production is running sits on a branch with no upstream — the exact shape that killed the portfolio’s first phone-built experiment, except deployed, which is stranger: the oldest failure mode here used to mean work nobody can see; a CLI deploy means it can now be work everyone can see and nobody can rebuild. A push costs four seconds. The record of the thing has fallen behind the thing, and this audit — which lives downstream of git — would have missed the whole edition if the branch had been the only copy.
What none of this has been tested on is still other people. A reversal with a “what was kept” clause is the most collaborative-looking artifact the portfolio has produced, and it is still one person negotiating with themselves — no colleague has ever disputed which premises expired, or co-signed which parts survive. Solo, the system compounds. Whether the premise audit survives a second set of hands on the log is the question this portfolio structurally cannot answer, and the back half of the year still owes an experiment on it.
Build to think; then push what you deployed, because a record that lives on one laptop is one spilled coffee from being a cold start with a live URL.
Seventeenth dated edition since 2026-03-29. Census through 2026-08-17. 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.
