Skip to content

Record wake outcomes and expand Monitor tab history rows - #27

Merged
Automage merged 1 commit into
mainfrom
feat/wake-history-detail
Sep 14, 2026
Merged

Automage merged 1 commit into
mainfrom
feat/wake-history-detail

Conversation

@Automage

@Automage Automage commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

What changed

History records runs, not ticks. A wake's history row is now written by the wake coordinator when the wake actually starts, and settled once when it ends. The scheduler mints the wake id at fire time and hands the coordinator a PendingWake; the coordinator calls wakeStarted when the headless child spawns or the live session accepts the wake (channel handoff, or codex push ack), and wakeFinished when it settles. The "agent is now running" notification and the schedule_fired event move to the same start moment. A wake the coordinator drops before it runs leaves no row, and an agent archived while its wake sat queued gets no row either.

Outcomes. succeeded (headless child exited, or the warm turn's Stop hook fired via a new WakeTransport.onTurnEnded), failed with a reason (resume_fail / spawn_fail / api_error) plus the classified failure category, or stopped (user Stop mid-run, or the live session went away before the turn ended).

StopFailure. Claude Code fires StopFailure instead of Stop when a turn ends in an API error. It is now registered in the generated agent settings.json (which the claude harness rewrites before every spawn, so existing agents get it on their next launch) and handled by /hook/status: same turn-ended bookkeeping as Stop, then WakeTransport.onTurnFailed settles the outstanding wake as failed with the category mapped from the hook's error value (categoryForStopFailure: billing_error → billing, rate_limit/overloaded → rate_limit, the credential states → auth, server_error → network, everything else → other). The stderr classifier for headless runs also gains a network category (transport codes, "fetch failed", connection wording, 5xx). For a headless run the hook lands before the child exits, so the coordinator holds the failure and an otherwise-clean exit settles failed rather than succeeded; a fast resume failure takes the hook's category over the stderr guess.

Schema v7 adds outcome, finished_at, failure_reason, failure_category to wakes, all nullable. Rows from earlier versions read NULL and render as before. Settling is one guarded UPDATE … WHERE outcome = 'running' RETURNING, so a wake settles at most once; any row still running at host start is marked stopped (nothing in flight survives a restart).

Monitor tab. schedule.forAgent now returns the agent's schedules/monitors with retired rows included (Scheduler.listTriggers), so a history row resolves its trigger after the trigger is gone; the panel filters enabled for its Active list itself. The MCP-facing listCron/listMonitors are unchanged. History rows keep their "Timer fired" / "Monitor fired" title and Background pill, and expand to the fire time, the outcome (category as a hint for recognized failures), and the trigger's prompt or command. The leading icon reflects state: spinner while running, red alert when failed, orange alert when stopped.

Telemetry and feedback. A wake_finished event is emitted where the row settles, with source, path, outcome, duration, and failure detail for both delivery paths. It replaces headless_run_finished, which only saw a headless child's exit code and read "ok" for a late API-error turn; path = headless is its successor series, and historical rows stay under the old name. The feedback diagnostics block gains seven-day wake counts: started, failed, stopped, failed on an API error, and the most frequent failure category.

Tests

  • Coordinator: recorded outcomes on the headless, channel, and push paths; stop mid-run; queued-behind-run; drop-before-start leaves no row; StopFailure on a warm wake, on an in-flight headless run (held until exit), overriding a fast resume-fail's category, and as a no-op with nothing outstanding.
  • Scheduler: wakeStarted writes running and wakeFinished settles the same row; listTriggers includes retired rows while listCron/listMonitors hide them.
  • Failure category: the StopFailure error mapping and the new network patterns in the stderr classifier (including the duration false-positive guard).
  • Status route (HTTP): Notification, Stop, and StopFailure payloads drive the expected registry, arbiter, and wake-transport calls.
  • Scheduler wakeStats, the diagnostics block with the new wake fields, the idempotent settle, and the boot sweep of orphaned running rows.
  • Migration: v7 on a v6 database preserves rows with NULL outcomes.

Gate: bun test app/src 420 pass / 0 fail, typecheck clean, production build clean, biome clean on changed files (a pre-existing useHookAtTopLevel false positive on a use-prefixed method in headless-strategy.ts is cleared by renaming it).

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 14, 2026

Copy link
Copy Markdown

Deploying opentradeoss with  Cloudflare Pages  Cloudflare Pages

Latest commit: c62b631
Status: ✅  Deploy successful!
Preview URL: https://5e7dabed.opentradeoss.pages.dev
Branch Preview URL: https://feat-wake-history-detail.opentradeoss.pages.dev

View logs

@Automage
Automage force-pushed the feat/wake-history-detail branch 8 times, most recently from 31b194b to 61db890 Compare September 14, 2026 21:39
Wake history rows are now written when a wake actually starts and settled
once when it ends, instead of being written when the timer or monitor
fires. The scheduler mints a wake id at fire time and hands the coordinator
a PendingWake; the coordinator calls back wakeStarted when the headless
child spawns or the live session accepts the wake (channel handoff or codex
push ack), and wakeFinished when it settles. The "agent is now running"
notification and the schedule_fired event move to the same start moment.
A wake the coordinator drops before it runs leaves no row, and an agent
archived while its wake sat queued gets no row either.

Outcomes: succeeded (headless child exited, or the warm turn's Stop hook
fired via a new WakeTransport.onTurnEnded), failed with a reason
(resume_fail / spawn_fail / api_error) and the classified failure category,
or stopped (user Stop mid-run, or the live session went away before the
turn ended). The failure category gains a network value, for connection
failures and server errors.

Claude Code's StopFailure hook, which fires instead of Stop when a turn ends
in an API error, is now registered in the generated agent settings (so
existing agents pick it up on their next launch) and handled by the status
route: it does the same turn-ended bookkeeping as Stop and settles the
outstanding wake as failed with the category mapped from the hook's error
value (WakeTransport.onTurnFailed). For a headless run the hook lands before
the child exits, so the coordinator holds the failure and an otherwise-clean
exit settles failed rather than succeeded.

A wake_finished telemetry event, replacing headless_run_finished, is emitted
where the row settles, carrying
the source, delivery path, outcome, duration, and failure detail for both
paths. The feedback form's diagnostics block gains seven-day wake counts:
started, failed, stopped, failed on an API error, and the most frequent
failure category.

Schema v7 adds outcome, finished_at, failure_reason and failure_category to
wakes, all nullable; rows from earlier versions read NULL and render as
before. Settling is a single guarded update on a running row, so a wake
settles at most once, and any row still running at host start is marked
stopped, since nothing in flight survives a restart.

schedule.forAgent now returns the agent's schedules and monitors with
retired rows included (Scheduler.listTriggers), so a history row can
resolve its trigger after the trigger is gone; the Monitor tab filters
enabled rows for its Active list itself. History rows expand to the fire
time, the outcome (with the category as a hint for recognized failures),
and the trigger's prompt or command. The row's leading icon reflects the
state: a spinner while running, a red alert when failed, an orange alert
when stopped.

Tests cover the recorded outcomes on the headless, channel and push paths,
StopFailure on warm and in-flight headless wakes, the drop-before-start
case, the wakeFinished update, listTriggers, wakeStats, the StopFailure
error mapping and network classifier patterns, the status route over HTTP,
the diagnostics block, and the v7 migration.
@Automage
Automage force-pushed the feat/wake-history-detail branch from 61db890 to c62b631 Compare September 14, 2026 21:49
@Automage
Automage merged commit f14d3ac into main Sep 14, 2026
1 check passed
@Automage
Automage deleted the feat/wake-history-detail branch September 14, 2026 22:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant