diff --git a/docs/subsystems/schedule.i18n.yaml b/docs/subsystems/schedule.i18n.yaml index c19e4d3ec6..361b61d322 100644 --- a/docs/subsystems/schedule.i18n.yaml +++ b/docs/subsystems/schedule.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write docs/subsystems/schedule.md -schedule.md: 3a7cbbb46837ff4ea74813eba1f47ed4758457be -schedule.zh.md: 2e24ffbaa6b53d3c5aef4158ecd3783a61b0b1af +schedule.md: 7a867d1c7a9c1853ce60f564c6ce0fc4bd210e5a +schedule.zh.md: 438a733b649d6864b39b1c700b1e68776cf7d2cd diff --git a/docs/subsystems/schedule.md b/docs/subsystems/schedule.md index 3a7cbbb468..7a867d1c7a 100644 --- a/docs/subsystems/schedule.md +++ b/docs/subsystems/schedule.md @@ -2,11 +2,11 @@ English | [中文](schedule.zh.md) -Schedule owns durable reminders that return to the original live Session as ordinary later conversation turns. The [durable Schedule Agent Note](../../.agents/notes/implemented/feature/2026-08-05-durable-web-schedule.md) owns the persistence and lifecycle decisions, [conversational delivery](../../.agents/notes/implemented/simplification/2026-08-09-conversational-schedule-delivery.md) owns the no-receipt boundary, and the [explicit time-zone boundary](../../.agents/notes/implemented/simplification/2026-08-09-explicit-schedule-time-zone.md) owns browser-local interpretation. This page records the durable and model-facing shapes from [`packages/schedule/tool-schedule/src/types.ts`](../../packages/schedule/tool-schedule/src/types.ts); the [package README](../../packages/schedule/tool-schedule/README.md) owns composition, tool behavior, and the exact reminder framing. +Schedule owns durable reminders that return to the original live Session as ordinary later conversation turns. The [durable Schedule Agent Note](../../.agents/notes/implemented/feature/2026-08-05-durable-web-schedule.md) owns the persistence and lifecycle decisions, [conversational delivery](../../.agents/notes/implemented/simplification/2026-08-09-conversational-schedule-delivery.md) owns the no-receipt boundary, the [explicit time-zone boundary](../../.agents/notes/implemented/simplification/2026-08-09-explicit-schedule-time-zone.md) owns browser-local interpretation, and [bounded fixed-rate Schedule](../../.agents/notes/implemented/simplification/2026-08-09-bounded-fixed-rate-schedule.md) owns recurrence. This page records the durable and model-facing shapes from [`packages/schedule/tool-schedule/src/types.ts`](../../packages/schedule/tool-schedule/src/types.ts); the [package README](../../packages/schedule/tool-schedule/README.md) owns composition, tool behavior, and the exact reminder framing. ## Durable records -`ScheduleId` is a [branded id](core.md#branded-ids), unique and never reused within one Session. Version 1 supports either a positive safe-integer `after_seconds` delay or an explicit absolute `at` target. Creation canonicalizes either selector into a four-digit-year RFC 3339 UTC `scheduledAt`; an `after` record retains its submitted delay, while an `at` record stores only the resulting instant. +`ScheduleId` is a [branded id](core.md#branded-ids), unique and never reused within one Session. Version 1 supports a positive safe-integer `after_seconds` delay, an explicit absolute `at` target, or a safe-integer `every_seconds` interval of at least five minutes. Creation canonicalizes every first target into a four-digit-year RFC 3339 UTC `scheduledAt`; an `after` record retains its submitted delay, an `at` record stores only the resulting instant, and an `every` record retains its fixed interval and next target. ```ts type-equiv /** Durable one-shot reminder created from a positive delay. */ @@ -38,9 +38,30 @@ interface AtScheduleRecord { } ``` +```ts type-equiv +/** Durable fixed-rate reminder whose next target remains creation-anchor-aligned. */ +interface EveryScheduleRecord { + /** Session-local stable identity. */ + readonly id: ScheduleId + /** Rule discriminator for a fixed-rate recurring reminder. */ + readonly kind: 'every' + /** Trimmed reminder content supplied at creation. */ + readonly prompt: string + /** Fixed safe-integer interval, never below five minutes. */ + readonly everySeconds: number + /** Earliest anchor-aligned occurrence not yet dispatched. */ + readonly scheduledAt: string +} +``` + +```ts type-equiv +/** One-shot record variants that terminate on an id-only dispatch. */ +type OneShotScheduleRecord = AfterScheduleRecord | AtScheduleRecord +``` + ```ts type-equiv /** The v1 durable reminder record union. */ -type ScheduleRecord = AfterScheduleRecord | AtScheduleRecord +type ScheduleRecord = OneShotScheduleRecord | EveryScheduleRecord ``` ## Absolute-time input @@ -68,9 +89,17 @@ The official Web overlay samples the browser's IANA zone for every prompt. Time- Schedule rejects invalid offsets and zones, offset-free strings, non-future targets, and local times inside daylight-saving gaps. A daylight-saving overlap chooses its first, earlier instant. Successful creation stores only canonical UTC `scheduledAt`, so replay never depends on ambient time-zone state. +## Fixed-rate input and catch-up + +`every_seconds` is a per-record interval of at least 300 seconds, anchored to creation time. It is fixed-rate recurrence only: the protocol has no calendar or Cron expression, recurrence time zone, shared cooldown, or cross-record admission gate. + +When a Session was cold or busy across several targets, one Every record contributes only its latest due occurrence. The dispatch advances it directly to the first creation-anchor-aligned target after the dispatch decision time, without enumerating, persisting, or replaying missed intervals. If that next target cannot fit in a four-digit UTC year, the final dispatch terminates the record. + +When multiple distinct Every records are overdue and no one-shot is due, each contributes one occurrence to the same follow-up batch in target and creation order. Every record keeps independent state, while all dispatches in that admitted batch use the same decision time. Batching bounds model turns; the five-minute minimum bounds each record's timer frequency. + ## Durable changes and replay -The version-1 `schedule/change` Session event is the only durable Schedule authority. Create stores the complete record. Delete and dispatch are terminal id-only transitions for one-shot reminders; dispatch means the follow-up was synchronously queued, not that a model answer succeeded or the user read it. +The version-1 `schedule/change` Session event is the only durable Schedule authority. Create stores the complete record, and delete is a terminal id-only transition. A one-shot dispatch is also terminal and id-only. An Every dispatch carries the wall-clock decision time used to select its latest due occurrence and normally advances the active record instead of terminating it. Dispatch means the follow-up was synchronously queued, not that a model answer succeeded or the user read it. ```ts type-equiv /** Creates one durable reminder record. */ @@ -92,19 +121,35 @@ interface ScheduleDeleteChange { ```ts type-equiv /** Records that one active one-shot reminder entered the durable dispatch history. */ -interface ScheduleDispatchChange { +interface OneShotScheduleDispatchChange { readonly version: 1 readonly operation: 'dispatch' readonly id: ScheduleId } ``` +```ts type-equiv +/** Records one fixed-rate decision and advances directly past missed occurrences. */ +interface EveryScheduleDispatchChange { + readonly version: 1 + readonly operation: 'dispatch' + readonly id: ScheduleId + /** Wall-clock decision time used to select the latest due occurrence. */ + readonly acceptedAt: string +} +``` + +```ts type-equiv +/** Durable dispatch shapes supported by the current rule set. */ +type ScheduleDispatchChange = OneShotScheduleDispatchChange | EveryScheduleDispatchChange +``` + ```ts type-equiv /** Strict version-1 durable Schedule mutation union. */ type ScheduleChange = ScheduleCreateChange | ScheduleDeleteChange | ScheduleDispatchChange ``` -The strict decoder and fold reject unknown versions, extra fields, reused ids, and delete or dispatch transitions against inactive records. A normal Session folds its complete event stream. A fork folds only events at or after `SessionHeader.seedLength`, so it retains history without adopting the parent Session's active reminders. The `schedule/change` declaration and source location are also indexed in the [persistence catalog](../persistence-catalog.md#schedulechange--log-only). +The strict decoder and fold reject unknown versions, extra fields, reused ids, mismatched one-shot or Every dispatch shapes, and delete or dispatch transitions against inactive records. A normal Session folds its complete event stream. A fork folds only events at or after `SessionHeader.seedLength`, so it retains history without adopting the parent Session's active reminders. The `schedule/change` declaration and source location are also indexed in the [persistence catalog](../persistence-catalog.md#schedulechange--log-only). ## Active views and management @@ -130,10 +175,12 @@ type ScheduleView = ScheduleRecord & { } ``` -The generated [tool catalog](../tool-catalog.md#deepseek-aidsh-tool-schedule) owns the argument and result schemas for `schedule_create`, `schedule_list`, and `schedule_delete`. Management calls serialize with due work in one Agent-scoped queue. Every read or decision first waits for the shared Session persistence barrier; create and an actual delete wait again after appending. A barrier failure reports `persistence_uncertain` instead of guessing whether an eager write committed. The other stable error codes are `invalid_prompt`, `invalid_selector`, `invalid_rule`, `invalid_time_zone`, `not_future`, `time_out_of_range`, `corrupt_schedule_log`, and `internal_error`. +The generated [tool catalog](../tool-catalog.md#deepseek-aidsh-tool-schedule) owns the argument and result schemas for `schedule_create`, `schedule_list`, and `schedule_delete`. Management calls serialize with due work in one Agent-scoped queue. Every read or decision first waits for the shared Session persistence barrier; create and an actual delete wait again after appending. A barrier failure reports `persistence_uncertain` instead of guessing whether an eager write committed. The other stable error codes are `invalid_prompt`, `invalid_selector`, `invalid_rule`, `invalid_time_zone`, `not_future`, `time_out_of_range`, `frequency_too_high`, `corrupt_schedule_log`, and `internal_error`. ## Live delivery -The process-local owner derives its earliest timer from the durable fold and rereads the wall clock after every bounded wait. Cold Sessions do no work; reopening one reconstructs timers and makes a past target overdue. An overdue reminder waits for the Agent to become fully idle and claims the maintenance phase before it refolds state, queues `followup()`, and appends dispatch. It never calls `steer()` and never interrupts a current turn. +The process-local owner derives its earliest timer from the durable fold and rereads the wall clock after every bounded wait. Cold Sessions do no work; reopening one reconstructs timers and makes past targets overdue. Due one-shots take priority and enter one later turn at a time. When no one-shot is due, all overdue Every records form the single batch described above. -The admitted follow-up starts one normal later turn and appears only through the ordinary conversation transcript; Schedule has no independent durable Web receipt or browser renderer. If framing or synchronous queue admission fails, no dispatch is recorded and the reminder stays active. The narrow crash interval after admission but before durable dispatch can repeat the reminder after recovery, so the boundary is best-effort at-least-once rather than exactly-once delivery. +Due work waits for the Agent to become fully idle and claims the maintenance phase before it refolds state, samples the decision, queues one `followup()`, and appends the corresponding dispatch changes. It never calls `steer()` and never interrupts a current turn. + +The admitted one-shot or fixed-rate batch starts one normal later turn and appears only through the ordinary conversation transcript; Schedule has no independent durable Web receipt or browser renderer. If framing or synchronous queue admission fails, no dispatch is recorded and the reminder stays active. The narrow crash interval after admission but before durable dispatch can repeat reminder content after recovery, so the boundary is best-effort at-least-once rather than exactly-once delivery. diff --git a/docs/subsystems/schedule.zh.md b/docs/subsystems/schedule.zh.md index 2e24ffbaa6..438a733b64 100644 --- a/docs/subsystems/schedule.zh.md +++ b/docs/subsystems/schedule.zh.md @@ -2,11 +2,11 @@ [English](schedule.md) | 中文 -Schedule 拥有持久提醒;这些提醒会作为普通的后续对话轮次返回原 live Session。[持久 Schedule Agent Note](../../.agents/notes/implemented/feature/2026-08-05-durable-web-schedule.md) 负责持久化与生命周期决策,[对话式交付](../../.agents/notes/implemented/simplification/2026-08-09-conversational-schedule-delivery.md) 负责无回执边界,[显式时区边界](../../.agents/notes/implemented/simplification/2026-08-09-explicit-schedule-time-zone.md) 负责浏览器本地解释。本页记录 [`packages/schedule/tool-schedule/src/types.ts`](../../packages/schedule/tool-schedule/src/types.ts) 中的持久数据形状和面向模型的数据形状;[包 README](../../packages/schedule/tool-schedule/README.md) 负责组合、工具行为与确切的提醒 framing。 +Schedule 拥有持久提醒;这些提醒会作为普通的后续对话轮次返回原 live Session。[持久 Schedule Agent Note](../../.agents/notes/implemented/feature/2026-08-05-durable-web-schedule.md) 负责持久化与生命周期决策,[对话式交付](../../.agents/notes/implemented/simplification/2026-08-09-conversational-schedule-delivery.md) 负责无回执边界,[显式时区边界](../../.agents/notes/implemented/simplification/2026-08-09-explicit-schedule-time-zone.md) 负责浏览器本地解释,[有界固定速率 Schedule](../../.agents/notes/implemented/simplification/2026-08-09-bounded-fixed-rate-schedule.md) 负责重复调度。本页记录 [`packages/schedule/tool-schedule/src/types.ts`](../../packages/schedule/tool-schedule/src/types.ts) 中的持久数据形状和面向模型的数据形状;[包 README](../../packages/schedule/tool-schedule/README.md) 负责组合、工具行为与确切的提醒 framing。 ## 持久记录 -`ScheduleId` 是[品牌化 id](core.md#branded-ids),在单个 Session 内唯一且绝不复用。版本 1 支持正的安全整数 `after_seconds` 延时或显式的绝对 `at` 目标。创建操作会将任一选择器规范化为使用四位年份的 RFC 3339 UTC `scheduledAt`;`after` 记录会保留提交的延时,`at` 记录则只存储结果时点。 +`ScheduleId` 是[品牌化 id](core.md#branded-ids),在单个 Session 内唯一且绝不复用。版本 1 支持正的安全整数 `after_seconds` 延时、显式的绝对 `at` 目标,或至少五分钟的安全整数 `every_seconds` 间隔。创建操作会将每个初始目标规范化为使用四位年份的 RFC 3339 UTC `scheduledAt`;`after` 记录会保留提交的延时,`at` 记录只存储结果时点,`every` 记录则保留固定间隔和下一个目标。 ```ts type-equiv /** Durable one-shot reminder created from a positive delay. */ @@ -38,9 +38,30 @@ interface AtScheduleRecord { } ``` +```ts type-equiv +/** Durable fixed-rate reminder whose next target remains creation-anchor-aligned. */ +interface EveryScheduleRecord { + /** Session-local stable identity. */ + readonly id: ScheduleId + /** Rule discriminator for a fixed-rate recurring reminder. */ + readonly kind: 'every' + /** Trimmed reminder content supplied at creation. */ + readonly prompt: string + /** Fixed safe-integer interval, never below five minutes. */ + readonly everySeconds: number + /** Earliest anchor-aligned occurrence not yet dispatched. */ + readonly scheduledAt: string +} +``` + +```ts type-equiv +/** One-shot record variants that terminate on an id-only dispatch. */ +type OneShotScheduleRecord = AfterScheduleRecord | AtScheduleRecord +``` + ```ts type-equiv /** The v1 durable reminder record union. */ -type ScheduleRecord = AfterScheduleRecord | AtScheduleRecord +type ScheduleRecord = OneShotScheduleRecord | EveryScheduleRecord ``` ## 绝对时间输入 @@ -68,9 +89,17 @@ type AtInput = string | LocalAtInput Schedule 会拒绝无效偏移量与时区、不带偏移量的字符串、非未来目标,以及落在夏令时缺口内的本地时间。遇到夏令时重叠时,会选择第一次出现的较早时点。创建成功后只存储规范化后的 UTC `scheduledAt`,因此回放绝不依赖环境时区状态。 +## 固定速率输入与补偿 + +`every_seconds` 是每条记录单独拥有且至少为 300 秒的间隔,以创建时间为锚点。它只提供固定速率重复调度:协议不包含日历规则或 Cron 表达式、重复调度时区、共享冷却时间或跨记录准入门禁。 + +如果一个 Session 在多个目标到期期间处于 cold 或 busy 状态,一条 Every 记录只会贡献其中最新的一次到期触发。dispatch 会直接将记录推进到 dispatch 判断时刻之后第一个与创建锚点对齐的目标,而不会枚举、持久化或回放错过的间隔。如果下一个目标无法落在四位数年份的 UTC 范围内,最后一次 dispatch 将终结该记录。 + +当多条彼此不同的 Every 记录均已到期,且没有一次性提醒到期时,每条记录都会向同一个 follow-up 批次贡献一次触发,并按目标时间和创建顺序排列。每条 Every 记录的状态互相独立,但该获准批次中的所有 dispatch 都使用同一个判断时刻。批处理限制模型轮次数量;五分钟下限限制每条记录的 timer 频率。 + ## 持久变更与回放 -版本 1 的 `schedule/change` 会话事件是 Schedule 唯一的持久权威。create 保存完整记录。delete 与 dispatch 是一次性提醒的终结性、仅含 id 的转换;dispatch 表示 follow-up 已同步入队,而不表示模型答复成功或用户已读取答复。 +版本 1 的 `schedule/change` 会话事件是 Schedule 唯一的持久权威。create 保存完整记录,delete 是终结性且仅含 id 的转换。一次性提醒的 dispatch 同样是终结性且仅含 id。Every dispatch 携带用于选择最新到期触发的墙钟判断时刻,通常推进活动记录而不终结它。dispatch 表示 follow-up 已同步入队,而不表示模型答复成功或用户已读取答复。 ```ts type-equiv /** Creates one durable reminder record. */ @@ -92,19 +121,35 @@ interface ScheduleDeleteChange { ```ts type-equiv /** Records that one active one-shot reminder entered the durable dispatch history. */ -interface ScheduleDispatchChange { +interface OneShotScheduleDispatchChange { readonly version: 1 readonly operation: 'dispatch' readonly id: ScheduleId } ``` +```ts type-equiv +/** Records one fixed-rate decision and advances directly past missed occurrences. */ +interface EveryScheduleDispatchChange { + readonly version: 1 + readonly operation: 'dispatch' + readonly id: ScheduleId + /** Wall-clock decision time used to select the latest due occurrence. */ + readonly acceptedAt: string +} +``` + +```ts type-equiv +/** Durable dispatch shapes supported by the current rule set. */ +type ScheduleDispatchChange = OneShotScheduleDispatchChange | EveryScheduleDispatchChange +``` + ```ts type-equiv /** Strict version-1 durable Schedule mutation union. */ type ScheduleChange = ScheduleCreateChange | ScheduleDeleteChange | ScheduleDispatchChange ``` -严格 decoder 与 fold 会拒绝未知版本、额外字段、重复使用的 id,以及针对非活动记录的 delete 或 dispatch 转换。普通 Session 折叠完整事件流。fork 只折叠 `SessionHeader.seedLength` 位置及其后的事件,因此保留历史,但不会接管父 Session 的活动提醒。`schedule/change` 声明和源码位置也编入[持久化目录](../persistence-catalog.md#schedulechange--log-only)。 +严格 decoder 与 fold 会拒绝未知版本、额外字段、复用 id、不匹配的一次性提醒或 Every dispatch 形状,以及针对非活动记录的 delete 或 dispatch 转换。普通 Session 折叠完整事件流。fork 只折叠 `SessionHeader.seedLength` 位置及其后的事件,因此保留历史,但不会接管父 Session 的活动提醒。`schedule/change` 声明和源码位置也编入[持久化目录](../persistence-catalog.md#schedulechange--log-only)。 ## 活动视图与管理 @@ -130,10 +175,12 @@ type ScheduleView = ScheduleRecord & { } ``` -生成的[工具目录](../tool-catalog.md#deepseek-aidsh-tool-schedule)负责 `schedule_create`、`schedule_list` 和 `schedule_delete` 的参数与结果 schema。一条 Agent-scoped 队列将管理调用与到期工作串行化。每次读取或判断都会先等待共享的 Session 持久化 barrier;create 与实际执行的 delete 在追加后还会再次等待。barrier 失败会报告 `persistence_uncertain`,而不是猜测 eager write 是否已提交。其他稳定错误代码是 `invalid_prompt`、`invalid_selector`、`invalid_rule`、`invalid_time_zone`、`not_future`、`time_out_of_range`、`corrupt_schedule_log` 和 `internal_error`。 +生成的[工具目录](../tool-catalog.md#deepseek-aidsh-tool-schedule)负责 `schedule_create`、`schedule_list` 和 `schedule_delete` 的参数与结果 schema。一条 Agent-scoped 队列将管理调用与到期工作串行化。每次读取或判断都会先等待共享的 Session 持久化 barrier;create 与实际执行的 delete 在追加后还会再次等待。barrier 失败会报告 `persistence_uncertain`,而不是猜测 eager write 是否已提交。其他稳定错误代码是 `invalid_prompt`、`invalid_selector`、`invalid_rule`、`invalid_time_zone`、`not_future`、`time_out_of_range`、`frequency_too_high`、`corrupt_schedule_log` 和 `internal_error`。 ## Live 交付 -进程内 owner 根据持久 fold 派生最早的 timer,并在每次有界等待后重新读取墙钟。cold Session 不执行任何工作;重新打开后会重建 timer,并使已经过去的目标进入 overdue 状态。overdue 提醒会先等待 Agent 完全 idle 并认领 maintenance phase,再重新折叠状态、将 `followup()` 排入队列并追加 dispatch。它绝不会调用 `steer()`,也绝不会中断当前轮次。 +进程内 owner 根据持久 fold 派生最早的 timer,并在每次有界等待后重新读取墙钟。cold Session 不执行任何工作;重新打开后会重建 timer,并使已经过去的目标进入 overdue 状态。到期的一次性提醒享有优先级,每次只进入一个后续轮次。当没有一次性提醒到期时,所有 overdue 的 Every 记录会组成上述单个批次。 -获得准入的 follow-up 会启动一个普通的后续轮次,且只通过普通对话 transcript(文本记录)出现;Schedule 不提供独立的持久 Web 回执或浏览器渲染器。如果 framing 构造或同步队列准入失败,则不会记录 dispatch,提醒仍保持活动。follow-up 获得准入后、持久 dispatch 前的狭窄崩溃窗口可能使提醒在恢复后重复,因此该边界提供的是尽力而为的至少一次交付,而非恰好一次交付。 +到期工作会先等待 Agent 完全 idle 并认领 maintenance phase,再重新折叠状态、采样本次判断、将一个 `followup()` 排入队列,并追加对应的 dispatch 变更。它绝不会调用 `steer()`,也绝不会中断当前轮次。 + +获得准入的一次性提醒或固定速率批次会启动一个普通的后续轮次,且只通过普通对话 transcript(文本记录)出现;Schedule 不提供独立的持久 Web 回执或浏览器渲染器。如果 framing 构造或同步队列准入失败,则不会记录 dispatch,提醒仍保持活动。队列准入后、持久 dispatch 前的狭窄崩溃窗口可能使提醒内容在恢复后重复,因此该边界提供的是尽力而为的至少一次交付,而非恰好一次交付。 diff --git a/scripts/type-equiv.manifest.json b/scripts/type-equiv.manifest.json index 04bbd58056..e1c70a0f6c 100644 --- a/scripts/type-equiv.manifest.json +++ b/scripts/type-equiv.manifest.json @@ -231,6 +231,11 @@ "symbol": "AtScheduleRecord", "source": "packages/schedule/tool-schedule/src/types.ts" }, + { + "doc": "docs/subsystems/schedule.md", + "symbol": "EveryScheduleRecord", + "source": "packages/schedule/tool-schedule/src/types.ts" + }, { "doc": "docs/subsystems/schedule.md", "symbol": "LocalAtInput", @@ -241,6 +246,11 @@ "symbol": "AtInput", "source": "packages/schedule/tool-schedule/src/types.ts" }, + { + "doc": "docs/subsystems/schedule.md", + "symbol": "OneShotScheduleRecord", + "source": "packages/schedule/tool-schedule/src/types.ts" + }, { "doc": "docs/subsystems/schedule.md", "symbol": "ScheduleRecord", @@ -256,6 +266,16 @@ "symbol": "ScheduleDeleteChange", "source": "packages/schedule/tool-schedule/src/types.ts" }, + { + "doc": "docs/subsystems/schedule.md", + "symbol": "OneShotScheduleDispatchChange", + "source": "packages/schedule/tool-schedule/src/types.ts" + }, + { + "doc": "docs/subsystems/schedule.md", + "symbol": "EveryScheduleDispatchChange", + "source": "packages/schedule/tool-schedule/src/types.ts" + }, { "doc": "docs/subsystems/schedule.md", "symbol": "ScheduleDispatchChange",