Human-triggered wakes claim before queued autonomous work

Wake runs stamp sourceSenderType into their secret scope, and the claim
query orders interactive-first: a wake born from an employee or board
message means a person is waiting at the keyboard, so it outranks any
autonomous backlog; within each lane FIFO holds. Non-chat runs carry no
stamp and stay in the autonomous lane. With wake expiry this closes the
live incident: the founder's CEO DM now claims on the next tick instead
of 13th in line. Red-green tested.
This commit is contained in:
ZacharyZhang-NY committed 2026-07-14 20:46:51 -04:00
1 parent 39aa292d09
commit aa4cfc056d
3 files changed
+120 -4

No files matched your search

+6 -2
View File
@@ -95,7 +95,7 @@ export class ChatAgentWakeService {
requiresFilesystem: false,
origin: "chat_wake",
});
const runId = this.createQueuedRun({ orgId: input.orgId, taskId, agent, workspace, messageId, threadId, now });
const runId = this.createQueuedRun({ orgId: input.orgId, taskId, agent, workspace, messageId, threadId, senderType: input.senderType, now });
this.recordPresence(agent.id, { command: "mention", args: "" }, now);
return { targetId: agent.id, taskId, runId };
}
@@ -118,7 +118,7 @@ export class ChatAgentWakeService {
requiresFilesystem: false,
origin: "chat_wake",
});
const runId = this.createQueuedRun({ orgId: input.orgId, taskId, agent, workspace, messageId, threadId, now });
const runId = this.createQueuedRun({ orgId: input.orgId, taskId, agent, workspace, messageId, threadId, senderType: input.senderType, now });
this.recordPresence(agent.id, slash, now);
return { targetId: agent.id, taskId, runId };
}
@@ -178,6 +178,7 @@ export class ChatAgentWakeService {
workspace: WorkspaceContext | null;
messageId: string;
threadId: string;
senderType: SendMessageInput["senderType"];
now: string;
}): string {
const providerId = input.agent.model_provider_id;
@@ -199,6 +200,9 @@ export class ChatAgentWakeService {
credentialAccess: "provider_runtime_only",
sourceMessageId: input.messageId,
sourceThreadId: input.threadId,
// Who spoke decides scheduling: the queue claims human-triggered wakes
// before autonomous work (see claimNextQueuedRun).
sourceSenderType: input.senderType,
});
this.db.prepare(`
insert into task_runs(