Repository navigation
docs: timezone in schedules, time to next run, short last check on scheduled refreshes and tasks (CUB-5559) - #12283
Conversation
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Automations to automatically generate PRs for you. |
|
Claude finished @mngr's task in 1m 17s —— View job Looks good overall, no blockers: 0 high, 1 medium, 1 low. Merge only after cubedevinc/cubejs-enterprise#16573, as the description says. Review details
Findings
Checked, no issues
Review threadsThe listing returned 0 of my threads, so none were resolved or re-affirmed. |
|
Claude finished @mngr's task in 1m 26s —— View job Review: looks good apart from wording fixes: 0 high, 1 medium, 2 lowDetails
Inline findings
Checked and fine
Not verifiable from this repo: UI strings such as "met, nothing sent", "Every run" and "Not scheduled", which live in cubejs-enterprise#16573. I relied on the PR description's walk-through for those. Review threads: the listing returned 0 of my threads. I resolved none and re-affirmed none (no prior threads). |
|
Claude finished @mngr's task in 1m 16s —— View job Looks good to merge once cubedevinc/cubejs-enterprise#16573 lands. 0 high, 0 medium, 2 low. Review details
FindingsLow
Checked
Review threadsThe listing returned 0 of my own threads, so there was nothing to resolve or re-affirm. |
…eduled refreshes and tasks (CUB-5559)
|
Claude finished @mngr's task in 1m 0s —— View job LGTM. No correctness issues found: 0 high, 0 medium, 2 low (not posted inline). Review detailsChecks
FindingsAll the new anchors resolve: You said only medium- and high-severity fixes go into this PR, so these two low-severity editorial notes are not posted inline:
Review threadsThe listing returned 0 of my own unresolved threads (no prior threads), so nothing was resolved or re-affirmed. |
…uns (CUB-5670) (#12266) Depends on cubedevinc/cubejs-enterprise#16532 (and its base cubedevinc/cubejs-enterprise#16531): do not merge before them. Also merge it together with, or after, the cube-js/cube API reference sync for the first `@cube-dev/platform-client` release that carries `notification` (cubedevinc/cubejs-enterprise#16532 adds the field and rewrites the `condition` descriptions in `packages/platform-client/src/schema.ts`): until that sync, `docs-mintlify/api-reference/api.yaml` has no `notification` field and still says the creator gets an inbox row only with `notificationEnabled: true`, which this page's Platform API section contradicts. ## Summary A scheduled task now notifies chosen people, user groups and Slack channels, by Inbox, Email and Slack together, instead of only its creator in the inbox. Rebased on master after #12283 (CUB-5559: list columns, Next run, Last check), #12307 (the **Manage all scheduled tasks** permission), #12309 (the task's **Agent**) and #12368 (data-model access in scheduled runs, a section this PR does not touch); their merged wording is the base. This PR updates: - `docs-mintlify/docs/explore-analyze/scheduled-tasks.mdx` - *Where to find it*: the list's **Notifications** column now says where a task's notifications go ("Inbox, Email · 3 people, 1 group · #sales, #finance-alerts", or "Nobody is notified"), and links the renamed section. - *Anatomy of a task*: the **Notify me when a run finishes** toggle becomes the **Notify** section. - *Conditional tasks*: recipients other than the creator, and Slack, are told the condition started to hold without the figures. A task with a condition must notify someone: the dialog's **Create** (or, when editing, **Update**) button stays disabled and says why, the agent refuses, and the Platform API refuses when the request sets `notification` (a request without that field is saved, as before). - *Managing tasks*: anyone the task is shared with can open its runs' threads, view-only (previously: sharing the task did not share its threads). - *Task detail page*: a **Notifies** line, as in the list's column. - *Last check*: the example of a task that notifies nobody is one created through the Platform API without a `notification` field. - *Getting notified when a run finishes* is rewritten as *Notifying people when a run finishes*: people and groups (expanded when the run finishes, one message per person), **Send by** Inbox / Email / Slack (Inbox and Email go to everyone picked; one or more Slack channels), the creator picked by default, what each notification carries, sharing on save of a new pick (dialog, agent and Platform API alike), who a run reaches (the creator, plus people who can open the task and read its deployment), and the two ways a picked person is skipped and marked **Not shared: won't be notified** (their share was removed in the **Share** dialog, or they can't read the deployment), notifications going to recipients whoever runs the task, email unsubscribe, a failed run reaching only the creator, and the agent and Platform API. - The agent paragraph of that section: channels belong to the whole task, so asking the agent to notify one more person by inbox turns **Inbox** on for everyone the task notifies, and the agent says so. - *Managing tasks from chat* and *with the Platform API*: the new `notification` field and its caps; `notificationEnabled` deprecated. - `docs-mintlify/docs/inbox.mdx`: the Scheduled task run row's "Who gets it", the figures shown only in the creator's notification, email/Slack from a task, and the anchor rename. ## Verified against the code (feature branch HEAD `e22eb3290b`) - Labels are the en-US keys in `packages/console-ui/src/i18n/locales/en-US/scheduledTasks.json`: `notifyLabel` "Notify", `notifyRecipientsLabel` "People and groups", `notifyChannelsLabel` "Send by", `notifyRecipientNotShared` "Not shared: won't be notified", `notifySlackChannelsDescription` "Slack posts once to each channel. Inbox and Email go to the people above.", `summary.notifiesNobody` "Nobody is notified", `detail.notifies` "Notifies". - The list's Notifications cell and the detail page's Notifies line both render `useNotificationSummary` (`task-notification.ts`; `ScheduledTaskListCells.tsx`, `ScheduledTaskInstructions.tsx`); Inbox drops out of it when the workspace's inbox is off (`deliveredNotification`). The hand-off walk on staging-mngr-7 read "Inbox, Email · 4 people, 1 group" and "Inbox · 3 people, 1 group". - The list's Last check reads "notified" when a crossing reaches anyone, not only the creator (`taskOutcome(check, notifiesAnyone)`). - The condition rule: `ScheduledTaskService.assertConditionNotifies` holds a save only when it sends `notification` (`sendsNotification`) or the agent's update asks for it; the agent's create tool always sends `notification` (`CreateScheduledTaskToolFactory.ts:112`). - Who a run reaches: `AiEngineerController.notifyScheduledTaskRecipients` expands groups at send time, de-duplicates, keeps only the creator on a failed run, and skips any non-creator for whom `AiEngineerService.canViewScheduledTask` (a ScheduledTask read grant or admin, plus deployment read) is false; Inbox is sent only with the tenant's `useNotificationInbox` on. - Caps: `NOTIFICATION_CAPS = { userIds: 1000, groupIds: 200, slackChannels: 50 }` (`packages/ai-engineer/src/dto/scheduled-task.ts:290`). - Sharing on pick: `ScheduledTaskService.grantRecipientShares` runs on every create and update (the dialog, the agent's `createTask`/`updateTask` tools and the REST controller all call the service), sharing only recipients the save ADDS and only if not already shared, so a share revoked in the Share dialog is not restored by a later save. The "Not shared" mark for a user is `recipientUserIdsWithoutAccess`, console-server's `findUsersWithoutScheduledTaskAccess` = `canViewScheduledTask` (task read grant or admin, AND deployment read), so a shared user who cannot read the deployment is marked too (PLAN AC-7d); a group is marked when it has no group grant and no organisation grant. - Channels are task-wide on the agent's path too: `NOTIFY_ARGUMENTS_DESCRIPTION` (`packages/ai-engineer/src/services/langgraph/tools/scheduled-task-recipients.ts:29`, "for the whole task") and the update tool's `channelsChanged` note (`channelChangeNote`, same file, "Channels are shared by everyone this task notifies … Tell the user."). The r3 hand-off walk on staging-mngr-7 asked the agent to also notify a second person in the inbox on an Email-only task: the stored channels became Inbox + Email for both, and the agent's reply said so. - The two feature commits since the last docs pass (`7e097cebb6` Slack picker error handling, `1257d35839` a failed task email answers 503) change nothing the pages describe. - The task dialog's submit button reads `dialog.submitCreate` "Create" on a new task and `dialog.submitUpdate` "Update" when editing (`ScheduledTaskDialog.tsx:203`); the r4 hand-off walk on staging-mngr-7 read "Create disabled" with the red line and Create's tooltip `conditionNeedsNotification`. The page used to call it **Save**; it now names both. - The feature commits since the last docs pass (`8904d17d1e` keeps the dialog's 12 px field gap around the condition switch and the Notify section, which Igor flagged after the hand-off; the Slack OAuth listener refactor `773666a9d9`/`baed62646a`; `50546100b7` drops a removed kit prop; `e149367c86` a failed task email answers 503) change no behaviour the pages describe. The hand-off, re-posted for the spacing fix, says nothing else changed. - A new task in the dialog starts with the creator picked and Inbox on; a task created by the agent or the API without a `notification` notifies nobody. Feature PR: cubedevinc/cubejs-enterprise#16532 Linear: https://linear.app/cube-d3/issue/CUB-5670/notify-other-people-about-scheduled-task-runs --------- Co-authored-by: Gleb <gleb@Glebs-MacBook-Air-2.local>
…ecks (CUB-5218) (#12306) Depends on cubedevinc/cubejs-enterprise#16509 and its part PRs cubedevinc/cubejs-enterprise#16507 (chat tools), cubedevinc/cubejs-enterprise#16508 (public API `alert`), and cubedevinc/cubejs-enterprise#16825 (sidebar status retry). **Do not merge this before cubedevinc/cubejs-enterprise#16509 merges.** Before that, the page describes % change and Anomaly on a KPI, which the product does not yet offer. ## Summary Data alerts' **% change** and **Anomaly** rules now work on a chart or KPI with no time dimension. On such a chart the alert remembers the value each check reads and compares with those values: % change with the previous check, Anomaly with the normal range of the earlier checks, once there are 8. The chat agent can list, create, change and delete a dashboard's scheduled refreshes together with their alert. The public notifications API takes an `alert` field. - `docs/explore-analyze/data-alerts.mdx` - **% change** / **Anomaly**: what each compares with on a chart with and without a time dimension, and the "vs the previous period" / "vs the previous check" suffix. - **Which charts support which rule**: a chart without a time dimension now supports every rule type (it used to say Threshold only). It quotes the dialog's checks line. - **What an alert checks**: the single-value paragraph names the comparison with previous checks. - New **Comparing with previous checks** section: - what is remembered: the last 30 checks; Threshold alerts and time charts remember nothing; - the first check's "no earlier check" line and the Anomaly "Needs 8 earlier checks, has N." count (only the creator sees the count; anyone else reads "Needs 8 earlier checks."); - Run now is a check, compared and remembered like a scheduled one; - what remembers nothing: no number read, or a fire that reached no one; - what keeps the remembered values and what discards them; republishing keeps them. - **When an alert notifies**: turning the schedule off still resets the notify-once state, but keeps the remembered values. - **The notification**: the email's previous-check and earlier-checks lines, and a check-based Slack sentence. - **Following an alert in the sidebar**: rebased onto master's CUB-5559 rewrite (#12283, the short "Last check: 3 minutes ago, …" line with the full check on hover), kept as merged. Added: the "vs the previous check" ending of the "Condition:" summary, and the hover's "Previous check …" / "Normal range of the earlier checks" lines on a chart without a time dimension, and that after **Run now** the open card shows the new check by itself (a run can take a few minutes). - **When a check can't run**: the check-based reasons, and that such a check still remembers a value it read. - New **Managing alerts from chat** and **Managing alerts through the API** sections. **Managing alerts from chat** says the agent never makes an alert on a chart of a published dashboard into a scheduled task with a condition: the alert belongs to that dashboard's scheduled refresh. - `docs/explore-analyze/scheduled-refreshes.mdx`: - **Managing schedules** → **Next run**: until an enabled schedule's status has been read (loading, or the read failing), a placeholder stands in for **Next run** and **Last check**, and the card asks again every few seconds. - **Managing schedules** → **Schedule**: a custom cron that matches no preset is now described in full ("At 09:00 AM, Monday through Friday UTC"), not shown as written. This sentence was made false by cubedevinc/cubejs-enterprise#16776 (CUB-5994, already on master: `describeSchedule` → `cronSentence`, cronstrue; `node -e "require('cronstrue').toString('0 9 * * 1-5')"` → "At 09:00 AM, Monday through Friday"), corrected here as an adjacent defect. - new **Managing schedules from chat** section, covering: - what the agent can do; - email to Cube users only (Slack, groups and control values stay in the dialog); - Edit/Manage needed to change a schedule; - last-check values shown to the creator only; recipients told only to those who can edit the schedule, anyone else told they are hidden; - no tools in published-dashboard or embedded chat. - `docs/explore-analyze/scheduled-tasks.mdx` → **Managing tasks from chat**: when data alerts are on, an alert on a chart of a published dashboard is not a task; it belongs to that dashboard's scheduled refresh, and the agent doesn't create a task for it. - `api-reference/api.yaml`: mirrors the regenerated public spec's change only: - the `DataAlertRule` / `DataAlertRuleInput` schemas and their enums; - `alert` on `NotificationDto` and `UpdateNotificationInput`; - the create and update notification descriptions. I produced it by running `scripts/extract-api.mjs` on master's `open-api-spec-public-v3.1.yaml` and on the head's, then applying the difference (6 hunks). That keeps it independent of master's other unreleased spec changes, which `api.yaml` (synced per platform-client release) does not carry yet. ## Verified against the code - **Form.** On the round-2 hand-off walk (staging-mngr-6, `handoff-run-r2.log`, 2026-10-19; unchanged on the round-3 and round-4 walks, `handoff-run-r3.log` / `handoff-run-r4.log`, 2026-10-21/22), a KPI with no time axis showed: - all three rule-type tabs enabled; - the suffix "vs the previous check"; - the checks line "Compares with the values this alert read on its previous checks."; - the anomaly hint; - no checks line under Threshold. The rule saved as `timeColumn: null`, `grain: null`. - **Comparison.** `evaluateAgainstChecks` (`ai-engineer/.../alerts/evaluate-alert-rule.ts`): - % change takes the last remembered point; - a previous 0 gives `previous-zero`; - Anomaly needs `DATA_ALERT_ANOMALY_MIN_POINTS` (8) and uses `medianMadBand` over the remembered values. - **What is remembered.** `alert-history.ts`: - `checkPointOf` remembers only a check-based verdict that read a number; - `appendCheckPoint` keeps `DATA_ALERT_CHECK_HISTORY_MAX` = 30; - `historyFor` / `keepsHistory` key on rule id, series and `filterParams`. `prepareDataAlertRule` keeps the rule id unless `dataAlertConditionKey` changes (chart, report, measure, type, direction, percent). - **Live checks** (walk log): - first check: line "Last check: less than a minute ago, could not check", hover "… could not check. There is no earlier check to compare with yet. Nothing sent."; - Anomaly: "Needs 8 earlier checks, has 0." and then "has 1." for the creator; "could not check. Needs 8 earlier checks. Nothing sent." for a non-creator on the same card (round-3 walk, run 4452); - after Run now with the sidebar left open, the card showed the new check with no reload; the round-3 walk measured 21–224 s from press to card, hence "a run can take a few minutes"; - after republishing the KPI: line "Last check: less than a minute ago, Count decreased by 50%, notified", hover "Last check Oct 19, 2026, 3:05 PM GMT+1: Count 20,003. Previous check Oct 19, 2026, 3:04 PM GMT+1: 40,000, -50%. Condition met, notified." This shows that republishing keeps the remembered values; - after a cron edit the last check is unchanged; - summary "Condition: Count decreases by ≥ 10% vs the previous check · Orders count". Pause and resume keeping the values: AC-5c, `verify-5-kept-through-edit-and-pause-has-3.png`. - **Email and Slack.** The en-US email keys `alertPreviousCheckValue`, `alertNormalRangeOfChecks` and `alertComparedWithPreviousChecks` (cloud-router). The Slack sentence comes from `alertStatement`'s `basis === 'checks'` branch; its format is pinned by `alert-notification.spec.ts`. - **Sidebar strings.** en-US `creatorMode.json`: `summary*Checks`, `lastCheckPreviousCheck`, `lastCheckBandChecks`, `reasonNoEarlierCheck`, `reasonTooFewChecks`, `reasonPreviousCheckZero`. - **Chat tools.** `DashboardScheduledRefreshToolsFactory.ts`: - email to `recipientUserIds`, or the current user when none are named; no Slack, groups or control values; - bound when `useScheduledRefreshes`, which `AiEngineerService` sets off for an embed session; - stripped from published-dashboard chat through `publishedDashboardUnsafeTools`; - writes need `WorkbookEdit` (`verify-11-read-only-user-refused.png`); - list values are withheld for a non-creator (`alertCheckForViewer`); - a caller who cannot edit the run gets `recipientsWithheld: true` instead of a recipient list (`describeRecipients`; console-server's `serializeScheduledRun` nulls the ids unless `viewer.canEdit`), and the description says never to report that as no recipients. Round-3 walk: the non-creator's chat reply named no "no recipients". - **Status placeholder.** `NextRunCell` / the last-check cell render `Placeholder` while `run.isEnabled && run.isStatusPending && !run.hasStatus`; a failed read leaves the run pending and joins the 5 s status poll (`use-scheduled-refreshes.ts`, cubedevinc/cubejs-enterprise#16825, spec AC-6g in `ScheduledRefreshSidebar.spec.tsx`). - **Run now on the open card.** `use-scheduled-refreshes.ts` keeps polling a Run now's status until it reports the run finished, then up to `RUN_NOW_CHECK_WAIT_MS` (60 s) more for the stored check. - **Chat routing of a dashboard alert** (cubedevinc/cubejs-enterprise#16507, `730cdb4add`): - `createDashboardScheduledRefresh`'s description says an alert on a published dashboard's chart is always set up there; - `createScheduledTask`'s says a task condition watches a measure outside any dashboard. It adds that clause only when `useScheduledRefreshes && useDataAlerts`, hence "when data alerts are turned on"; - the Chassis `schedule-tasks` skill says such an alert "is a scheduled notification on that dashboard, not a task" and points to the dashboard's schedule settings. So the page promises "never a task", not that the agent always creates the refresh itself; - round-4 hand-off walk (`handoff-run-r4.log`, [WALK 12], 2026-10-22): "Email me when the Orders count KPI … goes above 1000. Check every day at 9:00 UTC." made `createDashboardScheduledRefresh` 1 call and `createScheduledTask` 0. It created refresh 5050 with a `threshold`/`gt`/1000 alert on the KPI (`timeColumn: null`), and its card read "Condition: Orders Count is above 1,000 · Orders count". - **Public API.** The regenerated `open-api-spec-public-v3.1.yaml` on the feature branch. Feature PR: cubedevinc/cubejs-enterprise#16509 Linear: https://linear.app/cube-d3/issue/CUB-5218/data-alerts-percent-change-and-anomaly-rules-for-kpi-charts --------- Co-authored-by: Gleb <gleb@Glebs-MacBook-Air-2.local>
Depends on cubedevinc/cubejs-enterprise#16573. This page describes that PR's behaviour and must not merge before it.
Summary
Updates the docs for the schedule-clarity change on scheduled refreshes and scheduled tasks. The branch was rebuilt on master after #12258 (CUB-5556: the hover Edit button, the ⋯ shown on hover, the viewer-only Subscribe column) merged. Its wording on
scheduled-refreshes.mdxis kept as merged.scheduled-refreshes.mdx)TimezonePickeroffers 424 zones, andgetBrowserTimezonefalls back to UTC only for a zone the runtime can't resolve.data-alerts.mdx): rewrote "Following an alert in the sidebar" for the short last-check line ("Last check: 3 minutes ago, Count increased by 2.7%, notified"). It covers:scheduled-tasks.mdx):google-sheets-deliveries.mdx): the list and the dialog name each cron with the delivery's timezone. A cut schedule shows whole on hover.What I verified against the code
Checked against the feature branch (
mentor/cub-5559-improve-schedule-clarity-in-scheduled, HEAD2bf1a42753) and the round-4 hand-off walk on staging-mngr-9 (deployment 1259, dashboardVOXtdT7bUW6R,handoff-walk-r4.log):formatDurationinuse-schedule-labels.ts(1fb26501e1) gives minutes below an hour, then rounded hours below 24, then rounded days.formatTimeUntil(7add8d07d5) givesrelative.soon"in less than a minute",relative.dueNow"due now" andrelative.dueAgo"due {{duration}} ago".formatDateTimeusestimeZoneName: 'short'.NextRunTime(ScheduledTaskListCells.tsx:41).relativeTimeTooltip). A non-creator reads "1 minute ago, still met, not notified again", with "values not shown, as it ran with the access of the schedule's creator" on hover.TextItem(b5c204e8ca).scheduleSortKey(schedule.ts) is rank|day|minutes-of-day|zone. The walk's ascending order: Hourly :05, Hourly :30, Daily 7:00 AM, three 9:00 AM schedules (America/Argentina, America/New_York, UTC), 10:00 AM, 1:00 PM, Weekly Mon, Weekly Wed, Monthly day 1, Monthly day 15, then0 9 * * 1-5. On the tasks list, Manual sorts last.TextItem(report-delivery-cells.tsx:200, dac983b035).Feature PR: https://github.com/cubedevinc/cubejs-enterprise/pull/16573
Linear: https://linear.app/cube-d3/issue/CUB-5559/improve-schedule-clarity-in-scheduled-refreshes-and-tasks