agent-Specialization/cache_research/gateway/audit_research_summary_v2/research_summary.md
JOJO d9bd599c1c feat(runtime): Gateway 独立启动与公共协议落地(改造第 0-3 步)
- 闭环修复:审批 task_id 显式化(N2)、通知回退路径门闸 finally 释放(N1)、
  personalization 原子写(S10,公共 atomic_write_json)
- server.tasks 拆解:__init__ 轻量化、Blueprint/路由移至 blueprint.py/web.py,
  app_legacy 装配点惰性挂载;models.py 循环依赖死导入移除
- 执行链 Web 解耦:emit_event/run_background 安全包装(socketio 未绑定静默),
  清除 4 处裸 socketio.emit(含 task_stopped 先写事件流再推送的顺序修复)
- RuntimeService 补建对话下沉:chat 任务无 conversation_id 时服务层装配,
  客户端无需复制 Web 两步流程
- 事件协议:get_task_events 返回 meta.window_start 缺口检测水位
- 验收:test_runtime_standalone_lifecycle 子进程隔离(config import 固化问题),
  独立启动 + 协议全链路 + 审批语义全绿;全量 74 测试失败恰为 4 项存量
2026-09-07 23:00:15 +08:00

47 KiB
Raw Blame History

Gateway 既有研究文档汇总research_summary

生成日期2026-09-07 任务性质:全程只读,未修改任何项目文件(仅在交付目录生成本汇总)。 汇总者:子智能体 #6。 汇总原则:不掺入自身推测,所有结论注明来源文件;文档间有冲突时并列呈现并注明。

来源文件清单(实际读取的文件)

优先级 任务指定 实际路径(已确认) 状态
1 cache_research/gateway/gateway_work_plan.md cache_research/gateway/gateway_work_plan.md2026-09-07 修订版) 已读
2 cache_research/gateway/phase12_implementation_plan.md cache_research/gateway/phase12_implementation_plan.md 已读
3 cache_research/gateway/eval_summary.md cache_research/gateway/eval_summary.md(含 R1-R6 审阅注释) 已读
4 四份评估子报告 cache_research/gateway/eval_task_entry_points/task_entry_points.md 已读
cache_research/gateway/eval_flask_context_deps/flask_context_deps.md 已读
cache_research/gateway/eval_endpoint_classification/endpoint_classification.md 已读
cache_research/gateway/eval_event_approval_coupling/support_chains_coupling.md 已读
5 astrion_audit/astrion_gateway_gap.md cache_research/gateway/astrion_audit/astrion_gateway_gap.md实际位于此路径,工作区根无 astrion_audit/ 目录,见下方说明) 已读
6 外部参考 cache_research/gateway/opencode_study/opencode_architecture.md 已读
cache_research/gateway/openclaw_study/openclaw_gateway.md 已读

路径说明:任务指定 #5 为 astrion_audit/astrion_gateway_gap.md,但工作区根目录不存在 astrion_audit/;实测唯一一份 astrion_gateway_gap.md 位于 cache_research/gateway/astrion_audit/astrion_gateway_gap.md(已被 gateway 相关文档同置于 cache_research/gateway/ 下),本汇总即基于该文件。已按要求未读取 audit_entry_points_v2/ 等其他目录(属他人产出)。外部参考只需提炼被本项目借鉴的设计点,未做全文复述。


1. 三阶段路线全文要点来源gateway_work_plan.md2026-09-07 修订版)

总体目标:让 Astrion 的内部职责、状态修改规则和任务入口更清晰,使后续功能沿稳定边界扩展。近期明确新功能场景 = 定时任务。长期方向是 GatewayRuntime/Gateway近期交付是在现有进程内整理运行时服务边界,让 Web、CLI 和定时触发器复用同一套任务受理/执行/控制逻辑。验收依据 = 新增入口所需理解和修改的范围 + 现有行为是否保留。

近期主线(三件事)

  1. 固定已有状态边界和正确性保障。
  2. 抽出接收显式运行上下文的公共任务入口。
  3. 通过定时任务验证该入口,并补齐调度所需的持久记录和生命周期。

非本次前置条件:事件持久化、传输替换、公开 SDK、设备配对和远程执行分别评估。

参考资料边界work plan 原文)

  • 原始愿景 .astrion/user_upload/Astrion_Architecture_Product_Roadmap_Review_1.md(重点 §1014、§35、§3738
  • 原始盘点 astrion_audit/astrion_gateway_gap.md 的"无唯一 owner""补丁不是投影""恢复机制脆弱"等结论须结合新核查理解,不能直接当作未修复故障
  • 外部研究只参考职责分离/契约/幂等/恢复设计,不复制其部署/存储/认证方案。

现状关键结论work plan §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 偏移轮询;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 各有职责和直接调用方。
    • 过程记录为内存态:models.py:75 有界事件 deque、:108 清理旧任务、:762 分配任务级 idx审批 manager 为进程内实例。
  • 优化候选server/context.py:75 用户级广播(当前也是投影方案)。
  • 新能力(定时任务)本轮搜索只发现任务清理、idle reaper 等维护定时器,未发现用户 Schedule 实体与到期派发链路 → 需单独设计调度状态与记录,复用现有任务执行。
  • 两个有界核验项(勿将静态推断升级为故障):
    1. models.py:157"检查运行中任务→创建记录"与最终执行门闸分属两处 → 核验并发是否产生重复任务记录。
    2. 原报告提到 server/chat/terminal.py::issue_socket_token 发放竞争,本轮未复现;若仍存在作为独立小缺陷处理。

阶段一:固定契约与已有不变量(目标/范围/验收)

目标:明确状态属于谁、新入口应该调用哪里。 范围清单

  • 产出 docs/runtime_contract.md(先描述内部服务契约;暂不强制公开网络协议/握手/实体全面改名)。
  • 建立状态责任表:每项列明权威来源、允许的修改方、持久化入口、缓存刷新、并发裁决、失效条件。内存/文件/客户端缓存可共存,权威关系必须明确
  • 对齐概念:Session=现有 conversationRun=一轮主任务Schedule=计划Occurrence=某次到期触发Event=变化通知。子 agent、后台命令与主任务的关系单独说明不把现有 task 全部等同主 Run。
  • 审批与用户提问保留不同语义;可共享 ID/关联/等待/回答基础设施,提问答案不能被当作工具执行授权
  • 明确公共入口所需 principal、workspace、conversation、模型/运行配置与事件输出接口;默认值由明确解析步骤产生。
  • 建立调用方迁移表Web/CLI 对应 API、Workflow 激活、通知派发、定时触发;每项标注上下文来源、门闸获取/释放、取消传播。
  • 围绕修改范围保留/补充回归用例:同对话并发、不同对话隔离、保存不丢消息、取消、审批重复回答、偏移恢复、过期响应过滤。 完成标准:目标入口的状态修改路径和执行裁决可定位;已有保障成为明确约束,未验证风险有独立记录。

阶段二:抽出显式上下文与公共任务入口(目标/范围/验收)

目标:无浏览器也能通过受控入口启动、观察和停止一轮任务。 架构示意

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 行为兼容。执行可用可控模型/工具替身验证,无需真实外部副作用。

阶段三:定时任务纵向落地(目标/详细设计要求——本节最重要)

目标:时钟成为公共任务入口的另一个调用方。本节为待实施设计不代表当前已有调度器下列保守默认作为讨论起点UI 与默认行为在实现前确认。

4.1 计划与触发记录

  • Schedule 至少保存ID、所属 principal、目标 workspace、会话策略、提示词/任务配置、时间规则、时区、启用状态、配置版本。明确夏令时重复/不存在时刻的处理
  • 支持创建、暂停、恢复、删除计划。建议暂停/删除只影响未来触发,已受理的 Run 另行取消;最终行为须明确。
  • 明确使用已有会话还是每次新建会话;首版可只实现一种,但须说明上下文累积、目标删除和工作区失效时的行为
  • 模型配置确定"创建时固定"还是"触发时解析"权限在触发时按当前有效授权重新校验,不保存可绕过权限变更的长期授权快照
  • 每个 Occurrence 有稳定触发标识(例如 schedule_id + 计划时间点保存所用配置版本、受理状态、run_id 和终态。计划编辑后的未来触发身份规则须明确。

4.2 重复、重叠与停机

  • 为 Occurrence 登记和 Run 受理定义持久幂等规则:同一触发重试返回同一受理结果,相同键不同参数拒绝;记录保留期覆盖允许的重试窗口。
  • 明确"登记后未启动""已启动但关联未写完"等崩溃窗口。登记/受理应原子提交或具备可验证的恢复对账;不能只用内存 TTL 承诺跨重启不重复执行。
  • 选定单个活动调度器的启动与所有权规则,防重载器或多个服务进程重复派发;不要求因此引入分布式基础设施。
  • 同会话已有任务或上一轮仍运行时,定义 skip/queue/parallel 策略。建议首版跳过并记录原因,沿用会话门闸,不默默增加无限队列。
  • 定义服务关闭期间错过触发的策略。建议首版记录错过并等待下个未来时点,不集中补发;服务需运行才会触发,本阶段不包含 OS 唤醒/开机自启。
  • 重启后恢复 Schedule 和触发记录;上一进程未确认完成的 Run 标为中断或结果待核验,不显示仍在正常运行,不自动重做可能已产生副作用的动作
  • 触发去重仅保证任务受理规则,不承诺任意外部工具副作用 exactly-once。无法确认的执行结果进入显式待核验状态。

4.3 审批、存储与验收

  • 无人在线时仍保持原有权限限制:遇到审批/提问按明确超时等待,超时结束或中断本轮并记录原因,不自动扩大权限;等待中的任务也遵守重叠策略。
  • 审批关联当前 Run/会话,复用现有 pending/answer 链路。重启后旧请求不能被当作仍有执行现场的有效审批;持久审批记录与继续执行分别设计。
  • 为 Schedule/Occurrence/必要的运行摘要选持久化方案,先列出原子更新、唯一性、查询和恢复要求,再决定文件或 SQLite。数据走运行态路径解析,不写源码树;不强制迁移全部对话历史。
  • 沿用当前任务事件读取;补充触发记录查询,使旧内存任务被清理或重启后仍能解释触发结果。日志记录 schedule_id/occurrence_id/run_id复用既有设施。 完成标准:可控时钟与执行替身验证一次触发、重复触发、任务重叠、计划暂停/恢复、目标失效、无人审批超时、停机错过触发及重启对账;真实入口验证不依赖浏览器。明确只恢复计划与记录,不承诺从任意执行位置续跑

后续独立决策(有明确需求再启动)

决策 启动条件 决策前必须补充内容
SSE / WS / 保持轮询 延迟/连接数/带宽不满足,或新增双向交互 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 都需定义恢复、保留、迁移方案;选择依据是事务与查询边界,不承诺以后可低成本平移。

改造完成判断work plan §6

  • 新增任务来源只需构造显式上下文、校验目标并调用公共入口,无需复制 Web 聊天启动流程。
  • 已迁移路径有明确状态权威与写入规则,现有门闸、保存、客户端恢复保护保留。
  • 定时任务有可查询的计划、触发记录和终态;重复、重叠、权限变化与停机行为可解释。
  • 各阶段可独立验证;只为当前边界迁移做必要接口调整,不同时重写 Agent loop、前端状态管理或部署拓扑。
  • 每阶段说明实际迁移入口、剩余兼容依赖、验证结果。完成门面、生成架构图或更换传输本身不算完成改造

2. 范围评估核心结论来源eval_summary.md + 四份子报告,含 R1-R6 审阅修订)

2.1 196 个端点分类结果来源eval_endpoint_classification/endpoint_classification.md经 R1/R2 修订)

统计口径:以 Flask 路由注册Methods 合并计数)为准,共 196 个,分 26 个文件,与给定分布一致。

类别 数量 占比 是否迁移
T1 任务受理 3 1.5% 必须POST /api/tasks、/api/v1/.../messages、/api/workflow/activate
T2 任务控制 13 6.6% 必须cancel×2、runtime_guidance/queue×4、workflow deactivate、sub_agents/background 停止×3、审批回答×3
T3 任务观察 14 7.1% ⚠️ 可不动(只读 REST轮询协议天然可复用
C CRUD 131 66.8% 不动
S 状态查询 20 10.2% 不动
A 认证管理 15 7.7% 不动
合计 196 100%

核心答案:必须迁移的最低集合 = T1 + T2 = 16 个端点8.2%。16 个端点全部收敛到同一批 manager 单例方法task_manager / sub_agent_manager / background_command_manager / 三个 approval managerGateway 化实质 = 把这几个 manager 方法提升为 RuntimeService 公共入口HTTP 端点从"直接调 manager"改为"调 RuntimeService",而非改写端点本身。

迁移复杂度分布16 个)12 小 / 3 中 / 1 大(唯一大项 = workflow activate因门闸 token 移交 + 状态机编排)。

审阅修订要点

  • R1范围16 个是当前分类下的受理/控制端点集合,不是架构改造完成的充分条件server/chat/permission.py 的权限/执行环境/网络权限变更在任务运行期会排队生效,必须进入阶段一状态责任表;其余端点应描述为"多数可保持 HTTP 兼容",不能概括为"与运行时零耦合"。查询端点可保留原 URL但后台调用方CLI/定时任务)应能通过内部接口(如 get_task_events)查询,不必为观察任务发 HTTP。新增门面不等于全部写入口已收敛。对应子报告 §4.4 明确:chat/permission.py:166-185 / :265-284 / :352-368 分别排队修改运行中的权限/执行环境/网络权限,work-mode:420-445 拒绝运行中切换。
  • R2计数与编排11+3+1=15 应为 12 小 / 3 中 / 1 大 = 16仍为定性估算。Workflow 编排(会话补建、激活、门闸移交、失败回滚)留在 HTTP 层只适合作为过渡,长期应按复用需求下沉到工作流服务供非 HTTP 入口调用;无需全部塞入 RuntimeService。
  • R3依赖与异常路径core/modules/utils 无直接 Flask 导入已确认,但不能外推为所有间接调用都不依赖请求上下文"无旁路"须限定为正常受理路径:chat_flow_task_main.py:645-675 在任务创建失败后直接执行 handle_task_with_sender绕过 TaskRecord 登记(无事件 deque、不可按 task_id 轮询/取消);外围轮询器有预占门闸,不能仅凭回退认定并发写入 bug迁移验收必须覆盖回退路径的记录、事件、取消、门闸生命周期。socket send_messagesocket_handlers.py:259 已短路返回 DEPRECATED属死代码应与活跃回退分开。"5 个调用点"实为 5 类来源、6 处调用位置。
  • R4上下文设计与工作量9 字段是旧 session 依赖的搬迁清单,不是最终领域模型;应区分"可信身份与资源范围""本次任务参数""内部执行信息"(门闸 token/通知回滚不得成为普通客户端可提交字段);明确默认值/对话配置/本次覆盖的解析优先级。6-8 文件属估算;get_user_resources 有约 170+ 调用处(含 83 处 @with_terminal 装饰器路径),影响面需 host/Web/API 身份 × 会话 × 默认值来源回归覆盖,不宜承诺每处都小。
  • R5审批产品边界:拒绝当前工具后继续运行不自动意味着不安全(后续动作仍受权限约束)。等待人工/到期终止/拒绝当前动作后继续是不同产品策略,不能把"定时任务禁止人工审批"当作必选技术条件。工具审批、计划审批、用户提问应分别定义超时含义。超时策略可在阶段三明确,不阻塞保持原有语义的阶段二上下文重构。
  • R6取消与生命周期:标准停止按钮走 REST 硬取消,可打断审批等待;缺口应限定为仅设置软停止标志的路径socket stop_task 软 stop不能描述成所有停止按钮失效。需跟进超时/取消后 pending 终态更新、审批与 Run 关联;条清理不能只按 TTL 删仍有合法等待者的请求。task_id 恒 None 目前仍是静态疑点,须验证运行时载荷后定性。

2.2 任务链路 Flask 依赖性质来源eval_flask_context_deps/flask_context_deps.md经 R3 修订)

总体判定:依赖属于「浅层入口型」,集中两个枢纽函数,执行体干净。

  • 出口即枢纽
    1. 入口 server/tasks/models.py::create_chat_task(直读 session 快照)+ _run_chat_tasktest_request_context 包裹后台线程再调 get_user_resources
    2. 资源获取 server/context.py::get_user_resources(及内部 _apply_workspace_personalization_preferences、admin policy
  • 执行体干净core/modules/utils/ 零 Flask 隐式上下文session 同名变量全是终端会话/容器句柄或 dict 参数,非 Flaskserver/chat_flow*.py 9 个文件函数体内 session/request/has_request_context 使用(只有 import 行)。
  • 命中统计:测试 request_context 全仓仅 1 处models.py:794has_request_context ~17 处全在 context.pyB 类(必须消除)集中在 2 文件tasks/models.pysession 15 行)+ context.pysession 31 行)。
  • B 类依赖清单(必须消除/显式化):
    • B-1 models.py:785-812 _run_chat_task 的 test_request_context 包装(核心);难点不在删 wrapper 而在 get_user_resources 参数化。
    • B-2 models.py:180-203 create_chat_task 直接读 Flask session含 else 分支全量直读 http 上下文、setdefault 兜底,见下方"冲突/补充")。
    • B-3 context.py::get_user_resourcesL221-535核心内部 8-10 处 has_request_context 守卫读写 host_mode/workspace_id/host_workspace_id/run_mode/thinking_mode/model_key/is_api_user + 无守卫 record/role 读。
    • B-4 context.py::_apply_workspace_personalization_preferencesL116-178读 model_key/回写)。
    • B-5 context.py::ensure_conversation_loadedL750-810写 session 回写,任务线程内已天然跳过但属隐式耦合)。
    • B-6 server/auth_helpers.py:35-49 认证辅助被任务链路经 get_user_resources 无守卫调用。
  • C 类均已核查归 A可保留server/conversation.py 的 host_mode/input_draft/terminal 相关函数、with_terminal 装饰器83 处全部路由、socket_handlersflask-socketio 适配层)。
  • 依赖深度结论:浅层。B 类无条件耦合仅 2 处(创建入口 + 线程包装),守卫型耦合集中在 context.py 一个文件。
  • R3 修订:直接搜索不能证明所有间接调用都无上下文依赖;"浅层"描述依赖位置不等于改动风险低get_user_resources 的身份/资源分支需行为验证,不能以删除 import 或零关键词命中代替验收。

2.3 任务入口五点评估来源eval_task_entry_points/task_entry_points.md经 R3 修订)

  • 执行链正常受理路径已单一收敛5 类来源、6 处调用位置共用 create_chat_task → 线程 → _run_chat_task → run_chat_task_sync → process_message_task → asyncio loop.create_task(handle_task_with_sender)
  • 六处调用点概览:
# 文件:行 入口 触发来源 显式化程度 迁移难度
tasks/api.py:200 create_task_api Web HTTP POST 低(无 session_data 小~中
api_v1.py:320 send_message_api Web HTTP POSTBearer 低(无 session_data is_api_user/role 必须显式)
③a workflow_runtime_api.py:184 api_activate_workflow Web HTTP POST session_data 显式) 小~中
③b workflow_runtime_api.py:264 api_deactivate_workflow Web HTTP POST 高(同上,+通知池/门闸回滚) 小~中
chat_flow_task_main.py:613 _dispatch_completion_user_notice 内部后台轮询线程 极高(全显式)
chat_flow_task_main.py:1416 _dispatch_multi_agent_idle_messages 内部后台轮询线程 极高(全显式 + task_type=notice
  • 迁移真实难点(从大到小):
    1. get_user_resources 的 session 隐式读取参数化host_mode/is_api_user 分支选错即静默串工作区,最高风险)。
    2. API 身份字段is_api_user/role正确传递调用点②唯一无 session_data 的 API 来源)。
    3. main_task_gate 门闸移交语义预占→token 随 session_data 移交→线程认领→finally 释放/失败回滚)。
    4. task_type="notice" 互斥豁免与单对话互斥语义保持(调用点⑤)。
    5. 三套身份取数来源统一web session / token session / web_terminal 属性)。
  • 另项(不在本 5 点但相关):socket_handlers.py:345 → start_chat_tasksocket 直连执行链,不可达死代码chat_flow_task_main.py:664 通知回退直接执行(活跃,见 R3

2.4 四支撑链路评估来源eval_event_approval_coupling/support_chains_coupling.md经 R5/R6 修订)

总体判定:事件/取消/保存三条可直接复用(需适配层);审批链路需改造

  • 事件链路:直接复用。载体 TaskRecorddeque maxlen=20000 + 每任务 idx调用方只需 create_chat_task 拿 task_id 即可轮询/取消socket 推送按 user_{username} 房间(离线无影响,但用户在线会收到定时任务事件 → 前台干扰,需加 source 字段或确认产品预期)。适配点:消除 test_request_context、定义定时事件来源标识。
  • 取消链路:直接复用。寻址=username+task_idstop_flags 任务级 key=task_id=client_sid不依赖 terminalconversation 仅副作用);保留"独立事件循环 + entry 持 loop/task"模式以支持硬取消;公共入口须把 task_id 持久化到 Occurrence。
  • 保存链路:直接复用,前提明确。写入口收敛于 context_manager.add_conversation(每消息 auto_savemerge-on-save + _io_lockmanager 实例级,跨实例不互斥)+ 主任务门闸三道防线。前提:新调用方必须(1)走对话级 terminal、(2)遵守主任务门闸、(3)会话策略决定 conversation_id。存在执行链之外第二批写者设置/压缩/CLI共用同一保护。
  • 审批链路:需改造。核心问题§2.4
    1. 等待循环默认超时 3600s 且调用点(:435/:574/:883/:1153未传 timeout 参数(均有参数但调用点没传)。
    2. 超时语义现状=拒绝该工具、任务继续(非结束任务)——产品决策项,两种候选:(a)拒绝该工具继续(现状,风险无监督继续);(b)结束整个任务。
    3. 等待期间软停止无效(下一工具调用行首 :600 才生效)。
    4. manager 条目无 TTL/清理。
    5. 存储 manager 可复用(与 Web 前端共用 pending/answer 数据);auto_approval 分支ApprovalAgent是唯一现成无人工决策路径但仅覆盖 tool 审批。
    • 候选改造最小改动排序注入可配置超时session_data 透传)→ 定义超时语义 → 等待循环加 stop 检查 → manager 条目 TTL/清理 → 会话策略决定审批是否可达。
  • R5 修订§2.4 的"禁止人工审批 / 60-300s 超时"均为待讨论选项,不是定时任务的技术前提;拒绝当前工具后继续仍受权限限制,不自动等于不安全;可等用户上线回答。工具审批、计划审批、用户提问应分别确定超时处理。客户端离线但服务运行时可保留现有 pending跨服务重启保留记录与恢复等待执行是另外两层需求。
  • R6 修订:停止按钮无效应限定为只置软停止标志的路径(标准按钮走 REST 硬取消可打断);条目生命周期应先定义超时/取消终态与迟到回答处理,再设保留期清理,不能只按 TTL 删仍被等待的 pendingtask_id 恒 None 保持静态疑点,待运行时关联验证。

2.5 审阅修订要点汇总R1-R6 已嵌入各节)

见上述各节 R1/R2/R3/R4/R5/R6 处。


3. 阶段一/二实施与验收记录来源phase12_implementation_plan.md另见项目记忆 gateway_runtime_work_plan

状态:阶段一、阶段二代码工作全部完成;改造相关测试 24/24 全绿工作区改动尚未 commit;阶段三(定时任务)未做(功能未讨论)。

3.1 设计决策(按 R4 审阅意见RuntimeContext 三层分离

TrustedPrincipal   可信身份与资源范围username / workspace_id / host_mode /
                   host_workspace_id / is_api_user / role
                   ——只能由适配层认证后构造,客户端不可自报
TaskParams         本次任务参数message / images / videos / files / model_key /
                   run_mode / thinking_mode / max_iterations / conversation_id /
                   goal_mode / skill_context_messages / message_source
InternalDirectives 内部执行信息main_task_gate_token / auto_user_message_event /
                   auto_user_message_payload / preceding_user_notices /
                   approval_timeout_seconds仅透传机制默认语义不变
                   ——普通客户端不可提交,仅内部调用方(通知链/工作流/派发器)使用

默认值解析优先级:本次显式传参 > 对话元数据绑定 > 会话/用户偏好快照 > 系统默认。会话配置恢复仍在 get_user_resources + 会话加载链路内完成。

RuntimeService 最小接口集create_task(principal, params, directives) -> task_idcancel_task(username, task_id)enqueue_runtime_guidance / enqueue_runtime_pending_message / remove_runtime_pending_message / promote_runtime_pending_to_guidanceget_task / get_task_events(username, task_id, offset)内部查询接口CLI/定时任务不必走 HTTP。审批回答复用现有三个 manager通过明确关联接入不进 RuntimeService 首版。

两步走步骤①兼容期RuntimeContext + RuntimeService 骨架落地,create_chat_task 接受显式上下文6 处调用点迁移test_request_context 桥保留作兜底步骤②拆桥get_user_resources 增加显式参数变体,_run_chat_task 改走显式路径后删 test_request_context 桥ensure_conversation_loaded 的 session 回写移出任务路径。

3.2 关键风险与对策

  1. get_user_resources 参数化最高风险host_mode/is_api_user 分支选错 → 静默串工作区。对策:显式变体与 web 路径并存,先任务线程单点切换,回归验证后再推广。
  2. 门闸 token 移交语义InternalDirectives 原样承载;通知链"预占→移交→认领→失败回滚"不变。
  3. task_type="notice" 互斥豁免保留。
  4. 异常回退路径chat_flow_task_main.py:645-675 直接执行 handle_task_with_sender保留语义验收覆盖其门闸/事件/取消生命周期。
  5. 事件前台干扰:阶段二不加 source 字段(阶段三产品决策),现有行为不变。

3.3 实施内容清单(阶段一/二)

阶段一交付

  • docs/runtime_contract.md概念对齐Session/Run/Schedule/Occurrence/Event、10 项状态责任表、已有保障约束清单、RuntimeService 契约(含 RuntimeContext 三层模型定义、调用方迁移表、12 项回归用例 T01-T12。

阶段二交付

  • 新建 server/runtime/ 包:context.pyRuntimeContext 三层模型,from_terminal()principal_from_session_snapshot()to_session_data()+ service.pyRuntimeService + 进程级单例 runtime_service)。
  • TaskManager.create_chat_task 强制显式 session_data缺失即 ValueErrori18n key tasks.missing_session_data)。
  • 6 处调用点全部迁移到 runtime_service.create_task()server/tasks/api.pyserver/api_v1.pyserver/workflow_runtime_api.py×2、server/chat_flow_task_main.py×2完成通知派发 :613、多智能体 idle 派发 :1416。门闸 token 移交、task_type="notice" 互斥豁免语义原样保留。
  • server/context.py989 行)拆分为 server/context/ 子包identity / broadcast / personalization / usage / upload / conversation / resources / decorators / reaper 共 9 模块 + __init__.py 兼容 re-export外部 import 路径不变)。
  • get_user_resources 参数化:新增 RuntimeIdentity 显式身份快照(定义于 server/context/identity.pyruntime 包引用,依赖方向自下而上无循环)。
  • test_request_context 桥已拆除server/tasks/models.py::_run_chat_task 不再建立 Flask 请求上下文,任务线程全程 RuntimeIdentity 驱动。
  • 审批超时透传管道terminal 属性 _approval_timeout_seconds(默认语义 3600s 不变),_run_chat_task setattr → server/chat_flow_tool_loop.py::_approval_timeout_for() helper → 4 个 _wait_* 调用点。
  • 附带修复:config/_load_dotenv 对禁读 .env 的沙箱环境加 try/except不再 PermissionError 崩溃)。

3.4 测试构成24/24 绿的明细)

  • 改造相关 24/24 全绿
    • test_server_refactor_smoke6
    • test_runtime_service10,新增)
    • test_conversation_model_persistence4patch 目标随迁)
    • test_runtime_identity_resources4,新增,覆盖 get_user_resources 的 web/host/api 身份路由)
  • 验收还含:python3 -m py_compile 触及文件全过;测试显式上下文(无 HTTP 请求)受理任务 → 拒绝同对话并发 chat 任务 → 取消;不触达真实模型调用。
  • 存量失败 4 项conversation_workspace_storage / host_workspace_manager / skills_manager / token_usage_extractor经甄别与本次改动零相关,未修

3.5 遗留待办 / 未验证项

  1. 真实运行环境验证Web 聊天/停止/审批/workflow 激活/多智能体派发)需用户重启服务后人工完成——get_user_resources 分支选错会静默串工作区,是最高风险点。
  2. 审批条目 task_id 恒 None(静态疑点,待运行时验证)。
  3. socket 软 stop 不打断审批等待REST 硬取消可以),留待阶段三或独立决策。
  4. 工作区改动未 commit。

4. astrion_gateway_gap.md 的早期结论及其被新核查修正情况

来源:cache_research/gateway/astrion_audit/astrion_gateway_gap.md2026-09-07 早期盘点,静态代码分析,未做运行复现)。其结论须与 2026-09-07 的 gateway_work_plan / eval_summary 等新核查对照。

4.1 早期主要论断(原文)

  1. API 面12 个蓝图 RESTtasks_bp 轮询主线)+ 1 个 Socket.IO 辅助通道;消息发送与进度事件已收敛到 POST/GET /api/tasks 轮询模型socket send_message 已废弃。
  2. 事件通道:单一 sender 抽象(写入事件流 + socket 推送合并per-task idx、无全局序号事件流是任务作用域 + 内存 + 1h TTLdeque 20000 上限cleanup 1h
  3. 断线追数据三层:事件流偏移继续 → 对账接口 resumeTask(resetOffset) 全量重放 → 前端 task_id:idx 去重socket 重连取一次性 token。
  4. 状态归属四层①进程内存对象terminal/task_manager/三个 approval manager/GLOBAL_MULTI_AGENT_STATES/usage/socket-token/stop flags②运行态文件conversation/*.json、sub_agents.json、personalization.json、settings.json③Flask session ④前端本地。无系统级唯一 owner
  5. 无统一事件序号/事件总线idx 是 per-tasksocket 事件不带 idx通道间无法全局对齐
  6. 审批/提问/计划 = 进程内存 + 绑定 username+conversation_id无端认领,重启即失;无"哪个端在展示/谁决定"记录。
  7. 终端缓存 key 已按对话隔离(好),但实例是共享可变对象;每请求 attach_user_broadcast 重绑回调。
  8. 广播粒度是 user 房间,无 conversation 级订阅/投影"补丁不是投影"。
  9. socket-token 发放互踩issue_socket_token 清空同用户旧 token
  10. "停止/活动"仍假设任务绑定连接handle_disconnect 的 has_other_connection / REST running 判断)。
  11. REST-only 客户端存在事件盲区(标题更新无 running task 只走 sockettoken_update/todo_updated/edited_files_updated 全局广播不一定进任务事件流)。
  12. 认证两套并存session+CSRFWeb/CLI/host-login与 Bearer token/api/v1不互通。
  13. socket-token 发放互踩断线即停任务假设等多客户端缺陷尤甚。

4.2 哪些已被 2026-09-07 新核查推翻或修正(对照 work plan / eval_summary / 子报告)

新核查在 gateway_work_plan.md §0 参考资料的使用边界 明确要求:早期盘点的"无唯一 owner / 补丁不是投影 / 恢复机制脆弱"等结论不能直接当作未修复故障,须结合新核查理解。逐条对照:

早期论断 新核查状态
"无统一事件序号 / 无事件总线"作为差距 部分成立:新核查确认事件 idx 是 per-taskmodels.py:762-782、无全局序号但 work plan 已把它列入后续独立决策durable 事件),不构成阶段一/二/三的前置条件。子报告确认事件链路"可直接复用(需适配层)"。
"状态真源分四层、无唯一 owner"、"补丁不是投影" ⚠️ 需谨慎work plan §0 明确不能直接当未修复故障;阶段一目标正是"固定状态责任表、让权威关系明确",阶段二哲理性反对"把门面转发当 owner 完成"。这是改造目标陈述而非已证故障。
"恢复机制脆弱"(断线靠前端从 0 重放 + 去重) ⚠️ 修正work plan 现状确认客户端恢复保护task.ts 偏移轮询 + probe.ts 对账 + lifecycle.ts 去重)是要保留的已有保障;事件链路 sub 报告判定可直接复用。脆弱性被纳入阶段三"持久化选型"与"只恢复计划/记录"的边界。
"socket-token 发放互踩"issue_socket_token 清空旧 token ⚠️ 未复现work plan §1 保留为待核验项"本轮未重新复现;若仍存在作为独立小范围缺陷处理,不捆绑整个运行时改造")。早期报告自标"很大概率(依赖时序竞争)"。
"审批状态进程内存、重启丢失、无端认领" ⚠️ 部分成立并纳入阶段三:子报告确认三个 manager 纯内存、无 TTL/清理work plan 阶段三列为"重启后旧请求不能被当作有效审批"、审批持久化列为后续独立决策
"停止假设任务绑定连接"handle_disconnect 判断) 方向正确work plan 阶段三要求"任务生命周期独立于任何连接"但子报告R6补充标准停止按钮已是 REST 硬取消、可打断审批等待,软 stop 缺口才需处理。
"REST-only 盲区 / 广播按 user 房间" ⚠️ 部分成立work plan 把对话级订阅列入后续独立决策;事件链路判定可直接复用但需处理"前台干扰"。
"认证两套并存不通" 成立但列为后续独立决策work plan 身份体系整理,明确不能直接合并 Web/API 用户数据空间)。

结论说明:早期盘点提供素材与差距方向,但多数"差距"已被新核查重新定位为"后续独立决策"或"保留的已有保障"没有一条被新核查完全证实为当场需要修复的 bug,仅 socket-token 互踩与审批 task_id 恒 None 保留为待核验疑点。更详细的早期事实(蓝图清单、事件类型、状态归属表)见 astrion_gateway_gap.md 原文,此处不重复全文。


5. 外部参考借鉴点来源opencode_architecture.md / openclaw_gateway.md

按 work plan / eval 定位:仅提炼被本项目认可的职责分离 / 契约 / 幂等 / 恢复设计,不复制其部署、存储或认证方案;外部实现未在本轮重新核验。

5.1 opencode 被本项目认可的设计原则3-5 条)

  1. 事件 durable 化 + after=N 重放续传SQLite 事件表aggregate_id, seq, type, data+ durable(after) 先重放历史再续传实时;"live-only delta 不入库、ended 终值入库可重放"降本。→ 对应 work plan 后续"durable 事件与快照恢复"及五条硬边界。
  2. "单进程多 workspace 懒加载实例 + 请求头路由实例"x-opencode-directory)而非一项目一进程 → 对应 work plan "单活动调度器/单进程"思路。
  3. 协议包与实现分离 + handler 注入protocol/server/core 分层)→ 对应 RuntimeService 职责单一、避免把 manager 塞进新类。
  4. OpenAPI/协议单一事实源 + 代码生成 SDK(文档与代码同源,避免过期)→ 对应后续"TS 类型/SDK 生成"决策(单一 schema 权威源)。
  5. 审批 = 异步请求对象 + 阻塞等待 + 事件广播 + REST 回复,多客户端共享同一请求 ID、先到先得(无需连接路由,只需请求对象全局唯一、回复幂等)→ 对应后续"审批持久化与可恢复执行"决策的幂等/认领思路。

5.2 openclaw 被本项目认可的设计原则3-5 条)

  1. "Gateway 单所有者 + 客户端只读投影":真状态归 gateway 进程,前端只是 snapshot+增量事件镜像,写操作一律走 RPC 并做冲突检测 → 对应 work plan 状态责任表 / "不能把门面转发当 owner 完成"。
  2. 乐观锁lifecycleRevision + expectedRevisionpatch/send 带 expected_revision:轻量冲突检测 → 对应持久化"原子更新/唯一性"选型要求。
  3. 幂等键idempotencyKey:协议 schema 层强制必填;"内存 Map + TTL + 容量上限 + inflight 共享 Promise + 同 key 同参数校验"以及消息类"幂等键进 transcript + 落盘扫描"持久化去重 → 直接对应阶段三「持久幂等」要求(同触发重试返回同受理结果,同键不同参数拒绝)。
  4. 事件不重放 + seq 间隙检测 + 断线重连全量 snapshot(客户端无状态投影,服务端不缓存事件/只做 per-connection seq 计数)→ 对比 Astrion 现有"从 0 重放 + 去重"前端机制,为将来 durable 事件/重连语义提供参考。
  5. 事件广播受众过滤(按 sessionKey + 订阅者集合,只发订阅了该 session 的连接)+ 方法/事件清单白名单下发feature discovery → 对应对话级订阅决策的"订阅与资源授权分别校验"与内部查询接口思路。

说明:上述均为"被本项目认可/借鉴"的提炼,不构成对 opencode/openclaw 自身的全面评价。


6. 遗留问题全集(「待办/待验证/已知缺口」去重汇总,每条注明来源)

按来源文档分组;同名跨文档者已去重合并,标注多来源。

来自阶段一/二实施记录与项目记忆phase12 / gateway_runtime_work_plan

  • G1. 真实运行环境验证未完成(最高风险)Web 聊天/停止/审批/workflow 激活/多智能体派发需用户重启服务后人工完成get_user_resources 的 host/Web/API 分支选错会静默串工作区phase12 §遗留待办 1
  • G2. 审批条目 task_id 恒 None静态疑点待运行时验证getattr(web_terminal,"task_id",None) 全仓无赋值点;影响审批无法按 task_id 检索关联。phase12 §遗留待办 2eval_summary §4support_chains §2.3 A3R6 重申)
  • G3. 工作区改动未 commitphase12 状态;项目记忆)
  • G4. 存量测试失败 4 项conversation_workspace_storage / host_workspace_manager / skills_manager / token_usage_extractor甄别与本次改动零相关、未修。phase12 §测试验收)
  • G5. socket 软 stop 不打断审批等待REST 硬取消可以留待阶段三或独立决策。phase12 §遗留待办 3support_chains §2.4.3eval_summary §4
  • G6. 阶段二未加事件 source 字段前台干扰为阶段三产品决策phase12 §风险对策 5

来自 work plangateway_work_plan / 项目记忆)

  • G7. 两个待核验项:① models.py:157"检查运行中→创建记录"与最终门闸分属两处,并发是否产生重复任务记录未验证;② server/chat/terminal.py::issue_socket_token 发放竞争未复现若存在作为独立小缺陷。work plan §1
  • G8. 阶段三整体未实施Schedule/Occurrence 无代码;幂等/重叠/停机/审批超时/持久化选型全部待实现与讨论work plan §4项目记忆
  • G9. 后续独立决策均"有明确需求再启动"SSE/WS/轮询、对话级订阅、durable 事件与快照恢复、审批持久化、TS/SDK 生成、身份体系整理、设备配对/Remote Worker。work plan §5

来自范围评估与子报告eval_summary + 四子报告)

  • G10. 并发重复任务记录未验证(同 G7①工作区/交互层静态推断不能据此断言并发修改同一对话eval_summary / task_entry_points R3
  • G11. 审批等待循环超时 3600s 且调用点未传参;超时语义(拒绝工具继续 vs 结束任务)为产品决策未定;工具/计划/提问三类超时含义分别定义。R5 明确它不是定时任务技术前提。support_chains §2.4eval_summary R5
  • G12. 审批 manager 条目无 TTL/清理,未决条目永久留在内存;需先定义超时/取消终态与迟到回答处理再设保留期。support_chains §2.4.4R6
  • G13. 事件前台干扰:定时任务事件会推给在线用户 socket 房间,需加 source 或确认产品预期。support_chains §1.5eval_summary §3.5
  • G14. 执行链异常回退路径chat_flow_task_main.py:645-675绕过 TaskRecord 登记,迁移验收必须覆盖其记录/事件/取消/门闸生命周期。R3task_entry_points
  • G15. task_id 必须回传并持久化给发起方Occurrence 记录 run_id=task_id取消才可寻址support_chains §3.4
  • G16. 保存链路前提未全验证:新调用方须走对话级 terminal、遵守门闸、会话策略决定 conversation_id跨实例锁不互斥风险依赖多道防线。support_chains §4.4
  • G17. get_user_resources 约 170+ 调用处(含 83 处 @with_terminal影响面需 host/Web/API × 会话 × 默认值来源回归验证不宜承诺每处改动都小。eval_summary R4flask_context_deps B-3

来自早期盘点astrion_gateway_gap.md多数已被新核查降级/转为决策,见 §4.2

  • G18. 无统一事件序号/事件总线、状态无唯一 owner、审批重启丢失、REST-only 盲区、广播按 user 房间、token 互踩、停止绑定连接、认证两套并存等早期差距——均已按 §4.2 修正为后续独立决策或保留保障勿当作当场故障。astrion_gateway_gap

附:汇总口径与一致性说明

  • 本汇总未掺入子智能体自身推测,所有小节结论均标注来源文件;文档间冲突(如 R2 计数 15 vs 16、R5 审批超时作为技术前提与否)已在对应处并列呈现并注明修订来源。
  • 路径/行号均为各源文档读取时标注,可能因后续代码变动而失效,应以符号/函数名为主。
  • 交付物仅 research_summary.md 一份,存放于 cache_research/gateway/audit_research_summary_v2/