Skip to content

feat(results): temp-branch fallback + OK-to-resync (no force push)#1507

Merged
christso merged 4 commits into
mainfrom
feat/av-raf-temp-branch-resync
Jun 25, 2026
Merged

feat(results): temp-branch fallback + OK-to-resync (no force push)#1507
christso merged 4 commits into
mainfrom
feat/av-raf-temp-branch-resync

Conversation

@christso

Copy link
Copy Markdown
Collaborator

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_merge blocked outcome) is already on main; this PR adds the human-merge fallback path.

When resolveResultBranchPushConflict hits a genuine conflict:

  1. Push the diverged local work to a fresh timestamped temp branch (create-only, never force, never canonical).
  2. Surface a pending_merge wire block so the Dashboard can show a GitHub compare/PR link (GitHub's PR is the conflict surface — no merge UI built here).
  3. Add an explicit "OK" action (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 canonical agentv/results/v1 branch (git can't store a ref as both a file and a directory). Corrected to a flat scheme (doc updated to match):

agentv/results-sync/<timestamp_utc>-<branch_slug>-<rand6>
  • timestamp_utc = YYYYMMDDTHHMMSSZ (UTC)
  • branch_slug = slugified target branch (/[^A-Za-z0-9._-]+/-, fallback results)
  • 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 gh shell-out): parse github.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-merge fast-forwards the local checkout toward the target under an ancestor guard (update-ref only when local is an ancestor of the remote target; checkout mode uses merge --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 resolveResultBranchPushConflict via a single buildHumanMergeOutcome helper that attaches pendingMerge to the push details, so pending_merge flows to all needs_human_merge surfaces (4 status call sites + direct-push) through pushDetailsToWire. If the temp-branch push itself fails, the blocked needs_human_merge status is still returned (error appended to block_reason) — never crashes.

Test evidence (red/green)

  • Core (packages/core/test/evaluation/results-repo.test.ts): 62 pass
    • genuine overlay conflict → needs_human_merge + pending_merge whose temp_branch exists on the remote and carries the local work; no agentv/backups/*; no force push; canonical untouched; flat agentv/results-sync/... name (D/F-safe)
    • confirm-merge clears pending_merge after the temp branch is merged on the remote → status clean
    • premature confirm-merge keeps local artifacts intact and re-creates a temp branch on next sync
    • buildResultsCompareUrl unit test (GitHub vs non-GitHub)
  • Serve (apps/cli/test/commands/results/serve.test.ts): 121 pass
    • POST /api/remote/sync/confirm-merge (unscoped) and /api/projects/:projectId/remote/sync/confirm-merge (scoped) resume sync

bun run typecheck ✅ · bun run lint

Deferred

  • No Dashboard UI in this PR (GitHub PR is the conflict surface, as designed).

Refs bead av-raf.3.

christso and others added 4 commits June 25, 2026 02:28
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>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying agentv with  Cloudflare Pages  Cloudflare Pages

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

View logs

@christso christso marked this pull request as ready for review June 25, 2026 00:36
@christso christso merged commit c9aa8cb into main Jun 25, 2026
8 checks passed
@christso christso deleted the feat/av-raf-temp-branch-resync branch June 25, 2026 00:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant