Skip to content

Fix sandbox exec dropping uncommitted changes with unpushed commits#366

Merged
robinaugh merged 6 commits intomainfrom
fix/sandbox-exec-unpushed-commits
Feb 20, 2026
Merged

Fix sandbox exec dropping uncommitted changes with unpushed commits#366
robinaugh merged 6 commits intomainfrom
fix/sandbox-exec-unpushed-commits

Conversation

@robinaugh
Copy link
Contributor

@robinaugh robinaugh commented Feb 19, 2026

Summary

  • When sandbox exec runs on a branch with unpushed commits, the pull-back step was destroying local uncommitted changes. The sandbox diff (against HEAD) included the synced local changes, and the complex reset-and-apply logic couldn't reconcile them.
  • Fix this by snapshotting the post-sync state as a detached ref (refs/rwx-sync) rather than on the branch itself. After syncing local changes, we commit a snapshot, save it to refs/rwx-sync, then immediately reset HEAD back so the user's branch tip is unchanged during exec.
  • On pull, diff against refs/rwx-sync to capture only exec-produced changes, which apply cleanly regardless of unpushed commits.
  • The reset-files-to-HEAD step and local-changed-files merge logic are no longer needed — git apply is atomic, and the diff now inherently contains only exec changes.
  • Adds a CI test exercising the exact bug scenario: unpushed commit + uncommitted edit + sandbox exec.

Test plan

  • go test ./internal/... ./cmd/... — all unit tests pass
  • golangci-lint run ./... — no lint issues
  • CI: new test block in run-rwx-testing-sandbox verifies uncommitted changes survive sandbox exec with unpushed commits
  • Manual: branch with all commits pushed — normal flow still works

@robinaugh robinaugh self-assigned this Feb 19, 2026
@robinaugh robinaugh force-pushed the fix/sandbox-exec-unpushed-commits branch 2 times, most recently from ae87eca to 3cb79e5 Compare February 19, 2026 17:21
@robinaugh robinaugh marked this pull request as ready for review February 19, 2026 18:01
jmsanders
jmsanders previously approved these changes Feb 19, 2026
@robinaugh robinaugh force-pushed the fix/sandbox-exec-unpushed-commits branch 2 times, most recently from 2e1bf29 to f9a08fd Compare February 19, 2026 19:07
@robinaugh robinaugh marked this pull request as draft February 19, 2026 19:17
@robinaugh robinaugh force-pushed the fix/sandbox-exec-unpushed-commits branch from f9a08fd to 693f95d Compare February 19, 2026 19:31
When sandbox exec runs on a branch with unpushed commits, the pull-back
step was destroying local uncommitted changes. The sandbox diff (against
HEAD) included the synced local changes, and the complex reset-and-apply
logic couldn't reconcile them.

Fix this by snapshotting the post-sync state as a detached ref
(refs/rwx-sync) rather than leaving it on HEAD. After syncing local
changes to the sandbox, we commit a snapshot, save it to refs/rwx-sync,
then immediately reset HEAD back so the user's branch tip is unchanged
during exec. On pull, we diff against refs/rwx-sync to capture only
exec-produced changes, which apply cleanly regardless of unpushed
commits.

This also simplifies pullChangesFromSandbox — the local-changed-files
merge and per-file reset logic is no longer needed since the diff now
inherently contains only exec changes, and git apply is atomic.
@robinaugh robinaugh force-pushed the fix/sandbox-exec-unpushed-commits branch from 693f95d to dcdbd9e Compare February 19, 2026 19:41
When there are no local changes to sync, syncChangesToSandbox returned
early without creating refs/rwx-sync. This meant pull would either fail
(first exec) or diff against a stale ref (subsequent execs). Point the
ref at the current sandbox HEAD so pull always has a valid baseline.
Split the fire-and-forget compound shell command into two checked
steps so that partial failures (e.g. reset failing after update-ref)
are detected and reported instead of leaving the sandbox in a bad state.
When there are no local changes, sync creates refs/rwx-sync by pointing
it at HEAD. The error from this update-ref was previously silently
discarded, which could leave pull without a valid baseline and produce
a confusing error. Surface the failure so the root cause is clear.
…ailure

Previously, refs/rwx-sync was deleted at the start of sync before the
patch was applied. If sync failed between the deletion and the snapshot
step, pull would have no baseline ref to diff against. Move the deletion
into the snapshot command chain so the previous ref remains valid until
the new snapshot is ready.
@robinaugh robinaugh marked this pull request as ready for review February 19, 2026 20:46
@robinaugh robinaugh requested a review from jmsanders February 19, 2026 20:46
@robinaugh robinaugh merged commit 7a49d06 into main Feb 20, 2026
1 check passed
@robinaugh robinaugh deleted the fix/sandbox-exec-unpushed-commits branch February 20, 2026 14:15
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.

3 participants