Field report: the first end-to-end Gemini PARR run

We pushed a real job — an EKS Terraform module plus three FastAPI microservices — through the whole factory chain on Gemini: plan, govern, sign, build, hand off, verify. Here's what worked, what broke (and got fixed live), the one gap that's left, and where we go next. An honest field report, not a victory lap.

We set out to answer one question end to end: can a real, multi-service job travel the whole PARR pipeline — on Gemini, not just Claude — with every guard engaged? Not a toy. The brief was an AWS EKS Terraform module (generate + validate only, no live cloud) plus three FastAPI microservices — a tic-tac-toe frontend, an authenticated scoreboard with a database, and a Redis-backed leaderboard cache — with six acceptance criteria including a real auth requirement.

This is what we learned.

The run

flowchart LR H["EKS brief
6 ACs"] --> P["PFactory
gates 0.96"] P -->|"signed contract"| A["AIFactory
8/8 on Gemini"] A -->|"spec + contract"| T["TFactory
AC-mapped tests"] T -. "no code to run
(gap #547)" .-> X["verdict pending"] classDef ok fill:#b8bb26,stroke:#98971a,color:#1d2021; classDef gap fill:#fabd2f,stroke:#d79921,color:#1d2021; class P,A,T ok; class X gap;

What broke — and got fixed, live

The honest part. Getting that clean run required fixing four real things this week, each found by running the thing rather than trusting the green unit tests:

  1. We were quietly billing the Claude API. The cluster’s OAuth token had expired, so every agent silently fell back to an ANTHROPIC_API_KEY and billed the metered API instead of the subscription. We refreshed OAuth, removed the API key from all four factory pods, and made direct-key billing an explicit opt-in (AIFACTORY_ALLOW_API_KEY) for orgs that want it. Billing the wrong way is now structurally impossible by default.
  2. TFactory ingested specs but never started testing. A request-time import failed only inside the long-lived server (not in any fresh process), and the error was swallowed — so specs sat at pending forever. Fixed by pinning the import at startup; the planner now auto-runs on ingest.
  3. Trusted builds didn’t carry their contract to TFactory. The build rewrote the plan file mid-flight, dropping the test profile before the handoff fired. We now stash the signed contract in a build-safe location at ingest — so TFactory tests the declared criteria, not a guess.
  4. You couldn’t choose Gemini through the contract. The execution profile hardcoded Claude models. A small PFACTORY_EXECUTION_MODEL override makes the provider a one-line choice — which is how this entire run went to Gemini.

None of these showed up in CI. All of them showed up the moment we ran a real job across real services. That’s the point of running it.

The gap that’s left

TFactory generated the right tests — but it has no code to run them against. Today’s handoff carries the spec and the signed contract, but not the built branch (it’s the “no AIFactory branch” path). So the verify leg proves “we’d test the right things” without yet proving “the build passes them.” That’s why this run’s verdict is still pending rather than green.

We’ve filed it as a tracked issue. The fix is concrete: AIFactory pushes the build’s worktree branch and includes a {repo, branch, head_sha} reference in the handoff; TFactory checks that branch out into the spec workspace before it runs the lanes. That single change turns “right tests, no target” into “the declared tests, run against the real Gemini-built code” — and it’s also what makes the bounded handback loop (TFactory → AIFactory → re-test) meaningful.

What’s working — and why it matters

Everything except that last hop is proven, live, on a multi-service job:

The full map of those guards lives at /pipeline/.

What the future holds

We didn’t ship a perfect loop today. We shipped a real one, found its rough edge by running it, and wrote down exactly how we’ll smooth it. That’s the difference between a demo and a product.


← All posts