perf(recovery): read workspace contract without native launch prompts (#17621)

Project native input to the complete schema, binding, provider, and workspace evidence used by execution-blocker checks. Preserve absent and malformed fields and retain all saved inputs and recovery holds.

149 focused tests and 123 workspace-recovery tests pass. Server typecheck, build, all 55 CI checks, and exact-head Apex 5/5 pass.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Devin FoleyandPaperclip authored and GitHub committed 2026-10-25 09:53:27 -07:00
1 parent e302f2098f
commit b65897f9bf
3 files changed
+47 -4

No files matched your search

+6 -3
View File
@@ -68,9 +68,12 @@ update, including an edit outside the projection, defers repair to a fresh sweep
Execution-blocker reads select process, lifecycle, and task-binding fields rather
than full execution rows. Context retains typed task and pre-dispatch evidence;
Runner profiles retain the adapter type and complete native execution input and
workspace-sync receipts. Full result evidence stays available to the existing
retry and workspace checks. Stored context, profiles, and output are unchanged.
Runner profiles retain the adapter type, native input schema, binding, provider,
workspace-access evidence, and complete workspace-sync receipts. Native task and
runtime prompt payloads are not needed for these checks. Missing fields and
malformed input values retain their original shape. Full result evidence stays
available to the existing retry and workspace checks. Stored context, profiles,
and output are unchanged.
Committed native finalization reads run identity and ownership state before it
claims the coordinator. It loads complete saved input only when finalization
@@ -100,7 +100,9 @@ describe.skipIf(!support.supported)("execution blocker PostgreSQL read projectio
});
const input = { schema: "paperclip.native-execution-input.v6",
binding: { runId: f.run.id, companyId: f.companyId, agentId: f.agentId, issueId: f.issueId },
provider: { kind: "grok_bot" }, workspace: { access: "none", ...(hasCwd ? { cwd: null } : {}) } };
provider: { kind: "grok_bot" }, workspace: { access: "none", ...(hasCwd ? { cwd: null } : {}) },
task: { description: randomBytes(128 * 1024).toString("base64") },
runtimeContext: { instructions: randomBytes(128 * 1024).toString("base64") } };
await db.update(heartbeatRuns).set({ nativeIssueId: f.issueId,
runnerProfileJson: { ...f.run.runnerProfileJson, nativeExecutionInput: input } }).where(eq(heartbeatRuns.id, f.run.id));
expect(await compare(f)).toMatchObject({ workspaceRepairRequired: !hasCwd, canRetry: false });
@@ -108,6 +110,39 @@ describe.skipIf(!support.supported)("execution blocker PostgreSQL read projectio
expect(stored.runnerProfileJson?.nativeExecutionInput).toEqual(input);
});
it.each(["run", "company", "agent", "issue", "provider", "schema", "access", "workspace", "binding", "missing_binding",
"null_input", "array_input", "scalar_input", "number_input"])(
"does not relax native workspace recovery for invalid input (%s)", async kind => {
const f = await fixture({ runtimeMode: "native", driverKind: "grok_bot_mcp" }, {
workspaceRestoreFailure: "restore_unsafe_archive",
workspaceRestoreRecovery: { schema: "paperclip.workspace-restore-recovery.v1", leaseIds: [] },
});
const input: Record<string, unknown> = {
schema: "paperclip.native-execution-input.v6",
binding: { runId: f.run.id, companyId: f.companyId, agentId: f.agentId, issueId: f.issueId },
provider: { kind: "grok_bot" }, workspace: { access: "none", cwd: null },
task: { description: randomBytes(128 * 1024).toString("base64") },
};
const binding = input.binding as Record<string, unknown>;
if (kind === "run") binding.runId = randomUUID();
if (kind === "company") binding.companyId = randomUUID();
if (kind === "agent") binding.agentId = randomUUID();
if (kind === "issue") binding.issueId = randomUUID();
if (kind === "provider") input.provider = { kind: "codex" };
if (kind === "schema") input.schema = "unsupported";
if (kind === "access") input.workspace = { cwd: null };
if (kind === "workspace") input.workspace = "none";
if (kind === "binding") input.binding = [];
if (kind === "missing_binding") delete input.binding;
const selectedInput = kind === "null_input" ? null : kind === "array_input" ? []
: kind === "scalar_input" ? "input" : kind === "number_input" ? 42 : input;
await db.update(heartbeatRuns).set({ nativeIssueId: f.issueId,
runnerProfileJson: { ...f.run.runnerProfileJson, nativeExecutionInput: selectedInput } }).where(eq(heartbeatRuns.id, f.run.id));
expect(await compare(f)).toMatchObject({ workspaceRepairRequired: true, canRetry: false });
expect((await db.select().from(heartbeatRuns).where(eq(heartbeatRuns.id, f.run.id)))[0].runnerProfileJson?.nativeExecutionInput).toEqual(selectedInput);
},
);
it.each([null, [], "scalar", 42, { issueId: 42, taskId: false }].map(context => ({ context })))("preserves decisions for malformed context $context", async ({ context }) => {
const f = await fixture({ contextSnapshot: context as Record<string, unknown> | null });
expect(await compare(f)).toMatchObject({ canRetry: true });
+5
View File
@@ -28,6 +28,11 @@ const blockerProfileColumn = sql<Record<string, unknown> | null>`case
when ${heartbeatRuns.runnerProfileJson} is null then null else (
select coalesce(jsonb_object_agg(field.key, case field.key
when 'adapterDispatch' then jsonb_build_object('adapterType', field.value->'adapterType')
when 'nativeExecutionInput' then case when jsonb_typeof(field.value) = 'object' then (
select coalesce(jsonb_object_agg(input_field.key, input_field.value), '{}'::jsonb)
from jsonb_each(field.value) as input_field(key, value)
where input_field.key in ('schema', 'binding', 'provider', 'workspace')
) else field.value end
else field.value end), '{}'::jsonb)
from jsonb_each(case when jsonb_typeof(${heartbeatRuns.runnerProfileJson}) = 'object'
then ${heartbeatRuns.runnerProfileJson} else '{}'::jsonb end) as field(key, value)