One-time setup
muyan_pilot.py setup is the one-time, config-driven initialization
entry for a new machine or a new task-pool repository. It verifies the
local prerequisites, aligns the platform labels, installs the systemd
user units, checks the checkout, and reports the optional model proxy —
in one command, with a stable machine-readable result.
What it does, in order
Setup is fail-fast: a core prerequisite failure stops the run before any later mutation, with the concrete reason on stderr and a non-zero exit code.- Commands —
git,gh,python3on the PATH, and a reachablesystemctl --useruser bus (a container or headless session without a user bus fails with the bus error). - Auth —
gh auth status(logged in with a usable token). - Per target repository (every configured
source_reposentry by default; exactly one with--repo OWNER/REPO):- the repo exists and the viewer has write permission
(
gh repo view→viewerPermissionmust beWRITE,MAINTAINorADMIN); - the seven platform labels are aligned declaratively from the
repo-managed
labels.toml(repo root) — the single source of truth for label name, color and description: a missing label is created, a drifted label is updated, nothing is deleted, and business labels (bug,enhancement, …) are never touched.
- the repo exists and the viewer has write permission
(
- Systemd units — the repo templates
(
systemd/muyan-pilot.service,systemd/muyan-pilot.timer) are installed idempotently into the user unit directory (the same installinstall-unitsperforms: copy,daemon-reload, enable the timer — the service is never started, stopped or restarted), then the timer’s enabled/active state and next trigger time are reported. - Checkout + git transport — check of the configured
repo_dir: theoriginremote’s transport (Issue #114): git data operations (fetch, push — including.github/workflows/*.yml) must go over SSH ([email protected]:owner/repo.git), so an existing HTTPSoriginis migrated here with the plaingit remote set-url origin [email protected]:owner/repo.git(setup is the human-authorized migration path — the Runner itself never rewrites a remote), the SSH URL must match the first configured source repo — a remote pointing at a DIFFERENT repo is never migrated (the rewrite would re-target the checkout at another repository) and fails withsetup_failed reason=... origin remote repo mismatch ...— andgit ls-remote <ssh-url>must exit 0 (SSH reachable and authenticated — a failure issetup_failed reason=... ssh_unreachable ..., no HTTPS fallback). Then the read-only parts: current branch, clean worktree (a dirty checkout fails: the timer’sExecStartPrefast-forward refuses a dirty worktree, so the Runner could never start), and base freshness (localHEADvs freshly fetchedorigin/<base_branch>— reported, not a failure: the timer fast-forwards a clean checkout at each start). - Optional model proxy — the
local-llm-kv-cacheproxy health endpoint (http://127.0.0.1:18082/health) is checked and reported as optional: its absence or unhealthiness is a warning in the output and never blocks the core GitHub/Pilot setup.
Options
Output
The default output is stablekey=value lines (one per concern; values
containing spaces are quoted), so agents and scripts can parse it:
labels=7/7 means all seven platform labels match labels.toml;
next is the timer’s next trigger time (- when it has none);
optional_proxy is healthy, unhealthy or unavailable and never
changes the exit code. migrated=true means setup rewrote an HTTPS
origin to the SSH URL (a re-run then reports migrated=false);
ssh_reachable is the git ls-remote probe result.
--json prints the equivalent JSON document:
Success and failure examples
Success (exit code0):
optional_proxy=unhealthy —
but the core setup still succeeds with exit code 0.)
Failures (non-zero exit code, setup_failed reason=... on stderr):
Idempotency
Re-running setup on an already-initialized machine is a no-op for the external state: labels that already match are not rewritten, the unit templates are re-copied from the repo (drift repair), the timer stays enabled, and no Issues or business data are created or modified. The reported hashes and states are stable across runs. The HTTPS→SSH migration is one-shot: after the first run theorigin remote is SSH
and re-runs only re-verify it (migrated=false).