BeeverForge core architecture
Architecture overview
The BeeverForge core takes tickets from a board and drives existing coding agents through planning, implementation, validation, review, pull request, merge and deployment observation. It is an orchestrator: it does not contain a coding agent of its own.
This section describes the core as it exists in the repository at the commit linked under each page’s sources. Where a design record describes something the code does not yet do, the page says so.
Control model#
The project README states the model as “Policies authorise, humans evaluate.” The project’s manifest, .beeverforge/project.yaml, declares the merge policy, the quality floor and the promotion chain. Within those policies the factory acts without asking for approval at each step; people judge the result.
- A project that declares no
testgate is not treated as passing. Before the implementation pass, after sizing, the runner checks the floor and refuses the job, naming the missing gate and how to declare it. - The default merge policy is
human: a person merges the pull request. Automatic merge happens only when a project setsmerge_policy: autoand every condition for it holds. - Production promotion waits for a human approval. The approval reaches the workflow as a sealed, single-use answer (see The box and the quality floor).
- When a job cannot continue, it parks on the card with the options a person can take, instead of waiting silently.
Layer model#
The core’s vision document draws the system as applications on top of an action layer, a core that decides, an engine that drives it, and providers reached through ports. Capabilities are drawn as a boundary, not as a layer: the core and the engine both reach providers through the same kind of port.
| Layer | Where it is in the code | State |
|---|---|---|
| Applications | beeverforge/product/, beeverforge/techlead/, beeverforge/api/ | Realised. The panel, the tech-lead and the opt-in product role. |
| Action layer | beeverforge/actions/ | Realised. One catalogue that the panel API and the CLI both execute through. |
| Core | beeverforge/contracts/, beeverforge/policy/, beeverforge/lifecycle/ | Partly realised. The card lifecycle is decided by pure tables. The pure decision kernel for jobs proposed in ADR-0033 does not exist; job transitions are still decided inside the runner and the workflow. |
| Engine | beeverforge/runtime/temporal/ | Realised on Temporal. The engine is not behind a port of its own. |
| Capabilities and providers | beeverforge/adapters/ | Realised. Each provider is chosen by a registry from configuration. |
The core’s own boundary document describes orchestrator/machine.py as core policy and engine execution that are currently fused. The vision of a core that only decides and an engine that only executes is the direction of ADR-0033, which is recorded as proposed.
Deployment shape#
- The operator’s own machines. The default installation is
docker composeon one machine and needs no cloud account (ADR-0040). A cloud is reached only through add-on packages. - Services. The compose file runs a Postgres database for the engine, a Temporal server, the Temporal web UI, the worker and the panel. The published ports bind to
127.0.0.1by default. - The engine. Temporal holds job state. Every job is a durable workflow: its waits and timers survive a worker restart, and a job whose worker is lost during the agent pass parks for a person to resume or skip.
- The box. The worker runs each job in a box. The default kind is
container: a throwaway Docker container launched as a sibling on the host’s daemon, through the Docker socket that the compose file mounts into the worker. - Single-tenant, multi-project. One installation serves one team with one project registry. The registry holds any number of projects, each with its own repository, board and manifest (ADR-0001, D-14).
- One job at a time by default. The number of jobs in flight is
BEEVERFORGE_MAX_CONCURRENT_JOBS, default1.
127.0.0.1; the box’s network is described on The box and the quality floor.The worker holds the host’s Docker socket, which gives it control of the host’s Docker daemon. The default box has full outbound network access. Both are described with their limits on The box and the quality floor.
Outside the core#
- The coding agents. The core drives existing agent command-line tools through one adapter contract. The harness kinds in the tree are
claude_code(the default),codex,kimiandopencode. Each one calls its vendor’s service; that endpoint is a network destination every installation needs. - Chat channels. The core is complete without a chat connector (ADR-0038). The only channel and notifier in the tree is the panel. Slack and Telegram adapters ship in a separate add-on package and register through the same extension mechanism as any other adapter.
- Cloud runners and stores. The core ships no remote box runner. The remote task runner, the cloud metrics table, the remote session store and the cloud token pool are declared as add-on kinds.