feat(tasks): annotate GET /api/tasks/runs list runs with schedule title + email subject
What
List mode of GET /api/tasks/runs now annotates each run with title: string | null — the originating scheduled task's scheduled_actions.title, null when unresolvable. Retrieve mode (runId) and every existing field are unchanged; the addition is purely additive.
Why
Trigger.dev list runs carry only taskIdentifier, and every scheduled prompt shares customer-prompt-task — so the chat homepage renders five identical "Scheduled Task" rows (recoupable/chat#1850, video-parity item 1, promoted from the chat#1853 fast-follow note).
How runs link to schedules (mechanism)
Trigger.dev's v1 list-runs rows expose no schedule reference (verified against the live API; the schedule object exists only on single-run retrieve). The join is the reverse lookup the repo already uses in enrichTasks: for each of the account's scheduled_actions with a trigger_schedule_id, fetch its runs via filter[schedule] and map run id → title. Verified live: schedule-filtered run ids intersect the account-tag list exactly (run_cmr91tpc0… appears in both for sched_d4o3wm3xskug35izn59ej / "Weekly Social Media Health Check Report").
Per-schedule fetch uses the caller's limit, which is sufficient coverage: a schedule can contribute at most limit runs to the top-limit account list.
Implementation
lib/tasks/buildRunTitleMap.ts— run id → title map via per-schedulefetchTriggerRuns({ "filter[schedule]": … }); fails open per schedulelib/tasks/attachRunTitles.ts—selectScheduledActions({ account_id })(existing lib/supabase function) → map → annotate; fails open to all-null titles so the runs list never 500s on title resolutionlib/tasks/getTaskRunHandler.ts— list branch pipes runs throughattachRunTitles
One exported function per file; TDD RED→GREEN per unit (new modules failed collection + handler assertion failed before implementation).
Verification
- Full suite: 3,950 passed / 715 files (baseline 3,940 + 10 new: 5 buildRunTitleMap, 4 attachRunTitles, 1 handler)
pnpm exec tsc --noEmit: 200 errors = exact pre-existing baseline, 0 new (measured by stash/compare)pnpm lintclean, prettier clean- Live mechanism probe against Trigger.dev v1 + prod
scheduled_actions(above) - Preview: unauthed probe pending deploy; authed list-mode pass (titles on real runs) pending a bearer — will comment results on this PR
Links
- Tracking: recoupable/chat#1850 (Open — video/experience parity, item 1)
- Contract (merge first): recoupable/docs#268
- Consumer (merge last): chat PR
feat/home-run-titles(rendersrun.titleinHomeRunRowwith today's label as fallback) - Merge order: docs#268 → this → chat
🤖 Generated with Claude Code
Summary by cubic
GET /api/tasks/runs list mode now returns two optional naming fields per run: title from the originating scheduled task and email_subject from the newest linked email. Previously names were not available; retrieve mode and all existing fields are unchanged. This makes chat rows distinguishable and prefers email_subject over title for display.
- Resolves
title: string|nullby reverse-looking up each accountscheduled_actionsvia Trigger.devfilter[schedule]; failures or unmapped runs yieldnull. Implemented withattachRunTitles+buildRunTitleMap. - Adds
email_subject: string|nullby querying the newestemail_send_logrow pertrigger_run_id; lookup errors yieldnull. Implemented withattachRunEmailSubjects+selectEmailSubjectsByRunIds. - List handler now pipes runs through titles → email subjects; retrieve mode untouched. Types for
email_send_logincludesubjectandtrigger_run_id.