Find Trigger task groups
Trigger.dev tasks live in trigger/*.ts and are the production scheduler for
connector refreshes, reports, document lifecycle, and health watchdogs. This page indexes every
task; four groups get their own deeper page.
Customer portal delivery
All portal tasks share the sable-portal-notifications queue with concurrency one:
| Task id | Cadence | Purpose |
|---|---|---|
sable.portal.notifications.dispatch | */2 * * * * | Materialize outbox events and deliver immediate email |
sable.portal.notifications.digest.daily | Daily, 08:15 America/New_York | Deliver due daily digest batches |
sable.portal.notifications.digest.weekly | Monday, 08:30 America/New_York | Deliver due weekly digest batches |
sable.portal.notifications.digest.retry | */15 * * * * | Reclaim due daily and weekly digest retries |
sable.portal.notifications.reminders | Weekdays, 09:05 America/New_York | Enqueue due request, review, and milestone reminders, then dispatch |
sable.portal.attachments.cleanup | Daily, 03:35 America/New_York | Remove unpublished private file drafts older than 24 hours |
sable.portal.notifications.health | Not scheduled; run by hand | Report delivery readiness (gate, Resend key and sender, provider reachable, sender domain verified) without sending anything |
Each task invokes the scheduled-caller-only portal-notifications Edge Function and retries the invocation up to five times. The database owns outbox, delivery, digest-batch, and attachment-cleanup leases. See Release the customer portal for production checks.
Customer portal automation
Two opt-in automations, each set per client in Customer tabs & automation. A client with no policy row, or with the switch off, is skipped. Neither automation approves or publishes a draft. Both act as the lead who last saved the settings; if that person loses the admin/lead role, nothing is drafted or released until another lead saves the settings.
| Task id | Cadence | Purpose |
|---|---|---|
sable.weekly-update.draft | Friday 12:00 America/New_York | Plan pass: list clients with "auto draft weekly update" on and fan out one child run per active, current, non-internal project |
sable.weekly-update.draft.project | Child of the above | Create the weekly update draft for one project through the same path as POST /api/weekly-update. It lands as a pending_approval draft; a person still approves it |
sable.portal.auto-release | Hourly (0 * * * *) | For every client with automatic meeting sharing on, write a short AI client summary for qualifying meetings that have none (at most 10 per run, 3 per client, rotating which client goes first each hour), then ask auto_release_client_meetings to share them |
sable.portal.auto-release.client | On demand, payload { clientId } | The same pass for one client. Saving the policy with sharing newly on starts it so the lead does not wait for the hour |
The drafting tasks run on their own queues and dedupe per project and ISO week, so a retry never
creates a second draft. Auto-release shares meeting title and summary as ordinary, withdrawable
portal publications; the recording link is included only when the client's recording-link setting
is on (off by default). When a qualifying meeting has no summary of its own, the task first writes a
short client summary (2–4 sentences) with the portal-draft AI's auto_release mode
(web/api/_portal_drafts.js), acting as the lead who saved the policy. That mode reads only the
note-taker's summary (metadata.default_summary), never the transcript or meeting record. It discards
output that runs over 1,200 characters or contains any of the following:
- an email address, including spelled-out or mixed forms (
(at),[at]or@, then(dot),[dot],dotor.; oratwith a spelled-out dot) - a phone number: 10 or more digits, unless they are made up only of ISO dates and 19xx/20xx years
- any percentage: a number with
%, or the wordspercent,per centorpctwith or without a number - a currency symbol next to a number, an uppercase ISO currency code next to a number (so lowercase words such as "try" and "cad" pass), or a currency word (dollars, euros, pounds, bucks, cents, pence, rupees, yen, francs)
- an amount with a size word or suffix (
k,m,mm,bn, thousand, million, billion) - a rate:
perfollowed by hour, day, week, month, year, annum, seat, user, license, head or person; a slash rate (/hr,/hour,/day,/wk,/week,/mo,/month,/yr,/year,/seat,/user); or a number followed bya/anand hour, day, week, month or year
Only meetings from the last 30 days are drafted. The task stores the summary in sources.metadata.portal_summary with
portal_summary_generated_at. The release function shares it for 7 days; after that, an unshared
meeting is drafted again. It never overwrites a meeting's own summary, a staff-written
portal_summary, or a meeting with any publication. Writing the summary does not share the meeting;
the release function does that. Without ANTHROPIC_API_KEY the task skips drafting with a warning.
Every failed attempt is counted (portal_summary_attempts): a transient failure is retried next run
until the third attempt, then daily. A permanent failure (ineligible, no note-taker summary, rejected
or unusable output) waits a day at once. After 5 attempts the meeting is never drafted again; staff
can still publish it manually. Both automations stand down quietly until the
portal_policies migration has been applied.
Find connector refresh tasks
| Task id | Cadence |
|---|---|
sable.fathom.reconcile | 15 * * * * |
sable.granola.poll | 5,35 * * * * |
sable.asana.sync | 25 */2 * * * |
sable.toggl.hours | 55 */4 * * * |
sable.calendar.freebusy | 40 * * * * |
sable.drive.refresh (+ .continue) | Not scheduled; retired in #217 and kept invokable by hand |
sable.email.ingest | */10 * * * * |
sable.email.drain | 35 */2 * * * |
Find report and board tasks
| Task id | Cadence |
|---|---|
sable.report.morning | weekdays, 06:00 America/New_York |
sable.report.eod | weekdays, 16:30 America/New_York |
sable.learning.daily | weekdays, 17:00 America/New_York |
sable.report.deliver | invoked by the above, not independently scheduled |
Find document and cleanup tasks
| Task id | Cadence |
|---|---|
sable.document.reconcile-ingest-jobs | */15 * * * * |
sable.document.storage-purge-sweep | */10 * * * * |
sable.document.storage-purge | invoked per tombstone, not on a schedule |
sable.document.backfill-index-batch | invoked, not scheduled |
sable.feedback.retention | daily, 15 3 * * * |
sable.file-build.run | invoked per chat build request, payload { buildId }; off unless SABLE_FILE_BUILDS=on. Builds one .xlsx, a .pptx when SABLE_FILE_BUILD_PPTX=on too, or a .docx when SABLE_FILE_BUILD_DOCX=on (cleaned of comments, custom properties and author names before the check), or, when SABLE_FILE_BUILD_PDF=on and the request asks for it, a PDF of that file converted in the same sandbox run (or a document's brief as a web page when SABLE_FILE_BUILD_HTML=on, with no sandbox), with Anthropic's Agent Skills, checks it, and saves it as the requester's Library draft (spec) |
Find watchdog tasks
| Task id | Cadence |
|---|---|
sable.report.watchdog.morning | weekdays, 06:45 America/New_York |
sable.report.watchdog.eod | weekdays, 17:15 America/New_York |
Approvals, chat, portfolio, and smoke
These tasks run on demand:
| Task | Purpose |
|---|---|
sable.approval.execute | Claims and executes an approved Asana/Calendar write, replacing the emergency-fallback direct asana-act call path |
sable.chat | The durable Trigger chat agent (chat.agent), using a Trigger-managed prompt (sableChatSystemPrompt) rather than an inline string |
sable.portfolio.ingest-baseline, sable.portfolio.daily | Preview-only diff of the retired Drive workbook (manual; never writes project records), and daily reconciliation |
sable.smoke | The minimal live-environment check described in Observability |
Where the code lives
trigger/*.ts: one file for each task grouptrigger/queues.ts: the two shared queues (sable-connectors,sable-connector-writes) most connector and write tasks run through, controlling concurrency independently of scheduling.trigger/lib/: shared helpers (supabase.ts,edge.ts,env.ts,document-runtime-deps,portfolio-workbook, etc.).