Skip to Content
Design DecisionsThree-Repo Split

The three-repo split for solutions

Status: Accepted · Date: 2026-05 (month as recorded; implementation observed under way 2026-05-31) · Area: Repositories

Context

A Trajectory solution originally lived in a single repo per solution. That conflated three things with different audiences and lifecycles: the methodology (a global specification with schemas and frozen releases, shared by every solution), the customer deliverables (the solution tree the customer sees), and MaxQLabs internal IP (agent personas, catalog registries, templates, and the .orbit/ audit trail of agent runs). It also left an awkward question open: whether the agent’s .orbit/ working state should be committed to the customer-visible history at all.

Decision

The single-repo-per-solution model is split into three repos:

  1. Global trajectory-methodology (a public/open-source candidate) — the methodology spec, JSON Schemas, and frozen releases/v<X.Y>/ snapshots. Read-only; mounted only for the methodology upgrade operation.
  2. Per-solution customer repo (<solution>, customer-visible) — workspace/ (with the solution root at workspace/solution-definition/), repositories/, and a vendored, version-pinned copy of the methodology matching solution.yaml’s pinned version. Forked from solution-template. Keeps the per-request branch → merge git lifecycle.
  3. Per-solution internal repo (<solution>-internal, MaxQLabs-only) — agents/, catalog/ (the registries, renamed from shared/), templates/, .orbit/ (the full audit trail), and internal docs. Forked from solution-template-internal. Linear commits on main, no per-request branches.

The agent takes three explicit, overridable path env vars — since 2026-07-02 all three mount into the agent only (ADR-007).

One point is recorded as settled, not to be re-litigated: the .orbit gitignore/untrack debate is over. Under the split, .orbit/ is a first-class tracked part of the internal repo — safe because that repo never branch-switches, so the live tasklist.json is never swapped under the task processor. The earlier single-repo work that gitignored .orbit (and its untrackOrbit() startup routine, see ADR-010) is to be removed, not finished.

Consequences

  • Each audience gets exactly its repo: customers see deliverables plus the pinned methodology they were assessed against; internal IP and the audit trail stay MaxQLabs-only; the methodology can evolve globally while solutions stay reproducible on their vendored, pinned copy.
  • Normal authoring resolves the vendored methodology inside the customer repo; the global repo is only needed for upgrades — which also shaped the deployment mount decision (no third Azure Files share, D5 in ADR-002).
  • Solution provisioning becomes a two-fork operation (ADR-013), and every consumer of “the solution repo” (agent git subsystem, seeding, mounts) has to be dual-repo aware — an accepted cost paid across the agent and infrastructure work.
  • The internal repo’s linear-history rule is a real constraint: agent runs append, never branch, there.

Evidence

  • Sibling repos: solution-template/, solution-template-internal/ (under maxq-labs-orbit-platform/) and trajectory-methodology/ (under maxq-labs/) — the three bases
  • infrastructure/local/.env — the three mount paths (SOLUTION_REPOSITORY_PATH, SOLUTION_INTERNAL_REPOSITORY_PATH, TRAJECTORY_METHODOLOGY_PATH)
  • memory/repo-split.md (the decision record and the superseded .orbit debate), memory/orbit-platform-landscape.md, the platform CLAUDE.md WORKSPACE section