fix(runtime): validate sandbox paths and preserve live controller leases (#13432)

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents can run in remote sandboxes.
> - Connection checks must use the selected execution target.
> - Recovery must respect the controller that owns an active run.
> - A host path or PID does not describe a remote sandbox.
> - This pull request checks sandbox paths on the target and preserves
live controller leases.

## Linked Issues or Issue Description

**What happened?**

Selecting an AI account for a sandbox agent could fail because the
Claude ACP environment check tried to create the sandbox directory on
the Paperclip host. The recovery sweep could also interrupt a sandbox
run while its controller lease was still valid. It treated a PID absent
from the local host as proof that the run had stopped.

**Expected behavior**

ACP checks directories on the selected execution target. Recovery leaves
a run with a live controller lease alone. Its final database write
rejects a stale snapshot after renewal, a claim, a controller change, or
a runtime change.

**Steps to reproduce**

1. Test a Claude ACP sandbox agent with a directory that cannot be
created on the host. The check fails before this fix.
2. Give a running sandbox task a valid controller lease and a PID absent
from the host. Run the stale-lock sweep without an in-memory handle. The
sweep interrupts the run before this fix.
3. Renew or replace the controller between the sweep's read and write.
The old snapshot must not end that controller's run.

**Paperclip version or commit**

Rebased onto `origin/master` at
`0e9b24c8216171c26c8358ba387d77858e02c7a9`. All seven regression cases
still fail against this base.

Refs #13438, which supplies the managed hiring and task-connection
behavior, and #13433, which preserves non-assignee subscription comment
wakes. This PR preserves both upstream changes and addresses the two
remaining sandbox failures.

## What Changed

- Resolve and create Claude ACP test directories through the
execution-target helpers.
- Preserve active legacy controller leases during stale-lock recovery,
including finalization after a task becomes terminal.
- Recheck the controller, lease, runtime mode, and native ownership in
the terminal database write.
- Add two sandbox-directory cases and five database-backed
controller-lease cases.
- Document the target used for ACP directory checks.

## Verification

- Red: all seven new cases fail against `0e9b24c82` without these two
implementation changes.
- Before the final upstream sync, 192 focused tests passed. Full `pnpm
test:run` coverage completed using the repository's group/shard runner:
all general server and workspace groups passed, and all 147 serialized
server suites passed across the initial run and isolated continuations.
Five cold-import timeout suites passed with
`--experimental.fsModuleCache`; their assertions and deadlines were
unchanged.
- The hiring routes, default-selection service, and upstream hiring
tests match `origin/master` exactly. The two remaining fixes are
unchanged by the final rebase.
- On final head `bd28d5cefbdf7084acc3759199cd9661907e7a26`, all 372
focused tests pass across 16 suites covering both upstream changes and
these fixes. Two timeouts in the combined run (database setup and an
existing ACP case) pass in isolated reruns with fresh test homes and
temporary directories. `pnpm -r typecheck` and `pnpm build` also pass on
this head.
- All 32 active checks pass on final head `bd28d5cef`, including the
full test matrix and browser shards, in [CI run
34904204849](https://github.com/paperclipai/paperclip/actions/runs/34904204849).
Two Storybook checks are skipped by path filters.
- Greptile reviewed final head `bd28d5cef` at 5/5 with no findings or
unresolved review threads.

## Risks

- A failed remote directory check still blocks connection adoption.
- A live controller retains finalization authority after its task
becomes terminal. Cleanup waits for ownership to expire and must pass
the final ownership check.
- No schema or credential-storage changes.

## Model Used

OpenAI GPT-6 in Codex, with reasoning, repository inspection, code
execution, and API tools. The exact serving model ID and context-window
size are not exposed in this session.

## 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>
This commit is contained in:
DottaandPaperclip authored and GitHub committed 2026-09-14 22:13:57 -05:00
1 parent 8f1905d34d
commit a2e7ffdc34
5 files changed
+105 -3

No files matched your search

+3
View File
@@ -93,6 +93,9 @@ subsequent agent creation fails or is cancelled.
## Runtime isolation
`prepareManagedAiRuntime` is shared by runs, environment tests, and adoption.
Claude ACP validates working directories on the selected execution target. A
sandbox directory does not need to exist on the Paperclip server. When the agent
has no configured directory, the test uses the remote target's working directory.
It checks responsible identity, membership, compatibility, connection health,
human audience and agent installation before reading credentials.
Missing credentials produce an actionable configuration failure; responsible-user