Fork-with-upstream solution provisioning; the LLM is the glue
Status: Accepted · Date: 2026-06 (month as recorded; private-repo forking enabled on both orgs as of 2026-06-01) · Area: Solutions
Context
Creating a new Trajectory solution means standing up its two repos under the
three-repo split (ADR-006): a customer repo
from solution-template (into the maxq-labs-orbit-solutions org) and an
internal repo from solution-template-internal (staying in
maxq-labs-orbit-platform). The templates and the vendored methodology keep
evolving, so a mechanism was needed that lets existing solutions pull future
template updates. There was also a process question: how much of this should
an LLM skill do itself versus delegate.
Decision
- A true GitHub fork with rename (
gh repo fork --org --fork-name), not a template-generate and not clone-and-push. Chosen specifically to keep the “forked from” upstream link, so each solution can pull future template/methodology updates via GitHub Sync fork /gh repo sync. The script must never sever this link (no re-init or squash). Both repos are private; private-repo forking is enabled on both orgs. - One naming rule: inputs are an organization name and a solution name —
each letters-and-hyphens only, at most 20 characters, no leading/trailing
hyphen, lowercased. Repo base
solution-<org>-<sol>; the internal repo adds-internal;solution.yamlidentity is seeded from the same slugs. - The LLM is the glue; the deterministic work is the script. The
capability ships as a script + thin skill pair
(
.claude/skills/create-solution/withfork-solution-repos.sh); the skill never runsgh/gititself. - Validation before mutation: naming rules and GitHub uniqueness are
checked before any fork is created (the
--dry-runpath, which doubles as a leftover-partial-fork check). Schema validation of the seededsolution.yamlis best-effort only, not a gate. - Deliberately minimal v1 scope: fork both repos and initialize the
customer
solution.yaml— no README edits, no internal-repo seeding, no local clone or.envwiring.
Consequences
- Every solution stays connected to its templates; template fixes flow forward with git-native tooling instead of manual copying.
- The same naming rule now also governs registry identifiers — the customer
id is the org slug of solution naming
(ADR-008) — so one
validateNamecovers customers, tenants, and solutions. - The mechanism was later ported wholesale to the in-product native-octokit path (ADR-012), where the cross-org fork of a private source turned out to require a classic PAT.
- Recorded operational gotchas: with two
ghaccounts logged in, the active token silently being the wrong one surfaces as HTTP 404 (not 403) on the forks endpoint; and the working token lacksdelete_repo, so cleanup of a test run is a manual GitHub-UI delete.
Evidence
.claude/skills/create-solution/—SKILL.md+fork-solution-repos.shimplementation/aurora-webapp/codebase/src/lib/solutions/naming.ts— the ported naming rulememory/create-solution.md(mechanism decisions and gotchas),memory/orbit-platform-landscape.md(how the repos fit the platform)