This commit is contained in:
Svetlana Zolotenkova 2026-09-13 12:23:33 +02:00 committed by GitHub
commit 13de927e25
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 22 additions and 0 deletions

View File

@ -13107,6 +13107,7 @@ export function heartbeatService(
assigneeUserId: issues.assigneeUserId,
executionState: issues.executionState,
monitorNextCheckAt: issues.monitorNextCheckAt,
originKind: issues.originKind,
projectId: issues.projectId,
originKind: issues.originKind,
})

View File

@ -420,6 +420,18 @@ describe("successful run handoff decision", () => {
});
});
it("does not queue for routine execution issues left in_progress between fires", () => {
// A successful orphan-check routine run left its coalesced routine_execution
// issue in `in_progress`, and the handoff wrongly treated that steady state
// as a missing disposition -> blocked + recovery loop.
expect(decide({
issue: { ...issue, originKind: "routine_execution" } as any,
})).toEqual({
kind: "skip",
reason: "routine execution owns its own disposition",
});
});
it("does not queue for successful comment-driven wakes", () => {
expect(decide({
run: {

View File

@ -35,6 +35,12 @@ export const SUCCESSFUL_RUN_HANDOFF_OPTIONS = [
"delegate_or_continue_from_checkpoint",
] as const;
// Routine execution issues stay `in_progress` between cron fires by design — one
// open issue is coalesced across dispatches (see issues_open_routine_execution_uq).
// Their disposition is owned by the routine lifecycle, not by the missing-disposition
// handoff, so a successful routine run must not be treated as a missing next step.
const ROUTINE_EXECUTION_ORIGIN_KIND = "routine_execution";
const PRODUCTIVE_SUCCESS_LIVENESS_STATES = new Set<RunLivenessState>([
"advanced",
"completed",
@ -493,6 +499,9 @@ export function decideSuccessfulRunHandoff(input: {
return { kind: "skip", reason: "missing issue comment retry owns the next action" };
}
if (!issue) return { kind: "skip", reason: "issue not found" };
if (issue.originKind === ROUTINE_EXECUTION_ORIGIN_KIND) {
return { kind: "skip", reason: "routine execution owns its own disposition" };
}
if (!agent) return { kind: "skip", reason: "agent not found" };
if (issue.companyId !== run.companyId || agent.companyId !== run.companyId) {
return { kind: "skip", reason: "company scope mismatch" };