Skip to content

feat(cli): allocate isolated developer memorize runs - #698

Open
xnne-bot wants to merge 3 commits into
NevaMind-AI:mainfrom
XnneHangLab-Mirror:feat/developer-isolated-runs
Open

xnne-bot wants to merge 3 commits into
NevaMind-AI:mainfrom
XnneHangLab-Mirror:feat/developer-isolated-runs

Conversation

@xnne-bot

@xnne-bot xnne-bot commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

📝 Pull Request Summary

为 developer CLI 的每次 memu memorize prepare 自动分配独立 run workspace,解决多个应用调用共用固定目录、无法独立定位和清理失败运行的问题。

一次 prepare 的 1–10 个 canonical session 仍属于同一个 run,由一个 executor 串行执行,再通过返回的 run-id 提交。Host adapters 的 prepare–commit 流程保持现有行为。


✅ What does this PR do?

  • 使用标准库 tempfile.mkdtemp 在 ~/.memu/developer/runs/ 下原子分配私有目录,返回 run_id、workspace 和带 id 的 next_command。
  • commit <run-id>、生成指令中的 verify-resources <run-id> 定位同一个 run;拒绝路径穿越、未知 id 和重定向目录的链接。
  • 新增 discard <run-id> [--json],用于 executor 停止后的显式清理,不调用 backend;也可清理进程中断留下的不完整 run。
  • 普通 prepare 失败会清理刚分配的目录;后端 commit 失败保留 marker、inputs、jobs 和 edits 以供重试。
  • 成功 commit 删除整个 run 目录。若提交成功后刷新快照、清理工作文件或删除目录失败,错误信息明确提示已提交,应清理该 run 而非重新提交;即使 active marker 仍存在,也不能仅据此重试。
  • 保留 1–10 session 的批量能力和 2N + 1 个有序 jobs;底层接受显式 workspace 的 Python 函数保持原有目录生命周期。
  • 更新 README、developer 文档及 ADR 0019,覆盖并发 prepare、失败重试、定向清理和路径边界。

🤔 Why is this change needed?

主动 memorize 需要可独立跟踪、重试和结束的执行单元。每次调用拥有自己的目录后,待执行或失败的 run 不会占用其他调用的工作区。
在已合入的 #695 基础上,run 边界是一次 prepare 的整个 batch。

MrXnneHang and others added 3 commits September 10, 2026 17:30
Allocate a private directory for each prepare batch and return its run id.
Target commit, resource verification, and explicit discard by that id.
Keep failed backend commits retryable and remove successful runs completely.

Document the CLI migration, executor ownership, and backend conflict boundary.

BREAKING CHANGE: memorize commit and verify-resources require a run id.

Co-authored-by: Codex <codex@openai.com>
AI-Model: gpt-6-astra
Co-authored-by: Codex <codex@openai.com>
AI-Model: gpt-6-astra
Report successful backend submission when snapshot refresh or working-file
cleanup fails, so callers can discard the stopped run instead of resubmitting.
Cover snapshot, job, and directory cleanup failures in regression tests.

Co-authored-by: Codex <codex@openai.com>
AI-Model: gpt-6-astra
@xnne-bot

Copy link
Copy Markdown
Contributor Author

补充当前实现的 run 创建、返回和清理流程,便于直接核对生命周期。

1. run 如何创建

执行:

memu memorize prepare session-1.json session-2.json --json

顺序如下:

  1. 校验输入数量、stdin 使用方式,并读取和校验全部 canonical payload。
  2. 构建配置指定的 backend。
  3. 使用 tempfile.mkdtemp,在 ~/.memu/developer/runs/ 下原子创建一个私有目录,例如 run-a1b2c3d4/;目录名就是该次调用的 run_id。
  4. 将本次 1–10 个 session 的 JSONL 投影写入该目录,镜像当前 memory/skill,生成快照及按顺序执行的 jobs。
  5. 写入该 run 的 .memorize_run.json active marker,返回 executor handoff。

一次 prepare 对应一个 run。 同一次 prepare 的多个 session 共用该 run;不同 prepare 分配不同目录。

2. run-id 在哪里返回

使用 --json 时,prepare 返回顶层 run_id 字段,同时返回绝对路径 workspace 和已经带上 id 的 next_command。例如,以下是响应中的相关字段:

{
  "run_id": "run-a1b2c3d4",
  "workspace": "/home/alice/.memu/developer/runs/run-a1b2c3d4",
  "next_command": "memu memorize commit run-a1b2c3d4"
}

完整响应还包含 transcript 或 transcripts、jobs 和 executor_prompt。不使用 --json 时,终端输出也会显示 run_id:、workspace: 和带 id 的 commit 命令。

应用应在启动 executor 前保存这些返回值。生成的 resource job 内部使用 memu memorize verify-resources <run-id>,因此验证的也是同一个 run。

3. 什么时候删除 run 目录

时机 / 结果 run 目录的处理
prepare 成功返回 保留,供 executor 读取和修改。
executor 正在运行 保留。
executor 完成全部 jobs 仍然保留;executor 完成不会自动触发 commit 或删除。
应用执行 commit <run-id>,后端提交及本地清理成功 在 commit 命令成功返回前,删除整个 run 目录,包括 input、jobs、memory/skill 镜像、marker 和额外临时文件。后端已提交的记忆保留。
后端 commit 报错 保留 run 文件和 marker,修复后可用同一 id 重试 commit。
后端已成功提交,但快照刷新或文件/目录清理失败 明确报告 committed, but cleanup failed;目录可能部分清理,marker 也可能仍在。不要重新提交,停止该 run 的工作后使用 discard 清理剩余目录。
executor 失败或应用放弃运行 保留供检查;确认 executor 已停止后,应用显式执行 discard <run-id>。
discard <run-id> 成功 删除整个指定 run 目录,不调用 backend,不撤销已经提交的数据。
prepare 在分配目录后发生普通异常 尝试删除本次刚分配的目录后抛出错误;若删除本身失败,会报错并可能留下文件。
prepare 被强制终止、机器宕机 可能留下不完整目录,可检查后按目录名执行 discard。

两个关键点:

  • 正常路径的自动清理发生在成功 commit 时,而不是 executor 完成时。 CLI 不会自动判断外部 executor 是否已经完成。
  • 没有 TTL 或后台定时清理。 失败或中断的 run 通过显式 discard 回收;同一 run 的 executor、verify、commit、discard 由应用串行协调。

4. 已做的简单实测

使用两个真实 CLI 子进程,共享一个已初始化的临时 SQLite 数据库,同时 prepare 得到两个独立目录。对第一个执行 no-op commit 后,其整个目录及额外临时文件被删除,第二个 run 的全部文件逐字节保持不变;再 discard 第二个,runs/ 为空,数据库仍保留。此次实测验证目录生命周期,没有调用外部 executor 或 embedding。

另外,25 项 run 专项测试通过,覆盖失败保留与重试、prepare 失败清理、提交成功后的清理错误,以及路径边界。

@MrXnneHang MrXnneHang left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTMeow 🐾

@MrXnneHang

Copy link
Copy Markdown
Collaborator

已建立供分层评审的 upstream stack,由 MrXnneHang 创建,使用与原 PR 相同的提交:

评审可在该 stack 中进行;最终合入仍由 xnne-bot 的 #698 / #699 承接。已核对两层 head 与原 PR 完全一致。后续评审修改需要同步回相应合入 PR。

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants