## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work.
> - A control-plane replacement must restore saved work without its old
disk.
> - Online workspace migration saves a guarded physical source to object
storage.
> - Some older task directories have shared workspace mode in their
saved metadata.
> - Their physical paths still identify one company and one source
issue.
> - The selected-source check rejects that mode even though the alias
check accepts it.
> - This pull request admits the old mode under the same physical-source
and writer guards.
## Linked Issues or Issue Description
Refs #18835 and #19873 for workspace preservation and source-fence
ownership. Related #11914 addresses mode selection during workspace
reuse. This branch also carries the one-line API discovery correction
shared with #20370. The search found no duplicate fix for this migration
admission path.
**What happened?**
Online migration rejects an ordinary local task directory when its row
has legacy `shared_workspace` mode. The directory can have the exact
managed company and source-issue path, with no repository or branch. The
selected-source check requires `isolated_workspace`, while its existing
alias check permits both modes.
**Expected behavior**
Admit either saved mode only when the same physical path, company,
source issue, aliases, lifecycle state and writer checks prove a safe
source. Preserve the saved mode. Do not require global maintenance.
**Steps to reproduce**
1. Create a `local_fs`, `project_primary` workspace with
`shared_workspace` mode, a source issue, and a null provider reference.
2. Put its files at the managed
`isolated-workspaces/<company>/<sourceIssue>` path.
3. Inventory online migration. The previous code reports that the source
is unproven.
4. With this fix, migrate through the existing owner and restore the
saved archive.
**Paperclip version or commit**
Base: `0e3fdebea8257bdff11573081c76b306f12db230` from freshly fetched
master.
**Deployment mode**
Online local-filesystem workspace migration with durable snapshots.
## What Changed
- Permit `shared_workspace` beside `isolated_workspace` in the existing
physical task-source admission check. All other checks remain in their
existing owners.
- Extend the existing migration and archive-restore fixture with the
legacy shared-mode task path and null provider reference.
- Use the truthful task-case lookup summary “Find the cases for a task”.
This restores its existing first-page discovery contract without
changing search scores, pagination or tests.
## Verification
- Canonical worktree preflight passed in 26.2 seconds with cached Node
24 and pnpm 9.15.4. The existing SDK dependency preparation completed
before the server tests. An initial direct test attempt could not
resolve the unbuilt SDK and executed no test cases.
- **RED:** Against the previous admission rule, the original
project-path fixture passed and the new task-path variant failed with
`eligible: false`: 1 passed, 1 failed, 86 skipped, 13.58 seconds.
- **GREEN:** All **88 tests** in
`server/src/services/remote-workspace-online-source.test.ts` passed in
**35.47 seconds** after the one-line fix. This includes migration,
archive restore, foreign and mismatched source aliases, source-issue
fencing, active execution, lifecycle, and publication-race controls.
- Command: `node node_modules/vitest/vitest.mjs run
server/src/services/remote-workspace-online-source.test.ts
--maxWorkers=1 --fsModuleCache` under Node 24.
- `git diff --check` passed. Tests used disposable PostgreSQL and a
local object-storage provider. Hosted migration acceptance remains
separate.
- Required CI [attempt
1](https://github.com/paperclipai/paperclip/actions/runs/42704874763/attempts/1)
failed on previous head `c69ea90bc0f2f18707336004598e2429f590790d`.
[Server shard
12](https://github.com/paperclipai/paperclip/actions/runs/42704874763/job/129459250886)
failed `case-history-api-discovery.test.ts:14`: the first five results
for `case for task` did not include `GET /api/issues/{issueId}/cases`.
This test source is unchanged in this PR. The dependent final verify
gate failed. The attempt remains a nonpass; no retry has been requested.
- The shared API discovery diagnosis reproduced the existing lookup
route at rank six. The summary omitted a query term. The correction from
#20370 changes only that truthful summary. On final head
`0d645370545130a8a835da8c1a77030562b29049`, the unchanged three-case API
discovery regression passed in **10.64 seconds**. The 88-case workspace
proof above remains valid for its unchanged source and fixture inputs;
it was not rerun.
- Final head `0d645370545130a8a835da8c1a77030562b29049`: [fresh required
CI](https://github.com/paperclipai/paperclip/actions/runs/42707521663)
**passed** at 22:13:53 UTC on November 9. All 51 workflow jobs are
accounted for: 49 successful and 2 skipped. The [final verify
aggregate](https://github.com/paperclipai/paperclip/actions/runs/42707521663/job/129476327386)
passed. The exact-head rollup and classic Snyk status are successful,
with no failed or pending checks.
- Fresh Greptile review is **5/5** for this final head, with no open
inline threads. Ponytail's **5/5** review covers previous head
`c69ea90bc0f2f18707336004598e2429f590790d`; it is historical evidence
for the unchanged workspace patch, not a final-head review. The old
failed CI attempt remains recorded above.
## Risks
- This admits a previously refused saved metadata shape. The physical
directory must still match the company and original source issue. The
alias check still rejects a different issue on that task path.
- Source, lifecycle, task and active-run fences are unchanged. No live
metadata is rewritten to gain admission. Saved workspace modes and
snapshot formats carry forward; no schema or command changes are needed.
## Model Used
OpenAI Codex, GPT-6.1 Sol (`gpt-6.1-sol`), with reasoning, repository
tools and code execution. Context-window size is not exposed by the
runtime.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with 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 either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [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 any 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
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>