diff --git a/agent-queue/README.md b/agent-queue/README.md index d48c44d..f139bff 100644 --- a/agent-queue/README.md +++ b/agent-queue/README.md @@ -430,6 +430,7 @@ AQ_FLEET=1 AQ_FLEET_TOKEN=… AQ_PRODUCT_ID=… agent-queue.sh run # | `AQ_FLEET_AUTOSHIP` | `0` | `1` = when the local verify gate passes, advance the coordinator job `testing → shipped` (the factory's verify **is** the test phase); `0` = report `testing` and rest for the human review gate | | `AQ_FLEET_PR` | `0` | `1` = for a job carrying a `repo`, run the agent in an isolated checkout on branch `aq/job/`, then commit/push and `gh pr create`; the PR URL is reported back and recorded on the run | | `AQ_FLEET_REPOS_DIR` | `.state/repos` | cache dir for PR-mode repo checkouts (one per repo) | +| `AQ_FLEET_REPO_BASE` | _(none)_ | base dir of existing local repos; a job `repo` matching `/` is cloned from there (fast, no network) and PRs are pushed to its GitHub origin (embedded creds stripped) | | `GH_BIN` | `gh` | GitHub CLI used to open PRs in PR mode | | `AQ_FLEET_SHADOW` | `0` | shadow/dual-run: `1` (requires `AQ_FLEET=1` + `AQ_FLEET_ROUTE=0`) queries the coordinator in parallel and records divergence, **never acting on it** | | `AQ_FLEET_SHADOW_FACTORY_ID` | `-shadow` | isolated id used for the read-only shadow claim (never the real factory id) | diff --git a/agent-queue/agent-queue.sh b/agent-queue/agent-queue.sh index 1f2b374..7f358be 100755 --- a/agent-queue/agent-queue.sh +++ b/agent-queue/agent-queue.sh @@ -643,20 +643,31 @@ build_agent_cmd() { _fleet_pr_prepare() { local repo=$1 base=${2:-main} jid=$3 logf=$4 local reposdir="${AQ_FLEET_REPOS_DIR:-$STATE/repos}"; mkdir -p "$reposdir" - local safe dir url br + local safe dir url br src="" origin_url="" safe=$(printf '%s' "$repo" | tr -c 'A-Za-z0-9._-' '_'); dir="$reposdir/$safe" - # Resolve a clone URL: full URLs (ssh/https) pass through; absolute/existing - # local paths (bare repos, mirrors) are used as-is; otherwise `owner/name` is - # expanded to a GitHub HTTPS URL. - case "$repo" in - *://*|git@*) url="$repo";; - /*) url="$repo";; - *) [[ -e "$repo" ]] && url="$repo" || url="https://github.com/$repo.git";; - esac + # MVP: if AQ_FLEET_REPO_BASE/ is an existing local repo, use it as the clone + # SOURCE (fast, no network) and push/PR to its GitHub origin. Credentials embedded + # in the local origin URL are stripped — gh's credential helper handles auth. + if [[ -n "${AQ_FLEET_REPO_BASE:-}" && -d "$AQ_FLEET_REPO_BASE/$repo/.git" ]]; then + src="$AQ_FLEET_REPO_BASE/$repo" + origin_url=$(git -C "$src" remote get-url origin 2>/dev/null | sed -E 's#://[^@/]*@#://#') + fi + # Resolve a clone URL: local source wins; else full URLs pass through; absolute/ + # existing local paths used as-is; otherwise `owner/name` -> GitHub HTTPS. + if [[ -n "$src" ]]; then url="$src"; else + case "$repo" in + *://*|git@*) url="$repo";; + /*) url="$repo";; + *) [[ -e "$repo" ]] && url="$repo" || url="https://github.com/$repo.git";; + esac + fi if [[ -d "$dir/.git" ]]; then - git -C "$dir" fetch --quiet origin "$base" >>"$logf" 2>&1 || { echo "PR: fetch failed for $url ($base)" >>"$logf"; return 1; } + [[ -n "$origin_url" ]] && git -C "$dir" remote set-url origin "$origin_url" >>"$logf" 2>&1 || true + git -C "$dir" fetch --quiet origin "$base" >>"$logf" 2>&1 || { echo "PR: fetch failed for $base" >>"$logf"; return 1; } else git clone --quiet "$url" "$dir" >>"$logf" 2>&1 || { echo "PR: clone failed for $url" >>"$logf"; return 1; } + # Repoint to the upstream GitHub origin (when cloned from a local mirror). + [[ -n "$origin_url" ]] && git -C "$dir" remote set-url origin "$origin_url" >>"$logf" 2>&1 || true git -C "$dir" fetch --quiet origin "$base" >>"$logf" 2>&1 || true fi br="aq/job/$jid"