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:
- Global
trajectory-methodology(a public/open-source candidate) — the methodology spec, JSON Schemas, and frozenreleases/v<X.Y>/snapshots. Read-only; mounted only for the methodology upgrade operation. - Per-solution customer repo (
<solution>, customer-visible) —workspace/(with the solution root atworkspace/solution-definition/),repositories/, and a vendored, version-pinned copy of the methodology matchingsolution.yaml’s pinned version. Forked fromsolution-template. Keeps the per-request branch → merge git lifecycle. - Per-solution internal repo (
<solution>-internal, MaxQLabs-only) —agents/,catalog/(the registries, renamed fromshared/),templates/,.orbit/(the full audit trail), and internal docs. Forked fromsolution-template-internal. Linear commits onmain, 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/(undermaxq-labs-orbit-platform/) andtrajectory-methodology/(undermaxq-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.orbitdebate),memory/orbit-platform-landscape.md, the platformCLAUDE.mdWORKSPACE section