feat(results): temp-branch fallback + OK-to-resync (no force push)#1507
Merged
Conversation
When the auto-merge loop hits a genuine conflict, push the diverged local work to a fresh flat timestamped temp branch (agentv/results-sync/<utc_ts>- <branch_slug>-<rand6>) instead of only blocking. The flat name avoids a git D/F conflict against the canonical results branch. Surface a pending_merge wire block (snake_case) so the Dashboard can link to a GitHub compare/PR. Adds confirmResultsMergeAndPull (the explicit "OK" action): fetch the remote, ancestor-guarded fast-forward of the target into the local results checkout, then resume normal sync. A premature OK is a safe no-op that leaves local work diverged and intact. Never force-pushes and never touches the canonical branch. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Expose confirmRemoteResultsMerge (remote.ts) mirroring syncRemoteResults' config-load + error-wrap pattern, and wire it to two HTTP routes (POST /api/remote/sync/confirm-merge and the project-scoped variant) mirroring the existing sync handlers. RemoteResultsStatus inherits the new pending_merge block from ResultsRepoStatus. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Core tests: a genuine overlay conflict yields needs_human_merge + a pending_merge whose temp_branch exists on the remote and carries the local work (no backups ref, no force push, canonical untouched, flat D/F-safe name); confirm-merge clears pending after the temp branch is merged on the remote; a premature confirm-merge keeps local artifacts intact and re-creates a temp branch on the next sync; and a direct unit test of the GitHub compare-URL builder (built for GitHub remotes, omitted for non-GitHub). Serve tests: confirm-merge routes (unscoped + project-scoped) resume sync. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The nested agentv/results/v1/sync-<ts> name D/F-conflicts with the canonical agentv/results/v1 ref. Use the flat agentv/results-sync/<utc_ts>-<branch_slug>- <rand6> scheme so code and design doc agree. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Deploying agentv with
|
| Latest commit: |
722247e
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://86f9049b.agentv.pages.dev |
| Branch Preview URL: | https://feat-av-raf-temp-branch-resy.agentv.pages.dev |
This was referenced Jun 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary (bead av-raf.3 — Phase 2)
Implements Layer 2 — Human merge via GitHub PR + explicit OK of the
no-force-push results sync (design doc). Phase 0/1 (the auto-merge loop returning a
needs_human_mergeblocked outcome) is already onmain; this PR adds the human-merge fallback path.When
resolveResultBranchPushConflicthits a genuine conflict:pending_mergewire block so the Dashboard can show a GitHub compare/PR link (GitHub's PR is the conflict surface — no merge UI built here).confirm-merge) that pulls the merged target into the local results checkout and resumes normal sync.All changes are additive/non-breaking.
Corrected branch naming (critical)
The design doc originally suggested
agentv/results/v1/sync-<ts>-<rand6>, which is invalid — a nested ref D/F-conflicts with the canonicalagentv/results/v1branch (git can't store a ref as both a file and a directory). Corrected to a flat scheme (doc updated to match):timestamp_utc=YYYYMMDDTHHMMSSZ(UTC)branch_slug= slugified target branch (/[^A-Za-z0-9._-]+/→-, fallbackresults)rand6= 6 hex chars to avoid same-second collisions; create-only push retries once with a fresh token on ref-exists.compare_url
Built only for GitHub remotes via pure URL construction (no
ghshell-out): parsegithub.com[:/]<owner>/<repo>(.git)from the resolved push URL →https://github.com/<owner>/<repo>/compare/<urlenc(target)>...<urlenc(sync_branch)>?expand=1. Omitted (undefined) for non-GitHub remotes (file://, gitlab, etc.).Premature-OK safety
confirm-mergefast-forwards the local checkout toward the target under an ancestor guard (update-refonly when local is an ancestor of the remote target; checkout mode usesmerge --ff-only). If the user clicks OK before actually merging, the FF is a no-op: local work stays diverged and intact, and the next sync simply re-creates a temp branch. No data loss, no force push, source repo branch never touched.DRY wiring
The temp-branch push lives inside
resolveResultBranchPushConflictvia a singlebuildHumanMergeOutcomehelper that attachespendingMergeto the push details, sopending_mergeflows to allneeds_human_mergesurfaces (4 status call sites + direct-push) throughpushDetailsToWire. If the temp-branch push itself fails, the blockedneeds_human_mergestatus is still returned (error appended toblock_reason) — never crashes.Test evidence (red/green)
packages/core/test/evaluation/results-repo.test.ts): 62 passneeds_human_merge+pending_mergewhosetemp_branchexists on the remote and carries the local work; noagentv/backups/*; no force push; canonical untouched; flatagentv/results-sync/...name (D/F-safe)pending_mergeafter the temp branch is merged on the remote → statuscleanbuildResultsCompareUrlunit test (GitHub vs non-GitHub)apps/cli/test/commands/results/serve.test.ts): 121 passPOST /api/remote/sync/confirm-merge(unscoped) and/api/projects/:projectId/remote/sync/confirm-merge(scoped) resume syncbun run typecheck✅ ·bun run lint✅Deferred
Refs bead av-raf.3.