Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions plugins/genie/orca-entrypoint.min.js

Large diffs are not rendered by default.

13 changes: 9 additions & 4 deletions plugins/genie/orca-real-runtime-smoke.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,11 @@ runRealSmoke(
return;
}

// A terminal that is not bound to a Run reads back `run: null`; the smoke
// must not dereference it — there is simply nothing to restore afterwards.
const prior = await runtime.execute({ operation: 'run-current' });
const priorRunId = String(object(object(prior.result).run).id);
const priorRun = object(prior.result).run;
const priorRunId = priorRun === null || priorRun === undefined ? null : String(object(priorRun).id);
const suffix = randomUUID().replaceAll('-', '').slice(0, 12);
let disposableTaskId: string | undefined;

Expand All @@ -94,12 +97,14 @@ runRealSmoke(
tasks.some((task) => object(task).id === disposableTaskId && object(task).status === 'completed'),
).toBe(true);
} finally {
await runtime.execute({ operation: 'run-use', id: priorRunId });
if (priorRunId !== null) await runtime.execute({ operation: 'run-use', id: priorRunId });
}

expect(disposableTaskId).toBeDefined();
const restored = await runtime.execute({ operation: 'run-current' });
expect(object(object(restored.result).run).id).toBe(priorRunId);
if (priorRunId !== null) {
const restored = await runtime.execute({ operation: 'run-current' });
expect(object(object(restored.result).run).id).toBe(priorRunId);
}
expect(await snapshotLocalLifecycle()).toEqual(before);
},
30_000,
Expand Down
39 changes: 39 additions & 0 deletions src/lib/orca-orchestration-adapter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,45 @@ describe('runtime and executor boundary', () => {
]);
});

test('decodes the real Orca 1.4.192 run-list page (unbound coordinators, nextCursor null)', async () => {
// Captured from `orca orchestration run-list --json --limit 5` against a live
// 1.4.192 runtime on 2026-08-30: runs whose coordinator terminal is gone list
// with null coordinator fields, and the page carries `nextCursor`, not `cursor`.
const realRun = (id: string, bound: boolean) => ({
id,
objective: 'Genie A3 disposable smoke 6b2dacf88b03',
home_database: 'this_database',
coordinator_handle: bound ? 'term_9479beab-e0e3-4ccd-8f4e-3a6374c293c1' : null,
coordinator_pane_key: bound ? 'e1dd5d83-902f-4170-a054-360834ff6bc2:b7b71158-894b-4235-a996-775f998c12d6' : null,
consumer_generation: 2,
legacy: 0,
created_at: '2026-08-29T20:38:02Z',
updated_at: '2026-08-29T20:38:07Z',
});
const page = { runs: [realRun('run_ca7f3f1c6a2d', false), realRun('run_4f9c0796c24a', true)], nextCursor: null };
const adapter = __orcaAdapterTestOnly.createAdapter({
executor: async () => ({
exitCode: 0,
stdout: JSON.stringify({ id: 'req_1', ok: true, result: page, _meta: { runtimeId: 'rt_1' } }),
stderr: '',
}),
});
const response = await adapter.execute({ operation: 'run-list', limit: 5 });
expect((response.result as { runs: unknown[] }).runs).toHaveLength(2);
});

test('decodes an unbound terminal run-current (run: null) as a valid empty binding', async () => {
const adapter = __orcaAdapterTestOnly.createAdapter({
executor: async () => ({
exitCode: 0,
stdout: JSON.stringify({ id: 'req_2', ok: true, result: { run: null }, _meta: { runtimeId: 'rt_1' } }),
stderr: '',
}),
});
const response = await adapter.execute({ operation: 'run-current' });
expect((response.result as { run: unknown }).run).toBeNull();
});

test('requires one strict success envelope', async () => {
for (const stdout of ['', '{}', '{"id":"x","ok":true}', '{"id":"x","ok":true,"result":{},"extra":1}', '{}\n{}']) {
const adapter = __orcaAdapterTestOnly.createAdapter({
Expand Down
14 changes: 11 additions & 3 deletions src/lib/orca-orchestration-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -529,8 +529,10 @@ const publicRunEntity = receipt({
id,
objective: longText,
home_database: z.string().min(1).max(128),
coordinator_handle: terminalId,
coordinator_pane_key: z.string().min(1).max(256),
// A Run whose coordinator terminal has gone away (or that was never bound
// from a terminal) lists with null coordinator fields on real Orca 1.4.192.
coordinator_handle: terminalId.nullable(),
coordinator_pane_key: z.string().min(1).max(256).nullable(),
Comment on lines +534 to +535

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep nullable coordinator fields scoped to run-list

When a run-use receipt and its subsequent run-current response both use the public shape with the requested run ID but null coordinator fields, this shared schema now accepts both responses. The readback at readbackPlan compares only run IDs, while runtime attestation checks only the legacy coordinatorTerminalHandle field, so the adapter can report a successful run-use even though the terminal binding was not established. Use a separate nullable entity for run-list (and { run: null } for the unbound current case), while retaining required coordinator fields for bound mutation receipts and readbacks.

Useful? React with 👍 / 👎.

consumer_generation: z.number().int().positive(),
legacy: z.number().int().min(0).max(1),
created_at: z.string().min(1).max(64),
Expand Down Expand Up @@ -600,7 +602,13 @@ const responseSchemas: Readonly<Record<OrcaOrchestrationVerb, z.ZodTypeAny>> = {
receipt({ runId: id }),
receipt({ run: publicRunEntity, binding: bindingMetadata, mutation: mutationMetadata }),
]),
'run-list': receipt({ runs: z.array(runEntity).max(100), cursor: cursor.optional() }),
// Real Orca 1.4.192 pages with `nextCursor` (null on the last page); the
// legacy shape used `cursor`. Both are accepted, neither is required.
'run-list': receipt({
runs: z.array(z.union([runEntity, publicRunEntity])).max(100),
cursor: cursor.optional(),
nextCursor: cursor.nullable().optional(),
}),
'run-show': receipt({ run: z.union([runEntity, publicRunEntity]) }),
'run-current': z.union([
receipt({ run: runEntity, coordinatorTerminalHandle: terminalId }),
Expand Down
Loading