Skip to content

feat: homepage tasks module — recent runs + one-click starter task (Catalog HQ 2/3, chat#1850)#1853

Merged
sweetmantech merged 4 commits into
mainfrom
feat/home-tasks-module
Jul 7, 2026
Merged

feat: homepage tasks module — recent runs + one-click starter task (Catalog HQ 2/3, chat#1850)#1853
sweetmantech merged 4 commits into
mainfrom
feat/home-tasks-module

Conversation

@sweetmantech

@sweetmantech sweetmantech commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

What this does

Second PR of the Catalog HQ homepage stack (#1850). Adds the "Your label at work" tasks module under the valuation hero:

  • Accounts with task history see their most recent runs (capped at 5) from the existing GET /api/tasks/runs — run name, status pill, finished-at — each row linking to the existing /tasks/{runId} detail page.
  • Fresh accounts (zero runs, artist selected) see one pre-wired suggestion card: "Weekly valuation + streams report for {artist}, Mondays". One click creates the scheduled task via the existing POST /api/tasks path (which also mints the Trigger schedule), then the module shows it as scheduled.
  • While loading or on any fetch failure the module renders nothing — home never blocks on it.

Honest scope note on sent emails: the issue asks for each run's sent email (subject + sent-at). No existing chat-consumable endpoint exposes per-run email subjects today — GET /api/tasks/runs returns taskIdentifier/status/timestamps/metadata only, and the email send log isn't surfaced through any api.recoupable.dev endpoint the chat app uses. Per the module's ONLY-existing-endpoints constraint, this PR shows what IS available (run name, status, finished-at). Surfacing email subjects needs an api-side addition (runs response or an email-log endpoint) — left open on #1850.

Uses only existing hooks/patterns: useTaskRuns (existing), new useCreateStarterTask mirroring useCreateTask (auth + artist from providers), pure getHomeTasksModuleState selector for the module's render decision.

Tests (TDD — confirmed RED before implementing)

12 new unit tests, full suite 109 passed (31 files):

  • lib/home/__tests__/getHomeTasksModuleState.test.ts — runs shown for accounts with history, capped at 5; starter card for fresh account with artist; hidden while loading / on failure / without artist (the Done-when).
  • lib/home/__tests__/createStarterTask.test.ts — the one-click creation call fires POST /api/tasks with the exact payload (title, 0 9 * * 1 Monday schedule, artist_account_id, model); error propagation.
  • lib/home/__tests__/buildStarterTaskParams.test.ts — starter task title/schedule/prompt contents.

pnpm exec tsc --noEmit: no new errors (same two pre-existing failures as on main). eslint + prettier clean on changed files.

Screenshots

N/A (no preview screenshot in this PR; run/starter states verified via unit tests — see PR comment for preview verification).

Stack

Part of a 3-PR stack for chat#1850 (merge in order, each PR only after its base):

  1. feat: homepage valuation hero (Catalog HQ 1/3, chat#1850) #1852 feat/home-valuation-hero → base main
  2. this PR feat/home-tasks-module → base feat/home-valuation-hero
  3. feat/home-command-bar → base feat/home-tasks-module

When #1852 merges, this PR gets re-targeted to main.

Tracked in #1850.

🤖 Generated with Claude Code


Summary by cubic

Adds the "Your label at work" tasks module under the valuation hero to show recent task runs or let new users schedule a weekly report in one click. It now renders inside ChatGreeting and never blocks the page (chat#1850).

  • New Features

    • Renders via TasksModule under ValuationHero/greeting in ChatGreeting (order: valuation → tasks → chat input); shows up to 5 recent runs (name, status, finished-at) from GET /api/tasks/runs; rows link to /tasks/{runId}, header to /tasks.
    • For fresh accounts with a selected artist, a starter card schedules a Monday 9am report in one click through POST /api/tasks and reflects the scheduled state.
    • Self-hides while loading, on fetch error, or when no artist is selected; email subjects are omitted until the API exposes them (chat#1850).
  • Refactors

    • Starter task now pulls its prompt from /agents templates via the shared agent-templates query; findStarterTemplate prefers “Weekly Performance Dashboard,” falls back to any Report-tagged template, and hides the card when none exist. Only the title is personalized.

Written for commit 9e9095d. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features
    • Added a homepage tasks section showing recent task runs with status, time, and links to details.
    • Added an empty-state starter task card with a one-click schedule action when no runs are available.
  • Bug Fixes
    • Improved homepage behavior so the tasks section hides when loading, unavailable, or empty.
    • Added clearer success and error feedback for starter task scheduling.
  • Style
    • Adjusted homepage layout and spacing to fit the new tasks content.

@cursor

cursor Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

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 6, 2026

Copy link
Copy Markdown
Contributor

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

Project Deployment Actions Updated (UTC)
chat Ready Ready Preview Jul 7, 2026 6:51pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a new homepage "tasks" module: a state-derivation helper, run-row and starter-task-card components, a TasksModule composition component, and supporting helpers (buildStarterTaskParams, createStarterTask, findStarterTemplate). Extends useCreateStarterTask to fetch templates and create/schedule the starter task, and wires the module into ChatGreeting.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Changes

Homepage Tasks Module

Layer / File(s) Summary
State derivation
lib/home/getHomeTasksModuleState.ts
Adds HomeTasksModuleState union and getHomeTasksModuleState to choose hidden/runs/starter view states.
Task run row
components/Home/HomeRunRow.tsx
Renders a linked run row with display name, timestamp, and status pill.
Starter task helpers and hook
lib/home/findStarterTemplate.ts, lib/home/buildStarterTaskParams.ts, lib/home/createStarterTask.ts, hooks/useCreateStarterTask.ts
Queries agent templates, selects a starter template, builds task params, creates/schedules the task, invalidates queries, and shows success/error toasts.
Starter task card
components/Home/StarterTaskCard.tsx
Renders scheduled-status message or a "Schedule it" button using useCreateStarterTask.
Module composition and wiring
components/Home/TasksModule.tsx, components/Chat/ChatGreeting.tsx
Composes TasksModule from run/state/artist data, renders run rows or starter card, and wires it into ChatGreeting's valuation and non-valuation layouts.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant TasksModule
  participant getHomeTasksModuleState
  participant StarterTaskCard
  participant useCreateStarterTask
  participant createStarterTask

  User->>TasksModule: loads homepage
  TasksModule->>getHomeTasksModuleState: compute state(runs, hasArtist)
  getHomeTasksModuleState-->>TasksModule: hidden | runs | starter
  alt state = starter
    TasksModule->>StarterTaskCard: render
    StarterTaskCard->>useCreateStarterTask: get starterTemplate, isScheduled
    User->>StarterTaskCard: click "Schedule it"
    StarterTaskCard->>useCreateStarterTask: handleCreateStarterTask()
    useCreateStarterTask->>createStarterTask: createStarterTask(accessToken, input)
    createStarterTask-->>useCreateStarterTask: Task
    useCreateStarterTask-->>StarterTaskCard: isScheduled=true, toast success
  else state = runs
    TasksModule->>User: render HomeRunRow list
  end
Loading

Poem

A rabbit hopped upon the home page floor,
Found tasks half-hidden, wanting one thing more,
With template found and starter task in tow,
It scheduled Mondays, nine o'clock, all set to go,
🐰📅 Now the label works while rabbits doze.

🚥 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: the feature is split into focused components/hooks/utilities, with low nesting and shared helpers; no major SRP/OCP/DRY/KISS issues stand out.
✨ 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/home-tasks-module

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.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5eb9fc8dae

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

if (runs.length > 0)
return { view: "runs", runs: runs.slice(0, MAX_HOME_RUNS) };

return hasArtist ? { view: "starter" } : { view: "hidden" };

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Prevent duplicate starter schedules after reload

When a user creates the starter task, the persisted result is a scheduled action, but this selector only looks at run history. Until the first scheduled run happens, useTaskRuns still returns []; after a page reload the mutation's local isScheduled state is gone, so the homepage offers "Schedule it" again and another click creates a duplicate Monday task. Include existing scheduled actions in this decision, or otherwise persist/hide the starter once the task exists.

Useful? React with 👍 / 👎.

Comment on lines +28 to +30
if (!artistAccountId || !artistName) {
throw new Error("ARTIST_REQUIRED");
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Handle selected artists with missing names

For a selected artist/workspace whose name is null or empty, the module still renders because it only checks account_id, and the card displays the fallback "your artist"; however this mutation throws ARTIST_REQUIRED, so clicking the visible CTA fails with "Please select an artist first" even though an artist is selected. Use the same fallback for task creation or require a usable name before showing the starter card.

Useful? React with 👍 / 👎.

@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.

3 issues found across 11 files

Confidence score: 3/5

  • In hooks/useCreateStarterTask.ts, isScheduled is derived from mutation success and isn’t reset when selectedArtist changes, so the starter card can show the wrong status for the newly selected artist; that can mislead users into thinking a task is already scheduled when it isn’t — reset mutation state on artist change (or derive scheduled state from artist-scoped data) before merging.
  • In lib/home/getHomeTasksModuleState.ts, relying on mutation isSuccess means a reload can temporarily drop isScheduled while useTaskRuns is still empty, so the starter card reappears and users can re-trigger scheduling; this risks duplicate/confusing scheduling flows — persist/derive scheduled state from server-backed task/run data across reloads before merging.
  • In components/Home/StarterTaskCard.tsx, the “Schedule it” button is clickable in states where useCreateStarterTask will always fail (e.g., missing selectedArtist), creating avoidable error-toast loops and a frustrating UX — gate/disable the button on required preconditions, not just pending state.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="components/Home/StarterTaskCard.tsx">

<violation number="1" location="components/Home/StarterTaskCard.tsx:39">
P2: Users can click "Schedule it" in a state where creation is guaranteed to fail, causing an avoidable error toast loop. The button is only disabled during pending state, but `useCreateStarterTask` requires a non-null `selectedArtist.name`, so disabling when required artist fields are missing would prevent this broken path.</violation>
</file>

<file name="hooks/useCreateStarterTask.ts">

<violation number="1" location="hooks/useCreateStarterTask.ts:23">
P2: The starter card can show a false "scheduled" state after artist switching, because `isScheduled` is tied to mutation success and never reset. Consider resetting mutation state when `selectedArtist` changes (or deriving scheduled status from fetched tasks) so the UI reflects the current artist.</violation>
</file>

<file name="lib/home/getHomeTasksModuleState.ts">

<violation number="1" location="lib/home/getHomeTasksModuleState.ts:34">
P2: After a page reload, the mutation's `isSuccess` (used as `isScheduled`) resets and `useTaskRuns` still returns `[]` until the first scheduled run actually executes. This means the starter card reappears and the user can create duplicate Monday tasks on each visit.

Consider incorporating existing scheduled actions (e.g., from a `useScheduledActions` query or persisted flag) into this decision, so that once the weekly task exists the module no longer offers to create it again.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

<button
type="button"
onClick={() => handleCreateStarterTask()}
disabled={isCreating}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: Users can click "Schedule it" in a state where creation is guaranteed to fail, causing an avoidable error toast loop. The button is only disabled during pending state, but useCreateStarterTask requires a non-null selectedArtist.name, so disabling when required artist fields are missing would prevent this broken path.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At components/Home/StarterTaskCard.tsx, line 39:

<comment>Users can click "Schedule it" in a state where creation is guaranteed to fail, causing an avoidable error toast loop. The button is only disabled during pending state, but `useCreateStarterTask` requires a non-null `selectedArtist.name`, so disabling when required artist fields are missing would prevent this broken path.</comment>

<file context>
@@ -0,0 +1,48 @@
+      <button
+        type="button"
+        onClick={() => handleCreateStarterTask()}
+        disabled={isCreating}
+        className="shrink-0 rounded-xl bg-primary px-4 py-2 text-sm font-semibold text-primary-foreground transition-colors hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50"
+      >
</file context>

const {
mutate: handleCreateStarterTask,
isPending: isCreating,
isSuccess: isScheduled,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: The starter card can show a false "scheduled" state after artist switching, because isScheduled is tied to mutation success and never reset. Consider resetting mutation state when selectedArtist changes (or deriving scheduled status from fetched tasks) so the UI reflects the current artist.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At hooks/useCreateStarterTask.ts, line 23:

<comment>The starter card can show a false "scheduled" state after artist switching, because `isScheduled` is tied to mutation success and never reset. Consider resetting mutation state when `selectedArtist` changes (or deriving scheduled status from fetched tasks) so the UI reflects the current artist.</comment>

<file context>
@@ -0,0 +1,58 @@
+  const {
+    mutate: handleCreateStarterTask,
+    isPending: isCreating,
+    isSuccess: isScheduled,
+  } = useMutation({
+    mutationFn: async () => {
</file context>

if (runs.length > 0)
return { view: "runs", runs: runs.slice(0, MAX_HOME_RUNS) };

return hasArtist ? { view: "starter" } : { view: "hidden" };

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: After a page reload, the mutation's isSuccess (used as isScheduled) resets and useTaskRuns still returns [] until the first scheduled run actually executes. This means the starter card reappears and the user can create duplicate Monday tasks on each visit.

Consider incorporating existing scheduled actions (e.g., from a useScheduledActions query or persisted flag) into this decision, so that once the weekly task exists the module no longer offers to create it again.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At lib/home/getHomeTasksModuleState.ts, line 34:

<comment>After a page reload, the mutation's `isSuccess` (used as `isScheduled`) resets and `useTaskRuns` still returns `[]` until the first scheduled run actually executes. This means the starter card reappears and the user can create duplicate Monday tasks on each visit.

Consider incorporating existing scheduled actions (e.g., from a `useScheduledActions` query or persisted flag) into this decision, so that once the weekly task exists the module no longer offers to create it again.</comment>

<file context>
@@ -0,0 +1,35 @@
+  if (runs.length > 0)
+    return { view: "runs", runs: runs.slice(0, MAX_HOME_RUNS) };
+
+  return hasArtist ? { view: "starter" } : { view: "hidden" };
+}
</file context>

@sweetmantech

Copy link
Copy Markdown
Collaborator Author

Preview verification (sha 5eb9fc8, https://chat-git-feat-home-tasks-module-recoup.vercel.app/):

  • Vercel preview build: SUCCESS.
  • Loaded the preview homepage signed out: unchanged current experience (greeting + input + login modal), no tasks module (runs query is auth-gated), zero console errors — the module correctly renders nothing rather than blocking home.
  • Not verified on preview: the authenticated states (runs list for an account with history; starter card + one-click creation for a fresh account). I could not complete a Privy OTP login from this run (no access to the OTP inbox). Those behaviors are covered by unit tests (getHomeTasksModuleState, createStarterTask payload) and need a manual authenticated pass — recommend the clone-to-own-account [TEST] pattern before merge, since one click here creates a real schedule via POST /api/tasks.

@cursor

cursor Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

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.

@cursor

cursor Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

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.

@cursor

cursor Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

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.

@cursor

cursor Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

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.

@cursor

cursor Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

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.

@cursor

cursor Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

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.

@cursor

cursor Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

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.

… (chat#1850)

'Your label at work' module under the valuation hero: recent task runs
from the existing GET /api/tasks/runs (run name, status, finished-at),
capped at five, linking to the run detail pages. Fresh accounts get one
pre-wired suggestion (weekly valuation + streams report, Mondays 9am)
that creates the scheduled task in one click through the existing
POST /api/tasks path.

Module state is a pure, fully-tested selector; the module renders
nothing while loading or on failure so home never blocks on it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@sweetmantech sweetmantech force-pushed the feat/home-tasks-module branch from e2af7d4 to befcadd Compare July 7, 2026 15:36
@sweetmantech sweetmantech changed the base branch from feat/home-valuation-hero to main July 7, 2026 15:36
@cursor

cursor Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
components/Home/StarterTaskCard.tsx (1)

36-43: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider reusing a shared Button component instead of an ad-hoc styled <button>.

Per repo guidelines, interactive components should build on @radix-ui/react-* primitives / CVA variants and existing shared components rather than inline Tailwind classes, to keep styling and accessibility behavior (focus states, disabled state, etc.) consistent across the app.

As per coding guidelines, "Use @radix-ui/react-* primitives for behavior and accessibility" and "DRY: Extract common UI patterns into reusable components."

🤖 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 `@components/Home/StarterTaskCard.tsx` around lines 36 - 43, Replace the ad-hoc
`<button>` in `StarterTaskCard` with the app’s shared `Button` component so this
interaction follows the same Radix/CVA styling and accessibility patterns used
elsewhere. Update the `StarterTaskCard` render to pass the existing click
handler, disabled state, and loading label through the shared component instead
of inline Tailwind classes. Keep the existing `handleCreateStarterTask` behavior
and the `isCreating` conditional text, but let the reusable button handle
visuals, focus, and disabled styling consistently.

Source: Coding guidelines

🤖 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.

Inline comments:
In `@lib/home/buildStarterTaskParams.ts`:
- Line 25: The cron schedule in buildStarterTaskParams is currently
timezone-ambiguous and will default to UTC in Trigger.dev. Update the schedule
definition to include an explicit IANA timezone alongside the existing cron
expression so the 9am Monday run happens in the intended local time rather than
UTC.

In `@lib/home/getHomeTasksModuleState.ts`:
- Around line 23-35: getHomeTasksModuleState currently derives the starter view
only from runs and hasArtist, so a reload can show "starter" again even after a
starter schedule was already created. Update
getHomeTasksModuleState/GetHomeTasksModuleStateParams to accept a persisted
“starter already scheduled” flag (for example from scheduled-actions) and use it
in the return logic so the starter card is hidden once that schedule exists,
while keeping the existing runs and loading behavior unchanged.

---

Nitpick comments:
In `@components/Home/StarterTaskCard.tsx`:
- Around line 36-43: Replace the ad-hoc `<button>` in `StarterTaskCard` with the
app’s shared `Button` component so this interaction follows the same Radix/CVA
styling and accessibility patterns used elsewhere. Update the `StarterTaskCard`
render to pass the existing click handler, disabled state, and loading label
through the shared component instead of inline Tailwind classes. Keep the
existing `handleCreateStarterTask` behavior and the `isCreating` conditional
text, but let the reusable button handle visuals, focus, and disabled styling
consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7576d1ba-045e-40bf-825b-0b8ddc416caa

📥 Commits

Reviewing files that changed from the base of the PR and between 58e2071 and befcadd.

⛔ Files ignored due to path filters (3)
  • lib/home/__tests__/buildStarterTaskParams.test.ts is excluded by !**/*.test.* and included by lib/**
  • lib/home/__tests__/createStarterTask.test.ts is excluded by !**/*.test.* and included by lib/**
  • lib/home/__tests__/getHomeTasksModuleState.test.ts is excluded by !**/*.test.* and included by lib/**
📒 Files selected for processing (8)
  • components/Home/HomePage.tsx
  • components/Home/HomeRunRow.tsx
  • components/Home/StarterTaskCard.tsx
  • components/Home/TasksModule.tsx
  • hooks/useCreateStarterTask.ts
  • lib/home/buildStarterTaskParams.ts
  • lib/home/createStarterTask.ts
  • lib/home/getHomeTasksModuleState.ts

"how it changed since last week, and this week's streaming numbers " +
"for the top tracks with week-over-week deltas. Link every data " +
"source you cite and send the report by email.",
schedule: "0 9 * * 1",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does Trigger.dev support specifying a timezone for declarative cron schedules?

💡 Result:

Yes, Trigger.dev fully supports specifying a timezone for declarative cron schedules [1][2]. When defining a declarative schedule using the cron property in your task definition, you can specify a timezone to ensure the schedule runs according to that local time, automatically accounting for Daylight Saving Time [3][2]. If you provide the cron property as a simple string, it defaults to UTC [2]. To specify a timezone, you must provide the cron property as an object containing the pattern and the timezone string (in IANA format, such as "Asia/Tokyo" or "America/New_York") [2][4][5]. Example usage from official documentation: export const secondScheduledTask = schedules.task({ id: "second-scheduled-task", cron: { pattern: "0 5 * * *", timezone: "Asia/Tokyo", environments: ["PRODUCTION", "STAGING"], }, run: async (payload) => {}, }); You can also retrieve a full list of supported timezones using the SDK via schedules.timezones [2][6].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== buildStarterTaskParams ==\n'
sed -n '1,120p' lib/home/buildStarterTaskParams.ts

printf '\n== StarterTaskCard references ==\n'
rg -n "Mondays at 9am|timezone|cron" lib/home -S

printf '\n== Relevant task scheduler usage ==\n'
rg -n "schedule:\s*\"0 9 \* \* 1\"|cron:\s*\{|timezone:" -S lib . --glob '!**/node_modules/**'

Repository: recoupable/chat

Length of output: 1203


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
p = Path('lib/home/buildStarterTaskParams.ts')
text = p.read_text()
print('timezone' in text)
print(text)
PY

Repository: recoupable/chat

Length of output: 1146


Specify the cron timezone

"0 9 * * 1" defaults to UTC in Trigger.dev. If this is meant to run at 9am in the artist’s local time, pass an explicit IANA timezone here; otherwise delivery will land at the wrong hour.

🤖 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/home/buildStarterTaskParams.ts` at line 25, The cron schedule in
buildStarterTaskParams is currently timezone-ambiguous and will default to UTC
in Trigger.dev. Update the schedule definition to include an explicit IANA
timezone alongside the existing cron expression so the 9am Monday run happens in
the intended local time rather than UTC.

Comment on lines +23 to +35
export function getHomeTasksModuleState({
runs,
runsFailed,
isLoading,
hasArtist,
}: GetHomeTasksModuleStateParams): HomeTasksModuleState {
if (isLoading || runsFailed || !runs) return { view: "hidden" };

if (runs.length > 0)
return { view: "runs", runs: runs.slice(0, MAX_HOME_RUNS) };

return hasArtist ? { view: "starter" } : { view: "hidden" };
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check whether POST /api/tasks / Trigger schedule creation is idempotent per artist,
# and whether a "scheduled-actions" or similar query could be surfaced here to prevent duplicates.
rg -n -A10 'export async function createTask' lib/tasks/createTask.ts
rg -n 'scheduled-actions' -g '*.ts' -g '*.tsx'

Repository: recoupable/chat

Length of output: 469


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== lib/tasks/createTask.ts =="
cat -n lib/tasks/createTask.ts

echo
echo "== hooks/useCreateStarterTask.ts =="
cat -n hooks/useCreateStarterTask.ts

echo
echo "== search for task/schedule state sources =="
rg -n -A3 -B3 'isScheduled|scheduled-actions|scheduled action|pending schedule|createTask\(|/api/tasks|runsFailed|hasArtist' lib hooks app src

Repository: recoupable/chat

Length of output: 28249


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== call sites for getHomeTasksModuleState =="
rg -n -A8 -B8 'getHomeTasksModuleState\(' lib hooks app components pages

echo
echo "== home-related query/state sources =="
rg -n -A4 -B4 'useScheduledActions\(|scheduled-actions|useHome|home tasks|starter' lib hooks app components pages

echo
echo "== home module files =="
fd -a 'home' lib hooks app components pages

Repository: recoupable/chat

Length of output: 8342


Keep the starter card hidden once a starter schedule already exists.

getHomeTasksModuleState only looks at runs and hasArtist, so a reload before the first run fires will re-show "starter" even after the task was already created. That can let the user submit POST /api/tasks again and create a duplicate scheduled task.

Pass in a persisted “starter already scheduled” signal (for example from ["scheduled-actions"]) and use that to suppress the starter view once the schedule exists.

🤖 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/home/getHomeTasksModuleState.ts` around lines 23 - 35,
getHomeTasksModuleState currently derives the starter view only from runs and
hasArtist, so a reload can show "starter" again even after a starter schedule
was already created. Update
getHomeTasksModuleState/GetHomeTasksModuleStateParams to accept a persisted
“starter already scheduled” flag (for example from scheduled-actions) and use it
in the return logic so the starter card is hidden once that schedule exists,
while keeping the existing runs and loading behavior unchanged.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

DRY principle - We should use existing AGENTS (see /agents page) for example task prompts.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in a2e78199 — the hand-written prompt is gone. The starter card is now built from the existing /agents templates: findStarterTemplate prefers Weekly Performance Dashboard, falls back to any Report-tagged template, and the card hides entirely when none exist (no fallback string anywhere). The task's prompt is the template's verbatim; only the title gets the artist suffix so the tasks list reads per-artist. Templates come from the same ["agent-templates"] react-query key the /agents page uses, so the two surfaces share one source of truth. TDD RED→GREEN (findStarterTemplate + rewritten buildStarterTaskParams/createStarterTask tests); suite 121/121, tsc 0 new.

…nts template (DRY)

Review feedback on #1853: no hand-written example prompts — the starter
card is built from the agent-templates the /agents page already serves.
findStarterTemplate prefers 'Weekly Performance Dashboard', falls back to
any Report-tagged template, and the card hides when none exist; the
task's prompt is the template's verbatim, only the title is personalized
per artist. Templates come from the shared agent-templates react-query
key, so the /agents page and the card can never drift.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

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.

@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.

2 issues found across 8 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="hooks/useCreateStarterTask.ts">

<violation number="1" location="hooks/useCreateStarterTask.ts:27">
P2: Agent templates can be reused from a previous signed-in user/session because this user-specific fetch is cached under the global ["agent-templates"] key. Including userData.id in the query key would keep starter task template selection scoped to the current account.</violation>

<violation number="2" location="hooks/useCreateStarterTask.ts:32">
P3: When no Report starter template exists, the card disappears but the homepage module shell still renders with an empty body. Consider lifting template availability into the module state or otherwise hiding the parent section when starterTemplate is absent.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

const queryClient = useQueryClient();

const { data: templates } = useQuery<AgentTemplateRow[]>({
queryKey: ["agent-templates"],

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: Agent templates can be reused from a previous signed-in user/session because this user-specific fetch is cached under the global ["agent-templates"] key. Including userData.id in the query key would keep starter task template selection scoped to the current account.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At hooks/useCreateStarterTask.ts, line 27:

<comment>Agent templates can be reused from a previous signed-in user/session because this user-specific fetch is cached under the global ["agent-templates"] key. Including userData.id in the query key would keep starter task template selection scoped to the current account.</comment>

<file context>
@@ -1,22 +1,36 @@
   const queryClient = useQueryClient();
 
+  const { data: templates } = useQuery<AgentTemplateRow[]>({
+    queryKey: ["agent-templates"],
+    queryFn: () => fetchAgentTemplates(userData!),
+    retry: 1,
</file context>
Suggested change
queryKey: ["agent-templates"],
queryKey: ["agent-templates", userData?.id],

retry: 1,
enabled: !!userData?.id,
});
const starterTemplate = findStarterTemplate(templates);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: When no Report starter template exists, the card disappears but the homepage module shell still renders with an empty body. Consider lifting template availability into the module state or otherwise hiding the parent section when starterTemplate is absent.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At hooks/useCreateStarterTask.ts, line 32:

<comment>When no Report starter template exists, the card disappears but the homepage module shell still renders with an empty body. Consider lifting template availability into the module state or otherwise hiding the parent section when starterTemplate is absent.</comment>

<file context>
@@ -1,22 +1,36 @@
+    retry: 1,
+    enabled: !!userData?.id,
+  });
+  const starterTemplate = findStarterTemplate(templates);
+
   const {
</file context>

@sweetmantech

Copy link
Copy Markdown
Collaborator Author

Live preview verification — a2e78199 (template-sourced starter task) ✅

Signed into the branch-alias preview as the test account (which has real task history from the prod-DB scheduled reports).

Done-when criterion Result
Account with task history sees runs on home "YOUR LABEL AT WORK" renders 5 recent runs (timestamps + Completed status), "View all" → /tasks
Module reads existing endpoints only GET /api/tasks/runs?limit=20 → 200 (network log); no new api surface
Run click-through ✅ row → /tasks/run_cmranop… — status, created/started/finished, 17s duration
Coexists with the merged hero ✅ module renders above the hero (Ana Bárbara $8.1M · 154 tracks intact — no 1852 regression)
Starter card DRY (review fix) ✅ structurally: the ["agent-templates"] query fired on load and findStarterTemplate selected Weekly Performance Dashboard; the card itself is unreachable on this account (it has runs, so the runs view wins) — the one-click create is covered by the 121-test suite incl. the template-verbatim payload assertion (0 9 * * 1, template prompt untouched)

tasks module + hero live

Not exercised live: the starter-card click (needs an account with zero tasks — the test account's history makes the empty state unreachable; unit-covered). Display polish observation (not blocking): every run row is labeled "Scheduled Task" — GET /api/tasks/runs doesn't return the task title per run, so a friendlier label needs either an api field or a client-side join against the schedules list; worth a fast-follow note.

Ready to merge; chat#1854 re-targets after.

🤖 Generated with Claude Code

…o, not above it

Sweetman on #1853: valuation is the headline data customers arrive with
from the marketing funnel, so it leads. The page-level tasks container is
gone (HomePage is byte-identical to main again); TasksModule composes
into the empty-state header beneath the hero/greeting, self-hiding when
it has nothing to show. Order everywhere: valuation → label at work →
chat input.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
hooks/useCreateStarterTask.ts (1)

58-64: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Invalidate the task-runs query here as well. TasksModule reads from useTaskRuns() (queryKey: ["task-runs", { accountIdOverride }]), so invalidating only ["scheduled-actions"] leaves the starter card stale until another refetch/remount.

🤖 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 `@hooks/useCreateStarterTask.ts` around lines 58 - 64, The success handler in
useCreateStarterTask currently only invalidates the scheduled-actions query,
which leaves TasksModule data from useTaskRuns stale. Update the onSuccess logic
to also invalidate the task-runs query key used by useTaskRuns (including the
accountIdOverride shape where applicable) so the starter card refreshes
immediately after scheduling.
🤖 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.

Outside diff comments:
In `@hooks/useCreateStarterTask.ts`:
- Around line 58-64: The success handler in useCreateStarterTask currently only
invalidates the scheduled-actions query, which leaves TasksModule data from
useTaskRuns stale. Update the onSuccess logic to also invalidate the task-runs
query key used by useTaskRuns (including the accountIdOverride shape where
applicable) so the starter card refreshes immediately after scheduling.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d9fc1d3a-bb84-4604-875f-d23705bcdd0d

📥 Commits

Reviewing files that changed from the base of the PR and between befcadd and 49b2fc1.

⛔ Files ignored due to path filters (3)
  • lib/home/__tests__/buildStarterTaskParams.test.ts is excluded by !**/*.test.* and included by lib/**
  • lib/home/__tests__/createStarterTask.test.ts is excluded by !**/*.test.* and included by lib/**
  • lib/home/__tests__/findStarterTemplate.test.ts is excluded by !**/*.test.* and included by lib/**
📒 Files selected for processing (6)
  • components/Chat/ChatGreeting.tsx
  • components/Home/StarterTaskCard.tsx
  • hooks/useCreateStarterTask.ts
  • lib/home/buildStarterTaskParams.ts
  • lib/home/createStarterTask.ts
  • lib/home/findStarterTemplate.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/home/createStarterTask.ts
  • components/Home/StarterTaskCard.tsx

@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.

0 issues found across 2 files (changes from recent commits).

Requires human review: Auto-approval blocked by 5 unresolved issues from previous reviews.

Re-trigger cubic

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

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.

@sweetmantech

Copy link
Copy Markdown
Collaborator Author

Ordering fix verified live — valuation first (49b2fc14)

Per sweetman's review: valuation is the headline data customers arrive with from the funnel, so it leads. The page-level tasks container is gone — HomePage is byte-identical to main (1853 now touches zero shared components, same as 1852); TasksModule composes into the empty-state header beneath the hero, self-hiding when empty.

Verified on the retriggered preview (Vercel dropped the webhook for the original push — nudged with an empty commit 9e9095da): DOM order is ESTIMATED CATALOG VALUE ($8.1M) → YOUR LABEL AT WORK (5 runs) → chat input.

valuation first

Knock-on for chat#1854 at re-target: its modules prop no longer needs to carry the tasks module (it lives in the header now) — 1854 slims to prompt chips + docked layout.

🤖 Generated with Claude Code

@sweetmantech sweetmantech merged commit 4f58109 into main Jul 7, 2026
4 checks passed
sweetmantech added a commit that referenced this pull request Jul 7, 2026
…and bar (chat#1850)

Slimmed at re-target after chat#1852/#1853 merged: the hero and tasks
module now live inside ChatGreeting, so the modules prop this PR
originally carried is dead — deleted (YAGNI). What remains is this PR's
real addition: suggestedPrompts chips above the empty-state input, wired
to whichever homepage modules have data, plus one unified empty-state
layout (flex spacers center short content exactly as before; a tall
header scrolls with the input docked beneath — fixes the clipping risk
the taller hero+tasks header created).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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