DEVLOG
Silicon Valley Lattice
Growing an isometric Silicon Valley from nothing with Claude Code agents and a Unity command line — thirty years of startup history, 1995 to 2025, in seventy-five seconds.

The project fits in one sentence: a toy Silicon Valley with the texture of SimCity 2000, compressing thirty years of company history — 1995 to 2025 — into a 75-second time-lapse film. Companies sprout like plants, shoot up, stall, and wither; a garage becomes a campus, the campus grows a crane, the crane comes down and a FOR LEASE sign goes up on the lawn until the next company moves in.
It is also a second experiment riding on the first: the whole thing is built by AI agents. The Unity Editor has been running the entire time, but no human has clicked a mouse in it — every piece of modeling, set dressing, coding, grading, and sign-off happens through a command line, driven by Claude Code. These notes come in two halves: the first covers the design (why the city looks the way it does), the second covers the stack (how an agent with no screen builds a city that has to be judged by eye).
Part One · Design
The city is the chronicle
1.1 Two ancestors
Visuals and narrative each answer to a different ancestor. Visually it’s SimCity 2000: a locked orthographic dimetric camera, a bird’s-eye view, chunky modular buildings with a toy-like finish. Narratively it’s the main title sequence of HBO’s _Silicon Valley_ (by yU+co) — a sequence that is, at heart, a chronicle told in logos: the Pets.com inflatable deflates, the Facebook sign swallows the building next door, Twitter’s blue bird turns into an X overnight. ==The city itself is the plot; buildings rising and falling are the dialogue.

But we don’t replicate it. The title sequence is a hand-built, one-off set; this project needs a generative city — feed it a different random seed and it should grow a different Silicon Valley that holds up just as well. So the first step wasn’t modeling, it was “decompiling” the titles into a rulebook (docs/CITY-RULES.md): how the road network is tiered, how blocks are carved, how far buildings set back from the street, how street trees are spaced. Generation order equals chapter order: roads → blocks → buildings → vegetation → props and vehicles → global render. Each stage’s output is the next stage’s input, and stages talk to each other only through data structures — a convention that turns out to matter enormously once agents start dividing up the work.
1.2 A visual constitution
The art direction rests on one enforceable rule: cream buildings and green ground form the canvas; saturated color belongs only to logos, vehicles, and small accents.
Outside of logos and vehicles, no saturated color is allowed anywhere in the scene. Brand color is the accent, never the facade.
A few equally simple standards keep the world coherent: rounded forms stay smooth, small objects stay chunky, and anything elevated must show how it is supported. Because these rules can be checked, the generator does not need taste to remain inside the visual language.


1.3 A company is a state machine; its building is the shadow
The narrative engine is a very small state machine. Each company is a pure data record (id, name, logoId, cell, stage, funding, tickEntered), advanced one step per tick by CompanySim:

The full state machine. The green Acquired branch is the only exit where the building survives: the logo crossfades to the acquirer’s, the architecture stays put — which is exactly how acquisitions read in real life.
The interesting part is how state maps to picture (we call it hybrid stage visuals). Within a stage, small funding wobbles just add or remove a floor. But crossing a stage triggers a full rebuild of the building in the next architectural style — garage → tilt-up office → glass campus — and every rebuild passes through a crane site. The crane is the narrative beat: scan the city, and wherever there’s a crane, there’s a story. Decline runs the film backwards: first the brand color drains out (desaturation), and only then do the floors start coming off — a company loses its color before it dies.
1.4 A real-company roster and a thirty-year script
The city is populated by real companies, each carrying its own identity, architectural direction, and signage. Their growth and decline emerge from the simulation.
A second layer directs the historical beats: garages become campuses, bubbles inflate and burst, familiar logos disappear or change overnight. The simulation gives the city its rhythm; the script gives it memory.



Part Two · The Stack
Building eyes and hands for an agent that can’t see the screen
The literal stack is a short list: Unity 6 (URP) + the com.unity.pipeline package + the unity command-line tool + Claude Code. The real engineering is in answering one question: how does an agent with no mouse and no retina do work inside an engine whose whole selling point is what-you-see-is-what-you-get? The answer is to remodel the Unity Editor into a programmable terminal: every input goes through the command line, every output comes back as files and JSON.
2.1 The loop: act, perceive, contract

The workflow has three parts. The agent acts through the Unity command line, perceives the result through structured state and screenshots, and works inside a written contract that defines the design rules and verification steps.
The important shift is that the Editor becomes observable and programmable. When the agent cannot understand something, the answer is not another instruction—it is a better way to inspect or control the project.
That closes the loop: act, look, compare, correct. The same loop handles code, layout, art direction, and final sign-off.
2.2 Three hard rules: guardrails beat reminders
Keeping an agent productive over the long run isn’t done by repeating “be careful” in the prompt. It’s done by making the wrong move architecturally impossible. The project stands on three hard rules:
Rule one · Everything is code-generated; scenes are never hand-edited
Never edit .unity / .prefab / .asset files. The whole project has exactly one near-empty bootstrap scene; everything else is spawned from code at runtime. The reason is practical: agents are excellent at writing code and terrible at dragging things around a GUI, and a scene file’s YAML diff is unreadable to humans and agents alike — while code can be reviewed, reverted, and made to explain itself. “If you think you need to edit a scene, you’re solving the problem wrong.”
Rule two · Simulation and visuals are physically separated
CompanySim mutates data only and never touches a transform; BuildingFactory reads data and places meshes, never mutating state. Cross-calls are forbidden. This makes every bug bisectable: if the sim_state JSON is wrong, the simulation is at fault; if the JSON is right but the picture is wrong, the visuals are — the agent never has to suspect both worlds at once.
Rule three · Determinism is the floor, not a feature
One global SimClock (a tick every 0.1 s); all systems advance on tick only. All randomness flows through a single-seed SimRandom; calling UnityEngine.Random directly counts as a violation. The payoff: same seed + same data = byte-identical screenshots. A change that breaks determinism is a broken change, no matter how good it looks.
Rule three deserves an extra sentence, because it’s the foundation the whole agent workflow rests on: determinism converts “art sign-off” — a taste problem — into a regression-testing problem. Change a line of render code, run the same seed twice, pixel-diff the two frames, and the agent can answer “did I break anything else?” entirely on its own. No human eyeballs required.
2.3 An asset pipeline with no Blender in it
The project uses no external modeling tool. Buildings and props are generated from a small library of procedural parts, then assembled into different forms at runtime.
This keeps the visual system inside the same workflow as the simulation: the agent can create, rebuild, inspect, and revise an asset without leaving the command line. Variety comes from recombination, while the shared rules keep the city visually related.

2.4 The verify loop: TDD for agents
Every change walks the same verification loop, written into CLAUDE.md as the agent’s muscle memory:
“Done” has a hard definition: it compiles + `regen --seed 42` runs clean + the screenshot matches intent + two runs on the same seed produce the same screenshot — all four, no exceptions. Animation changes additionally require before/after frames, with a tick --steps N between the two captures. That’s exactly where this pair comes from — the same city, advanced 250 ticks (ten years):


2.5 Missing a tool? Build one. Don’t ask a human.
The single most load-bearing sentence in the operating manual:
Add new commands with
[CliCommand]when a task needs a new observation or action — prefer adding a command over asking the human to check something in the Editor.— CLAUDE.md
This is the workflow’s self-reinforcing loop: every time the agent hits something it can’t see, it crystallizes that missing observability into a command — and from then on, every future task inherits the eyesight. That’s exactly how sim_state was born: debugging the lifecycle logic by screenshot was tedious, so the first move was writing a JSON dump command. The command table keeps growing: regen / tick / sim_state are shipped on the simulation side; spawn_event (manually firing events to test easter eggs) and record (clip capture via Unity Recorder) are queued for M4.
2.6 Milestones and the ledger
The project advanced in layers: first a deterministic city skeleton, then a functioning simulation, then a finished visual world and film. Each milestone had to be reproducible before the next one began.
Within two days, the system could generate the city, run its history, and verify the result through the same agent loop.
Part Three · The Road
A city isn't a road network plus buildings. It's a land code.
After the first film shipped, one weakness became impossible to ignore: the companies changed, but the road grid did not. The city looked generated only above the ground. The rewrite began with a broader idea—a city is not a road layer with buildings placed on top. Roads shape blocks, blocks shape parcels, and parcels determine what can be built. To make the city genuinely different from one seed to another, the land itself had to become generative.


3.1 Grow it first, then draw it
The new system grows a road hierarchy outward from a few seeds. Broad routes establish the city’s structure, while smaller streets respond to local density and connect the spaces between them. Only after the network exists does the system walk its enclosed faces to form blocks and divide those blocks into parcels. The order matters: grow the network, read the land, then build on it. This replaces a repeated grid with a city that develops a centre, an edge, and distinct neighbourhood shapes while remaining reproducible from the same seed.
3.2 A junction is not where two lines cross
Once roads could arrive at arbitrary angles, intersections stopped being simple overlaps. Each approach had to be trimmed back, its edges joined into a continuous ring, and the remaining surface finished with kerbs, pavement, and crossings. That process exposed three distinct stages rather than one universal junction formula.
MISTAKE 1 The miter formula diverges on a straight-through
A construction that behaves well at a corner becomes unstable when two roads continue almost straight through. Instead of forcing every junction through the same geometry, the system now recognises the straight-through case and preserves the road’s natural continuation before joining the remaining approaches.
MISTAKE 2 Ordering the junction ring by bearing
Sorting points around the centre looked plausible, but it could connect the wrong road edges whenever the junction became irregular. The reliable sequence comes from the network itself: follow which edge belongs to which approach, then build the ring from that topology rather than from visual angle alone.
FINISH Chamfer exactly the one point that needs it
Once the topology is correct, the visual finish becomes restrained rather than corrective. The exposed corner receives a small chamfer, the carriageway remains clear, and the pavement closes into one continuous ring. The geometry no longer needs extra decoration to hide a broken underlying connection.

3.3 The building wasn't in the wrong place. It was on the wrong land.
The first curved roads exposed buildings that appeared to sit in the street. Moving each building back only transferred the problem somewhere else, because the real mistake was deeper: the generator treated an entire block as one buildable surface. Real cities separate public right-of-way, parcels, setbacks, and buildable area. Once the system adopted the same sequence, every building inherited a legal envelope from the land beneath it, and larger structures could assemble neighbouring parcels before construction. The lesson was not about placement but ownership: fix the land model, and the buildings follow.

3.4 Geometric intersection ≠ topological connection
The original graph assumed that any crossing created a junction. That works on flat ground, but it makes bridges and viaducts impossible: two roads may overlap in the image without connecting in the network. The solution was to separate four questions that had been forced into one model—where you can travel, what occupies the road corridor, how the ground is divided, and what can be developed. Elevated roads can then belong to the movement and corridor layers without cutting the land beneath them.

With those responsibilities separated, blocks can grow beneath a bridge while its piers still reserve real ground. A change to the road section also moves parcels and buildings automatically, because each layer reads from the same corridor definition. The distinction is simple but foundational: geometric overlap does not imply topological connection, and infrastructure does not always consume the land beneath it.
3.5 Twenty faces of the same bug
The curved network produced a parade of apparently unrelated failures: markings rotated incorrectly, parcels crossed road boundaries, and entrances measured from the wrong origin. Fixing each symptom separately only created more patches. Once the shared assumption was removed, the individual failures disappeared with it. What looked like twenty bugs was one old model showing through in twenty places.
They were not new mistakes. They were lattice-era assumptions—true only while roads followed the world axes.
3.6 One false report
One verification pass reported zero violations, but the result was wrong: a naming mismatch had silently excluded every company building from the check. From then on, each assertion had to report not only its verdict but also what it examined. A green result matters only when its denominator proves that the test actually looked.
An assertion that never reports a category looks exactly like a passing one.
Coda
A loop worth carrying forward
When an agent-built system starts to drift, move through the same four questions:
1 · OBSERVE
Can the agent see what happened?
Add the missing screenshot, state report, or measurement.
↓
2 · REPRODUCE
Can the result be repeated?
Lock the inputs so the same run produces the same output.
↓
3 · CONSTRAIN
Can the wrong path be removed?
Turn important rules into architecture, not reminders.
↓
4 · RE-AUDIT
What old assumption just became false?
After changing a foundation, inspect everything that depended on it.
See clearly → reproduce reliably → constrain structurally → question the old model. Then run the loop again.