Files
PaperClipAI/doc/plans
DottaandPaperclip 253bf071f0 fix(workspaces): preserve resolved pending merges in snapshots (#19429)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task workspaces must survive replacement of the web server.
> - Workspace snapshots therefore preserve both files and portable Git
state.
> - A resolved merge can still await its merge commit.
> - The archive rejected this state, so an existing workspace could not
migrate.
> - This pull request saves and checks the complete supported merge
state.
> - The benefit is that migration preserves the user's choice to
continue or abort the merge.

## Linked Issues or Issue Description

**What happened?**

A legacy workspace contained a resolved merge with `MERGE_HEAD`,
`MERGE_MODE`, `MERGE_MSG`, `ORIG_HEAD`, and `AUTO_MERGE`. Its index had
no unresolved entries. The snapshot owner refused the operation. This
kept the original safe but blocked migration.

**Expected behavior**

Save this supported state without changing the source. Restore it
without the original repository, borrowed object store, or linked
worktree. Retain the merge parents, selected index, later edits, and
Git's normal safety checks.

**Steps to reproduce**

1. Merge two branches that conflict.
2. Resolve and stage the conflict. Leave the merge uncommitted.
3. Capture the workspace. The base implementation rejects the merge
marker.

Related prior work: #19310 preserves an inactive rebase bookmark. No
duplicate open merge-preservation PR was found. This is a workspace
preservation fix, not a new roadmap feature.

## What Changed

- Admit only resolved pending merges with valid, bounded metadata and
available objects.
- Retain and verify the merge mode, message, parents, original head,
automatic merge tree, and index.
- Verify copied metadata and object closure before publication. Keep the
before/after source checks.
- Keep unresolved conflicts, autostash, rerere, mixed operations,
malformed state, and unsafe links blocked.
- Test real ordinary, linked, and borrowed repositories through local
and serialized capture. Delete all original sources before continuing or
aborting the restored merge.
- Document the supported state and the remaining refusal cases.

## Verification

- Six new continuation cases fail against the unchanged base at the
pending-operation guard.
- The first candidate restored and continued the merges, but six abort
assertions failed. The fixture rewrote the worktree without updating
Git's index cache. It now first verifies that abort protects later
edits, uses normal `git restore` to discard those fixture edits, then
aborts. No archive assertion was removed.
- The final archive and environment suites pass all 98 tests at
`3c87d13d1b`, including linked-metadata protections and pending merges
in ordinary, linked, borrowed, shallow, partial, and SHA-256
repositories. All 12 local/serialized continuation cases pass after
source removal.
- Full repository build and typecheck pass at `1544cc4a90`. The build
first found a nullability error; an explicit rejection return fixed it.
- The first full local test attempt stopped before tests ran because
omitted package postinstall steps left PostgreSQL library links absent.
Direct `initdb --version` reproduced the missing-library failure.
Restoring the package links made that probe pass; the full test rerun is
active.
- The initial typecheck also found missing excluded-plugin SDK links
after the same install. Running the repository postinstall link helper
corrected this, and the full typecheck now passes.
- All current-head CI gates pass at `3c87d13d1b`: 54 success, 2 skipped,
1 neutral. Fresh Greptile is 5/5 and no review threads remain open.
- Review requested shallow and SHA-256 coverage. The current commit adds
both plus partial-clone coverage; all 98 archive tests and the full
server typecheck pass.
- All six local chat shards pass. The monolithic local general-suite run
reports one viewer-permission test failure and remains active. That
exact test passes alone, and its full 505-test file also passes alone.
The original failure cause is unresolved; this is not a full local-suite
PASS. The complete current-head CI suite is green.

## Risks

- This widens capture eligibility only for the checked resolved-merge
state. No migration commits or aborts the source operation.
- A missing object or changed metadata still blocks publication and
retains the source.
- Unresolved merges and other operation formats remain unsupported.
Their preservation guard is unchanged.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, repository tools, and code
execution. The runtime does not expose a more specific serving model ID
or context-window size.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used with the available version and
capability details
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have described the issue in-PR following the relevant issue
template
- [x] I have not referenced internal or instance-local Paperclip issues
or links
- [x] My branch name describes the change and contains no internal task
id
- [x] I have run the affected tests locally and they pass; full-suite
limitations are recorded above
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented the risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-06 04:20:32 -06:00
..