From 11af59c39a1e6046fe9ee8fce6737c710c71196b Mon Sep 17 00:00:00 2001 From: Byntham <135178921+Byntham@users.noreply.github.com> Date: Tue, 10 Nov 2026 05:13:27 -0800 Subject: [PATCH 1/2] fix(server): idle compaction no longer runs after a delegated result arrives The idle-compaction service read the thread as idle, then a delegated task's result landed around its /compact. The orchestrator queued the compaction behind that turn, or started it ahead of the result, so it ran mid-task on a cache the agent was about to refresh. The orchestrator now drops a beforeCacheExpires compaction when a run is queued or active, or a delegated result is waiting to be sent. Co-Authored-By: Claude Opus 5.5 --- .../src/orchestration-v2/Orchestrator.ts | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/apps/server/src/orchestration-v2/Orchestrator.ts b/apps/server/src/orchestration-v2/Orchestrator.ts index e95fb6ec4865..7de1c8a55153 100644 --- a/apps/server/src/orchestration-v2/Orchestrator.ts +++ b/apps/server/src/orchestration-v2/Orchestrator.ts @@ -5949,6 +5949,33 @@ const makeOrchestrator = Effect.fn("orchestrationV2.Orchestrator.layer")(functio } } + // The service checked idleness before this command; a run or a delegated result that landed + // since makes the thread busy, and that turn refreshes the cache anyway. + if ( + command.idleCompaction === "beforeCacheExpires" && + projection.runs.some( + (run) => + run.status === "queued" || + isActiveRun(run) || + (run.delegatedCompletion?.disposition === "open" && + run.delegatedCompletion.delivery !== null && + !projection.messages.some( + (message) => message.id === run.delegatedCompletion?.delivery?.messageId, + )), + ) + ) { + yield* emit( + events, + command, + )({ + type: "thread.metadata-updated", + threadId: command.threadId, + occurredAt: yield* DateTime.now, + payload: projection.thread, + }); + return; + } + if (projection.thread.lastVisitedAt === null && !isNativeMaintenanceCommand(command)) { const now = yield* DateTime.now; // Null keeps imported history read. The first fresh dispatch establishes From 8b440bf3829e0f409253967445a7c73f54a3e1c6 Mon Sep 17 00:00:00 2001 From: Byntham <135178921+Byntham@users.noreply.github.com> Date: Tue, 10 Nov 2026 05:53:15 -0800 Subject: [PATCH 2/2] test(server): idle compaction waits for a delegated result in either order Co-Authored-By: Claude Opus 5.5 --- .../DelegatedCompletionDelivery.test.ts | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/apps/server/src/orchestration-v2/DelegatedCompletionDelivery.test.ts b/apps/server/src/orchestration-v2/DelegatedCompletionDelivery.test.ts index 7bc7ef37d42d..ecc53758ee90 100644 --- a/apps/server/src/orchestration-v2/DelegatedCompletionDelivery.test.ts +++ b/apps/server/src/orchestration-v2/DelegatedCompletionDelivery.test.ts @@ -754,6 +754,67 @@ it.layer(layerTest)("delegated completion delivery repairs", (it) => { }), ); + it.effect.each([ + { name: "no result is waiting", delivery: "none", compacts: true }, + { name: "a result is waiting to be sent", delivery: "pending", compacts: false }, + { name: "a result was just sent", delivery: "sent", compacts: false }, + ] as const)("compacts before the cache expires only when $name", ({ delivery, compacts }) => + Effect.gen(function* () { + const orchestrator = yield* Orchestrator.OrchestratorV2; + const now = yield* DateTime.now; + const threadId = ThreadId.make(`thread:idle-compaction-delivery-${delivery}`); + const runId = RunId.make(`run:idle-compaction-delivery-${delivery}`); + const taskId = NodeId.make(`node:idle-compaction-delivery-${delivery}-task`); + + yield* seedParentWithTerminalTask({ + threadId, + projectId: ProjectId.make(`project:idle-compaction-delivery-${delivery}`), + runId, + rootNodeId: NodeId.make(`node:idle-compaction-delivery-${delivery}-root`), + taskId, + deliveryState: delivery === "none" ? "delivered" : "claimed", + completionWake: "always", + parentRunStatus: "completed", + ...(delivery === "none" ? {} : { deliveryTaskIds: [taskId] }), + now, + }); + if (delivery === "sent") { + yield* orchestrator.dispatch({ + type: "message.dispatch", + commandId: CommandId.make(`command:idle-compaction-delivery-${delivery}`), + threadId, + messageId: MessageId.make(`message:delegated-delivery:${threadId}`), + text: `Delegated task ${taskId} reached a terminal state.`, + attachments: [], + dispatchMode: { type: "queue_after_active" }, + createdBy: "agent", + creationSource: "server", + delegatedCompletion: { parentRunId: runId, generation: 1, taskIds: [taskId] }, + }); + } + + const compactionId = MessageId.make(`idle-compact:${threadId}:${runId}`); + yield* orchestrator.dispatch({ + type: "message.dispatch", + commandId: CommandId.make(`server:idle-compact:${threadId}:${runId}`), + threadId, + messageId: compactionId, + text: "/compact", + attachments: [], + createdBy: "agent", + creationSource: "server", + idleCompaction: "beforeCacheExpires", + dispatchMode: { type: "start_immediately" }, + }); + + const projection = yield* orchestrator.getThreadProjection(threadId); + assert.equal( + projection.messages.some((message) => message.id === compactionId), + compacts, + ); + }), + ); + it.effect.each([ { name: "oversized UTF-8 result",