mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-31 14:16:39 +01:00
Reduce restored workspace overhead and trace cache publication (#18240)
## Thinking Path > - Paperclip runs agents in isolated workspaces. > - A native sandbox turn must restore its workspace before the provider starts. > - Restored Git metadata can cause expensive work in the provider's first snapshot. > - Cache replay also hashes the same archives twice, and workspace helpers open sessions that do not need output. > - This pull request removes that repeated work and refreshes the restored index before OpenCode starts. > - It also adds cache-publication timings so the next measurement can separate quota checks, lock waiting, and archive IO. ## Linked Issues or Issue Description **What existing behavior does this improve?** Native sandbox workspace preparation and copyback. **Current behavior** Cache replay validates shared archives, copies them, and validates them again. Exit-status-only helpers use persistent sessions. A restored checkout can make OpenCode's first snapshot recheck much of the repository. Cache publication has an unexplained interval after archive verification. **Proposed behavior** Validate the private archive copy that staging will consume. Use the existing one-shot command path for helpers that only need an exit status. Refresh the Git index after workspace transfer for a new native OpenCode sandbox. Keep the refresh inside the awaited inbound barrier and use the existing command timeout. Add nested publication spans. **Reason and benefit** Two matched local component pairs reduced preparation plus provider time from 8.563/8.553 seconds to 7.313/7.511 seconds, including the refresh cost. Two alternating remote copyback pairs reduced the median from 9.110 to 7.943 seconds. These are component results. They do not establish an end-to-end hosted improvement. Related: #18181 and the earlier closed #18195. This implementation uses the existing fully awaited transfer boundary. It does not use an optional preparation deadline. ## What Changed - Materialize cache hits into caller-owned staging and validate those exact bytes once. Remove incomplete copies on failure. - Select the existing one-shot path for exit-status-only run and removal helpers. Output-reading helpers keep their existing behavior. - Refresh restored Git stat metadata before OpenCode starts. Enable this only for newly acquired native OpenCode host-current workspaces. Skip recovery and retained sandboxes. Keep dirty files unstaged, accept Git's dirty-worktree status, and propagate real command errors. - Trace cache capacity checks, eviction, the body after lock acquisition, archive copy, sync, and hashing. Keep the operator endpoint gate and bounded phase names. ## Verification - On the rebased branch: 202 focused tests pass: 152 workspace seed/cache/runtime tests, 27 managed command tests, and 23 native workspace/tracing tests. Adapter TypeScript build and server typecheck pass. - Tests cover corrupted copies, cache changes after private materialization, dirty working trees, quoted paths, recovery, the awaited refresh barrier, real command failure, and company-lock contention. - A real-filesystem probe through the server phase mapper verified parentage and endpoint-off behavior. A controlled lock wait stayed outside the locked-publication span. No external export was used. - A full local Core/Daytona replay on the pre-rebase implementation saved its synthetic reply. It retained the pinned large public workspace, all 209 skill files, positive Git context, and 66 tool schemas. Both model calls stayed on sandbox loopback. Index refresh took 0.644 seconds and the first provider snapshot took 0.499 seconds. The run took 162.004 seconds, including large laptop uploads; it is not a hosted acceptance result or a matched end-to-end comparison. The failed installer attempt remains recorded separately. Normal cleanup removed all owned sandboxes. - The current head passed 53 CI checks, with two optional skips. Greptile is 5/5 on the exact head, with no open review threads. No deployment or hosted latency claim is included. ## Risks - Index refresh adds one awaited command. It uses the existing timeout. A real Git failure stops preparation. - Cache hits need temporary disk space for a private copy. Existing corruption fallback and per-run recovery archives remain. - One-shot command transport must preserve exit status and timeout behavior across providers. The agent's native session and output-reading helpers are unchanged. - Local component gains are small relative to the remaining hosted latency. Batch the fixes with the diagnostic spans; measure the actual deployed path before claiming success. ## Model Used OpenAI Codex, GPT-6 family, with reasoning, tool use, and code execution. The session does not expose the exact model SKU 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 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:
1 parent
6a67471644
commit
2aa3ea47e3
11 files changed
+252
-27
No files matched your search
@@ -813,6 +813,7 @@ async function prepareRuntime(input: {
|
||||
durableSeed?: WorkspaceDurableSeedPaths;
|
||||
seedCacheDirectory?: string;
|
||||
seedCacheCompanyDirectory?: string;
|
||||
workspaceGitIndexRefresh?: boolean;
|
||||
onPhase?: RuntimeSpanRunner;
|
||||
onCheckpoint?: (metrics: WorkspaceCheckpointMetrics) => Promise<void>;
|
||||
}): Promise<PreparedAdapterExecutionTargetRuntime> {
|
||||
@@ -829,6 +830,7 @@ async function prepareRuntime(input: {
|
||||
workspaceRemoteDir: input.target.remoteCwd,
|
||||
workspaceInboundMode: input.mode,
|
||||
workspaceSnapshotIsolation: "worker",
|
||||
workspaceGitIndexRefresh: input.workspaceGitIndexRefresh,
|
||||
workspaceDurableSeed: input.durableSeed,
|
||||
workspaceBaseline: input.baseline,
|
||||
workspaceGitSnapshot: input.gitSnapshot,
|
||||
@@ -901,6 +903,7 @@ export async function prepareNativeWorkspaceSync(input: {
|
||||
restartRecovery?: NativeRestartRecoveryClaim;
|
||||
sameRunRecovery?: boolean;
|
||||
resourceDisposition?: NativeWorkspaceResourceDisposition;
|
||||
workspaceGitIndexRefresh?: boolean;
|
||||
onPhase?: RuntimeSpanRunner;
|
||||
onCheckpoint?: (metrics: WorkspaceCheckpointMetrics) => Promise<void>;
|
||||
onEvent?: (event: AdapterRuntimeEvent) => Promise<void>;
|
||||
@@ -1017,6 +1020,9 @@ export async function prepareNativeWorkspaceSync(input: {
|
||||
mode,
|
||||
seedCacheCompanyDirectory,
|
||||
seedCacheDirectory,
|
||||
workspaceGitIndexRefresh: input.workspaceGitIndexRefresh === true
|
||||
&& acquisition === "created" && mode === "host_current"
|
||||
&& !input.restartRecovery && !input.sameRunRecovery,
|
||||
durableSeed: {
|
||||
workspaceArchivePath: seedPaths.workspaceArchivePath,
|
||||
gitArchivePath: seedPaths.gitArchivePath,
|
||||
|
||||
Reference in new issue
Block a user