fix(grok): distinguish instruction collection from workspace restore

Collect in the execution boundary before the separate restoration callback. A collection rejection still restores and cleans up, but retains its own error instead of requesting workspace recovery.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-09-27 19:35:00 -05:00
1 parent 185238b172
commit 85654d4c5c
2 files changed
+37 -7

No files matched your search

@@ -847,6 +847,33 @@ describe("grok_local execute", () => {
expect(await pathExists(stagedDir)).toBe(false);
});
it("keeps collection failure separate from a successful workspace restore", async () => {
delete process.env.XAI_API_KEY;
mocks.state.isRemote = true;
await seedHostGrokAuth("{}");
const collectionError = new Error("instruction collection failed");
const order: string[] = [];
let stagedDir = "";
runProcessMock.mockImplementation(async (_run, _target, _command, _args, options) => {
options.onProcessStopped();
return makeSuccessfulRunResult();
});
prepareRuntimeMock.mockImplementationOnce(async (input: { assets?: Array<{ localDir: string }> }) => {
stagedDir = input.assets?.[0]?.localDir ?? "";
return {
workspaceRemoteDir: "/remote/workspace",
assetDirs: { home: "/remote/workspace/.paperclip-runtime/grok/home" },
restoreWorkspace: async () => { order.push("restore"); },
};
});
const ctx = await makeCtx("run-collection-reject", await makeTempRoot());
ctx.onProviderStopped = async () => { order.push("collect"); throw collectionError; };
await expect(execute(ctx)).rejects.toBe(collectionError);
expect(order).toEqual(["collect", "restore"]);
expect(stagedDir).not.toBe("");
expect(await pathExists(stagedDir)).toBe(false);
});
it.each(["completed", "failed", "timed_out"])("preserves %s output and removes the staged home when restore fails", async (state) => {
delete process.env.XAI_API_KEY;
mocks.state.isRemote = true;
@@ -728,13 +728,16 @@ async function executeTurn(ctx: AdapterExecutionContext): Promise<AdapterExecuti
};
try {
return await withWorkspaceRestore(executeTurn, async () => {
try {
await providerStop.collectBeforeRestore();
} finally {
await restoreRemoteWorkspace?.();
}
});
return await withWorkspaceRestore(
async () => {
try {
return await executeTurn();
} finally {
await providerStop.collectBeforeRestore();
}
},
async () => { await restoreRemoteWorkspace?.(); },
);
} finally {
// Cleanup runs after settlement on both success and failure.
if (stagedGrokHomeDir) {