58,588 lines in 12 days: the guardrails that made AI shipping safe

A MacBook with lines of code on its screen on a busy desk

The question comes up every time someone sees what AI-assisted development can produce. The polite version: “Isn’t that just vibe coding?” The less polite version skips the pretense. The term comes from Andrej Karpathy, who described accepting every change without reading diffs. For a weekend prototype, that works fine. For software holding insurance policies, medical bills and passwords, it’s a non-starter.

Dr. Holger Flick built Hearth, a household system for his wife, in twelve days. The numbers are staggering on their own: 58,588 lines of code across seven applications, 313 automated tests, 34 isolation checks, 52 pull requests, 48 releases. The real story is the engineering discipline underneath the speed.

️ The Raw Numbers

Everything comes from Git logs, test runners, and Claude Code session logs. Blank lines and generated code are excluded from line counts.

MetricCount
Calendar days, first prompt to last release12 (Oct 7 to Oct 18)
Active session time with AIabout 20 hours
Messages to AIabout 110
Non-blank lines of code58,588
Database tables / migrations44 / 30
Merged pull requests / tagged releases52 / 48
Automated tests294 + 15 + 4 = 313
Isolation script checks34
Database triggers enforcing ownership49
Applications on one backend7

The web app and server carry most of the 58,588 lines (39,910), followed by the iPhone and iPad app (4,959), database schema and migrations (3,133), and unit tests (2,000). The busiest day, October 8, saw sixteen merged pull requests in roughly five and a half hours of session time.

Active hours count session time with breaks longer than twenty minutes excluded. Overlapping parallel sessions count once. That twenty hours doesn’t include thinking time, testing on real devices, or living with the app before deciding what to change.

Guardrail 1: Every Change is a Pull Request

Vibe coding has no history. Accept, run, move on. Hearth has 52 merged pull requests, each with a written description of what changed and why. The bigger ones include verification details. The security review’s description ends with: “tsc, biome, pnpm build and pnpm check:isolation (26/26) pass” plus a database backup restored into a scratch database and compared with the live one.

Small pull requests aren’t bureaucracy. They let you find the change that broke something, read a diff in five minutes instead of an hour, and roll back one thing. The DORA research program has shown for years that small batch sizes and thorough testing matter. Its 2024 report found AI adoption correlated with lower delivery stability. That finding isn’t an argument against AI. It’s an argument for keeping batches small when the AI makes it tempting to make them huge.

lines of HTML codes

Guardrail 2: Tests That Found Real Bugs on Day One

On October 12, the project got its unit tests: 186 at first, 294 today, written with Vitest for pure functions in src/lib covering date math, schedules, business rules, parsers, and request guards. They run in about half a second. The test machine pretends to be in Honolulu, which is neither UTC (the server) nor New York (the household). Code that forgets to name a time zone fails there instead of in production.

The first run found four real bugs:

  1. Quotes on the wrong day. Two quotes sent at 3 PM and 9:30 PM New York time landed in different “rounds” because 9:30 PM is already tomorrow in UTC. The cheaper afternoon quote counted as replaced.
  2. An open redirect. The function guarding “return to this page after sign-in” accepted / /evil.example. Browsers drop tabs and line breaks, so that address led to another site.
  3. Inherited names. A parser accepted names that every JavaScript object inherits, such as toString.
  4. Days that don’t exist. The date check accepted 2026-02-30.

The same day, tests became law. The deploy script runs them before building and refuses to ship when one fails. To prove the gate works, the developer broke the relativeDays function on purpose and watched the deploy stop with “Unit tests failed: not deploying.”

The unit tests cover logic, not screens. There are no browser end-to-end tests yet. Every screen change was checked by running the app in browser, simulators, and on real devices, but that’s manual verification.

Guardrail 3: Sign-In Done Properly

Hearth offers passwords and passkeys (the FIDO Alliance phishing-resistant standard built on WebAuthn, implemented with SimpleWebAuthn). Passwords are stored with bcrypt. An unknown user name is checked against a dummy hash of the same cost, so the answer takes exactly as long and doesn’t reveal which accounts exist.

Failed attempts are throttled per user name and per address, with counters in the database so a restart doesn’t reset them. Session tokens are random and stored only as an HMAC. The cookie is httpOnly, secure, and sameSite. Every route handler checks the request’s origin. Changing your password signs out other sessions and connected apps. Adding a passkey asks for the password first. An administrator’s password reset removes passkeys too. Every server action and API route checks the user itself instead of trusting middleware.

Guardrail 4: One Family Can Never See Another

Hearth is multi-tenant: several families, and within each family, shared and private records. A mistake here isn’t a bug; it’s a privacy incident. Isolation is enforced at three levels:

  • Layer 1: the family client. Every query is scoped to the family and member automatically, including nested relations and counts.
  • Layer 2: the database. Forty-nine PostgreSQL triggers verify ownership when a transaction commits, whatever the code above did.
  • Layer 3: a script that attacks it. Creates a throwaway family, tries 34 ways to read, change, or link across families, then cleans up.

Any developer can write where familyId = ?. The question is what happens when someone forgets.

️ Guardrail 5: Secrets Stay Secret

The password vault encrypts every field (title, address, user name, password, notes) with AES-256-GCM, with a key derived from a server secret. Each value is bound to its family, entry, and field as additional authenticated data. Copy an encrypted password from one row to another, and it no longer opens. Earlier passwords stay in history, encrypted the same way.

Each app signs in separately with a code confirmed on the web, and its token is stored only as an HMAC. Each kind of app may only do what it was made for: Apple TV and iPhone/iPad apps only read, never change. Notes for Mac sees only notes. The Chrome extension sees only passwords. Inside the extension, only the background worker holds the token, and it answers a web page only about that page’s own site after a real click.

black computer keyboard

Guardrail 6: A Review That Found What the AI Got Wrong

On October 11, the AI reviewed its own code base for authorization, privacy between members, and security. It found real problems. A stored cross-site scripting hole: an upload could choose its own content type, and a crafted file could run script in the app. Places where editing a private record could make it visible to the family. An AI usage report that showed document titles to the administrator.

All were fixed in the same pull request, along with database throttling, password-change sign-outs, and nightly backups. The AI wrote those bugs. The AI found them, because the developer asked for a review and treated it as a gate, not a ritual.

Guardrail 7: Releases and Operations

Hearth runs on a Raspberry Pi 5 in the house, in a Docker container behind Caddy, which handles HTTPS certificates. Every release follows the same pipeline, written down as a skill the AI executes step by step. The pipeline:

  1. Pull request: typecheck, lint, tests
  2. Merge and tag vYYYY.MM.DD-N
  3. Test gate fails = no build
  4. Build arm64 image (copied, no registry)
  5. Start on the Pi, migrations run
  6. Release notes on GitHub
  7. Health check: login 200, root 307

The last five release images stay on the Pi. A rollback is one line in the compose file. The database is dumped every night to a separate storage bucket, with daily and monthly copies. A backup was restored into a scratch database and compared with the live one before it was trusted.

What the AI Did vs. What the Human Did

In twelve days, the developer wrote about 110 messages. The AI made roughly 3,900 tool calls in reply: reading files, writing code, running tests, building, deploying. It wrote nearly all the code, tests, and pull request descriptions.

What it didn’t do was decide. The human chose the architecture and stack: Next.js 16 with React 19, Prisma 7 on PostgreSQL, TypeScript 7 with its new native compiler, SwiftUI for Apple apps, and a Manifest V3 Chrome extension. The developer decided isolation is enforced in the database, that passwords are bound to their row, that each app gets only its own part, and that tests gate every release. The human tested on real devices, wrote down interface rules (“dates first, newest on top”, “no plain dropdowns, always searchable”), and said no often.

The Takeaway

Fast and careful aren’t opposites anymore. The same AI that wrote 58,588 lines in twelve days also wrote the 313 tests, 34 isolation checks, 49 triggers, and the security review that kept those lines honest. The speed came from tooling. The care came from thirty years of knowing what goes wrong in production and refusing to skip the boring parts.

AI didn’t remove the engineering. It removed the excuse for skipping it.

The METR randomized controlled trial found experienced developers were 19% slower with early-2025 AI tools on their own codebases while believing they were faster. The lesson isn’t that AI is slow or fast. It’s that the gain depends on how precisely you specify, how strictly you review, and whether you treat tests and reviews as gates. Without those, you get vibes. With them, you get Hearth.

Stay on top of AI & Automation with BizStack Newsletter
BizStack  —  Entrepreneur’s Business Stack
Logo