BuildingViharSync · 9 min read
164 commits in seven days: rebuilding ViharSync with coding agents
We chose a stack for AI agents to write, then built guardrails so strict that an agent can’t finish while anything is broken. What that looked like in practice.
ViharSync V1 — Express, MongoDB and Next.js — proved the idea. But a society’s books need guarantees: balanced entries, transactions, constraints the database enforces. We wanted those from the ground up, so we rebuilt on Postgres — and made an unusual decision about who would write most of the code.
The first architecture decision record for V2 says it outright:
“Coding agents will write most of the code, so the stack is chosen for agent-friendliness… rules encoded as types, linters, tests and hooks rather than left to reviewers.”
- commits between 8 and 14 October 2026
- 164
- commits between 8 and 14 October 2026
- hand-written lines across Go, Dart and TypeScript
- ~50k
- hand-written lines across Go, Dart and TypeScript
- command that gates every change: make check
- 1
- command that gates every change: make check
Why Go, why a monolith#
Go was picked for its fast build-and-test loop and its explicitness — an agent reading Go code rarely has to guess what happens. The backend is a modular monolith: one binary, with modules for identity, access, society, finance, community, gate and amenities. Each module’s public API is its root package; everything else is in an internal/ folder that Go itself forbids other modules from importing. An architecture test enforces the rest. Modules may read each other’s tables, but only the owning module writes them.
One contract to rule three clients#
ViharSync has three clients: a resident app and a guard app in Flutter, and a committee console in Next.js. All of them, and the server, are generated from a single OpenAPI file — 130 operations today.
- 1
Server
oapi-codegen produces a strict Go server interface. A missing handler is a compile error. - 2
Database
sqlc turns hand-written SQL into typed Go. No ORM. - 3
Clients
Dart clients for both Flutter apps, and TypeScript types for the console. - 4
Freshness
Generated files are committed; CI fails if they’re stale, and a hook blocks anyone — human or agent — from hand-editing them.
And one rule makes the contract do security work, too:
# Every operation must declare one of these, or the server refuses to start.
x-permission: finance.bills.issue
# or
x-public: trueGuardrails only work if they always run#
make check runs codegen, formatting, linting and every test across the backend, both apps and the console. It runs in the pre-commit hook, in CI — and in a hook that fires when a coding agent tries to stop.
“They only work if they always run.”
In practice that means an agent can’t declare a task done while the build is red. Agents worked in parallel git worktrees — finance, gate, community and society landed on the first day as separate branches — and each one had to pass the same gate before it merged.
Tests an agent can’t talk its way past#
- No mocks for SQL. Integration tests run against real Postgres 18 in containers.
- The demo is a test. A seed command builds a whole society through the public API — wings, flats, three months of bills, payments, expenses, complaints, gate traffic — and fails if the books don’t balance.
- Pixels are pinned. 110 golden images cover the Flutter UI, plus a live end-to-end test on an iOS simulator.
- Time is injected.
time.Now()is banned in modules; business time comes from an IST app clock, so deadlines are testable regardless of the server’s time zone.
What the agents were good at — and what they weren’t#
Given a crisp contract and a red-or-green gate, agents were excellent at breadth: whole modules, screens, migrations and their tests, in parallel. They were weakest exactly where you’d expect — domain judgement. Which rule from the bye-laws applies to a co-operative versus a condominium, what a treasurer actually calls a report, why a refuge floor must never be billed. Those came from humans reading research briefs and writing them into specs the agents could follow.
Keep reading
- Making a housing society’s books balance — in paiseWhy ViharSync keeps a real double-entry ledger, stores every rupee as an integer, and lets Postgres refuse any journal entry that doesn’t add up.Building · ViharSync
- Putting Maharashtra’s co-operative housing law into the softwareBilling bases, a 12% interest cap, complaint clocks and refuge floors that must never become flats. What we learned turning bye-laws into types and constraints.Product · ViharSync
- Everything between a working app and a launched oneViharSync V2 runs end to end on a demo society. Here is the honest list of what still stands between that and real money moving through it.Launch · ViharSync