# Astrion 运行时边界整理与定时任务工作清单 > 更新日期:2026-09-07 > 状态:修订后的设计与实施建议,尚未实施。 > 原题为「Astrion Gateway 化工作清单」,保留文件名便于既有引用。 > 依据:用户对目标的澄清、三份研究报告,以及本轮三个 Luna 子智能体的只读核查。 > 本轮核查为静态代码分析,没有运行并发、断线或进程重启复现;下文区分已有机制、待核验风险与拟新增能力。 ## 0. 改造目标与范围 本次目标是让 Astrion 的内部职责、状态修改规则和任务入口更清晰,使后续功能沿稳定边界扩展。当前明确的新功能场景是**定时任务**。 Gateway 是长期架构方向;近期交付是在现有进程中整理运行时服务边界,让 Web、CLI 和定时触发器复用任务受理、执行与控制逻辑。验收依据是新增入口所需理解和修改的范围,以及现有行为是否得到保留。 近期主线: 1. 固定已有状态边界和正确性保障。 2. 抽出接收显式运行上下文的公共任务入口。 3. 通过定时任务验证该入口,并补齐调度所需的持久记录和生命周期。 事件持久化、传输替换、公开 SDK、设备配对和远程执行分别评估,不构成本次完成的前置条件。 ### 参考资料的使用边界 - 原始愿景:`.astrion/user_upload/Astrion_Architecture_Product_Roadmap_Review_1.md`,重点 §10–14、§35、§37–38。 - 原始盘点:`astrion_audit/astrion_gateway_gap.md`。其中“无唯一 owner”“补丁不是投影”“恢复机制脆弱”等结论须结合下表理解,不能直接当作未修复故障。 - 外部研究:`opencode_study/opencode_architecture.md`、`openclaw_study/openclaw_gateway.md`。参考其职责分离、契约、幂等和恢复设计,不要求复制其部署、存储或认证方案;外部实现未在本轮重新核验。 ## 1. 现状:已有保障、剩余耦合与待核验事项 以下路径相对仓库根目录;行号是本轮读取时的定位锚点,后续以符号为准。 | 类别 | 当前证据 | 对改造的含义 | |---|---|---| | 已有:对话级资源隔离 | `server/context.py:58` 按 username/workspace/conversation 生成终端 key | 保留每对话资源边界;多端共享同一对话资源本身合理 | | 已有:主任务门闸 | `server/chat_flow.py:139` 获取门闸,`:258` 在 finally 释放;实现位于 `server/main_task_gate.py` | 公共入口复用同一执行裁决,不新增平行门闸 | | 已有:对话保存保护 | `utils/conversation_manager/crud_mixin.py:335` 按 message_id 合并、防止意外缩减;`:194` 使用 I/O 锁;`index_mixin.py:104` 原子替换文件 | 将保存语义纳入契约;不能因存在内存和文件副本就断言写入竞争未解决 | | 已有:客户端恢复 | `static/src/stores/task.ts:156` 偏移轮询;`static/src/app/methods/taskPolling/probe.ts:73` 对账恢复;同目录 `lifecycle.ts:137` 按 task_id/idx 去重 | 保留恢复闭环和过期响应过滤;当前轮询是增量事件读取,不是每轮全量读取 | | 已有:审批单次决定 | `modules/tool_approval_manager.py:65` 在锁内裁决 pending,已决定时返回现状 | 复用决定规则;记录谁决定与提前认领审批是不同需求 | | 耦合:执行依赖 Web 环境 | `server/tasks/models.py:785` 后台任务建立 test_request_context、回填 session 后获取资源和执行 | 优先抽出显式上下文,减少隐式请求状态依赖 | | 耦合:写入口分散 | 任务 manager、terminal、conversation manager 各有职责和直接调用方 | 按状态明确权威、写入口和缓存更新;新增门面不是完成所有权收敛的证明 | | 边界:过程记录为内存态 | `server/tasks/models.py:75` 有界事件 deque,`:108` 清理旧任务,`:762` 分配任务级 idx;审批 manager 为进程内实例 | 不能承诺服务重启续跑或无限期回放;也不能说任务一结束事件就立即丢失 | | 优化候选:用户级广播 | `server/context.py:75` 给事件补 conversation_id,由客户端筛选 | 当前也是投影方案;对话级订阅用于减少无关流量和明确受众,不是 Owner 正确性的必选前提 | | 新能力:用户定时任务 | 本轮搜索只发现任务清理、idle reaper 等维护定时器,未发现用户 Schedule 实体与到期派发链路 | 单独设计调度状态与记录,复用现有任务执行 | 保留两个有界核验项,避免将静态推断直接升级为故障结论: - `server/tasks/models.py:157` 的“检查运行中任务→创建记录”与最终执行门闸分属两处。核验并发请求是否产生重复任务记录;不能据此断言会并发修改同一对话。 - 原报告提到 `server/chat/terminal.py::issue_socket_token` 发放竞争。本轮未重新复现;若仍存在,作为独立的小范围缺陷处理,不捆绑整个运行时改造。 ## 2. 阶段一:固定契约与已有不变量 **目标:明确状态属于谁、新入口应该调用哪里。** - [ ] 产出 `docs/runtime_contract.md`,先描述内部服务契约;暂不强制公开网络协议、握手或实体全面改名。 - [ ] 建立状态责任表:每项列明权威来源、允许的修改方、持久化入口、缓存刷新、并发裁决和失效条件。内存/文件/客户端缓存可以共存,权威关系必须明确。 - [ ] 对齐概念:Session 对应现有 conversation,Run 对应一轮主任务,Schedule 表示计划,Occurrence 表示某次到期触发,Event 表示变化通知。子 agent、后台命令与主任务的关系单独说明,不直接把所有现有 task 等同主 Run。 - [ ] 审批与用户提问保留不同语义。可共享 ID、关联、等待和回答的基础设施,但提问答案不能被当作工具执行授权。 - [ ] 明确公共入口所需的 principal、workspace、conversation、模型/运行配置与事件输出接口;默认值由明确的解析步骤产生。 - [ ] 建立调用方迁移表:Web/CLI 对应 API、Workflow 激活、通知派发、定时触发。每项标注上下文来源、门闸获取/释放和取消传播。 - [ ] 围绕修改范围保留或补充回归用例:同对话并发、不同对话隔离、保存不丢消息、取消、审批重复回答、偏移恢复和过期响应过滤。 **完成标准:**目标入口的状态修改路径和执行裁决可定位;已有保障成为明确约束,未验证风险有独立记录。 ## 3. 阶段二:抽出显式上下文与公共任务入口 **目标:无浏览器也能通过受控入口启动、观察和停止一轮任务。** ```text Web / CLI 适配层 定时触发器 Workflow / 通知派发 \ | / 公共任务受理与控制入口 | 现有执行门闸与 Agent 执行 | 现有保存、审批、事件和取消链路 ``` - [ ] 以 `TaskManager.create_chat_task` 及执行链路为基础抽出服务接口。`RuntimeService` 可作为名称候选;文件位置按真实职责确定,避免把所有 manager 和状态塞入一个新类。 - [ ] 服务接口至少覆盖提交、查询和取消;审批回答复用现有 manager,通过明确关联接入服务层。会话创建按需要复用现有服务,第一条验证链路可使用已有会话。 - [ ] HTTP 参数解析、Cookie/CSRF/Bearer 验证放在适配层,向服务层传入可信 principal 和经校验的资源范围。不能接受客户端或 Schedule payload 自报的 role 作为授权依据。 - [ ] 消除目标执行链路对隐式 Flask session 的读取。迁移期可在明确的兼容适配层保留旧上下文,但须列出剩余依赖;只把 test_request_context 包进新方法不算完成解耦。 - [ ] 复用门闸、取消、审批和保存规则;分别定义任务受理去重与实际执行互斥,防止重复启动或门闸泄漏。 - [ ] Web 任务入口先接入服务,再逐条迁移 Workflow/通知等调用方;每次明确哪些旧写路径已封闭。不能把“门面转发成功”写成“全部状态唯一 Owner 已完成”。 - [ ] 内部错误采用稳定状态/错误码,HTTP 状态码由适配层映射;事件先适配现有 idx/offset 和 sender,不同时重写客户端。 **完成标准:**不创建浏览器会话、不伪造 HTTP 请求,测试能通过显式身份和资源上下文启动一次受控任务、读取结果并取消;同对话重入仍受门闸保护;现有 Web/CLI 行为兼容。执行可使用可控模型/工具替身验证,无需真实外部副作用。 ## 4. 阶段三:定时任务纵向落地 **目标:时钟成为公共任务入口的另一个调用方。** 本节是待实施设计,不代表当前已有调度器。具体 UI 和默认行为在实现前确认,下列保守默认作为讨论起点。 ### 4.1 计划与触发记录 - [ ] Schedule 至少保存:ID、所属 principal、目标 workspace、会话策略、提示词/任务配置、时间规则、时区、启用状态和配置版本。明确夏令时重复/不存在时刻的处理。 - [ ] 支持创建、暂停、恢复和删除计划。建议暂停/删除只影响未来触发,已受理的 Run 另行取消;最终行为须明确。 - [ ] 明确使用已有会话还是每次新建会话;首版可只实现一种,须说明上下文累积、目标删除和工作区失效时的行为。 - [ ] 模型配置确定“创建时固定”还是“触发时解析”;权限在触发时按当前有效授权重新校验,不保存可绕过权限变更的长期授权快照。 - [ ] 每个 Occurrence 有稳定触发标识,例如 schedule_id + 计划时间点;保存所用配置版本、受理状态、run_id 和终态。计划编辑后的未来触发身份规则须明确。 ### 4.2 重复、重叠与停机 - [ ] 为 Occurrence 登记和 Run 受理定义持久幂等规则:同一触发重试返回同一受理结果,相同键不同参数拒绝;记录保留期覆盖允许的重试窗口。 - [ ] 明确“登记后未启动”“已启动但关联未写完”等崩溃窗口。登记/受理应原子提交或具备可验证的恢复对账;不能只用内存 TTL 承诺跨重启不重复执行。 - [ ] 选定单个活动调度器的启动与所有权规则,防止重载器或多个服务进程重复派发;不要求因此引入分布式基础设施。 - [ ] 同会话已有任务或上一轮仍在运行时,定义 skip/queue/parallel 策略。建议首版跳过并记录原因,沿用会话门闸,不默默增加无限队列。 - [ ] 定义服务关闭期间错过触发的策略。建议首版记录错过并等待下个未来时点,不集中补发;服务需运行才会触发,本阶段不包含操作系统唤醒/开机自启。 - [ ] 重启后恢复 Schedule 和触发记录;上一进程未确认完成的 Run 标为中断或结果待核验,不显示仍在正常运行,不自动重做可能已产生副作用的动作。 - [ ] 触发去重仅保证任务受理规则,不承诺任意外部工具副作用 exactly-once。无法确认的执行结果进入显式待核验状态。 ### 4.3 审批、存储与验收 - [ ] 无人在线时仍保持原有权限限制:遇到审批/提问按明确超时等待,超时结束或中断本轮并记录原因,不自动扩大权限。等待中的任务也遵守重叠策略。 - [ ] 审批关联当前 Run/会话,复用现有 pending/answer 链路。重启后旧请求不能被当作仍有执行现场的有效审批;持久审批记录与继续执行分别设计。 - [ ] 为 Schedule/Occurrence/必要的运行摘要选择持久化方案,先列出原子更新、唯一性、查询和恢复要求,再决定文件或 SQLite。数据走运行态路径解析,不写源码树;不强制迁移全部对话历史。 - [ ] 沿用当前任务事件读取;补充触发记录查询,使旧内存任务被清理或重启后仍能解释触发结果。日志记录 schedule_id/occurrence_id/run_id,复用既有设施。 **完成标准:**可控时钟与执行替身验证一次触发、重复触发、任务重叠、计划暂停/恢复、目标失效、无人审批超时、停机错过触发及重启对账;真实入口验证不依赖浏览器。明确只恢复计划与记录,不承诺从任意执行位置续跑。 ## 5. 后续独立决策:有明确需求再启动 | 决策 | 启动条件 | 决策前必须补充的内容 | |---|---|---| | SSE / WebSocket / 保持轮询 | 现有延迟、连接数或带宽不能满足目标,或新增双向交互需求 | 部署 worker 模型、代理缓冲、重连、慢消费者处理;传输更换不等于状态正确性提升 | | 对话级订阅 | 需要减少无关广播、精确控制受众 | 订阅与资源授权分别校验,区分任务/会话事件与用户级通知 | | durable 事件与快照恢复 | 需要超出内存保留窗口的过程追溯、跨重启生命周期查询 | 提交时机、序号作用域、快照边界、日志裁剪、缺口处理与 schema 版本 | | 审批持久化与可恢复执行 | 需要重启后继续等待并执行原动作 | 重建上下文和待执行动作、权限重校验、过期请求处理及结果不确定性;恢复 pending 记录不能实现续跑 | | TS 类型 / SDK 生成 | 对外契约或多客户端类型维护成为实际成本 | 选一个 schema 权威源、兼容策略与生成检查;不强制新网络握手 | | 身份体系整理 | 跨凭证访问同一资源或统一授权成为需求 | 统一 principal/resource/authorization;各适配层可保留不同凭证机制,不能直接合并 Web/API 用户数据空间 | | 设备配对 / Remote Worker | 明确需要多设备接入或远程执行 | 执行契约、连接身份、所有权转移及故障语义,独立设计验收 | 若进入事件恢复改造,必须遵守以下边界: 1. 快照注明覆盖的事件水位 N,并与同一状态版本一致;续传从 N 之后开始。快照生成、订阅和历史读取之间不得有漏事件窗口,重复投递仍需幂等应用。 2. durable 事件只承诺已提交记录可恢复;live delta 是否恢复单独定义。运行中未完成的 Item 需要当前内容快照、覆盖式更新或不完整标记,不能只依赖最终 completed 事件。 3. 状态和事件写入需要一致的提交/恢复规则。对话 JSON、事件 JSONL、审批 JSONL 不天然构成一致快照与日志。 4. 连接序号、任务偏移和持久会话序号不能混用;连接重建、历史裁剪或会话重置时给出明确的重新同步规则。 5. JSONL 与 SQLite 都需定义恢复、保留和迁移方案。选择依据是事务与查询边界,不承诺以后可低成本平移。 ## 6. 改造完成的判断 - 新增任务来源只需构造显式上下文、校验目标并调用公共入口,无需复制 Web 聊天启动流程。 - 已迁移路径有明确状态权威与写入规则,现有门闸、保存和客户端恢复保护得到保留。 - 定时任务有可查询的计划、触发记录和终态;重复、重叠、权限变化与停机行为可解释。 - 各阶段可独立验证;只为当前边界迁移做必要的接口调整,不同时重写 Agent loop、前端状态管理或部署拓扑。 - 每阶段说明实际迁移的入口、剩余兼容依赖和验证结果。完成门面、生成架构图或更换传输本身不算完成改造。