Skip to main content

Scheduling Interface

The Schedule UI enables users to configure automated, recurring work generation runs. It provides controls for enabling/disabling automation, selecting cadence, managing billing modes, configuring failure thresholds, and triggering immediate runs.

Component Hierarchy​

WorkSchedulePage (server component)
|
+-- WorkScheduleHeader
| +-- Page title
| +-- Subtitle with work name
|
+-- WorkScheduleCard
|
+-- ScheduleEmptyState (if no schedule)
| +-- Repeat icon
| +-- Empty state title + description
| +-- Refresh button
|
+-- ScheduleForm (if schedule exists)
+-- Header (title + subtitle)
+-- Summary chips (status, next run, last run, failures)
+-- ActiveProvidersBar (active AI/pipeline providers)
+-- Form fields (2-column grid):
| +-- Automation toggle (Switch)
| +-- Billing mode selector (subscription/usage) OR PR toggle
| +-- Cadence selector (hourly/daily/weekly/monthly)
| +-- Max failures input (1-10)
| +-- Pipeline override selector (optional)
| +-- Create Pull Request toggle
+-- Action buttons: Run Now, Save, Cancel

Key Components​

WorkScheduleHeader​

File: apps/web/src/components/works/detail/schedule/WorkScheduleHeader.tsx

A simple header card displaying the page title and a subtitle personalized with the work name.

WorkScheduleCard​

File: apps/web/src/components/works/detail/schedule/WorkScheduleCard.tsx

The main schedule management component. If no schedule exists, it shows an empty state with a refresh button. Otherwise, it renders the full ScheduleForm.

type WorkScheduleCardProps = {
schedule: WorkScheduleDto | null;
pipelineProviders?: ProviderOption[];
activeProviders?: ResolvedProvider[];
};

ScheduleForm​

The core form component (internal to WorkScheduleCard) that manages all schedule configuration.

Data Model:

interface WorkScheduleDto {
status: WorkScheduleStatus; // ACTIVE | PAUSED | CANCELLED
cadence?: WorkScheduleCadence; // HOURLY | DAILY | WEEKLY | MONTHLY
billingMode?: WorkScheduleBillingMode; // SUBSCRIPTION | USAGE
nextRunAt?: string; // ISO datetime
lastRunAt?: string; // ISO datetime
failureCount: number;
maxFailureBeforePause: number; // default: 3
alwaysCreatePullRequest: boolean;
providerOverrides?: { pipeline?: string };
allowedCadences?: { cadence: string; allowed: boolean }[];
subscriptionsEnabled: boolean;
planCode?: 'free' | 'standard' | 'premium';
}

Form Fields​

Summary Chips​

Four read-only summary cards displayed at the top of the form:

ChipValue Source
Statusschedule.status mapped to localized label
Next Runschedule.nextRunAt rendered via ShowDateTime
Last Runschedule.lastRunAt rendered via ShowDateTime
FailuresfailureCount / maxFailureBeforePause ratio

Automation Toggle​

A Switch component that enables or disables the schedule. When enabled, the schedule will execute at the configured cadence.

Cadence Selector​

A Select dropdown with four options:

CadenceCron EquivalentDescription
HOURLY0 * * * *Every hour
DAILY0 0 * * *Once per day
WEEKLY0 0 * * 0Once per week
MONTHLY0 0 1 * *Once per month

When subscriptions are enabled, cadence options are restricted by the user's plan. Disallowed cadences are rendered as disabled options. A HelperPill displays whether the selected cadence is allowed on the current plan or requires usage-based billing.

Billing Mode (Subscription-Only)​

Visible only when subscriptionsEnabled is true:

ModeDescription
SUBSCRIPTIONRuns are included in the subscription plan allowance
USAGERuns are billed per execution (pay-as-you-go)

If the selected cadence is not allowed on the current plan, the billing mode must be set to USAGE.

Max Failures Before Pause​

A numeric Input field (range: 1-10) controlling how many consecutive failures are tolerated before the schedule is automatically paused. Displays as {failureCount}/{maxFailureBeforePause} in the summary.

Pipeline Override​

Visible when multiple pipeline providers are configured. Allows overriding the default pipeline for scheduled runs:

interface ProviderOption {
id: string;
name: string;
configured: boolean;
}

Unconfigured providers are shown but disabled in the dropdown. The "Inherit" option uses the work's default pipeline.

Create Pull Request Toggle​

A Switch controlling whether scheduled generation runs create a git pull request for review rather than committing directly.

Action Buttons​

ButtonActionDisabled When
Run NowrunWorkSchedule(workId)Loading, or schedule status is not ACTIVE
SaveupdateWorkSchedule(workId, formData)Loading
CancelcancelWorkSchedule(workId)Loading

Each action uses a separate useTransition for independent loading states: isSaving, isRunning, isCancelling.

State Management​

WorkScheduleCard
|
+-- ScheduleForm
|-- form.enable: boolean
|-- form.cadence: WorkScheduleCadence
|-- form.billingMode: WorkScheduleBillingMode
|-- form.maxFailureBeforePause: number
|-- form.alwaysCreatePullRequest: boolean
|-- form.pipelineOverride: string | undefined
|-- isSaving: boolean (useTransition)
|-- isRunning: boolean (useTransition)
|-- isCancelling: boolean (useTransition)

The form state is initialized from the schedule prop via deriveFormState() and re-derived whenever the schedule prop changes (via useEffect).

Background Task Integration​

The schedule dispatcher runs as a Trigger.dev cron task defined in packages/tasks/src/tasks/trigger/work-schedule-dispatcher.task.ts:

export const workScheduleDispatcherTask = schedules.task({
id: 'work-schedule-dispatcher',
cron: `*/${interval} * * * *`, // configurable interval
run: async () => {
const dispatcher = appContext.get(WorkScheduleDispatcherService);
const dispatched = await dispatcher.dispatchDue();
return { dispatched, intervalMinutes: interval };
}
});

This cron task checks for due schedules and dispatches generation tasks at the configured interval.

ActionServer Action FunctionHTTP Method
Update scheduleupdateWorkSchedule(workId, formData)PATCH
Run immediatelyrunWorkSchedule(workId)POST
Cancel schedulecancelWorkSchedule(workId)POST

Internationalization​

All strings use next-intl under these namespaces:

  • dashboard.workDetail.schedule.page -- page header title and subtitle
  • dashboard.workDetail.schedule.card -- form labels, summaries, actions, cadence labels, billing labels, error messages, success messages
  • dashboard.workDetail.schedule.card.cadence.* -- cadence option labels (hourly/daily/weekly/monthly)
  • dashboard.workDetail.schedule.card.plans.* -- plan names (free/standard/premium/unmetered)

Cross-References​