ZCode / Off-Peak Task

一个任务,
多段续跑

从用户提交到服务端取号,从本地认领到 Agent 分段执行,再到 History 和核销: 完整解释 Task、Session、Ticket 三种身份如何协作。

1 USER TASK
= 1 logical run
+ 1 reusable session
+ N server tickets
+ 0 / 1 history row
00 /

先选对观察视角

Off-Peak 不是单纯的定时任务。它把一次用户任务拆成产品身份、本地控制、 Agent 执行和服务端准入四个层次;每层回答的问题不同。

01PRODUCT

用户看到什么

提交一次性任务,等待低峰执行;无论中间续跑多少段,任务卡片和 History 都保持一个身份。

02LOCAL CONTROL

客户端控制什么

SQLite 保存聚合当前态;Service 同步票据;Scheduler 负责认领、派发、超时回收和退避。

03AGENT RUNTIME

任务如何真正执行

首段创建 Session,后续段恢复同一 Session;每次模型请求都必须携带当段有效 ticket。

04SERVER GATE

谁决定何时能跑

服务端维护 FIFO、并发和 ticket 生命周期。客户端只观察结果,不复制服务端排队真相。

推荐阅读顺序 Product → Local Service / Scheduler → Host / Agent → Server Gateway。 但运行时状态会反向回流:服务端票据决定准入,Agent 结果决定本地终态,本地聚合再决定 UI。
01 /

先把表的角色说准

每一行代表一个跨多段执行仍保持稳定身份的逻辑任务。服务端 ticket 可以反复更换, Session 始终复用,History 只做一次执行摘要。

Canonical definition

off_peak_tasks 是当前态聚合根,同时兼任调度锁、服务端快照、 核销 outbox 和 History tombstone。

02 /

四个对象,三种基数

任务是稳定聚合根,Session 是连续上下文,Ticket 是每一执行分段的准入凭证, History 则只是面向用户的派生投影。

STABLE AGGREGATE ROOT

OffPeakTask

用户只创建一次。task_id、Prompt、工作区、产品状态和最终结果都挂在这里; 暂停、取消、删除 History 也以它为入口。

1 task = 1 logical run
EXECUTION CONTEXT

Session · 1 : 1

首段 create,续跑 resume。它保留上下文,但不是 Off-Peak 调度状态的真源。

ADMISSION SEGMENT

Ticket · 1 : N

每个最多约 3 小时的准入分段一张票。当前本地聚合行只留“现在这张”,旧票会被覆盖。

PRODUCT PROJECTION

History · 1 : 0..1

只有真正启动过才出现;删除只写 tombstone,不删除任务、Session 或执行字段。

产品真相off_peak_tasks
上下文真相Session runtime
准入真相Server ticket DB
展示真相Derived History
03 /

端到端架构

Renderer 不直接调度;Host 负责取号和同步;Scheduler 只读写 SQLite;Main 只路由; Agent 的每一次模型请求再经过服务端细粒度准入。

Renderer Automations UI 灰度 / 表单 / 卡片 / History
Host RPC Task Service CRUD / sync / settle / retake
WAL · multi-process off_peak_tasks ~/.zcode/v2/tasks-index.sqlite
Utility Process Scheduler claim / backoff / recovery
Desktop Main Router resolve local host / forward result
Workspace Host Run Dispatch create or resume + sendPrompt
ZCode CLI Agent Loop per-turn idle plan overlay
Server Authority Off-Peak Gateway FIFO / ready / active / 429 / 3102
权责边界 客户端 timer 负责“什么时候再来问”,服务端 Promote timer 负责“什么时候从 queued 推进到 ready”。 Status 查询只是读取服务端状态,不应承担推进 FIFO 的职责。
User
  │ create task
  ▼
Renderer ─RPC─▶ Host Service ─take/status/settle─▶ Server Ticket DB
                    │                                  │
                    │ persist current snapshot         │ Promote timer
                    ▼                                  ▼
            off_peak_tasks ◀──── queued / ready / active / expired
                    │
                    │ claim ready task
                    ▼
               Scheduler ─dispatch─▶ Workspace Host ─create/resume─▶ Session
                                             │
                                             │ sendPrompt + ticket overlay
                                             ▼
                                          Agent Loop ─each model call─▶ Gateway
                                             │                            │
                                             └──── result / 3102 / 429 ──┘
                    ▲
                    └──── task terminal or continuation ────
04 /

五组接口串起完整闭环

取票和核销由 Host Service 负责;真正的模型准入发生在 CLI 请求模型时。 把这两层混在一起,会误以为“ready 就等于已经执行”。

01
HOST SERVICE · QUOTA SNAPSHOT

GET /ticket/availability

读取当前用户能否创建新 ticket;不可创建时返回精确的 next_take_at,供 UI 提前置灰并到点重查。

true → enable create
false → disable until next_take_at
error → disable until refresh
02
HOST SERVICE · TAKE

POST /ticket

task_id 换取当前 ticket_id。服务端可能立即 queued,也可能返回额度、资格或网络错误。

OK → persist ticket
3101 / 3103 → reject + refresh snapshot
5xx / network → backoff
03
HOST SERVICE · OBSERVE

POST /ticket/status

批量读取最多 100 张票,按 ticket_id 回写 queued / ready / active / expired / settled / not_found 投影。

ready → next_run_at
expired → continuation
not_found → needs repair
04
ZCODE CLI · ADMIT EACH MODEL CALL

POST /anthropic/v1/messages

每一次模型请求携带 X-Off-Peak-Ticket-ID。Agent 已启动不代表后续每个 turn 都天然获准。

2xx → model response
429 / 3105 → retry later
400 / 3102 → segment expired
05
HOST SERVICE · SETTLE OUTBOX

POST /ticket/:ticket_id/settle

任务终态或分段结束后核销。客户端先落本地 pending,再异步发送,避免一次网络失败丢失终态意图。

2xx / 4xx → acknowledged
5xx / network → retry
delete row → current risk
关键结论 队列位置、Promote、并发和票据有效性都由服务端 MySQL 真源决定。本地 SQLite 只保存调度所需的当前快照。
05 /

两条轴,不能硬合并

本地轴描述“任务执行到哪一步”;服务端轴描述“当前 ticket 获得了什么准入资格”。 本地表不会保存服务端完整 state,只保存面向调度的投影。

本地任务执行轴

7 STATES
queued
→
等待服务端 ready;可 Pause、编辑、删除
paused
⇄
仅停止本地派发;服务端 ticket 继续存在
running
→
Prompt 已被 Host/Agent 接受,Agent turn 在跑
terminal
■
completed / failed / cancelled,不可逆出

服务端票据准入轴

6 STATES
queued
→
进入服务端 FIFO,拥有 position
ready
→
粗阀开放;本地投影为 schedulable=1
active
→
首个 message 准入,获得本段 3h 窗口
expired
↺
ready TTL 或 active 3h 到期;需要换票
settled / not_found
■
已核销,或票不存在/不属于当前用户
本地状态 可能对应的服务端状态 为什么不一一对应
queued queued / ready / expired / not_found ready 快照到 scheduler 派发之间有窗口;废票重取也有短暂窗口。
paused queued / ready / expired Pause 只停本地派发,不退出服务端 FIFO。
running ready / active / expired 当前实现先写 running,首个模型请求可能仍在 429 细阀等待。
terminal active / settled 本地先落终态,服务端资源通过 settle outbox 异步释放。
06 /

字段分组地图

用搜索框可按字段名或语义过滤。内部调度字段不会进入 UI 领域对象,但和业务字段共处一行, 这是该表既是聚合根又是基础设施状态表的直接体现。

8 GROUPS · 30 COLUMNS

身份与表单

6 fields
off_peak_task_idTEXT · PK
稳定逻辑身份;同时作为服务端 task_id,跨多张 ticket 不变。
titleTEXT · NOT NULL
任务卡标题;空标题兼容时 UI 回落显示 prompt。
promptTEXT · NOT NULL
用户提交的 Instructions;首跑派发时读取最新值。
permission_modeTEXT · NOT NULL
复用 ZCodeTaskMode;随每次首跑或 resume 派发。
modelTEXT · NULLABLE
指定 idle 模型;为空时派发阶段回落 allowed_models 第一项。
thought_levelTEXT · NULLABLE
推理强度;为空时走 workspace 默认。

Workspace 边界

3 fields
workspace_keyTEXT · NOT NULL
身份隔离键:workspaceIdentity?.trim() || workspacePath。
workspace_pathTEXT · NOT NULL
文件读写、命令 cwd 和 Host 执行路径。
workspace_identityTEXT · NULLABLE
远程身份预留;当前新建入口只允许本地项目,存量仍可携带。

Session 绑定

2 fields
conversation_idTEXT · NULLABLE
首次派发后回填 ZCode taskId;续跑用它定位同一任务。
session_idTEXT · NULLABLE
History/卡片跳转与冷恢复 resume;没有数据库外键。

本地执行聚合

6 fields
statusTEXT · NOT NULL
七态本地状态;Repo 用条件 UPDATE 实现迁移守卫。
queued_atINTEGER · NOT NULL
本地首次创建和 claim 排序依据;换票时不覆盖。
started_atINTEGER · NULLABLE
首段 Host 接受 Prompt 的时间;续跑使用 COALESCE 保留。
ended_atINTEGER · NULLABLE
最终 completed / failed / cancelled 的时间。
failure_reasonTEXT · NULLABLE
最终失败错误;3102 票过期不会作为普通失败保留。
files_changedINTEGER · NULLABLE
从现有 task diff 汇总;部分 Bash 改动可能不在统计内。

服务端调度快照

5 fields
server_ticket_idTEXT · NULLABLE
只保存当前分段 ticket;重新取号覆盖,不保留旧票历史。
registered_atINTEGER · NULLABLE
最近一次取号成功时间;重新取号会更新。
schedulableINTEGER · DEFAULT 0
服务端 ready 的布尔投影;scheduler 的粗阀。
queue_positionINTEGER · NULLABLE
服务端 FIFO 位次;queued/paused 卡片展示。
next_poll_atINTEGER · NULLABLE
已持久化,但当前同步循环没有按任务实际过滤使用。

调度 Lease 与诊断

4 fields
claim_runningINTEGER · DEFAULT 0
single-flight 认领锁;只防单任务重复,不限制任务间并发。
claimed_atINTEGER · NULLABLE
认领开始时间;超过 10 分钟可按僵尸认领回收。
attempt_countINTEGER · DEFAULT 0
Host 派发失败次数;成功 markRunning 后不归零但不暴露 UI。
last_errorTEXT · NULLABLE
最近一次派发错误;进入 running 时清空。

核销与 History

2 fields
settled_atINTEGER · NULLABLE
服务端核销 ack;NULL 的终态行构成可补报 outbox。
history_deleted_atINTEGER · NULLABLE
History tombstone;只隐藏摘要,不删任务、Session 或执行字段。

审计时间

2 fields
created_atINTEGER · NOT NULL
本地任务创建时间;当前 UI 额度预判按它计数。
updated_atINTEGER · NOT NULL
状态、调度快照、History 操作等最近更新时间。
07 /

完整分支流

每个折叠块是一段具有独立失败语义的业务链路。默认展开关键路径,可一键查看全部分支。

01

灰度、订阅与额度

先决定入口是否存在,再由服务端决定请求能否真正取号。

+
灰度关闭且无存量:整个闲时区域隐藏。
灰度关闭但有存量:只藏创建入口,任务继续跑。
非 Coding Plan:按钮锁定并展示升级提示。
client/configs:只负责功能曝光与 allowed models,不再下发静态 limit。
availability=false:按服务端 next_take_at 提前置灰并展示 Tooltip;到点自动重查。
服务端 3103:处理查询后的并发竞态,展示错误并刷新 availability,不保存永久 boolean。
桌面远程 / 手机 remote:不提供新建入口。
client/configs: exposure + models
  -> GET /ticket/availability
     -> false: disable until next_take_at, then refresh
     -> true/error: allow create
        -> POST /ticket
           -> success: create local task
           -> 3103: show error + refresh availability

POST /ticket remains the final quota authority
02

创建与首次取号

先取号,成功才 INSERT;创建阶段不会预建 Session。

+
3101 / 3103 / 凭证缺失 / 网络失败:不落本地任务行。
ticket=queued:保存 position,等待状态同步。
ticket=ready:schedulable=1,并立即唤醒 scheduler。
异常返回 active/expired/settled/not_found:仍会创建本地 queued 行且 schedulable=0;只有后续 expired 分支会自动重取,settled/not_found 可能停滞。
取号成功但 SQLite INSERT 失败:存在服务端孤儿票风险,当前无主动 settle。
random offPeakTaskId
  → POST /ticket
    → failure: no row
    → success: INSERT queued
03

状态同步与服务端分支

先 flush settle outbox,再批量读取最多 100 张非终态 ticket。

+
ready:写 schedulable=1;queued 新晋级时 wake scheduler。
queued:写 schedulable=0 和 position。
active:只清 position,不直接改本地状态。
expired + local queued:清快照并同 taskId 重取票。
expired + local paused:原地等待用户 Continue。
settled / not_found / 未匹配:当前实现忽略。
整轮失败:10s 指数退避到 5min;running 不受影响。
outbox → nonTerminal
  → missing ticket: retake
  → batchStatus ≤ 100
  → apply by ticketId
  → schedule next cycle
04

Pause / Continue / 编辑

Pause 只停本地,Continue 决定复用旧票还是显式消耗额度重取。

+
Pause:仅 queued 且未认领可进入 paused;票继续排队。
Continue + 活票:paused→queued,零成本恢复。
Continue + expired/not_found/无票:同 taskId 重取号。
Continue + settled:当前会被视为“票仍活着”,但后续同步又不处理 settled,存在停滞边界。
Continue 状态查询失败:按票活处理,避免白耗额度。
编辑:只允许 queued/paused;workspace 不可改。
queued --pause--> paused
paused --continue--> queued
  ├─ alive ticket: reuse
  └─ dead ticket: retake
05

Scheduler 认领与派发

BEGIN IMMEDIATE 保证单任务 single-flight;任务间没有本地并发上限。

+
认领条件:queued + schedulable=1 + claim_running=0。
僵尸认领:claimed_at 超过 10min 后释放。
内存退避未到:立即 release claim,等待后续 tick。
没有 Host / forward 失败:保持 queued,30s 指数退避到 15min。
Host ok:markRunning 并回填 conversation/session。
结果迟到且任务已 Pause/Cancel:markRunning 守卫拒绝。
BEGIN IMMEDIATE
  SELECT due
  UPDATE claim_running = 1
COMMIT

dispatch → main → host
06

Host 首跑 / 续跑 / Provider

Session 常驻模型不被污染,idle plan 只活在自动派发的当前 turn。

+
首跑:createTask + 原始 prompt;派发后才产生 Session。
续跑:resume 同一 Session + 固定 continuation prompt。
无 ticket / 无模型 / 无凭证:Host 返回 transient,scheduler 重试。
Session 正忙:拒绝 turnRuntimeModel 延迟入队,避免边界失真。
Turn 结束:清临时 overlay,恢复用户原 provider。
用户插话/终态后聊天:天然走用户 provider。
first:
  createTask → send original prompt

resume:
  resumeTask → send continuation

both:
  turnRuntimeModel = idle plan
07

模型请求:429 / 3102 / 真错误

细阀可在每一次模型请求发生;排队不消耗普通 API 重试预算。

+
429/3105:min(Retry-After, 5min),无头默认 60s,无限探测。
用户 Cancel:AbortSignal 中止 sleep 和在途请求。
400/3102 或旧 3001:写稳定错误标记,由 Host 改走换票续跑。
其他错误:使用普通 Agent retry;耗尽后进入 failed。
普通 Provider 429:不享受无限探测,保持原重试预算。
429/3105 → queued hold → retry ∞
3102      → marker → requeue + retake
other     → normal retry → failed?
08

敏感操作与确认

当前代码只复用普通 Session 的 permission / elicitation 交互,聚合态保持 running。

+
敏感工具请求:普通 Session 展示确认,Off-Peak 卡片保持 Running。
批准 / 拒绝:同一自动 turn 继续,仍使用 idle plan。
通知:由 Session 通用链路负责,不重复发送 Off-Peak 等确认通知。
取消:进入 cancelled,并中止 Agent loop。
历史兼容:旧库预留值初始化时迁移为 running。
permission requested
  → session waits for response
  → off_peak_tasks stays running
  → same turn keeps idle plan
09

3h 换票续跑

逻辑任务和 Session 不变,只替换当前 ticket;History 仍是一条完整执行。

+
触发:模型请求收到 3102,不依赖客户端本地计时。
回队:running/awaiting→queued,保留 startedAt/session。
重取成功:覆盖 server_ticket_id,等待新票 ready。
重取失败:保持 queued,后续同步继续补取。
Runtime 不可用:无法续跑,按普通 failed 收口。
task-A + ticket-1 + session-X
           ↓ 3102
task-A + ticket-2 + session-X
10

终态、通知与核销

本地终态先落库,服务端资源释放通过异步 settle outbox 完成。

+
succeeded:completed;stopped:cancelled;其他:failed。
终态回写:endedAt、failureReason、filesChanged,清 claim/schedulable。
迟到终态:终态不可逆守卫拒绝覆盖。
settle 2xx:写 settledAt。
settle 4xx:按幂等 ack 写 settledAt。
网络/5xx:保留 NULL,下个 sync 周期补报。
通知:completed / failed / awaiting 状态边沿触发。
local terminal
  → unread + history status
  → settle current ticket
    ├─ ack: settled_at
    └─ retryable: outbox
11

Cancel / Delete / Delete history

三个入口分别是终止、物理删除和视觉隐藏,数据后果完全不同。

+
Cancel:先写 cancelled,再 best-effort stopGeneration,异步 settle。
Delete 非终态:先 Cancel,再 DELETE 本地任务行。
Delete 终态:直接 DELETE,不删除 Session。
Delete history:只写 historyDeletedAt,无确认、无 Undo。
未启动任务删 History:不写 tombstone。
重复删 History:幂等,保留首次时间。
cancel  = terminal state
delete  = physical row delete
history = visibility tombstone
12

重启、崩溃与 Keep Awake

Off-Peak 没有 misfire skip;中断统一回队并复用 Session 接续。

+
App 重启:running/awaiting→queued,保留 session、startedAt、queuedAt。
Scheduler 正常退出:主动 release in-flight claim。
Scheduler 崩溃:认领超过 10min 后回收。
机器休眠:queued 原地保留,唤醒后继续同步,无 skip。
Keep Awake:设置开启且 running/awaiting 数量>0 时阻止闲置休眠。
合盖:powerSaveBlocker 无法阻止。
recoverInterrupted:
  running / awaiting
    → queued
    → resume same session later
08 /

为什么 History 是 0 / 1

没有独立 runs 表。UI 直接从任务聚合行计算一条摘要,因此多张 ticket、多段执行对用户保持透明。

从未启动

纯 queued / paused,没有 startedAt,History 显示空态。

started_at IS NULL

已经启动

startedAt 存在且未隐藏,展示 Prompt、Triggered、Status、Duration 和 Session 入口。

started_at IS NOT NULL

用户隐藏

只写 tombstone;任务后续完成、失败或核销都不会让该行重新出现。

history_deleted_at IS NOT NULL
本地任务状态 History 文案 Duration 终点
runningIn progressDate.now()
completedSucceededendedAt
failedFailureendedAt
cancelled after startSkippedendedAt
09 /

要不要像普通定时任务一样加 Run History

普通 Automation 的同一定义会按周期产生很多次独立触发,runs 表既是幂等账本也是历史。 Off-Peak 当前只有一次逻辑运行,重复发生的是 ticket 分段。

CURRENT · V1

继续只用聚合行

最少的表和写路径,足够完成一次性任务、分段续跑与 0/1 History。

  • 优点:模型简单,升级成本最低
  • 代价:旧 ticket 被覆盖
  • 代价:删除任务可能丢 settle 重试
NOT RECOMMENDED

照搬 off_peak_runs

如果一条任务仍然只允许一次逻辑执行,那么 task 与 run 永远接近 1:1,只会把同一状态拆写两遍。

  • 适合:未来支持重复触发同一任务定义
  • 不适合:只为保存 ticket 分段
  • 风险:History 语义被误改成 1:N
AGGREGATE · KEEP

off_peak_tasks

id · title · prompt · workspace status · started_at · ended_at session_id · history_deleted_at current_ticket_id · current snapshot scheduler claim · task-level failure

回答产品与调度问题:这项任务是谁、现在在哪、是否终态、用户是否隐藏历史。

1 → N segments
LOCAL LEDGER · ADD ONLY WHEN NEEDED

off_peak_tickets

ticket_id PK · task_id FK ordinal · server_state · taken_at ready_at · active_at · expires_at segment_started_at · segment_ended_at end_reason · last_error settle_state · settle_attempts · settled_at

回答可靠性问题:经历过哪些准入分段、哪张票待核销、一次续跑为什么结束。

不要越权 服务端已经有权威的 MySQL ticket 生命周期和审计;本地 ticket 表只是可靠执行账本与诊断缓存, 不能成为 FIFO、并发额度或准入有效性的第二真源。
10 /

引入 Ticket 表可以平滑升级

采用纯增量迁移,不改现有任务主键、不立刻删除旧字段。新旧代码在一段时间内都能读取 off_peak_tasks 完成核心流程。

PHASE 01

只加表,不改读路径

使用 CREATE TABLE IF NOT EXISTS 创建 ticket ledger 和索引;原任务表、原 RPC、原 UI 全部不动。

PHASE 02

回填当前票快照

每个任务最多回填当前 server_ticket_id,标记为 legacy backfill。已经被覆盖的历史票无法凭空恢复。

PHASE 03

先双写,再观察

Take、status、segment end、settle 同时写旧聚合字段与新子表;对账后再把诊断和 outbox 查询切到子表。

PHASE 04

逐项切换消费方

先切 settle 重试,再切本地额度与诊断;任务卡片和 0/1 History 继续从聚合表读取,避免产品语义漂移。

向前升级:可以无感

新版本首次启动自动建表并回填当前票。旧任务照常运行;没有历史票时只影响审计完整度,不影响执行。

回退旧版:功能可用,但有边界

保留聚合字段即可让旧版本继续跑;旧版本期间产生的新票不会写 ledger,重新升级后无法补回完整链路。

删除策略 若 ticket 子表承担 settle outbox,不应简单使用 ON DELETE CASCADE。 任务删除后至少保留未核销票据和最小任务标识,直到 acknowledged 或明确放弃。
11 /

当前实现核对

以下项目是从代码全链路得出的事实,包含已经闭环的不变量,也包含文档目标和当前实现之间的差异。

终态不可逆

所有终态写入都带非终态 WHERE 守卫,Cancel 可以稳定压住迟到 stopped 回写。

单任务 single-flight

BEGIN IMMEDIATE + claim_running 原子认领,多个任务之间不做错误的本地串行化。

确认链路已收敛

Permission / elicitation 只走普通 Session;Off-Peak 聚合保持 running,不暴露不可达状态。

running 写入早于网关 admitted

sendPrompt 受理后即 markRunning,因此细阀 429 期间本地已经显示 In progress。

not_found 没有自动修复

普通同步对 not_found 不做重取;queued 任务可能持续携带旧票,只有 Continue 会处理。

next_poll_at 尚未真正驱动

字段会写库,但同步仍是 Service 级公共 timer,不按每条任务的 next_poll_at 过滤;即使无任务,finally 仍会约 5 分钟后再排一次 timer。

额度误判改为服务端快照

D39 删除本地 task.createdAt 与静态 limit 预判,改由 availability 返回实时 can_take_number 与 next_take_at。

client/configs 不再携带 limit

共享配置只控制曝光和模型列表;服务端内部 limit/window 不再泄漏为客户端推断规则。

3103 不再形成永久锁

客户端保存的是带 next_take_at 的短期服务端快照,不保存 quotaExhausted boolean;到点重查,查询失败则保持禁入直到成功刷新。

Delete 可丢 settle outbox

行被物理删除后,如果异步 settle 遇到网络/5xx,已经没有本地记录可继续补报。

多 Host 重复同步

每个窗口 Host 都启动 sync;写入和接口幂等,但批量状态请求和 settle 扫描会放大。

客户端没有票据审计历史

服务端有 ticket 真源和审计,但本地旧 ticket 会被覆盖;离线诊断无法还原每段耗时、结束原因与 settle 重试。

客户端注释与服务端 Promote 已漂移

当前服务端由独立 timer 推进 queued → ready;若客户端仍假定 status 查询会触发 Promote,轮询语义和故障判断会失真。

12 /

最终能力边界

一眼判断一个需求是否还能继续塞进当前表,还是已经应该拆出 runs / tickets / events。

It is

当前态聚合与可靠执行控制面

  • 逻辑任务当前态快照
  • 当前服务端 ticket 快照
  • 跨进程 scheduler lease
  • 终态 settle outbox
  • History 可见性 tombstone
  • 一个 Session 的分段续跑锚点
It is not

事件溯源或多运行审计系统

  • 不是多次执行 History 表
  • 不是多 ticket 审计表
  • 不是 Session 生命周期真源
  • 不是服务端 FIFO 队列副本
  • 不是模型请求事件流水
  • 不能回答每一执行分段的历史细节