Skip to content

feat(tasks): surface the schedule's timezone on the task read path (chat#1881 3c·api-read) - #781

Merged
sweetmantech merged 1 commit into
mainfrom
feat/3c-task-read-timezone
Jul 22, 2026
Merged

feat(tasks): surface the schedule's timezone on the task read path (chat#1881 3c·api-read)#781
sweetmantech merged 1 commit into
mainfrom
feat/3c-task-read-timezone

Conversation

@sweetmantech

@sweetmantech sweetmantech commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

What

Adds timezone to GET /api/tasks — the read side of chat#1881 3c. Implements the docs#276 contract.

Since the timezone lives on the Trigger.dev schedule (not scheduled_actions — the 3c source-of-truth decision), enrichTasks now reads it back from the schedule (retrieveScheduleTimezone, in parallel with the runs fetch) and exposes it as timezone on each enriched task. This lets the chat edit UI prefill the current timezone (chat#1883's getTaskTimezone reads task.timezone). null when the task has no schedule or Trigger.dev is unavailable.

Why it's needed

api#780 (write side, merged) stores the tz only on the Trigger.dev schedule. Without this, GET /api/tasks returns no timezone, so the chat picker's edit-prefill falls back to the browser zone and would overwrite the real tz on save. This closes that gap.

Tests

enrichTasks 4/4: returns the schedule's timezone; null when no schedule (retrieve not called); null on Trigger.dev failure; timezone present even with no runs. tsc + eslint clean.

Sequencing

Merge order: docs#276 → this. Then chat#1883 works as-built. Tracking: chat#1881 item 3c·api-read.


Summary by cubic

Adds timezone to GET /api/tasks by reading it from the Trigger.dev schedule. This meets chat#1881 (3c · api-read) and lets the chat edit UI prefill the correct timezone.

  • New Features
    • Expose timezone on each task from retrieveScheduleTimezone (fetched in parallel with fetchTriggerRuns).
    • Return timezone: null when no schedule exists or Trigger.dev is unavailable.

Written for commit 7aa8416. Summary will update on new commits.

Review in cubic

…#1881 3c·api-read)

enrichTasks now reads the timezone back from the Trigger.dev schedule
(retrieveScheduleTimezone) alongside the runs, and exposes it as `timezone` on
each task in GET /api/tasks. The schedule is the source of truth (no stored
column), so this lets the chat edit UI prefill the current timezone. Null when
the task has no schedule or Trigger.dev is unavailable. enrichTasks tests updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 22, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@vercel

vercel Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
api Ready Ready Preview Jul 22, 2026 10:05pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

enrichTasks now retrieves and exposes the Trigger.dev schedule timezone alongside recent and upcoming runs, using parallel requests for scheduled tasks and nullable fallback values when schedule data is unavailable.

Changes

Task timezone enrichment

Layer / File(s) Summary
Timezone enrichment flow
lib/tasks/enrichTasks.ts
EnrichedTask and TriggerInfo include nullable timezone data; scheduled tasks retrieve timezone and trigger runs concurrently, while missing schedules and failures return timezone: null.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Poem

Runs march on, both near and far,
A timezone joins each task’s star.
If schedules fade or APIs stall,
Null keeps the shape intact for all.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Solid & Clean Code ✅ Passed PASS: enrichTasks stays a focused enrichment entrypoint, the file name matches its primary export, and the timezone addition reuses the existing Trigger.dev helper cleanly.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/3c-task-read-timezone

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
lib/tasks/enrichTasks.ts (1)

37-46: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract per-task Trigger.dev enrichment into a focused helper.

enrichTasks is now a roughly 68-line function combining schedule/run retrieval, payload parsing, error handling, account-email enrichment, and result mapping. Extract the per-task Trigger.dev work—including the timezone lookup—into a small helper so enrichTasks remains focused and stays within the repository’s function-size limit.

As per coding guidelines, keep functions small and focused. As per path instructions, domain functions must remain under 50 lines and follow single responsibility.

Also applies to: 65-71

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/tasks/enrichTasks.ts` around lines 37 - 46, Extract the per-task
Trigger.dev retrieval and transformation logic from enrichTasks into a focused
helper, including fetchTriggerRuns, retrieveScheduleTimezone, payload parsing,
error handling, account-email enrichment, and result mapping. Keep enrichTasks
responsible only for coordinating tasks and collecting helper results, while
preserving the existing fallback behavior and output shape; ensure both
functions remain under the repository’s function-size limit.

Sources: Coding guidelines, Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@lib/tasks/enrichTasks.ts`:
- Around line 37-46: Extract the per-task Trigger.dev retrieval and
transformation logic from enrichTasks into a focused helper, including
fetchTriggerRuns, retrieveScheduleTimezone, payload parsing, error handling,
account-email enrichment, and result mapping. Keep enrichTasks responsible only
for coordinating tasks and collecting helper results, while preserving the
existing fallback behavior and output shape; ensure both functions remain under
the repository’s function-size limit.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 68db024a-9709-484d-982b-52211714092a

📥 Commits

Reviewing files that changed from the base of the PR and between a2d9510 and 7aa8416.

⛔ Files ignored due to path filters (1)
  • lib/tasks/__tests__/enrichTasks.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
📒 Files selected for processing (1)
  • lib/tasks/enrichTasks.ts

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.
Architecture diagram
sequenceDiagram
    participant Client as Chat Edit UI
    participant API as GET /api/tasks
    participant enrich as enrichTasks
    participant Supa as Supabase
    participant Trigger as Trigger.dev API
    participant Schedule as Schedule Resource
    participant Runs as Runs Resource

    Note over Client,Trigger: Task Read Path — includes timezone lookup

    Client->>API: GET /api/tasks (scheduleId in each task row)

    API->>enrich: enrichTasks(tasks[])

    enrich->>Supa: selectAccountEmails(accountIds[])
    enrich->>enrich: For each task with trigger_schedule_id

    alt scheduleId is NOT null
        enrich->>enrich: Promise.all([fetchTriggerRuns({filter[schedule]: scheduleId}, 5), retrieveScheduleTimezone(scheduleId)])
        enrich->>Trigger: fetchTriggerRuns()
        Trigger->>Runs: get recent runs
        Runs-->>Trigger: TriggerRun list
        Trigger-->>enrich: runs[]
        Note over enrich,Schedule: NEW: parallel timezone fetch
        enrich->>Trigger: retrieveScheduleTimezone(scheduleId)
        Trigger->>Schedule: get schedule
        Schedule-->>Trigger: schedule.timezone (IANA string)
        Trigger-->>enrich: timezone string
        enrich->>enrich: Extract upcoming datetimes from last run's payload
    else scheduleId IS null
        enrich->>enrich: Return { recent_runs: [], upcoming: [], timezone: null }
    end

    alt Trigger.dev unavailable
        enrich->>enrich: Catch error -> return { recent_runs: [], upcoming: [], timezone: null }
    end

    enrich->>enrich: Build EnrichedTask per task

    enrich-->>API: EnrichedTask[] (each with timezone field)

    API-->>Client: JSON response with task.timezone

    Note over Client,API: Chat edit UI reads task.timezone to prefill picker
Loading

Auto-approved: Adds timezone from Trigger.dev schedule to task read path; bounded read-side enrichment with tests covering all edge cases.

Re-trigger cubic

@sweetmantech

Copy link
Copy Markdown
Contributor Author

✅ Preview verification — GET /api/tasks now returns task.timezone (read from the schedule)

Tested against the preview with a Privy Bearer, creating/patching a real task and reading it back. Cleaned up after.

# Case Result
1 POST /api/tasks { timezone: "America/Bogota" } ✅ 200. The POST response omits timezone (it's only read-enriched, not a scheduled_actions column) — correct.
2 GET /api/tasks?id=… afterward ✅ returns timezone: "America/Bogota" — enrichTasks read it back from the Trigger.dev schedule.
3 tz-only PATCHAmerica/New_York, then GET GET now returns timezone: "America/New_York" — reflects the current schedule value, proving it's read live from the source of truth (not a cached/stored copy).
4 DELETE cleanup ✅ 200

This closes the read side: the chat edit UI (chat#1883's getTaskTimezone) can now prefill the real timezone from task.timezone instead of falling back to the browser zone. Matches the docs#276 contract (Task.timezone, string | null), which was locally-verified + merged. enrichTasks tests 4/4; CI green.

Verdict: verified — ready to merge. After this, chat#1883 can be verified as-built. Tracking: chat#1881 3c·read·api.

@sweetmantech
sweetmantech merged commit 31567ad into main Jul 22, 2026
6 checks passed
sweetmantech added a commit that referenced this pull request Jul 22, 2026
… chat#1881 3c; chat picker preview reads this deployment)
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