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