Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
8770df8
docs: 按 dev 基线重写跨仓清单
claude Sep 1, 2026
788eb1e
docs: 定稿 dev 基线接入的六条契约增补 (C6~C11)
claude Sep 1, 2026
707c08e
docs: 回写 dev 基线接入决策到架构设计
claude Sep 1, 2026
f5ac9c9
docs: 登记 M13 dev 基线接入配套任务
claude Sep 1, 2026
bf18964
docs: 修订 C10 显式包索引首选与改写前缀声明 (T13.4)
qiyinxi Sep 1, 2026
8de0da9
feat(backend): managed 后端工作目录改为 app-root (T13.1)
qiyinxi Sep 1, 2026
806cba7
docs: 记录 T13.1 完成情况
qiyinxi Sep 1, 2026
b34053d
docs: 记录 T13.4 依赖同步镜像改写设计与计划 (T13.4)
qiyinxi Sep 1, 2026
81f47a3
feat: 为包索引源显式声明锁改写前缀 (T13.4)
qiyinxi Sep 1, 2026
f20cd1b
feat: 增加 uv.lock 两处前缀的纯字符串改写 (T13.4)
qiyinxi Sep 1, 2026
30fe0ba
feat(process): Job 允许显式请求脱离 (T13.2)
qiyinxi Sep 1, 2026
4cfdd95
docs: 记录 T13.2 完成情况
qiyinxi Sep 1, 2026
a94228f
feat: 增加依赖同步临时项目目录与受控删除类别 (T13.4)
qiyinxi Sep 1, 2026
39cf370
feat(cli): backend supervise 新增 --shutdown-timeout (T13.3)
qiyinxi Sep 1, 2026
9d21bc1
feat: dependencies sync 按包索引镜像轮换改写锁副本 (T13.4)
qiyinxi Sep 1, 2026
81029ea
feat: 显式包索引首选改为排在轮换最前 (T13.4)
qiyinxi Sep 1, 2026
f12f070
feat: dependencies sync 报告镜像源与尝试次数 (T13.4)
qiyinxi Sep 1, 2026
f204746
test: 让假 uv 识别改写后的临时项目并按锁内容注入失败 (T13.4)
qiyinxi Sep 1, 2026
e5ef0ab
fix(backend): 优雅关闭不再误报 BACKEND_FORCE_TERMINATED (T13.3)
qiyinxi Sep 1, 2026
cf7598a
docs: 记录 T13.3 完成情况
qiyinxi Sep 1, 2026
a53bab7
test: 覆盖依赖同步镜像轮换的组件矩阵 (T13.4)
qiyinxi Sep 1, 2026
850c61b
test: 契约锁定 dependencies sync 的镜像源 details (T13.4)
qiyinxi Sep 1, 2026
bba97c9
refactor: 移除包索引的 --default-index 死代码路径 (T13.4)
qiyinxi Sep 1, 2026
eef95db
docs: 记录 T13.4 依赖同步镜像改写完成情况
qiyinxi Sep 1, 2026
cd7f69f
Merge branch 'feat/t13-mirror-rewrite-20260901' into integ/t13-20260901
qiyinxi Sep 1, 2026
1402129
docs: 记录 T13.5 受管基础设施与镜像源注入设计与计划 (T13.5)
qiyinxi Sep 1, 2026
25a04fb
feat(uv): 受管进程注入基础设施与有序镜像源 (T13.5)
qiyinxi Sep 1, 2026
8918e4b
feat(backend): 解析有序镜像源并随受管环境下发 (T13.5)
qiyinxi Sep 1, 2026
020b3b9
test: 端到端证明后端收到受管基础设施与镜像源 (T13.5)
qiyinxi Sep 1, 2026
1228110
fix(cli): bootstrap 与 repair 同样上报依赖同步的镜像源 (T13.4)
qiyinxi Sep 1, 2026
bde5d73
docs: 回写协议实现偏差与能力标识矛盾
qiyinxi Sep 1, 2026
1f6b13c
feat(protocol): backend supervise 公告 stdin.shutdown 与 stdin.status
qiyinxi Sep 1, 2026
ba27db3
docs: 记录 T13.5 注入面完成情况
qiyinxi Sep 1, 2026
bcadcb3
docs: AGENTS.md 状态表回写 T13.4 完成与 T13.5 注入面
qiyinxi Sep 1, 2026
9d9bb2b
docs: T13.5 池目录重新分类按设计关闭,T9.1 development 联调记为完成
qiyinxi Sep 2, 2026
e774647
docs: 定稿增补 1 C12/C13 并立项 T13.7 受监督端口注入与 T13.8 宿主断开即关闭
qiyinxi Sep 2, 2026
5c21fb4
feat(uv): 受管进程注入 AUTO_MAS_SUPERVISED_PORT (T13.7)
qiyinxi Sep 2, 2026
3d1ff06
feat(health): 健康端点地址按 Expectation.Port 派生 (T13.7)
qiyinxi Sep 2, 2026
c09adc0
feat(backend): 受监督端口按模式取缺省并派生健康、关闭地址与 baseUrl (T13.7)
qiyinxi Sep 2, 2026
77bb0f2
feat(cli): backend supervise 新增 --port (T13.7)
qiyinxi Sep 2, 2026
f7d5edb
test: 假后端从 AUTO_MAS_SUPERVISED_PORT 取监听端口,E2E 改用空闲端口 (T13.7)
qiyinxi Sep 2, 2026
33c6bc8
feat(protocol): ControlReader 报告输入是否已到达 EOF (T13.8)
qiyinxi Sep 2, 2026
64a0554
feat(cli): backend supervise 把 stdin EOF 与读取出错视为隐式 shutdown (T13.8)
qiyinxi Sep 2, 2026
41c51d3
test: 真实 exe 黑盒证明 stdin EOF 优雅关闭且 stdout 已断仍能退出 (T13.8)
qiyinxi Sep 2, 2026
6f7e5fc
docs: 记录 T13.7 受监督端口注入与 T13.8 宿主断开即关闭完成情况
qiyinxi Sep 2, 2026
677586d
docs: C13 定稿 stdout 已断不影响优雅关闭 (T13.8)
qiyinxi Sep 2, 2026
85b7615
test: 假后端落盘优雅关闭标记,断言 stdout 已断时后端仍被 HTTP 优雅关闭 (T13.8)
qiyinxi Sep 2, 2026
23033f9
feat(backend): shutdown 路径上协议输出失败不再中断优雅关闭 (T13.8)
qiyinxi Sep 2, 2026
846b923
docs: 记录 T13.8 收尾——stdout 已断不影响优雅关闭
qiyinxi Sep 2, 2026
88d8a6f
docs: 定稿增补 1 C14 孤儿回收与强制终止分离并立项 T13.9
qiyinxi Sep 2, 2026
da710c4
feat(backend): 孤儿回收改报 BACKEND_ORPHANS_REAPED,强制终止只留给主进程被强杀 (T13.9)
qiyinxi Sep 2, 2026
33060c8
docs: 记录 T13.9 孤儿回收与强制终止分离完成情况
qiyinxi Sep 2, 2026
303596e
docs: 落盘首版验收记录并回写 T9.2~T9.4 状态 (T9.4)
qiyinxi Sep 3, 2026
5e60f38
docs: 修订 C13 第 4 条并定稿 C15,立项 T13.10 / T13.11
qiyinxi Sep 3, 2026
c46babf
fix(backend): 后端日志转发失败不再终止进程树 (T13.10)
qiyinxi Sep 3, 2026
7fa56a1
fix(runtime): 身份校验容忍启动窗口,根进程已退出时不再发关闭请求 (T13.11)
qiyinxi Sep 3, 2026
d1d0f5e
docs: 记录 T13.10 与 T13.11 的完成情况
qiyinxi Sep 3, 2026
d958634
Merge branch 'feat/t13-port-eof-20260902' into integ/t13-20260901
qiyinxi Sep 3, 2026
9427c7b
docs: T9.3 Electron 接入支持记为完成
qiyinxi Sep 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Vue/Electron/Python 的改写、CI/CD 发布流程本身。

---

## 2. 当前状态(截至 2026-08-13
## 2. 当前状态(截至 2026-09-03

| 里程碑 | 状态 |
| --- | --- |
Expand All @@ -43,10 +43,11 @@ Vue/Electron/Python 的改写、CI/CD 发布流程本身。
| M5 uv、Python 与依赖 | T5.1~T5.8 **已完成**(复审修复收口于 `8deb9d7`,含官方 uv 资产、完整组件矩阵与 race 验证) |
| M6 后端监督 | T6.1~T6.7 **已完成**(真实 Windows Job/health/control/restart/development/E2E 与对抗复审收口于 `ea886f8`) |
| M7 GitHub CI/CD 发布 | T7.1~T7.4 **已完成**(beta.2 Release run `31407585577`、三 job 全绿、独立资产/NDJSON 验收通过);T7.5 按 D3 延后 |
| M9 联调与首版验收 | 未开始 |
| M9 联调与首版验收 | T9.1 development 真后端联调 **已完成**(2026-09-02,`ba27db3` 构建对 AUTO-MAS 集成树 `integ/runtime-20260901` 跑通启动→就绪→优雅关闭);T9.2 managed 全链路 **已完成**(2026-09-02,用本地 HTTPS smart-git 模拟 `release/*` 分支:bootstrap → supervise → 升级 → 降级 → 关 stdin 隐式关闭,真实发布分支复跑待 push 后);T9.3 Electron 接入 🚧(`off` 六场景与 `development` 一轮桌面 E2E 完成,复跑进行中,未宣布通过);T9.4 首版验收清单核对 **已完成**(2026-09-03,[`doc/首版验收记录.md`](doc/首版验收记录.md):标准第 1~11 条满足,第 12/14 条不满足、第 13 条未验证,均属 AUTO-MAS 侧发布动作并附解除条件);M9 整体待真实 `release/*` 复跑与阶段 0/5/6 收口后勾选 |
| M10 工程可维护性收敛 | T10.1 文档信息架构已完成;后续阶段见维护设计 |
| M11 跨平台适配(Linux/macOS) | 规划中(决策 D7,2026-08-04 立项);仅 T11.1 设计任务可执行 |
| M12 遥测与错误观测(Sentry-only) | T12.1、T12.2、T12.4、T12.5、T12.7 已完成;T12.6 本地发布配置已提交,待 Repository secret 与授权后的远端验收;T12.3/Umami 已取消 |
| M13 dev 基线接入配套 | 2026-08-31 按决策 D12 与 `doc/契约补充-v1-增补1.md`(C6~C11)立项;T13.1(后端工作目录)、T13.2(Job 允许显式脱离)、T13.3(关闭超时参数化,含优雅关闭误报修复)、T13.4(锁副本改写参与包索引镜像轮换,显式 package-index 排最前)**已完成**;T13.5 **已完成**(注入面 `020b3b9`:`AUTO_MAS_UV_CACHE_DIR` / `AUTO_MAS_UV_PYTHON_INSTALL_DIR` / `AUTO_MAS_MIRROR_PACKAGE_INDEX` / `AUTO_MAS_MIRROR_PYTHON`;池目录重新分类按设计关闭——Runtime 的 repair/cleanup 只处理自己的目录,池 venv 失效后由后端判定重建);T13.6 ⏸ 未开始;2026-09-02 真机联调后按增补 1 **C12 / C13** 完成 T13.7(`f7d5edb`:`backend supervise --port`,缺省 managed 36163 / development 36164,注入 `AUTO_MAS_SUPERVISED_PORT`,健康/关闭地址与 `baseUrl` 由 `internal/health` 派生,E2E 改用空闲端口)与 T13.8(`41c51d3`,收尾 `23033f9`:`backend supervise` 的 stdin EOF / 读取出错视为隐式 shutdown,stdout 已断不影响 HTTP 优雅关闭,真实 exe 黑盒 E2E 锁定,宿主崩溃不再留孤儿)**已完成**;T13.9(`da710c4`,增补 1 C14:新 warning `BACKEND_ORPHANS_REAPED`,`BACKEND_FORCE_TERMINATED` 收窄为主进程被强杀)**已完成**;T13.10(`c46babf`,C13 第 4 条修订:协议日志转发失败不再回给 process 层,避免宿主崩溃时把正在优雅关闭的后端连同进程树杀掉)与 T13.11(`7fa56a1`,C15:Job 快照跳过正在消亡的成员、健康探针错误连续 3 次才判失败、根进程已退出时不再发 close)**已完成** |

代码现状:

Expand Down Expand Up @@ -76,13 +77,14 @@ Git:远端 `origin` = `git@github.com:AUTO-MAS-Project/AUTO-MAS-Runtime.git`
| --- | --- | --- |
| [doc/README.md](doc/README.md) | 文档导航、分层与生命周期规则 | 查找任何项目文档时 |
| [doc/架构设计.md](doc/架构设计.md) | 冻结的系统架构:边界、CLI 命令树、NDJSON 协议、错误码/退出码/stage/state 全集、Git 更新流程、uv 策略、目录安全、测试矩阵、验收标准 | 任何涉及对外契约的改动 |
| [doc/契约补充-v1.md](doc/契约补充-v1.md) | 协议 v1 的 5 项定稿细节(C1~C5:固定端口 36163、身份注入环境变量、`failed` 字面量、`AUTO_MAS_SUPERVISED=1`、development 检查边界) | 涉及后端启动/健康检查/环境变量 |
| [doc/任务拆分.md](doc/任务拆分.md) | 逐任务清单、依赖、验收项、决策记录 D1~D6、待决项 D-open-*、AUTO-MAS 侧 TODO、变更记录 | **每次开工前**确认自己在做哪个任务 |
| [doc/契约补充-v1.md](doc/契约补充-v1.md) | 协议 v1 的 5 项定稿细节(C1~C5:后端端口(已由增补 1 C12 改为 Runtime 注入)、身份注入环境变量、`failed` 字面量、`AUTO_MAS_SUPERVISED=1`、development 检查边界) | 涉及后端启动/健康检查/环境变量 |
| [doc/契约补充-v1-增补1.md](doc/契约补充-v1-增补1.md) | 对 v1 的增量修订(C6~C11:后端工作目录、受监督优先级扩展到端口、Job 逃逸、关闭预算参数化、依赖镜像改写轮换、运行池基础设施共享),并修订 C2 第 1 条与 C4 第 1 条 | 同上;**与 `契约补充-v1.md` 冲突时以本文件为准** |
| [doc/任务拆分.md](doc/任务拆分.md) | 逐任务清单、依赖、验收项、决策记录 D1~D12、待决项 D-open-*、AUTO-MAS 侧 TODO、变更记录 | **每次开工前**确认自己在做哪个任务 |
| [doc/代码审查清单.md](doc/代码审查清单.md) | 自动化门禁覆盖不到的架构边界检查 | 提交前自查、审查他人代码 |
| `doc/current/M*/` | 尚未完成任务的设计与实施计划 | 执行某个具体任务时 |
| `doc/archive/M*/` | 已完成阶段仍有解释价值的设计与审查记录 | 追溯设计背景时 |

**优先级:** 契约补充-v1(更具体) > 架构设计(概括) > 任务拆分(派生清单)。
**优先级:** 契约补充-v1-增补1(最新增量修订) > 契约补充-v1(更具体) > 架构设计(概括) > 任务拆分(派生清单)。

---

Expand Down Expand Up @@ -472,5 +474,7 @@ Go 测试惯例([Go Code Review Comments](https://go.dev/wiki/CodeReviewCommen
“退出码为 0”“输出不含 `[no tests to run]`”“出现 `--- PASS:`”,照抄这个模式。
- **注释中文、标识符英文**:注释(含 doc comment)写中文,doc comment 仍以英文标识符开头;
Go error 字符串保持英文小写;不要把设计文档写成英文,也不要在同一声明里中英混排。
- **改协议前先看 `doc/契约补充-v1.md`**:架构设计里的概括描述常被它进一步收紧。
- **决策已冻结的事项不要重开**:D1~D6 与 C1~C5 是用户已确认的结论;D-open-4~7 才是待决项。
- **改协议前先看 `doc/契约补充-v1.md` 和 `doc/契约补充-v1-增补1.md`**:架构设计里的概括描述常被它们进一步收紧;
增补 1 还修订了 C2 第 1 条(`protocol` 由后端自报而非回显)与 C4 第 1 条(受监督但非管理员时记 warning 并继续运行)。
- **决策已冻结的事项不要重开**:D1~D12 与 C1~C11 是用户已确认的结论(D2/D4/D8/D9/D10 已被后续决策取代,原文只作追溯);
当前仍待决的是 D-open-4、D-open-5、D-open-7、D-open-10。
7 changes: 5 additions & 2 deletions doc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
| 文档 | 用途 |
| --- | --- |
| [架构设计](./架构设计.md) | 系统边界、对外契约、目录安全、命令树和验收标准 |
| [协议 v1 契约补充](./契约补充-v1.md) | 后端端口、身份注入、健康检查等具体契约 |
| [协议 v1 契约补充](./契约补充-v1.md) | 后端端口、身份注入、健康检查等具体契约(C1~C5) |
| [协议 v1 契约补充 增补 1](./契约补充-v1-增补1.md) | 对 v1 的增量修订:工作目录、受监督优先级、Job 逃逸、关闭预算、依赖镜像、运行池基础设施(C6~C11) |
| [任务拆分](./任务拆分.md) | 任务依赖、验收、决策和当前进度 |
| [代码审查清单](./代码审查清单.md) | 自动化门禁之外的架构边界检查 |
| [T1.3 生命周期设计](./设计-T1.3-生命周期状态机.md) | 协议测试直接读取的生命周期契约夹具 |

权威优先级仍为:`契约补充-v1.md` > `架构设计.md` > `任务拆分.md`。
权威优先级仍为:`契约补充-v1-增补1.md` > `契约补充-v1.md` > `架构设计.md` > `任务拆分.md`。

## 按用途浏览

Expand All @@ -22,6 +23,8 @@
- [历史归档](./archive/README.md):已完成阶段仍有解释价值的设计与审查记录。
- [代码审查记录](./code-review.md):跨轮次 Review 发现的问题、修复状态与待执行的
Windows 侧验证清单;修复前先查这里是否已有记录。
- [首版验收记录](./首版验收记录.md):T9.4 对架构设计「发布验收标准」的逐条核对、证据索引、
不满足项与本地模拟的缺口说明;真实发布分支复跑后在原文档上更新。

## 文档生命周期

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# 设计与计划 T13.1 后端工作目录与绝对入口路径

- 契约:[增补 1 C6](../../契约补充-v1-增补1.md#c6后端进程工作目录与入口路径)
- 任务:[任务拆分 T13.1](../../任务拆分.md)
- 状态:设计 + 计划(本文件同时承担四段式的前两段)

## 目标

managed 模式下把 Runtime 创建的后端子进程工作目录从 uv 的 project dir(`<app-root>/repo`)
改为 **app-root**,入口参数从裸 `main.py` 改为绝对路径 `<app-root>/repo/main.py`。
`--project` 仍指向 `<app-root>/repo`。development 模式的 cwd 与入口**不变**。

修的是实现偏离文档:架构设计「目录模型」与「插件环境职责边界」本就要求 cwd = 项目根目录,
而 `internal/uv/managed.go:83` 无条件用 `resolved.ProjectDir`。按现实现,后端会把
`config/ data/ history/ script/ debug/` 建进 `repo/`,被 `workspace sync` 的整体替换清掉。

## 边界(不负责)

- 不改 development 模式的任何行为(cwd 仍是 `--repo`,入口仍是裸 `main.py`);
- 不改一次性 uv 命令(`uv python install` / `uv sync` / `uv pip`)的既有行为——新字段为空时
回退 `ProjectDir`,这些调用方一个都不传新字段;
- 不新增、不改名任何协议字段、`stage`、`state`、错误码或 error `details` 键(M13 不得扩大契约面);
- 不改 Python 侧(`AUTO-MAS` 的 `TODO-PY-4` / `TODO-PY-10` 成对落地,本仓库管不到)。

## API 形态

`internal/uv`:

```go
// RunOptions
WorkingDir string // 子进程工作目录;为空回退 ProjectDir
```

`resolvedRunOptions` 同步增加 `WorkingDir`,`resolveOptions` 在解析出 `ProjectDir` 之后
用它做默认值,显式非空值覆盖。`UVRunner.Run` 与 `UVRunner.StartManaged` 都改用
`resolved.WorkingDir` 作为子进程 `Dir`。

`internal/backend`:

- `supervisor.go` 的 managed 无控制通道路径:argv 末项改 `s.layout.BackendEntryFile()`,
`RunOptions.WorkingDir = s.layout.AppRoot()`;
- `control.go` 的受控启动路径(**managed 与 development 共用同一处 `StartManaged`**,
与任务描述里「control.go 是 development 路径」的说法不符,以仓库现状为准):按 mode 分支,
managed 用绝对入口 + app-root,development 保持 `"main.py"` + 空 `WorkingDir`;
- `production.go` 的 `productionUV.StartManaged` 整体透传 `uv.ManagedOptions`,无需改动。

## 失败语义

`WorkingDir` 与其余受管路径一样进 `validateRunnerPaths`:空字符串(回退后仍为空)或含 NUL
时返回 `UV_EXEC_FAILED`,与既有路径校验完全一致,不新增错误码。启动失败的
`details` 键集合保持不变。

## Task 拆分

### Task 1:`internal/uv` 的显式工作目录

- 文件:`internal/uv/runner.go`、`internal/uv/managed.go`、`internal/uv/managed_test.go`、
`internal/uv/runner_test.go`
- 红灯:`TestManaged_WorkingDirOverridesProjectDir`(StartManaged 传 `WorkingDir` 后子进程
`os.Getwd()` 等于该目录)与 `TestRunner_WorkingDirDefaultsToProjectDir`(一次性 `Run`
不传时 cwd 仍为 ProjectDir、传了则用新值)——字段不存在,编译失败
- 绿灯:加 `WorkingDir` 字段与回退逻辑
- 验证:`go test ./internal/uv -run 'WorkingDir' -count=1 -v`

### Task 2:managed 的 app-root 与绝对入口

- 文件:`internal/backend/supervisor.go`、`internal/backend/control.go`、
`internal/backend/supervisor_test.go`、`internal/backend/control_test.go`
- 红灯:`TestSupervise_ManagedUsesAppRootAndAbsoluteEntry`、
`TestControl_ManagedUsesAppRootAndAbsoluteEntry`、
`TestControl_DevelopmentKeepsRepoWorkingDirAndRelativeEntry`
- 绿灯:按 mode 分支设置 argv 末项与 `WorkingDir`
- 验证:`go test ./internal/backend -run 'AppRoot|RelativeEntry' -count=1 -v`

### Task 3:E2E 的真实 cwd 证明

- 文件:`testdata/fakebackend/main.go`(health 响应增加 `workingDir`,仅测试夹具,不是协议)、
`internal/backend/e2e_windows_test.go`
- 红灯:development E2E 断言子进程 cwd == `--repo`;新增 uv 记录断言 argv 末项形态
- 绿灯:夹具落地 cwd 文件 + 断言通过
- 验证:`go test ./internal/backend -run 'BackendE2E' -count=1 -v`

## 验收对照

| 任务拆分验收项 | 覆盖方式 |
| --- | --- |
| 后端 cwd 为 app-root、入口为绝对路径 | Task 2 单测(`StartSpec.Dir`/argv)+ Task 1 真实子进程 `os.Getwd()` |
| development E2E 与既有一次性命令无回退 | Task 1 回退语义 + Task 3 development E2E cwd 断言 |
| 单次自动重启后 cwd 与入口不漂移 | `control.go` 的重启复用同一处 `StartManaged`,Task 2 断言覆盖两次调用 |
| 用户数据在 `workspace sync` 后仍存在 | 由 cwd 移出 `repo/` 直接保证;跨仓联合验收(TODO-PY-4/10)才能端到端证明 |
59 changes: 59 additions & 0 deletions doc/current/M13/设计-T13.2-Job-Object-允许显式脱离.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# 设计与计划 T13.2 Job Object 允许游戏与模拟器脱离

- 契约:[增补 1 C8](../../契约补充-v1-增补1.md#c8job-object-逃逸与游戏模拟器的进程归属)
- 任务:[任务拆分 T13.2](../../任务拆分.md)
- 状态:设计 + 计划

## 目标

Runtime 创建的 Job Object 在 `JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE` 之外追加
`JOB_OBJECT_LIMIT_BREAKAWAY_OK`,使 AUTO-MAS 在拉起模拟器与 PC 游戏时可以用
`CREATE_BREAKAWAY_FROM_JOB` 让它们脱离受管进程树,从而**不随后端退出**——这是为保持
今天的用户可见行为而定的产品决策。

## 边界(不负责)

- **不用 `JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK`。** 那一位让所有子进程默认脱离,
后端自己的 worker 与 Agent 会一起逃出回收边界;只放开「显式请求」这一条路径;
- `KILL_ON_JOB_CLOSE` 保留,未请求脱离的进程归属、`Snapshot`/`WaitEmpty` 的证明方式、
`details.pid` 语义、`BACKEND_FORCE_TERMINATED` 警告一律不变;
- 不引入任何按进程名的清理(红线第 5 条);
- Runtime 单独开这一位不产生任何行为变化——真正的效果要 AUTO-MAS 侧 `TODO-PY-11`
带上 `CREATE_BREAKAWAY_FROM_JOB` 才出现,验收以跨仓联合「跑着游戏关 AUTO-MAS」为准。

## API 形态

无导出 API 变化。`internal/process/job_windows.go` 的 `NewJob` 只改一行 `LimitFlags`,
并更新 `NewJob` 的 doc comment 与 `internal/process/doc.go` 的包注释措辞——注释是文档的
一部分,「进程树唯一受管」的绝对表述必须收敛为「未显式请求脱离的进程唯一受管」。

## 失败语义

不变。`SetInformationJobObject` 失败仍关闭句柄并返回原错误。
需要注意的是**加这一位之前**,带 `CREATE_BREAKAWAY_FROM_JOB` 的 `CreateProcess`
会直接失败(`ERROR_ACCESS_DENIED`),这正是红灯测试的失败原因。

## Task 拆分

### Task 1:Job 允许显式脱离

- 文件:`internal/process/job_windows.go`、`internal/process/doc.go`、
`internal/process/managed_windows_test.go`
- 红灯:
- `TestJob_BreakawayGrandchildSurvivesJobClose`——孙进程带
`CREATE_BREAKAWAY_FROM_JOB` 启动,`IsProcessInJob(孙, 本 Job)` 为 false,
`Close()` 之后仍存活(测试自行终止它);无 `BREAKAWAY_OK` 时孙进程根本起不来
- `TestJob_NonBreakawayGrandchildStaysInJobAndIsReaped`——不带该标志的孙进程
`IsProcessInJob` 为 true,`Close()` 之后被杀
- 绿灯:`LimitFlags |= windows.JOB_OBJECT_LIMIT_BREAKAWAY_OK`
- 验证:`go test ./internal/process -run 'Breakaway|StaysInJob' -count=1 -v`,
以及 `go test ./internal/process -count=100`(并发相关)与全仓 race

## 验收对照

| 任务拆分验收项 | 覆盖方式 |
| --- | --- |
| 带 `CREATE_BREAKAWAY_FROM_JOB` 的子进程能脱离、Job 关闭后仍存活 | `TestJob_BreakawayGrandchildSurvivesJobClose` |
| 不带该标志的子进程仍随 Job 回收 | `TestJob_NonBreakawayGrandchildStaysInJobAndIsReaped` + 既有 `TestJobE2E_RuntimeTerminationReapsGrandchildren` |
| 既有进程树清理、`BACKEND_FORCE_TERMINATED`、`details.pid` 无回退 | 既有 `internal/process` 与 `internal/backend` 全套测试不改 |
| 「跑着游戏关 AUTO-MAS」 | 跨仓联合验收,本仓库单侧做不到 |
Loading