任务 ID: T022  |  文件: session.md  |  最后修改: 2026-02-23 08:59:13

Task T022 — 执行日志


步骤 1:Reviewer 方案审计

执行时间: 2026-02-23 08:55 GMT+8
审计对象: /root/.openclaw/workspace/memory/docs/todo/T022-session-reset.md v1.0
结论:✅ 方案审计通过,可进入实现阶段


审计意见

✅ 整体设计

方案逻辑清晰,分工合理:
- 以 active.json 作为跨夜任务保护的判断依据,简单可靠
- 删除 sessions.json 中的 sessionKey 而非直接操作进程,安全、无副作用
- Telegram 通知不走 Gateway,避免触发 Agent 响应,设计正确


审计要点逐项检查

1. 原子写是否正确(mktemp + mv)
✅ 方案第四节给出了标准实现:mktemp 创建临时文件,修改完成后 mv 原子替换,不存在写入中途崩溃导致 JSON 损坏的风险。

2. active.json 不存在时的默认行为
✅ 方案第三节明确:"若 active.json 不存在或为空,视为所有 Agent 空闲,全部重置。"
此设计安全且符合直觉,不会因文件缺失而静默保留旧 session。

3. sessions.json 不存在时的行为
⚠️ 轻微缺口,需 coder 在实现时补充:
方案第六节实现要求第4条指明"文件不存在 → 跳过(不报错)",方案本身已有要求,但第四节的示意代码中 json.load(open(path)) 在文件不存在时会抛出 FileNotFoundError
要求 coder 实现时必须用 try/exceptos.path.exists() 判断后再打开,确保优雅跳过。

4. Telegram 通知内容
✅ 方案要求通知内容包含:重置了哪些 agent / 跳过了哪些(含原因)。
格式充分,能让运维人员快速判断执行结果。
提示 coder:通知消息中应明确列出每个 agent 的处理结果(RESET/SKIP + 原因),而非仅汇总数字。

5. morning-tasks.sh 修改格式
✅ 方案第五节给出了完整的 Step 4 代码块,格式与现有 Step 一致(log + if/else + 不影响其他任务的 fail 处理)。

6. 合并方案
✅ 通过 cp 从沙箱复制到正式目录,双重 reviewer 审计后执行,流程严谨。


给 coder 的实现提醒

  1. session-reset.shjson.load(open(path)) 需要 try/except FileNotFoundError 保护,或先检查文件存在性
  2. Python 内联脚本中的 $tmpfile 变量引用方式:注意 shell 变量在 Python heredoc / -c 字符串中的展开,避免转义问题
  3. Telegram Bot Token 读取:确认 openclaw.json 中字段名称(建议 coder 先 cat /root/.openclaw/openclaw.json | python3 -m json.tool | head 确认 token 字段路径)
  4. 退出码:有任何 agent 重置失败(非 sessions.json 不存在,而是 mv 失败等)→ exit 1


步骤 2:Coder 实现

执行时间: 2026-02-23 08:57 GMT+8
工作区: /root/sandbox/T022/
结论:✅ 实现完成,两个文件均已创建


实现产出

  1. /root/sandbox/T022/session-reset.sh(新建,可执行)
  2. /root/sandbox/T022/morning-tasks.sh(从 scripts/ 复制并修改)

关键设计决策

session-reset.sh

1. active.json 读取(跨夜保护)
- 文件不存在 → 视为所有 Agent 空闲,全部重置(符合方案第三节)
- Python3 解析,提取 status=running 任务的 agents,构建 SKIP_AGENTS 列表

2. Python 原子写实现(解决 reviewer 审计要点)
- 采用 python3 - "$sessions_file" "$session_key" "$tmpfile" << 'PYEOF' heredoc 方式
- Python 代码内部用 sys.argv 接收参数,完全避免 shell 变量在 Python 代码中展开的转义问题
- 用 os.path.exists() 检查文件存在性,优雅跳过不存在的 sessions.json(无 FileNotFoundError)
- 读 → 修改 → 写临时文件 → mv 原子替换,不存在写入中途崩溃风险

3. Telegram 通知
- 从 /root/.openclaw/openclaw.json.channels.telegram.botToken 读取 token
- Chat ID 使用 .channels.telegram.allowFrom[0](= 92763607,主人主账号)
- 通知内容包含每个 agent 的具体处理结果(RESET/SKIP + 原因),非仅汇总数字
- 通知发送失败不影响脚本退出码(|| log "[WARN]..." 处理)

4. 退出码
- mv 失败或 Python 执行失败 → EXIT_CODE=1,最终 exit $EXIT_CODE
- sessions.json 不存在 → 正常跳过,不计入失败

morning-tasks.sh 修改


语法验证

bash -n session-reset.sh → OK
bash -n morning-tasks.sh → OK

步骤 3:Reviewer 代码审计

执行时间: 2026-02-23 08:58 GMT+8
审计对象:
- /root/sandbox/T022/session-reset.sh
- /root/sandbox/T022/morning-tasks.sh
结论:✅ 代码审计通过,无重大问题,可合并


审计要点逐项检查

1. 原子写是否正确(mktemp + mv)
✅ 完全正确。tmpfile=$(mktemp) 创建临时文件,Python heredoc 写入临时文件,成功后 mv "$tmpfile" "$sessions_file" 原子替换。失败时 rm -f "$tmpfile" 清理临时文件,无残留。

2. active.json 不存在时的默认行为
✅ 正确处理。if [[ -f "$ACTIVE_JSON" ]] 外层判断,文件不存在时直接 log 提示并视为全部空闲。Python 内部也有 os.path.exists() 二次检查(双重保险)。

3. sessions.json 不存在时是否优雅跳过
✅ 正确处理,且超出方案要求。Shell 层面先 [[ ! -f "$sessions_file" ]] 检查,不存在则直接跳过(计入 RESET_LIST,标注"不存在")。Python 层面内部也有 os.path.exists() 检查(冗余但无害)。

4. Telegram 通知内容是否完整
✅ 每个 agent 均有明确的 RESET/SKIP/FAIL 状态记录,通知消息包含:
- 时间戳
- ✅ 已重置列表(含"sessions.json 不存在"场景说明)
- ⏭ 已跳过列表(含跳过原因如 "task T005 still running")
- ❌ 失败列表(仅有失败时才显示)
- 整体状态图标(✅/⚠️)

符合方案要求"明确列出每个 agent 的处理结果"。

5. morning-tasks.sh 修改是否与现有格式一致
✅ 完全一致。Step 4 格式与 Step 1/2/3 保持相同风格:
- log "--- Step 4: Session 清理 ---" 分隔线
- if bash "..." >> "$LOG" 2>&1 日志重定向
- 失败时 log 提示且不影响后续(log "失败(不影响其他任务)"
- log "========== 早间任务完成..." 结束行在 Step 4 之后,位置正确


轻微观察(不影响通过)

  1. build_list 函数中空数组展开"${RESET_LIST[@]+\"${RESET_LIST[@]}\"}" 写法略显繁琐,但在 set -u 环境下是正确的安全写法,无功能问题。

  2. Telegram parse_mode=Markdown:通知文本中含有 字符和括号,Markdown 模式下通常无问题,但若 agent 名称或 task_id 含特殊字符(_*[])可能触发 Markdown 解析错误。实际使用中 agent 名为 main/coder/reviewer,task_id 为 TXXX 格式,无风险。

  3. set -uo pipefail(无 -e:脚本未设置 set -e,依靠手动检查命令退出码管理错误流,这在有 || 处理的脚本中是合理选择,避免非预期退出。


结论

所有方案审计要点均已正确实现,方案第六节实现要求逐条满足。代码质量良好,错误处理完整,格式规范。

✅ 批准合并