feat: cloud 门禁/超时/成本/沙箱收敛为单一判定源

- 新增标准库叶子层 timeouts/gates/quota/sandbox_policy:
  审批 3600 与单轮 600 各有名常量与环境覆盖层,已建项
  expires_at 永不重算;目录/控制/合并状态门禁统一判定,
  目录违规无任何覆盖参数;配额取数与比较唯一来源
  (USD 先于无价、命中均为 >=、无价只计 actual 行);
  /tmp 隔离矩阵与失联清理判定纯函数化。
- 调用点委托:server/worker/automations/auto_memory 的
  配额 SQL 与比较、server/tree/marker 的目录解析、
  marker 的控制门、sandbox 的任务容器名正则、两处 300 秒
  陈旧阈值默认值均收敛,别名与错误文案不变。
- 统一两个 P0 口径分歧:服务端无价计数由全部 usd IS NULL
  行改为 actual-only;显式不限额用户在服务端准入亦不受
  无价上限约束(与 worker 运行时一致)。
- 不新增门禁种类与 record 模式(主线无此实现);不改
  skill_seed/skills/SKILL.md;不改 v1.1 契约与分支保护。
- 新增 test_arch_converge.py 18 项。
This commit is contained in:
host committed 2026-11-03 02:49:25 +00:00
1 parent 2720acef46
commit 41e8c98512
16 files changed
+1068 -301

No files matched your search

+88
View File
@@ -0,0 +1,88 @@
"""沙箱与清理的单一口径(纯函数层,只依赖标准库)。
收敛前分层口径散在各处注释里,本模块把它钉成可单测
的函数,调用点只传事实、不再各写一套:
1. /tmp 隔离矩阵(Docker 外层 vs 宿主 bwrap 内层):
- Docker 执行器:容器 /tmp 与 /var/tmp 固定为 tmpfs
(sandbox.build_run_command 在额外挂载之后追加
--tmpfs,且 /tmp 目标的额外挂载在解析时即被拒绝),
容器内 /tmp 绝不落在宿主 /tmp。
- 宿主 bwrap / 本地执行器:/tmp 不隔离。宿主级 bwrap
的 /tmp 会落到宿主 /tmp 上,内层 codex 的 bwrap
--proc 挂载亦不受本仓库控制——本模块只如实标注,
绝不宣称“内层沙箱已修”。
- 任务容器名正则(codex-<32 位 hex 任务 id>)此前只
活在 sandbox.cleanup_stale_containers 的注释与正则里;
现收为 TASK_CONTAINER_RE,sandbox 直接复用它。
清理绝不按 "codex-" 前缀删:基础设施容器
(如 codex-postgres)名字不匹配正则,永远不被删。
2. 失联清理判定(cleanup_decision):worker
_reap_kill_requests 的状态与心跳两道门——任务必须
已是 interrupted,且心跳停滞超过阈值(心跳取
COALESCE(last_heartbeat, updated_at),与
server.sweep_stale_tasks 同口径;无心跳时间戳时按
已停滞处理,与 _reap 旧代码的 fall-through 一致;
恰等于阈值时不杀,旧代码是 hb >= now - threshold 即
跳过)。请求 pending、执行器有 kill_container、容器
名由任务 id 派生这三道门仍在 worker 侧,不进本层:
本层只判“该不该杀”,不执行杀。
3. Worker 寻址(worker_address):workers 注册表只有
worker_id 一列身份,默认形为“主机名-进程号”
(worker.py,未给 --worker-id 时)。本函数从该串
派生 (host, pid):取最后一个连字符后全为数字的一段
作 pid,否则 pid 为 None。注册表本身不加 host/pid
列——加列需 PG 迁移与 test_p2_migrations 登记,超出
本轨收敛范围;寻址先用派生函数,不动表结构。
单一状态来源仍是:workers 表(注册与心跳)+
tasks.last_heartbeat(陈旧判定)+ kill_requests
(清理意图),三者缺一不可,不得另起一套状态表。
"""
import re
TMPFS_PATHS = ("/tmp", "/var/tmp")
TASK_CONTAINER_RE = re.compile(r"^codex-[0-9a-f]{32}$")
def tmpfs_isolated(executor_kind, path):
"""某执行器下某路径是否走 tmpfs 隔离:(isolated, reason)。"""
if executor_kind == "docker" and path in TMPFS_PATHS:
return True, "docker --tmpfs 隔离,容器内路径不落宿主"
if executor_kind == "docker":
return False, "docker 下仅 /tmp 与 /var/tmp 走 tmpfs"
if executor_kind in ("host-bwrap", "local"):
return False, "宿主 bwrap / 本地执行器 /tmp 不隔离,会落宿主"
return False, "未知执行器,按不隔离处理(fail-closed 口径)"
def cleanup_decision(status, heartbeat_ts, now, threshold_seconds):
"""失联清理判定:放行回 (True, reason),否则 (False, reason)。
status 必须为 'interrupted';心跳停滞须严格超过阈值
(恰等于阈值不杀);heartbeat_ts 为 None 时按已停滞
处理(与 _reap 旧代码一致:无时间戳不阻拦收殓)。
"""
if status != "interrupted":
return False, "任务不在 interrupted,不杀(防复活任务被旧请求误杀)"
if heartbeat_ts is None:
return True, "无心跳时间戳,按已停滞处理"
try:
age = now - float(heartbeat_ts)
except (TypeError, ValueError):
return False, "心跳时间戳不可解析,不杀"
if age > threshold_seconds:
return True, "心跳停滞 %.0f 秒,超过阈值 %s 秒" % (
age, threshold_seconds)
return False, "owner 可能还活着(心跳 %d 秒前),留待下轮" % age
def worker_address(worker_id):
"""从 worker_id 派生 (host, pid):pid 取末段纯数字,否则 None。"""
if not worker_id or not isinstance(worker_id, str):
return "", None
if "-" in worker_id:
host, _, tail = worker_id.rpartition("-")
if host and tail.isdigit():
return host, int(tail)
return worker_id, None