Memory 接口

Scheduler 负责时间、执行、状态和结果;Memory 负责长期语义事实。两者通过稳定引用和现有 Memory 工具连接,但不共享状态文件或写入事务。Agent 可以在规划、执行和关闭任务时显式维护关联的 Memory 记录。

1. 目标与边界

一次性任务

保存带时区的 run_at,到期后只执行一次。旧的有日期 Commitments 迁移为此类型。

周期任务

复用现有五字段 cron 解析、owner 签名、冻结 sandbox policy 和非交互执行边界。

监控任务

使用 cron 周期执行观察 prompt。首版记录执行日志和状态,不承诺跨渠道 exactly-once 通知。

明确排除

Memory writer 不推断任务;Memory 页面不显示 Commitments;Scheduler service 不隐式创建或修改 Memory;不新增跨 Scheduler 与 Memory 的联合事务、外部 token 权限模型、已删除记录的占位对象或 ID 转发、第二套执行器、项目管理、任务依赖或子任务。

2. 目标数据关系

1 创建owner Web、Agent tool 或外部 API 创建 Scheduler task。
2 冻结Runtime 签名 prompt/command、cwd、权限、sandbox 与 MemoryRef。
3 唤醒常驻 OpenProgram worker 每分钟判断 once/cron 是否到期。
4 解析执行前按 workspace_id + memory_id 读取当前 Memory 内容。
5 执行在冻结的非交互权限边界中执行,并写 Scheduler 日志与状态。

Worker tick 异常边界

初始 @reboot tick 和后续普通 tick 抛出 Exception 时,daemon 以 warning 和完整 traceback 写入 stderr,在下一分钟边界继续;不立即重放、不补偿,初始失败后后续 tick 使用 reboot=False。常驻 OpenProgram worker 重定向后的 stderr 进入全局 worker 日志;独立前台 scheduler-worker 则显示在当前终端。两者都不是某个任务的 execution log。run_once、KeyboardInterrupt、SystemExit 与其他 BaseException 保持 fail-fast。

3. MemoryRef 公共契约

字段规则失败
workspace_id必须等于当前 Memory workspace 的稳定 ID。拒绝跨 workspace 隐式读取。
memory_id创建和更新时必须解析到唯一 Topic block;内容在每次执行时重新读取。写入时拒绝缺失、重复、跨 workspace 或格式错误的引用;执行前引用失效时任务失败,不回退到旧快照。
写入能力MemoryRef 本身不授予编辑权。由本地 owner 创建的 prompt task 可以使用 memory_status、memory_get 与 memory_update,所有修改仍走现有 revision、格式校验、派生视图和 Git 事务。缺少当前 revision、Topic 格式错误或并发更新时,Memory 事务独立失败;Scheduler 状态不回滚。

4. Agent 生命周期协议

阶段Agent 行为边界
规划或创建仅当任务本身值得长期保留时,Agent 使用 memory_update.create_record 创建任务记录,再把返回的 memory_id 作为 memory_refs 附到 Scheduler task。普通临时提醒可以不写 Memory。两个调用顺序执行,不伪装成一个原子事务;任一步失败都明确返回给 Agent。
执行或状态变化Prompt task 在执行时收到当前 MemoryRef 内容。若该记录描述本任务,Agent 先读取 revision 和原记录,再使用 update_record 写入当前状态、结果或下一次仍需保留的信息。Scheduler 不能使用 shell、文件写入、网络发送等其他副作用工具;新增写能力只限现有 Memory 事务工具。
关闭仍有长期价值时,把关联记录更新为已完成、已关闭或最终结果;完全没有保留价值时,使用 delete_record 删除。交互 Agent 可同时禁用或删除 Scheduler task。删除后当前 Memory API 不再解析旧 ID,仍引用该 ID 的 Scheduler task 会在下次解析时失败,因此应先移除或关闭任务。

Git 恢复边界

删除记录前的提交仍可从同一 Memory Git 仓库的可达历史中检索和恢复;这要求相关变更已经提交、仓库未丢失且历史未被重写或清理。当前 memory_get 只查询 HEAD,因此 Git 历史可恢复不等于旧 memory_id 可由当前 API 直接查询,也不构成绝对的 100% 保证。

5. 旧 Commitments 迁移

6. 调度器布局

调度器使用共享页面标题区与主题变量。四个紧凑筛选项横排在标题区下方,不使用全高侧栏;容器较窄时换行。任务行保留计划、状态与操作。

空状态

简介与“创建任务”操作在可用内容区域居中。三张建议卡片共用居中、最大宽度 960px 的网格,窄容器中变为单列。每张卡显示标题、计划、提示词,以及打开现有表单的“使用”操作。已有任务仍采用全宽列表。

验收:/scheduler 不设专用分类栏;在 360px、768px、1440px 容器宽度下四个筛选项均可访问;建议卡片换行且无横向溢出;“创建”和“使用”打开现有表单但不创建任务;加载、搜索和错误状态保持原行为。不修改调度器 API、持久化、执行或终端 TUI。

实现状态:布局通过规格与质量审查、Web 静态检查、152 项单元测试、TypeScript 检查、生产构建和文档链接检查。浏览器组件在 360px、768px、1440px 的预览均无横向溢出;“创建任务”和“使用”打开现有对话框。默认 App 也正确显示布局;“使用”打开现有预填表单,Escape 返回调度器且不创建任务。

7. 采用、修改与拒绝

参考处理
用户提供的 Scheduled tasks 页面截图采用独立页面、Create、搜索和一次性/周期/监控的产品分类;不采用重复 hero 标题和大面积留白。页面直接复用 OpenProgram 的 ManagePageHeader、ManageRow、主题一致的筛选按钮与主题 token。
现有 OpenProgram cron保留执行安全机制与 cron 兼容入口,产品名称迁移为 Scheduler,并集成到常驻 worker。
原 Commitments/heartbeat拒绝继续作为 Memory 类型;只保留迁移读取,不保留 Memory tab、status 字段或特殊 heartbeat。
Scheduler 自动写 Memory拒绝在 service 层隐式双写。采用 Agent 显式组合两个现有工具,并以 MemoryRef 保存关联,避免新增跨存储事务和重复 CRUD。

8. 实施 brief 与验收

本轮修改限定为 Scheduler prompt task 的内部 Memory 生命周期:保留现有 Scheduler service、REST、UI 和 Memory 数据格式;允许 Scheduler 来源调用 memory_status、memory_get 与 memory_update,补充 Agent 工具说明和执行上下文提示。公共 RED 必须证明上述三个工具可执行,同时 shell、普通文件写入、网络发送和 Scheduler 自修改仍被硬约束拒绝;Memory 写入继续经过现有 authority、revision、transaction 与 Git 路径。外部 API 权限不在本轮实现;记录删除后,旧 memory_id 的当前查询按最终语义返回 NOT_FOUND。

独立的 worker reliability 修改隔离 run_forever 的完整 tick 异常,并让 scheduler-worker 与 cron-worker 绕过仅供 Ink TUI 启动的 stdio 重定向;不改变 Scheduler service、REST、任务状态格式、claim、spawn 或 run_once。

验收项当前证据
专项 PythonScheduler、权限、cron CLI、Memory routes/runtime 共 133 passed;Ruff 通过。
Memory 生命周期真实 Scheduler prompt worker 会加载 merged permission rules;本地 owner 任务可使用 memory_status、memory_get 与 memory_update,deny/ask 仍优先,其他副作用仍拒绝。真实 ScriptedProvider 链路已更新 Topic 并产生 Memory Git 提交;多条 MemoryRef 超限时保留每条 ID 与 Topic 路径,只截断内容并显式标记。规格复审与质量复审均通过。
守护循环故障隔离run_forever 把普通 tick 异常以 warning 和完整 traceback 写入 stderr(常驻 worker 重定向到全局 worker 日志,独立前台命令显示在终端),按原分钟 cadence 等待后继续下一 tick;初始失败不重放 @reboot tick。该输出不进入任务 execution log。run_once 仍立即传播异常,KeyboardInterrupt 等 BaseException 不转为重试。正式命令、兼容别名及其 --once/--list 入口均绕过 TUI stdio 重定向。公共回归覆盖启动/普通 tick、正常等待、oversleep、下一 tick、日志、CLI 入口与两类 fail-fast 边界。
完整 Python5316 passed, 15 skipped, 2 deselected, 1 xfailed。剩余 4 项失败在基线提交 17db67dc 上逐项复现,分别属于既有 channel HTTP inventory 与 agentic harness 扫描。
Web全量静态检查、Scheduler 检查与 tsc --noEmit 通过;独立页面包含首次加载错误、操作错误和 icon button 可访问名称。视觉验收要求只有一个页面标题、64px 管理页 topbar、搜索与主操作同栏、topbar 下方显示横向分类筛选、任务按可见顺序编号、空状态居中显示响应式建议卡片,并在默认 18100 App 中截图确认。
独立审查规格审查通过;质量审查提出的权限、状态 claim、并发、MemoryRef、兼容入口与 UI 错误处理问题全部修复,复审通过。管理页结构统一修订另行完成规格 PASS;质量审查要求补充窄分栏重排、可区分操作名称和可执行视图逻辑检查,修复后 scoped re-review PASS。

本轮实现状态:内部 Agent 的 Scheduler-Memory 生命周期关联和守护循环的普通 tick 异常隔离已经实现;记录删除后不保留占位对象或 ID 转发,旧 memory_id 的当前查询返回 NOT_FOUND。外部 token 权限模型仍按边界延期。