Skip to content

feat(m13): dev 基线接入配套(T13.1~T13.11)与 M9 联调收口 - #4

Merged
ClozyA merged 59 commits into
AUTO-MAS-Project:mainfrom
qiyinxi:feat/t13-dev-baseline-20260903
Sep 4, 2026
Merged

feat(m13): dev 基线接入配套(T13.1~T13.11)与 M9 联调收口#4
ClozyA merged 59 commits into
AUTO-MAS-Project:mainfrom
qiyinxi:feat/t13-dev-baseline-20260903

Conversation

@qiyinxi

@qiyinxi qiyinxi commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

里程碑 M13「dev 基线接入配套」与 M9 联调收口,配套 AUTO-MAS 的 AUTO-MAS-Project/AUTO-MAS#550,两边需要一起上线:#550 合入前必须先有一个含本 PR 的 Runtime 版本,再把它 build-app.yml 里钉的 RUNTIME_VERSION 提上去。

  • 契约先行(红线第 2 条):doc/契约补充-v1-增补1.md 新增 C6~C15doc/架构设计.mddoc/契约补充-v1.mddoc/任务拆分.md 同步修订,协议仍为 v1,只追加一个 warning 码与一个 CLI 选项,不改名任何字段、stage、state。
  • T13.1 managed 下后端子进程 cwd 改为 app-root、入口传绝对路径——此前用 uv 的 project dir,会把用户数据建在 repo/ 里并被 workspace sync 整体替换掉。T13.2 Job 开 JOB_OBJECT_LIMIT_BREAKAWAY_OK,让 AUTO-MAS 拉起的模拟器与游戏能显式脱离。T13.3 backend supervise --shutdown-timeout 参数化,并修掉优雅关闭误报 BACKEND_FORCE_TERMINATEDsnapshot() 的 TOCTOU)。
  • T13.4 依赖同步参与镜像轮换:uv lock --check 口径不变,uv sync 改为在受管临时目录里用改写过下载地址的锁副本执行 --frozen,逐个换源、全部失败回退原锁,哈希仍由锁内 sha256 与 uv 校验,repo/ 内文件字节不变。T13.5 向后端注入 AUTO_MAS_UV_CACHE_DIRAUTO_MAS_UV_PYTHON_INSTALL_DIRAUTO_MAS_MIRROR_PACKAGE_INDEXAUTO_MAS_MIRROR_PYTHON,让 MaaFW 运行池复用同一份缓存、解释器与有序镜像源。
  • T13.7 backend supervise --port(1024~65535,缺省 managed 36163 / development 36164),注入 AUTO_MAS_SUPERVISED_PORT,健康地址、关闭地址与 baseUrl 全部由它派生——此前钉死 36163,受监督的开发版必然撞上同机常驻的正式版。T13.8 stdin EOF 或读取出错视为隐式 shutdown,宿主崩溃不再留下占着端口与互斥量的孤儿。
  • T13.9 新增 warning BACKEND_ORPHANS_REAPEDBACKEND_FORCE_TERMINATED 收窄为「后端主进程被强杀」——真机上脚本留下的孙进程会让每次正常关闭都误报强杀。T13.10 协议日志转发失败不再回给 process 层:宿主崩溃时 stdout 读端已断,后端收到 close 后输出的第一行日志会触发 recordSinkErrorjob.Terminate(97),把正在优雅关闭的后端连同进程树杀掉。T13.11 身份校验容忍启动窗口:Job 快照按「是否已收到结束信号」跳过正在消亡的成员、健康探针错误连续 3 次才判失败、根进程已退出时不再发 close。
  • 验证:gofmt / go vet / go build / go test ./... / git diff --checkgo test -race ./... -count=1 全部退出码 0。真机联调 T9.1(development 真后端,ready 3.2 秒、优雅关闭 0.35 秒、无 warning)、T9.2(managed 全链路,本地 smart-git 托管两个 release 分支模拟,含升级、降级与用户数据逐字保留)、T9.3(Electron 桌面端到端,正常退出 1 秒内、宿主被强杀后自行优雅收口)已完成,逐条核对表落盘 doc/首版验收记录.md
  • 已知未满足项写在验收记录里:锁文件尚未进入真实 release/* 分支、Lite/Full 安装包冒烟未跑、旧更新入口待灰度切换后移除;T13.6(Full 预置 uv 缓存)按优先级保持未开始。

🤖 Generated with Claude Code

claude and others added 30 commits September 1, 2026 21:17
登记决策 D12(AUTO-MAS 侧配合改造基线由 dev_v2 改为 dev 3c422093),
D4 标注为已由 D12 取代并保留原文追溯;第 5.1 节按接入契约 P-1~P-8 重写,
新增 MaaFW 专项 TODO-PY-9~13。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
新增 doc/契约补充-v1-增补1.md:后端工作目录、受监督标记对端口的优先级、
Job Object 逃逸、关闭预算参数化、主项目依赖的锁内 URL 改写轮换、
MaaFW 运行池的基础设施共享与镜像源下发;并修订 C2 第 1 条与 C4 第 1 条。
协议版本保持 v1。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
按增补 1 的 C6~C11 在目录模型、后端启动、项目依赖同步、镜像与网络策略、
CLI 设计、插件环境职责边界、健康检查与关闭契约、Lite/Full 边界和数据分类
九处补入增补段落,并补全 dev 基线下后端生成目录的分类。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
新增里程碑 M13(T13.1~T13.6)对应增补 1 的 C6~C11,补里程碑总览与执行顺序;
AGENTS.md 同步权威文档表、决策区间与状态表。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
显式 --mirror package-index=<key> 不再返回 INVALID_ARGUMENT,改为排在尝试顺序最前、
与自动轮换走同一条锁改写路径;改写用的 simple/packages 前缀改为目录显式声明。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
按增补 1 C6:uv RunOptions 新增 WorkingDir(为空回退 ProjectDir),
managed 的后端子进程 cwd 固定为 app-root、入口改传绝对路径
<app-root>/repo/main.py,避免用户数据落在会被 workspace sync 整体替换
的 repo/ 里。development 的 cwd 与裸入口保持不变,一次性 uv 命令
一个都不传新字段,行为字节不变。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
KindPackageIndex 源新增 simple/packages 两个显式前缀,不由 baseURL 推导——
官方源的 artifact 在 files.pythonhosted.org,与索引不同 host。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
单遍 strings.Replacer 只替换 https://pypi.org/simplehttps://files.pythonhosted.org/packages/ 两个精确前缀,hash 与 size 逐字保留。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
按增补 1 C8:Job 的 LimitFlags 追加 JOB_OBJECT_LIMIT_BREAKAWAY_OK,
使 AUTO-MAS 用 CREATE_BREAKAWAY_FROM_JOB 拉起的模拟器与 PC 游戏不随
后端退出。刻意不用 SILENT_BREAKAWAY_OK——那会让 worker 与 Agent 也
默认脱离。KILL_ON_JOB_CLOSE 与未请求脱离的进程归属不变。
DependencySyncDir 把临时项目目录钉在 build 缓存下,新增 DeleteDependencySync
让删除走 filesystem 受控原语而不是裸 RemoveAll。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
按增补 1 C9:正整数秒、合法范围 1~120、默认 5,越界或非整数映射
INVALID_ARGUMENT(退出码 2)。选项收 string 自行解析,让非整数与越界
共用同一条 result 失败语义——pflag 的 int 解析失败只走 stderr 诊断。
backend.Request 增加 ShutdownTimeout,优先级高于 Dependencies 注入值,
两者都缺省时仍是编译期的 5 秒,既有行为不变。就绪侧预算不参数化。
每个镜像源在受管临时项目目录里用改写后的锁执行 --frozen;plan 末位的官方源
改用 repo 原锁与 --locked,即 C10 的回退。--mirror-only 因此天然不回退。
临时目录在成功、失败与取消三条路径上都经 filesystem 受控删除收口。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
按 C10 的 2026-09-01 修订删除三处 INVALID_ARGUMENT 拒绝(uv validateRequest、
cli rejectPackageIndexOverride 及 bootstrap/repair 调用)。不存在的 key 仍由
mirror.BuildPlan 拒绝,语义不变。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
result.details 增加 sourceKind/source/attemptCount/lockRewritten;每次镜像尝试
发一条 dependencies.sync progress 供展示。bootstrap 与 repair 同样报告尝试。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
规则新增 argumentsContain 与 lockContains 两个条件,调用记录新增 projectDir
与 lockIndexPrefixes,动作新增 readyFile/releaseFile 用于精确注入取消。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
真机联调发现后端 0.4s 内自行退出(exit 0、无残留)却仍收到
BACKEND_FORCE_TERMINATED,并进入 result.details.warnings。

根因在 windowsJob.snapshot:它先查 Job 的 pid 列表、再查 Toolhelp32
进程表,两次查询不是原子的,刚退出的根进程会出现在前者而不在后者,
于是整个快照报 "process entry is missing";cleanupProcess 把该错误
当成「有残留后代」直接判 forced。探针在本机 20/20 复现,是必然误报。

snapshot 现在把「成员在两次查询之间退出」视为正常过渡态跳过(pid 无效
导致的 OpenProcess 失败同理),其余错误仍上报;cleanupProcess 在
Exited 之后再排除根进程自身,只有真正的存活后代才判 forced。
真有残留后代时仍强制回收并发出警告,由对照组 E2E 锁定。
七条收场:换源、回退原锁、全失败、离线不改写、mirror-only 不回退、
显式首选排最前、取消收口。每条都断言临时目录不残留且 repo 文件字节不变。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
该分支没有任何调用方,且正是 C10 明令禁止的做法——传 --default-index 会让
uv 判定锁需要更新并破坏 --locked 不变量。留着它是陷阱,不是备用方案。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
qiyinxi and others added 27 commits September 2, 2026 01:10
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
T13.5 的后半段「MaaFW 运行池目录重新分类」不再实施:注入面落地后,池里真正
可重建的 uv 缓存与受管解释器已物理落在 Runtime 自己的 runtime/cache/uv 与
runtime/environment/python(真机 manifest.json 的 installerMetadata 证实),本就在
cleanup/repair 的既有分类内;config/maafw_runtime_pool/runtimes/<hash>/ 只剩 venv
与 manifest,让 Runtime 认布局、删 venv 留 manifest 等于维护池清单,触红线第 4、6 条。
分工定为 Runtime 只处理自己的目录,池 venv 因基解释器缺失失效后由后端自行判定重建。
按红线第 2 条先改文档:增补 1 C11 结论第 4 条加修订标注并保留原文,架构设计三处、
任务拆分(T13.5 ✅、0.3 顺序说明、TODO-PY-13 对应要求、变更记录)与 AGENTS.md
状态表同步。T13.6 保持 ⏸。

T9.1 按 2026-09-02 真机联调记为 ✅:ba27db3 构建对 AUTO-MAS 集成树
integ/runtime-20260901 的真后端跑通启动→就绪→优雅关闭(ready 3.21s、shutdown 后
收口 0.35s、exit 0、无 warning),附带修复 e5ef0ab 交叉引用 T13.3。T9.2~T9.4 不动。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
真机联调暴露两个首版前必须修掉的问题,按红线第 2 条先改文档:
- C12:backend supervise --port(1024~65535,缺省 managed 36163 / development 36164),
  注入 AUTO_MAS_SUPERVISED_PORT 并并入受控监督键集合,健康/关闭地址与 baseUrl 由它派生;
  同步修订 C1、C7 结论第 1 条、架构设计五处、TODO-PY-8 与 D-open-2
- C13:backend supervise 的 stdin EOF 或读取出错视为隐式 shutdown,stdout 已断也须能退出,
  其他命令不变
- 任务拆分新增 T13.7 / T13.8 条目与变更记录;doc/current/M13 各补一份设计与计划;
  AGENTS.md 状态表同步

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
ManagedOptions.Port 非零时以十进制注入 AUTO_MAS_SUPERVISED_PORT,并入受控监督键集合,
宿主与 RunOptions.Environment 的同名变体被清除;越界端口在 spawn 前失败关闭。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
新增 DefaultPort / BaseURL / HealthURLForPort / ValidPort 作为端口与地址的唯一来源;
Expectation.Port 零值回退缺省端口,越界在发出请求前失败关闭。HealthURL 保留为缺省端口的派生值。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Request.Port 零值按模式取缺省(managed 36163 / development 36164),越界映射 INVALID_ARGUMENT
且不打开任何资源;解析一次写回 Request,首启与单次自动重启同值。注入 uv 的
AUTO_MAS_SUPERVISED_PORT、health.Expectation.Port、running 事件的 baseUrl 与 /api/core/close
地址全部由 health.BaseURL 派生,关闭器改为按端口构造的 loopbackHTTPCloser。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
整数、合法范围 1024~65535;未显式给出时按模式取缺省(managed 36163 / development 36164),
显式空串、非整数与越界映射 INVALID_ARGUMENT(details.field=port)并在 backendFactory 之前拒绝。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
夹具不再设置 listenAddress,健康检查能通过即证明后端从环境变量读到了端口;E2E 用
net.Listen(":0") 探空闲端口并经 Request.Port 传入,端口辅助函数改为带端口参数,
跨进程 helper 的 signal 增加 port,串行化 Mutex 改为与端口无关的名字。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
新增 InputClosed:Run 因 EOF 结束时为 true,因 StopAccepting 或 ctx 取消结束时为 false;
Run 的返回值不变,一次性命令的行为不受影响。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
hello 之后 reader 因 EOF 结束(InputClosed)或读取出错时,向同一个 mailbox 投一条没有
commandId 的 shutdown,走与显式 shutdown 相同的优雅关闭路径与结局;已有终止命令时
Submit 被拒即幂等。读取出错保留 stderr 诊断;reader 自身 panic 仍走基础设施故障路径。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
用 go build 出的 auto-mas-runtime.exe 以 development 模式监督夹具后端:关闭 stdin 后
Runtime 走 stopping_backend → stopped、result.status=stopped 且无 controlCommandId、退出码 0、
无 BACKEND_FORCE_TERMINATED,后端 PID 退出、端口 / Mutex / 事务无残留;stdout 读端先关再
关 stdin 时 Runtime 仍在有限时间内退出并收口。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
进入 shutdown 之后协议事件写失败不再中断关闭流程:仍 HTTP close、等待关闭预算、超时才收 Job、
清理 Mutex 与事务,最后以 OUTPUT_WRITE_FAILED 退出并在 stderr 留诊断。架构设计两处与
T13.8 条目、设计文档同步。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
fakebackend 新增 shutdownFile,只在 close → server.Shutdown 成功后写入,被 Job 硬杀时不出现;
E2E 用它把「stdout 已断仍能退出」加强为「后端被 HTTP 优雅关闭且 Runtime 以 OUTPUT_WRITE_FAILED 退出」,
主用例同样断言优雅标记;backend 单测锁定关闭路径上输出失败仍执行 HTTP close。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
按增补 1 C13 结论第 4 条:finishControlShutdown 只记录首个输出错误,照常 HTTP close、等待关闭预算、
Job 兜底与 Mutex / 事务收口,最后才把 OUTPUT_WRITE_FAILED 交给 CLI;主循环里 gate 因
OUTPUT_WRITE_FAILED 故障而 shutdown 已 latch 时同样走优雅关闭而不是硬杀。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
协议 v1 内追加 warning 码 BACKEND_ORPHANS_REAPED(后端主进程自己退出、Job 残留孤儿被回收),
BACKEND_FORCE_TERMINATED 收窄为主进程被强杀;架构设计错误码全集与关闭契约同步,任务拆分
新增 T13.9 与变更记录,AGENTS.md 状态表同步,设计与计划文档就位。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
协议 v1 追加 warning-only 码 BACKEND_ORPHANS_REAPED(退出码 0、open-log)。cleanupProcess 区分
根进程仍存活时被 Terminate(rootForced)与根进程已自行退出、只回收残留成员两条路径,并在终止前
快照孤儿清单;finishControlShutdown 在 !graceful || rootForced 时发 BACKEND_FORCE_TERMINATED,
否则残留被回收时发 BACKEND_ORPHANS_REAPED(orphanCount / orphans[≤20]{pid, executable} /
orphansTruncated)。既有「留下 detached 孙进程后自行退出」E2E 改为断言新 warning 与孙进程 PID。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- 新增 doc/首版验收记录.md:对照架构设计「发布验收标准」14 条逐条核对,附测试名与联调记录;
  第 1~11 条满足,第 12/14 条不满足、第 13 条未验证,均附解除条件;
  开头显眼标注 T9.2 与第 3/4/5 条真机部分是用本地 smart-git 模拟发布分支完成的原因与缺口
- 任务拆分:T9.2 ✅(本地模拟,真实发布分支复跑待 push 后)、T9.3 🚧、T9.4 ✅;
  M9 里程碑行、0.3 节顺序说明与变更记录各加一行
- AGENTS.md 状态表 M9 行同步;doc/README.md 增加入口

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
桌面 E2E 暴露:宿主崩溃真实路径下后端第一行关闭日志的协议转发失败会让进程包终止 Job,
T13.8 的容错没机会生效;启动期短命子进程退出让 Job 快照报错、探针立即判 BACKEND_HEALTH_INVALID。
C13 第 4 条明确日志转发失败不终止进程树;C15 定稿快照跳过退出中成员、探针错误连续 3 次才判失败、
祖先链判定与根进程已退出不发 close;架构设计同步,任务拆分立项 T13.10 / T13.11。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
宿主崩溃的真实路径:Electron 被强杀后 stdout 读端已断,Runtime 读到 stdin EOF、
按 C13 发出 POST /api/core/close,后端随即输出第一行关闭日志——streamSink 把它
转发成 log 事件时写失败,错误回到 process 层,`ManagedProcess.recordSinkError`
对首个 sink 错误的既有策略是 job.Terminate(97),于是正在优雅关闭的后端连同整棵
进程树被 Runtime 自己杀掉,T13.8 的容错根本没机会生效。桌面实测退出码 20、
后端日志里没有任何关闭序列。

协议出口失败改为只登记 gate 故障并返回 nil:继续读管道、继续写文件日志,监督
循环经 Faulted() 观察到故障后走既有的关闭收口,最终仍以 OUTPUT_WRITE_FAILED
退出。运行日志(文件)写失败仍然失败关闭,语义不变。

假后端新增 shutdownEvents / shutdownDelayMs 以模拟真实关闭序列;E2E 用「关掉
stdout 与 stderr 读端 + 关 stdin」的真实组合。红灯:Runtime 在 EOF 后 6.5ms
就退出;绿灯:等满后端 1.5 秒的关闭序列后才退出。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
桌面 E2E 约四分之一的生命周期 startBackend 返回 BACKEND_HEALTH_INVALID
「无法验证受管后端进程」:后端启动期的短命子进程(git version 之类)恰在 Job
快照的两次系统查询之间退出,映像查询失败让整个快照带错误返回,探针错误又是
一次就判失败。三处收紧:

- internal/process:快照对映像查询失败的成员改问进程是否已收到信号,已退出
  就跳过,仍存活才上报。此前只认 ERROR_INVALID_PARAMETER 一种错误码,而正在
  消亡的进程可能先 OpenProcess 成功、随后查询失败。
- internal/health:探针错误连续 3 次才判失败,任一次成功清零;明确的否定结果
  (身份无效)仍然立即失败,语义不变。
- internal/backend:根进程已经自己退出时不再发 POST /api/core/close——端口
  此刻可能已被别的进程接手,那一发就打到了别人身上(桌面 E2E 里出现过「刚起来
  的后端收到来源不明的 close」正是这个形态)。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Sorry @qiyinxi, your pull request is larger than the review limit of 150,000 diff characters

@ClozyA
ClozyA merged commit d1eee3e into AUTO-MAS-Project:main Sep 4, 2026
2 checks passed
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.

3 participants