Skip to content

Killed Control turns stay "streaming" for 17 minutes before the reaper runs #418

Description

@charlesrhoward

Problem

The Control chat route dies at its 800 second maxDuration. The reaper that marks stale ai_calls rows as failed uses a 30 minute threshold sized for /api/chat (1800 seconds). Between those two numbers the row sits in streaming, the UI shows the "Saving the coordinator handoff" spinner, and the user cannot tell the turn is dead.

The reaper itself is correct. It only runs from Trigger.dev. The Vercel cron fallback route exists but is not scheduled, so if the Trigger deploy is stale nothing reaps at all.

Where

  • app/api/control/chat/route.ts:8: maxDuration = 800.
  • lib/interactive-runs.ts:30: ACTIVE_CHAT_STALE_THRESHOLD_MS = 30 * 60 * 1000, applied at :372-378 for every type === "chat" call.
  • lib/zombies/zombie-reaper-ai-calls.ts (reaper logic), scheduled at trigger/zombie-row-reaper.ts:44.
  • app/api/cron/zombie-row-reaper/route.ts exists, is auth-gated, and is absent from vercel.json crons.

Fix

  1. Split the constant: ACTIVE_CONTROL_CHAT_STALE_THRESHOLD_MS = 800_000 + 60_000 (route lifetime plus a minute of grace) and select it when the call is a Control chat. Find how Control calls are distinguished from /api/chat calls in ai_calls.metadata and branch on that, not on a string in the prompt.
  2. Add { "path": "/api/cron/zombie-row-reaper", "schedule": "*/5 * * * *" } to vercel.json.
  3. Add export const maxDuration = 300 to the cron route so it matches the Trigger task's 240 second budget with headroom.

Exit criteria

  • Vitest test in lib/ for the staleness check: a Control chat call started 15 minutes ago is stale, a /api/chat call started 15 minutes ago is not. Must fail on main.
  • vercel.json lists the reaper cron. Confirm it appears in the Vercel dashboard crons after the deploy.
  • Manual, on preview: kill a Control turn (block the route mid-stream), wait, confirm the timeline shows a failed turn within 15 minutes instead of a spinner.
  • pnpm lint, pnpm typecheck, pnpm test pass.

Out of scope

Making the UI detect a dead stream client-side before the reaper runs.

https://claude.ai/code/session_01SQ4nS96XYRztd5w9QkubPf

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1Reliability or a user-visible class of bug.bugSomething isn't workingcontrolControl surface (coordinator, missions, sidebar).infrareliabilityStuck states, races, lifecycle gaps.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions