Bug: scheduler completion callback races with trigger auto-completion for Intent Signal Discovery
Severity: P2 — MEDIUM
Summary: The scheduler exposes an external completion callback for separate-process execution, but the trigger path also auto-completes the same execution internally. In callback-based deployments this creates a double-completion race and 404 close failures.
Steps to Reproduce:
- Start an execution via
POST /api/scheduler/trigger.
- Let the downstream scan service finish and call
POST /api/scheduler/complete/:executionId, as the endpoint docs describe for separate-process/service mode.
- Observe that one completion path succeeds first.
- Observe that the second completion path returns
404 with Execution <id> not found in active executions.
Expected: Exactly one component owns execution completion, and the documented callback path works without racing the trigger path.
Actual: POST /api/scheduler/trigger always calls runIntentSignalScan() and then auto-runs completeExecution() in its promise handlers, while /api/scheduler/complete/:executionId also tries to close the same execution.
Root Cause:
- File:
server/api.ts L406-L420
- File:
server/api.ts L442-L468
- File:
server/scheduler/workflow-scheduler.ts L317-L320
The trigger endpoint starts an execution, dispatches the HTTP scan request, and unconditionally completes the execution in-process on success/failure. The API also exposes a completion callback specifically documented for external worker/service mode. completeExecution() only succeeds while the execution remains in activeExecutions, so whichever path closes first causes the other to fail with a not-found error.
Suggested Fix: Pick a single completion owner per execution mode. Either (a) let /api/scheduler/trigger only enqueue/dispatch work and require the callback to close the execution, or (b) keep in-process completion and remove/disable the callback path for that mode. If both paths must exist, make completion idempotent and explicitly gate which actor is authoritative.
Related: #10, PR #11
Bug: scheduler completion callback races with trigger auto-completion for Intent Signal Discovery
Severity: P2 — MEDIUM
Summary: The scheduler exposes an external completion callback for separate-process execution, but the trigger path also auto-completes the same execution internally. In callback-based deployments this creates a double-completion race and 404 close failures.
Steps to Reproduce:
POST /api/scheduler/trigger.POST /api/scheduler/complete/:executionId, as the endpoint docs describe for separate-process/service mode.404withExecution <id> not found in active executions.Expected: Exactly one component owns execution completion, and the documented callback path works without racing the trigger path.
Actual:
POST /api/scheduler/triggeralways callsrunIntentSignalScan()and then auto-runscompleteExecution()in its promise handlers, while/api/scheduler/complete/:executionIdalso tries to close the same execution.Root Cause:
server/api.tsL406-L420server/api.tsL442-L468server/scheduler/workflow-scheduler.tsL317-L320The trigger endpoint starts an execution, dispatches the HTTP scan request, and unconditionally completes the execution in-process on success/failure. The API also exposes a completion callback specifically documented for external worker/service mode.
completeExecution()only succeeds while the execution remains inactiveExecutions, so whichever path closes first causes the other to fail with a not-found error.Suggested Fix: Pick a single completion owner per execution mode. Either (a) let
/api/scheduler/triggeronly enqueue/dispatch work and require the callback to close the execution, or (b) keep in-process completion and remove/disable the callback path for that mode. If both paths must exist, make completion idempotent and explicitly gate which actor is authoritative.Related: #10, PR #11