How we decided
An architecture decision record fixes what was decided and describes the architecture that follows — nothing else. These pages carry the reasoning around each one: the question as it arrived, the options that were on the table, the one taken and why, what the choice costs, and what has changed since. Each is written from the decision as it stands today, and links to the record it explains.
Foundations
- ADR-0001 Every port has two adapters and one contract The domain never touches a vendor. Each piece of infrastructure is a port the domain defines, with at least two adapters and a contract suite both must pass — which is what lets the same binary run on Google Cloud and on a laptop cluster. 2026-08-29
- ADR-0012 A core in Go, a BFF in Python, and one rule between them Go for state, transactions, events and the agent runtime; Python for the edge that talks to the cockpit and the CLI. The boundary fits in one sentence: the BFF has no database and no secret. 2026-08-30
- ADR-0013 One contract, generated everywhere One .proto per domain is the only description of the API. The core's server, the edge's client, the CLI and the cockpit's hooks are generated from it, and a breaking change fails the build instead of surfacing in production. 2026-08-30
- ADR-0015 The local environment runs production's SDK, and Terraform owns the rest Firebase's emulators provide identity and object storage locally with the same SDK and the same configuration files as production. Infrastructure is created by Terraform only, so nothing exists that the state does not know about. 2026-08-30
Accounts, identity and access
- ADR-0002 The account owns everything One entity, personal or organization, owns every integration, workspace and project; every table carries its id from the first migration. An organization is created instantly and proves itself later, by a DNS record. 2026-08-29
- ADR-0019 An invite is an address, not a key An invite carries no secret. Its link is the row's id, safe to travel in events, projections and e-mails, because accepting requires signing in with the verified e-mail the invite was sent to. 2026-09-01
- ADR-0020 One second factor, three verifiers, in the core The identity provider does the first factor only. The second — authenticator app, e-mail or SMS — is a domain of the core, so it is the same for every identity provider, runs locally, and keeps its secrets in the vault. 2026-09-02
- ADR-0022 The core verifies a signature on every call A call with a person carries the person's token; a call without one carries an assertion signed by the platform. The network boundary is additional — Cloud Run IAM in the cloud, a network policy on a cluster — never the only guarantee. 2026-09-03
Resources, integrations and credentials
- ADR-0003 The organization acts; the person is the author; the agent is the committer Pushes and pull requests use the organization's credential, so nothing breaks when a person leaves. Every commit names the developer as author and the agent thread as committer, so the history still says who asked and who wrote. 2026-08-29
- ADR-0009 One resource type, one way to share Integrations, skills, workflows and git flows are all resources of an account, shared by the same grants and the same invite. A new kind of resource never touches the sharing mechanism. 2026-08-30
State, events and communication
- ADR-0004 Every write is an event; everything else is a projection Every write in the core emits an immutable event carrying who, what, when and in which context. The dossier, the timeline, auditing, replay and metrics are read from that log — none of them is written separately. 2026-08-29
- ADR-0014 One database, an outbox, and a queue for what fails PostgreSQL holds the relational spine, the documents and the vectors. Every state change writes its event in the same transaction; a relay publishes it to NATS; a delivery that keeps failing lands in one dead-letter queue with everything needed to retry it. 2026-08-30
- ADR-0018 A notifier decides; a channel delivers One consumer of the event spine decides what to notify and to whom, from a table of rules. One port per channel delivers it, and each adapter — OneSignal, SendGrid, SMTP — resolves its own templates. Use cases publish events and nothing else. 2026-08-31
The agents and their cost
- ADR-0007 Threads you can address, findings you can publish A demand's conversation is a set of threads — the main agent and one per specialist — each with its own history and card. Specialists share what they found as structured findings, not by copying their whole context into each other. 2026-08-29
- ADR-0008 Measure, cap, route — and design the prompt for the cache Every model call emits a cost event; every demand has a budget that pauses rather than kills; a router picks the class of model per kind of work — never cheaper for the critic. And the prompt is laid out so the expensive part is cached. 2026-08-29
- ADR-0011 A techlead agent per project, and it never pauses a demand When a project has two or more active demands, an orchestrator agent watches for overlap, dependencies and interference, plans a solution and brings the developer a decision — without stopping any demand while it waits. 2026-08-30
- ADR-0016 A port per model vendor, running where the credential is The runtime that talks to a model sees no vendor SDK: it sends a conversation through the AgentProvider port and the account's resource decides which adapter answers. It runs in the core, next to the vault, so a provider's credential never crosses the network. 2026-08-31
Knowledge and context
- ADR-0006 Three layers of knowledge, one curated package per demand A project's knowledge is rules, an index of its code and a memory of past demands. Each demand receives a curated package assembled from them, and the whole shelf is cloned into the sandbox for the agent to open what it needs. 2026-08-29
- ADR-0021 The project's knowledge is a git repository the platform hosts Every project has a root repository, born with it, cloned into every sandbox. Agents write by committing; every push is an event; a per-demand token opens exactly that repository; the user's own remote is a mirror. 2026-09-03
The work, its verification and its delivery
- ADR-0005 No green, no PR — and a merge queue after the green A pull request opens only when executable acceptance passes and an independent critic has reviewed it, carrying its evidence. After the green, a queue per repository re-verifies each PR against the current main and merges one at a time. 2026-08-29
- ADR-0010 The flow is data: typed stages, free composition, inheritance Stages have a type the platform knows how to render and act on; flows compose them freely and are resolved down a chain — platform, account, workspace, project, demand. No conditionals, no rules language: a flow is data a loader reads. 2026-08-30
- ADR-0017 One microVM per demand, one worktree shared by its threads The hard boundary is between accounts and between demands, so each demand gets one sandbox and its agents share one workspace. Verification never runs there: it runs in a separate environment built from a commit. 2026-08-31
- ADR-0023 Verification runs in a runner that builds from source An ephemeral runner pulls the commit, builds the application from source and starts it — no image of the project is ever built, pushed or deployed. The account's cache makes the second run fast; the runner takes the demand's address while it runs. 2026-09-04