AI as an Engineering Partner — and How We Stay in Control

July 8, 2026 in engineering, ai by Dimitri Tombroff, Simon Cariou and Yahya Zaim Mounajed8 minutes

Fred is a full cloud-native agentic platform: speed and batch layers, Temporal workflows, identity propagation, ReBAC authorization, observability. We use AI assistants — for code, but also for backlogs, RFCs, and PMO tracking. This post is an honest account of the guardrails we built into the repository so that the humans, not the assistants, stay in control of a robust, industrial, maintainable application.

Co-authored by Dimitri Tombroff and Simon Cariou (Fred team) and Yahya Zaim Mounajed — two teams that independently converged on the same conviction: AI assistants have outgrown the code editor, and that is precisely why they need governance.


A Real Project, Not a Demo

Most “AI-assisted development” stories are told on greenfield demos. Ours is not. Fred is a complete cloud-native platform: several FastAPI backends and a React frontend, a speed layer for interactive chat and a batch layer built on Temporal workflows, agentic execution in isolated pods, end-to-end user identity propagation with service-account patterns for asynchronous workers, ReBAC authorization with OpenFGA, observability and KPIs, Helm charts and ArgoCD deployments on Kubernetes.

At that scale, the question is no longer “can the AI write this function?” — it can. The question is: who is in control of the architecture, the contracts, and the roadmap? If the answer drifts toward “the assistant, implicitly”, you will ship something fast that nobody can maintain.

This post describes how we equipped the repository itself so that the answer stays: us.

The Failure Mode We Were Avoiding

An unconstrained assistant on a large codebase is not malicious — it is eager. Left alone, it will happily:

  • reinvent a type that already exists three folders away,
  • add a parallel endpoint family instead of extending the documented one,
  • “fix” a design decision it never saw the rationale for,
  • and produce a beautiful pile of code the team no longer fully understands.

The result is entropy: duplicated abstractions, contract drift between backend and frontend, documentation that describes a system that no longer exists. On an industrial application with security and compliance requirements, that is disqualifying.

So we inverted the setup. Instead of asking the assistant to code everything, we made the repository the boss — and the assistant its most disciplined employee.

Equip the Repository, Not the Prompt

Everything the assistant must know and obey is versioned in the repository, next to the code it governs. Four mechanisms carry most of the weight.

1. An operational contract for assistants

Our CLAUDE.md (mirrored for other assistants) is not a “context file” — it is an operational contract. Its prime directive: extend, do not duplicate. Before writing anything, the assistant must run a reuse audit: does a task ID already exist? A backlog item? A contract field? An RFC covering this area?

It then enforces a task lifecycle that cannot be skipped or reordered: RFC first → backlog entry → explicit developer confirmation → GitHub issue → implementation → verification → documentation convergence. The assistant writes the RFC and the backlog entry, then stops until a human says go. One sentence of approval is enough — but it must exist.

2. A machine-readable project registry

Prose status reports rot. So the project’s ground truth is structured data the assistant reads and is required to keep in sync:

  • id-legend.yaml — the canonical registry of every tracked unit of work: 108 IDs today across 16 domains (RUNTIME, AUTHZ, MEMORY, EVAL, MIGR, …), each with an owner, a status, a backlog reference and an RFC reference.
  • Layered backlogs — a dozen files, append-only, one per major track.
  • STATUS.md and a PMO board — the human-facing mirrors, updated in the same change whenever a tracked field moves.

Every commit subject carries a task ID. When an assistant (or a human) asks “what is AUTHZ-05 and who owns it?”, the answer comes from data, not from someone’s memory.

3. Frozen contracts and generated clients

The execution surface and the product API surface are described in two frozen contract documents that change only through a dated amendment. The frontend never hand-writes a type that mirrors a backend model: all clients are generated from the OpenAPI specs, and touching a backend controller without regenerating the client is a rule violation. This one rule eliminated an entire class of silent drift that no amount of AI code review would reliably catch.

4. AI reviewing AI — with humans arbitrating

We wrote our own review skills, versioned in the repository: a contract reviewer (does this change keep backend, generated client, and UI consistent?), a minimality reviewer (is this adding a parallel code path instead of simplifying?), a design-system reviewer, an async-progress reviewer, plus pre-PR audits for dead code and test gaps. We also cross review: a branch produced with Claude gets reviewed by Codex, and vice versa. Different models fail differently — the disagreements are where the insight is.

Does It Work? An Honest Scorecard

What worked better than expected
  • The process caught an architecture-level mistake before merge. A signed execution-grant design was fully implemented, then challenged during security review and entirely removed — replaced by pod-side ReBAC checks with Keycloak resource servers. The PR was closed, not merged. Without the RFC-and-review discipline, that design would be in production today.
  • Cross-assistant review finds real bugs. One security-hardening branch went through a Codex review that raised seven findings — all seven were valid, and all seven were fixed before the PR.
  • AI-built self-tests found platform bugs humans had missed, including a global RAG misconfiguration (wrong vector index bound to an embedding model) and a regression where user context prompts silently never reached the model.
  • Documentation stays alive. Because updating the backlog, the status board, and the design docs is part of the assistant's definition of done — verified by a convergence check — our docs describe the system we actually have. That has never been true on any previous project we've worked on.
  • The upstream work is where the leverage is. Roadmap grooming, RFC drafting, backlog convergence, PMO reporting: the assistant handles the coordination overhead that usually eats senior engineers' time.
What is genuinely hard
  • The scaffolding is heavy and must be defended. Assistants drift. They forget rules under long contexts, produce redundant documents, and occasionally try to "helpfully" reopen decided questions. The reuse audit exists because we got burned.
  • Humans must still read everything. The bottleneck moved from writing to reviewing — deliberately. That is the point of the setup, but it is real work, and it does not compress.
  • It costs tokens and time. RFC-first means slower starts. We consider it the price of an application we will still understand in two years.
  • Process without conviction decays. The guardrails hold because the team believes in them, checks the convergence, and fixes divergence immediately. Tooling alone would not survive a sprint.

Two Teams, One Conclusion

Yahya Zaim Mounajed reached the same conclusion from the opposite end of the scale — not a multi-service cloud-native platform, but a personal project, built and maintained by one person. The size is different; the failure mode he describes is not.

My clearest experience with this came from a much smaller project than Fred. The scale was different, but the lesson was the same: for work that needs to remain maintainable, explainable, and easy to resume, AI does not automatically make the work better. It amplifies the way the work is framed. A vague workflow leads to vague output. An undefined deliverable leads to more content, not necessarily more progress. And when the project memory only lives in the chat, the assistant ends up guessing continuity.

The first rule I took from this was simple: design the work before executing it. The assistant can help with that design, but the workflow itself has to become explicit before implementation starts. On a software project, that means deciding the path first: specification, critical review, validation, roadmap, architecture, implementation, review, testing, and documentation. It also means giving each conversation a single purpose. One discussion, one output: a specification, an audit, a roadmap, an architecture note, an installation guide, or a recovery context for the next session.

This changed how I think about project memory. I do not want the assistant to rebuild the project from whatever it remembers from the previous exchange. The project should carry its own memory: specifications, roadmap, architecture, decisions, known limitations, and next steps. Updating that memory at the end of a session is part of the work. It is what allows the next session to start from the actual state of the project instead of from a plausible reconstruction of it.

That is where my experience converges with Fred’s, even at a very different scale. The goal is not to add process for the sake of it. The goal is to make the work clear enough for the assistant to accelerate it without taking ownership of it. Once the work is designed, the next questions become easier to handle: where the assistant should be autonomous, where the workflow should stay deterministic, and where a human decision is still required.

What strikes us is that our two teams, on very different projects — a multi-service cloud-native platform on one side, a single-person project on the other — converged on the same shape: the assistant proposes, the repository (or the project’s own memory) constrains, the human decides. Not because a methodology told us to, but because every alternative we tried produced work we did not want to own. Scale changes the tooling; it does not change the discipline.

Takeaways

  1. Put the governance in the repository, not in the prompt. Versioned, reviewable, shared by every assistant and every human.
  2. Make the assistant stop. RFC-first with mandatory human confirmation is the single highest-value rule we have.
  3. Registries beat prose. Task IDs, machine-readable status, one source of truth per fact.
  4. Generate, never mirror. Contracts and generated clients kill silent drift.
  5. Use AI to check AI — and different AIs against each other — but keep a human as the arbiter.
  6. Accept the cost. Staying in control is slower per task and faster per project.

Feedback welcome — open an issue on the Fred repository or reach out directly.