| name | repo-factory-router |
| description | Run at TASK INTAKE — the moment you pick up a ticket/issue in this multi-agent repo and before you touch a file or launch anything. Turns a ticket into a routing decision: build its file/signature dependency DAG, pick a throwaway worktree workcell that won't collide with in-flight work, and pick the right box (Spark GPU / Mac MLX judge / RunPod x86 / pure-CPU). Fires on "start this ticket", "pick up issue #NNN", "where should this run", "can I work on X in parallel", "assign this to a worktree", "route this task", or any hand-off that names files to change plus maybe a GPU/judge step. It is a JUDGMENT recipe that composes existing tools and reads the DAG — it holds NO state.
|
| metadata | {"short-description":"Task intake → dependency DAG → collision-free worktree + right-box routing decision"} |
repo-factory-router
Intake router for the sophia-agi "repo factory". A ticket arrives; this skill decides where the work
lives (which worktree) and where it runs (which box), so parallel agents don't collide on files or
starve the one shared GPU. It composes the existing skills and tools below — it does not replace them,
does not launch jobs, and holds no state. Make ZERO capability/uplift claim; canClaimAGI stays false.
Depends on: git-discipline (situational awareness), spark-cluster-ops (box map, one-GPU-job
invariant, git-crypt worktree bypass), session-handover + SESSION-COORDINATION.md (who owns what),
ci-artifact-drift (make claim-check exit gate). Route to those for mechanics; this is the decision layer.
1. Read the board FIRST — you are routing into live traffic (read-only, ~5 s)
git fetch origin --prune
python .agents/skills/git-operations/scripts/git_situational_awareness.py --json
Then read the two live ledgers before claiming anything:
SESSION-COORDINATION.md (untracked, live CLAIM/OWNS/DONE) — the real-time list of files/seeds/pods
peers already own. This is the collision oracle.
- Newest
SESSION-HANDOVER-YYYY-MM-DD.md + agi-proof/failure-ledger.md — is this ticket already
done, or already someone's open item? If so, stop and re-route, don't duplicate.
2. Build the ticket's dependency DAG (file + signature level)
Enumerate the ticket's change set and its blast radius — this is what the collision + box decision keys off.
git grep -n "def <changed_symbol>\|class <ChangedThing>\|import <changed_module>" -- '*.py'
python -m compileall -q <touched dirs>
Write the DAG down as: nodes = files/modules to edit; edges = "A's signature is imported/called by B".
Classify each node:
- leaf (new file / no importers) → safe to parallelize, low collision risk.
- hub (many importers:
agent/, okf/, tools/lint_*, a shared schema) → high collision risk; serialize or coordinate.
- generated artifact (RESULTS.md, RAG index, wiki, local-Sophia dataset, VERSION, failure-ledger,
rlvr.public-report.json) → NOT a source node; do not edit by hand — regenerate via the ci-artifact-drift table.
3. Collision check — intersect your DAG with in-flight work
For each node, ask: does any live claim in SESSION-COORDINATION.md, any sibling worktree
(git worktree list), or any open PR (gh pr list --state open --json number,title,headRefName,files)
already touch it?
- No overlap → green, take a fresh workcell (§4).
- Overlap on a leaf → coordinate the file, still parallelizable.
- Overlap on a hub → STOP. Either wait for the peer's PR to land + rebase onto it, or negotiate in
SESSION-COORDINATION.md. Two agents editing a hub signature = guaranteed rebase pain.
4. Spin the workcell — a throwaway detached worktree off origin/main (NEVER the primary tree)
Isolate every ticket in its own worktree so edits can't cross-contaminate the shared checkout. This repo is
git-crypt, so a plain worktree add re-runs the smudge filter and aborts — use the -c bypass
(spark-cluster-ops §3) and verify plaintext before working:
git -c filter.git-crypt.smudge=cat -c filter.git-crypt.clean=cat -c filter.git-crypt.required=false \
worktree add -b feat/<ticket-slug> /path/to/wc-<ticket-slug> origin/main
head -1 /path/to/wc-<ticket-slug>/README.md
Then append your CLAIM to SESSION-COORDINATION.md: session id + pid, OWNS <files>, box, do-not-touch list.
Rules that still apply: explicit git add <paths> only (never -A); never git stash (shared stack);
--force-with-lease never --force; never git switch a branch out from under a sibling worktree.
5. Pick the box — match the DAG's heaviest node to the right tier (spark-cluster-ops §0)
| The ticket's heaviest node needs… | Route to | Guardrail |
|---|
| pure code / lint / artifact regen / CPU tests | local worktree, no GPU | just run make claim-check |
| iteration LoRA/QAT, low-RAM cert, data-refinery, ONE Qwen judge | DGX Spark GPU | one-GPU-job invariant — route THROUGH the bridge poller, or nvidia-smi headroom-check before any direct tmux/ollama launch |
| a SECOND, less-correlated judge family (Llama MLX) | Mac Studio M3 (MLX) | keyless: OPENAI_API_KEY=none, else judge silently yields n=0 |
| the REGISTERED / headline / source-of-record number | RunPod x86 (H100/A100) | GHA-dispatched behind runpod-paid human approval + --yes; announce pod id in coordination ledger; NEVER a Spark number as headline (aarch64 numerics) |
Decision rule: default latency-tolerant iteration to the free Spark; reserve RunPod for the one registered
arm; put the independent judge on the Mac. If two heavy Spark nodes are queued, they must serialize through
the bridge (128 GB fits ~two 7B trainings, a third heavy load has KILLED an in-flight seed).
6. Emit the routing decision + watch
Record the decision (in SESSION-COORDINATION.md and your reply), then hand off:
- Watch GPU/train work via TrainWatch (
trainwatch skill; dashboard binds 0.0.0.0:8420 for Mac/Tailscale
at spark-2f2d) and proactively surface elapsed + ETA + progress.
- Exit gate before any commit/push from the workcell:
make claim-check must pass, and regenerate any
generated artifact your DAG touched (ci-artifact-drift §2 table). Never lower a gate threshold to pass.
- Tear down the workcell when the PR lands:
git worktree remove <dir>; drop your CLAIM block.
Stop-and-ask / abstain
- If the DAG can't be built because the ticket is underspecified (no concrete files/symbols named), abstain:
ask for the file list before routing — don't guess a blast radius.
- If routing would change what is claimed (a number's status, "validated", a RESULTS.md entry), that's the
no-overclaim contract — stop and ask (see ci-artifact-drift / sophia-agi). This router picks where work runs,
never what it may claim.
canClaimAGI stays false.