Files
werkator/docs/adrs/0009-2026-09-01.multi-repo-instance.md
mhoennigandClaude Fable 5 ff3aa61eca ADR 0009: one Werkator instance serves a set of repositories
Records the tenet revision and its shape: instance registry and
instance keys in ~/.werkator.yml (one instance per OS user), optional
repo defaults in an explicit defaults: block merged below every repo's
own layers, repo config unchanged in each repository, registry-wins
precedence, basename repo names. Rejected: a federation dashboard over
single-repo instances (keeps N services), and the status quo.
Konzept/AGENTS architecture wording changes only when the
implementation lands; the decision list carries 0009 now.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-01 14:15:15 +02:00

4.2 KiB
Raw Permalink Blame History

One Werkator Instance Serves a Set of Repositories

Status:

  • proposed: 2026-09-01
  • accepted: 2026-09-01
  • rejected: -
  • superseded: -

Decision [accepted]: The founding tenet "one instance per repository" is revised to "one instance per repository set": a Werkator instance aggregates self-contained repositories listed in an instance registry, sharing one service, one port, one UI, one watcher schedule, and one global executor cap. Implementation is planned as docs/plan/22-multi-repo.md; this ADR records the decision and its shape, not the code.

Context and Problem Statement

"One instance per repository" (docs/Werkator-Konzept.md) does not scale even to two repositories on a Hostsharing Managed Webspace: building Werkbaum next to Werkator on mih34 would need a second service, a second assigned port, a second tunnel or domain, a second UI and metrics page. Every repository multiplies operations while the instance-level resources could be shared.

Technical Background

Everything repository-specific already lives inside the repository or is keyed by it: machine config with secrets, build results, auto-build slots, worktrees, and buildenvs under .git/werkator/; the artifact store under a per-repo key. An instance can therefore aggregate repositories without absorbing their state — adding or removing a repository is a registry entry, never a data migration, and single-repo mode stays the degenerate case (a registry of one, implicitly the current working directory).

Considered Options

  • One instance per repository set (registry + aggregation) — chosen
  • A federation dashboard proxying several single-repo instances
  • Status quo: one instance, one repository

One Instance per Repository Set

Good:

  • One service, port, UI, tunnel/domain, metrics page for any number of repositories.
  • Repositories stay self-contained; per-repo secrets, history, and pinning semantics are untouched.
  • Global concurrency control across all repositories.

Bad:

  • The repo dimension must be threaded through executor pools, watcher cycle, routes, and UI — the largest refactor since the rewrite (mitigated by a behavior-preserving RepoContext session first).
  • Instance-level and repo-level configuration must be split cleanly (see below).

Federation Dashboard over Single-Repo Instances

Rejected: less invasive, but it keeps N services, N ports, and N tunnels — it solves only the UI aggregation, not the operations burden that motivated the change.

Status Quo

Rejected: on a webspace, ports and domains are the scarce, manually assigned resource; per-repository services do not scale there.

Decision Outcome

One instance per repository set, with the configuration split decided 2026-09-01:

  • Instance config lives in ~/.werkator.yml in the home directory of the user running the instance — one instance per OS user, matching the platform model. It carries server.* (port, domain/public base URL, nginx), the repository registry, the control token, the global executor.maxConcurrent, and the watcher schedule. The file name stays .werkator.yml in all three locations; the location carries the meaning.
  • Repo defaults may live in the home file, but only in an explicit defaults: block, merged below every repository's own layers (home defaults → committed project config → repo machine config → branch layer); pinning semantics are unchanged. Accepted cost: secrets may then live in two places.
  • Repo config stays in each repository: the committed .werkator.yml and the machine config in its .git/werkator/.
  • Instance keys found in a repo's machine config are ignored with a warning naming both files once a home config exists — never merged silently.
  • When a home config with a registry exists, werkator server serves the registry regardless of the current directory; without one it serves the current directory exactly as before.
  • Repository names (routes, UI) default to the directory basename, are overridable per registry entry, and duplicates abort the start loudly.

Consequences: docs/Werkator-Konzept.md and AGENTS.md change their wording when the implementation lands (plan step 22 sessions BD); until then this ADR documents the target and the existing behavior remains accurate.