Skip to content

feat(todo): add timezone-aware resume_at triggers - #4347

Merged
huangruiteng merged 5 commits into
mainfrom
codex/typed-date-resume-trigger
Sep 13, 2026
Merged

huangruiteng merged 5 commits into
mainfrom
codex/typed-date-resume-trigger

Conversation

@huangruiteng

Copy link
Copy Markdown
Collaborator

动机

LoopX 现有 Todo 恢复条件无法表达一个精确日期。自然语言日期可能继续留在可执行 Todo 中,而 CLI、heartbeat 与托管 Turn 没有同源的到期证明。该切片把日期恢复收敛到既有 resume_when owner,不新增调度器或消息队列。

改动

  • 新增 resume_at:<timezone-aware-rfc3339-timestamp>,强制显式时区并规范为 UTC;无时区、非法日期与非法 offset 在写入前失败。
  • 同一次 active-state 投影复用一个 runtime-clock 快照;到期前 generation 为 0,到期后固定为 1。
  • 到期后生成内容寻址的 todo_resume_receipt_v0;重复 tick 和进程重启复现同一回执。
  • quota 与托管 Turn 复用现有 agent_scope_wait / successor_replan_required,回执不授予执行权限,也不隐式 reopen Todo。
  • 扩展既有 Personal Workspace Todo 暂缓与详情入口,双语显示 pending / ready / receipt,并更新打包前端。
  • Lark 无独立状态改动:Goal Channel 继续消费同一 status/interaction projection,避免第二真相源。
  • 新增中英文协议与 CLI、跨层、重启、重复投递、浏览器验收。

English summary

Adds a strict, timezone-aware one-shot resume_at Todo condition to the existing resume owner. Equivalent instants normalize to UTC; due reads emit one stable content-addressed receipt across ticks and restarts. CLI, heartbeat quota, managed Turn, frontend, and Lark share the same projection and retain explicit lifecycle authority.

验证

  • PATH="$PWD/.venv/bin:$PATH" npm run test:control-plane — 1495 passed, 1 skipped
  • focused Python cross-layer suite — 44 passed
  • npm run typecheck:control-plane
  • dashboard router, schema, status projection smokes
  • dashboard production build
  • Personal Workspace development and packaged browser acceptance, including rendered due state and receipt
  • git diff --check

Fixes #4346

Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
@huangruiteng
huangruiteng force-pushed the codex/typed-date-resume-trigger branch from d920df4 to 6098862 Compare September 13, 2026 17:02

@huangruiteng huangruiteng left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approval conclusion (author-owned PR; GitHub blocks formal self-approval)

动机

基线 0933d48ef 的 Todo resume_when 不能表达精确日期:同一个 resume_at:2026-09-15T09:00:00+08:00 在真实 CLI dry-run 中被判为不支持。若日期只存在于自然语言描述,managed Turn、heartbeat、Dashboard 与 Lark 无法获得同源的到期事实,可能提前选中任务,或依赖人工重新唤醒。最小正确修复不是新增定时服务或解析自然语言,而是在既有 resume_when owner 中增加一个带显式时区的 typed variant;本 PR 正是沿这一边界实现。

改动思路

不可约的用户意图仍只有 Todo 上的 resume_when=resume_at:<timezone-aware-rfc3339>;evaluated_at、resume_ready、generation 与 receipt 都由该值和一次 runtime tick 捕获的时钟派生,不能独立编辑。Python active-state 边界在写入前验证并规范化,TypeScript resume_condition reducer 仍是 readiness 决策 owner;quota、managed Turn、Dashboard 与 Lark 只消费同一 projection。未来时间得到 generation 0 且没有 receipt,到期得到 generation 1 与稳定的 todo_resume_receipt_v0。该 receipt 只证明时间条件满足,不授予执行 Todo 外部动作的权限。

仓库搜索确认复用了现有 normalize_todo_resume_when、condition reducer、summary、quota 与 personal-workspace 路径,没有引入第二套 scheduler、store 或 message queue。Python/TypeScript 的重复仅限跨运行时的 wire-format 边界验证,并由同一组正常/边界样例约束。

具体改动

精确 head:609886257f7ca7f617b2998bf87e06521d25bdba。完整 diff 为 32 个文件、+693/-49;其中约 249 行为 production source,262 行 tests/fixtures,180 行双语 docs,51 行 packaged Dashboard 生成物。

关键代码讲解

  • loopx/control_plane/todos/resume_condition.ts:84 的 resumeTimestamp 要求显式 offset,将时间规范为 UTC,并在 offset 换算后拒绝超出 1000..9999 年的值。它只解析,不写状态、不调度工作。
  • loopx/control_plane/todos/resume_condition.ts:403 的 conditionFor 在同一次 tick 的时钟上判定 future/due,生成 typed condition 与 content-addressed receipt;原有条件分支保持不变。
  • loopx/control_plane/todos/active_state_todo_parser.py:56 的 parse_active_state_todos 把同样的支持范围放在 Python 写入边界,非法/naive/越界时间在持久化前失败。
  • apps/presentation/dashboard/src/views/dashboard-page.tsx:709 的 personalTodoResumeReceiptId 及相邻 mapping 只投影 canonical backend facts;到期后 active Todo 仍显示 resume condition,前端不自行判断 readiness。

用户路径已经同时覆盖 CLI/managed Turn、Dashboard 与 Lark 的共享状态。文档说明 UTC 规范化、无时区拒绝、receipt 语义以及 successor_replan_required 与执行授权的区别。

对主干的风险

我主动构造的最强反例有两个:一是“语法合法的本地时间经 offset 转 UTC 后越出宿主日期范围”,普通 2026 fixtures 不会发现;二是 due 后 Todo 变 active,旧的 deferred-only UI guard 会隐藏仍有用的恢复条件。当前 head 已在 Python/TypeScript 同时加入换算后范围检查,并将 UI 条件改为 deferred || resumeWhen;对应极端年份回归测试和 packaged/development smoke 均通过。

本地证据:focused TypeScript 18 cases、focused Python 24 cases;完整 control-plane 为 1495 passed、1 skipped、0 failed;build:chat、packaged/development personal-workspace smokes 与 git diff --check 均通过。默认路径通过 exact tag 隔离:没有 resume_at 的 Todo 不新增 required field、prompt、state、quota 或 side effect。残余风险是 host wall-clock 被人工校正时 readiness 的观测时点会变化;本实现是 reducer projection,不宣称 timer/monotonic-clock 保证。

我的整体评价

同一真实 CLI 输入在基线为 exit 1/unsupported,在本 head 为 exit 0/planned,并读回规范化的 resume_at:2026-09-15T01:00:00Z,且 dry-run 无写入;这是预期且已验证的 observable semantic change。机制留在既有 owner,范围与重复出现的精确日期需求相称,没有扩大 actor 或执行 authority。revision-3 结构化结果校验通过,未发现阻塞问题。

Verdict: APPROVE for exact head 609886257f7ca7f617b2998bf87e06521d25bdba. Because this is author-owned, this comment records the approval conclusion rather than a formal GitHub approval. Publication is gated on all required GitHub checks completing successfully and the remote head remaining unchanged.

@huangruiteng
huangruiteng merged commit 201da97 into main Sep 13, 2026
31 checks passed
@huangruiteng
huangruiteng deleted the codex/typed-date-resume-trigger branch September 13, 2026 17:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Todo: add timezone-aware resume_at with a stable due receipt

1 participant