CedarCopilot wants to merge 3 commits into staging from fix/scheduled-task-unrecorded-outcome
Live on prod, no production signal yet
Libra has verdicts on 0 of 6 tracked behaviors on prod; 6 are still being checked. Libra checks hourly for 3 days after each deploy.
Reworked after review. The first version cancelled these tasks. That was wrong, and the reason is the point of the PR , see below.
executeTask claims a task and runs the orchestrator. The run finishes, and nothing writes the
outcome to the task. The row stays todo with executionRunId set, and on the next promotion
tick promoteScheduledTasks sees a completed execution and deletes the KV entry. The task is
then permanently overdue, open, and unscheduled , it will never run again, and no programmatic
path will ever close it.
377 tasks are in that state, accruing at roughly 95 a month.
The first version did. It treated "run completed + no artifact + still todo" as meaning the
work stopped being necessary. It doesn't , the same observable state covers three different
situations, and only one is obsolete:
| what actually happened | still needed? |
|---|---|
| "No action needed as collaborator" | no , cancelling is right |
| couldn't proceed: missing contact, ambiguous data, blocked | yes |
| errored partway and still closed out | yes |
Auto-cancelling deletes the user's commitment in two cases out of three, silently. That is the same class of failure as the direction-blind close fixed in #2618 , something deciding a commitment is finished when it isn't.
The distinguishing information exists only inside the run. So the run makes the call.
1. executeTask instructs the executor to record its outcome. Three branches, stated
explicitly:
cancel-task, which writes agent_deleted. Never status: 'done', which
claims the work happened2. isScheduledTaskUnresolved detects and logs. It never writes. Same predicate as before,
read-only, hooked into the same place , promoteScheduledTasks' completed-execution branch,
which already proves the rest of the precondition (task exists, agent execution on, status = 'todo', dueDate unchanged) and is the last moment anything looks at the task.
['cedar-prod']
| where message == "[promoteScheduledTasks] Completed run recorded no outcome"
| summarize count() by bin(_time, 1d)
Falling means the instruction lands. Flat or rising is the case for something stronger , made with evidence rather than assumed up front.
3. Dropped the task-notes write, which only existed to explain a cancellation that no longer happens.
tsc -b on @zero/server , cleanpnpm deps:check , no violations (1577 modules, 8224 dependencies)oxlint , clean; the single warning is in deal-audit.ts, outside this difforganizations.test.ts fails in shard 2 and is pre-existing ,
reproduces on a clean origin/staging worktreescheduled-task-unresolved.test.ts , 4 tests, including an explicit assertion that the
detector performs no write even when it detects the stateForward-looking. The ~377 already-stranded tasks had their KV entries deleted when their runs completed, so promotion will never see them again. Draining that backlog is separate, and now clearly needs the same per-task judgement rather than a sweep.
Also includes the branch-C design doc, with ยง2 corrected to describe this approach and record why the cancelling one was rejected.
๐ค Generated with Claude Code
Libra has not measured any production surfaces for this change yet.