# Kuruwa M6 交付验收 本文是首次使用者和最终验收者的入口。它说明从干净 checkout 到构建、启动、完整行为验收的命令,并记录本次在独立干净源码目录中的实际执行结果。 ## 1. 一条验收命令 在干净 checkout 的仓库根目录执行: ```sh scripts/check.sh ``` `scripts/check.sh` 是固定顺序入口,不跳过失败阶段,不删除用户已有的 `target/`,也不创建 Git 提交。任一阶段失败会立即以非 0 退出并打印 `CHECK_FAIL stage '<阶段名>' failed (exit N)`。全部成功后最后打印 `CHECK_PASS`。 首次 RMUX 构建会从固定 codeload URL 下载上游 0.8.0 源码;后续运行复用 `target/rmux/`,并通过 pin/patch 标记校验。需要强制干净重建 RMUX 时: ```sh scripts/build-rmux.sh --fresh scripts/check.sh ``` 不要为了重跑验收而调用 `git clean -fdx` 或删除整个 `target/`;那会同时删除用户其他构建产物。`--fresh` 只删除并重建 `target/rmux/`。 ## 2. 环境前提 `scripts/check.sh` 启动时检查 Linux、基础命令存在和 bwrap namespace 可用性。`rustfmt`/clippy 等并非在启动时单独探测,而是在对应的 `cargo fmt --check` 或 `cargo clippy` 阶段实际执行时失败。任何缺前提或阶段失败都会以非 0 退出,不会跳过阶段并报告 PASS。 - Linux。当前验收范围是 Linux;macOS、Windows 和其他 Unix 未验证。 - 可用的 bubblewrap(`bwrap`)和用户 namespace/挂载权限。脚本会执行一次 `bwrap --ro-bind / / --dev /dev --proc /proc true` 冒烟检查;仅安装 bwrap 但无权限仍会失败。 - Rust 工具链:`cargo`、`rustc`,以及对应阶段需要的 rustfmt/clippy。 - `python3`。M2–M5 测试使用 Python 3 驱动真实 CLI、UnixStream 和 PTY。 - `curl`、`patch`、`tar`、`cmp`、`install`:固定 RMUX 下载、解包、打补丁和安装。 - `timeout`、`pgrep`、`grep`、`sed`、`tee`、`mktemp`、`readlink`、`seq`、`wc`、`cut` 及常规 coreutils。 - 首次构建需要网络访问固定 RMUX 下载 URL;Cargo 依赖可使用已有全局下载缓存,但干净源码目录不能复用原仓库的 `target/rmux/source` 或 `target/debug/kuruwa`。 建议在项目已有的 devenv/direnv 环境中执行,但 `check.sh` 不修改环境配置。 ## 3. check.sh 的阶段 | 阶段 | 命令 | 验什么 | | --- | --- | --- | | 前提 | `scripts/check.sh` 内建检查 | Linux、工具存在、bwrap 可用;缺项直接失败 | | RMUX 构建 | `scripts/build-rmux.sh` | 固定 0.8.0 commit、listener patch、release `rmux`/`rmux-daemon` | | RMUX 回归 | `scripts/check-rmux.sh` | 源码 fmt、listener 导入测试、非法 FD、普通路径启动、真实 pane 输出/退出码/socket 清理 | | Rust 格式 | `cargo fmt --check` | 产品源码格式 | | 产品构建 | `cargo build --locked` | 干净源目录可构建主 daemon/CLI | | 单元测试 | `cargo test --locked` | 配置、协议字段、名称、权限纯关系等单元测试 | | Clippy | `cargo clippy --locked --all-targets -- -D warnings` | 全目标无警告 | | M2 | `python3 scripts/test-m2.py` | 真实 host/bwrap 实例、终端、失败清理、downgrade/重启边界 | | M3 | `python3 scripts/test-m3.py` | 双租户、owner 与 grant、权限矩阵、即时撤回、名称代际 | | M3 blocked | `python3 scripts/test-m3-blocked.py` | 后端阻塞时 revoke/shutdown 取消真实请求 | | M3 write | `python3 scripts/test-m3-write.py` | 响应写出背压时 revoke/shutdown 断连接且不追加坏 JSON | | M4 | `python3 scripts/test-m4.py` | run/tail/transcript/cancel/gc/resize/PTY attach/skill | | M5 | `python3 scripts/test-m5.py` | 持久配置、完整用户流程、cleanup、重启、实例失效 | | 继承 FD | `prototypes/rmux-listener-fd/verify.sh` | 外侧预绑定 listener 经可信 init 跨 exec、路径隐藏、FD 不泄漏、原生 attach、SDK | 继承 FD 阶段显式使用本次干净 checkout 的构建源码: ```sh RMUX_SRC="$PWD/target/rmux/source" \ RMUX_BIN="$PWD/target/rmux/bin/rmux" \ prototypes/rmux-listener-fd/verify.sh ``` 它不会读取 `/tmp/rmux-src`,也不会把原型旧二进制当成最终构建证据。 ## 4. M1–M5 对应证据 - **M0 契约**:`docs/contracts.md`。 - **M1 固定 RMUX**: - 构建/适配说明:`docs/rmux-build.md`。 - 构建:`scripts/build-rmux.sh`。 - listener 导入、非法 FD、普通路径回归:`scripts/check-rmux.sh`。 - 端到端继承 FD、路径隐藏、FD 泄漏、原生 attach、SDK:`prototypes/rmux-listener-fd/verify.sh`。 - **M2 最小闭环**:`scripts/test-m2.py`,覆盖 host/bwrap 两实例、真实输出、fast exit 42、客户端断开、init 失败/超时清理、实例 daemon 失效、重复启动/残留拒绝、shutdown/SIGTERM。 - **M3 租户授权**:`scripts/test-m3.py`、`test-m3-blocked.py`、`test-m3-write.py`,覆盖 A/B 入口、owner/grant 正反矩阵、伪造字段拒绝、长时间等待撤回、写背压取消、grant 序列不复活旧连接。 - **M4 终端与人工干预**:`scripts/test-m4.py`,覆盖 run 正常/非零/超时/断线、screen/tail/transcript 区别、非 UTF-8 raw transcript、voluntary/forced cancel、gc 年龄与 running、typed resize、真实 PTY attach 的观察/输入/resize/detach、missing backend 不 autostart。 - **M5 生命周期与部署**:`scripts/test-m5.py` 与 `docs/deployment.md`,覆盖持久配置、bwrap/host、grant/revoke、原生 attach、强制销毁、自定义 cleanup 一次/失败、独立进程存活、shutdown/restart、旧 grant 不恢复、同名新对象隔离、实例 daemon 意外退出。 ## 5. 本次干净 checkout 实测 本次实际执行的干净源码目录: ```text /tmp/opencode/kuruwa-m6.0BSH74 ``` 该目录由 `git archive HEAD` 导出,HEAD 为: ```text 21570bc test(m5): verify deployment and complete lifecycle workflow ``` 导出后执行前只复制了本次未提交的 `scripts/check.sh`;没有复制或复用原仓库的 `target/rmux/source`、`target/debug/kuruwa`、运行目录或 Cargo 构建产物。检查通过后,将本轮未提交的 README、contracts、deployment、acceptance 文档和示例注释同步到该干净目录以保持交付文档一致;这一步只改文档,没有替换或重跑任何构建产物。完整日志保存在: ```text /tmp/opencode/kuruwa-m6-clean.log ``` 执行命令: ```sh cd /tmp/opencode/kuruwa-m6.0BSH74 ./scripts/check.sh ``` 实际结果: ```text CHECK_EXIT=0 CHECK_PASS root=/tmp/opencode/kuruwa-m6.0BSH74 rmux=/tmp/opencode/kuruwa-m6.0BSH74/target/rmux/bin/rmux stages=prereqs,rmux-build,rmux-check,fmt,build,test,clippy,M2,M3,M3-blocked,M3-write,M4,M5,inherited-fd ``` 各阶段日志要点: ```text prerequisites: Linux, rustc/cargo/python3/bwrap present, bwrap_namespace=ok build pinned RMUX: Finished release profile in 6m 46s, RMUX_BUILD_OK check pinned RMUX: CHECK_PASS fmt=ok imported_listener_tests=2 invalid_fds=3 ... socket_cleanup=ok cargo fmt --check: pass cargo build --locked: pass cargo test --locked: 13 passed; 0 failed cargo clippy --locked --all-targets -- -D warnings: pass M2: M2_PASS assertions=141 M3: M3_PASS assertions=812 M3 blocked: PASS blocked M3: 31 assertions M3 write: M3_WRITE_PASS assertions=16 M4: M4_PASS assertions=434 M5: M5_PASS assertions=297 inherited FD: FD_CHECK_OK no_listener_or_accepted_ipc_fd_leak inherited FD: PTY_ATTACH_OK resize=34x120 detach=detached inherited FD: SDK_OK sessions=["fdtest"] ... no_autostart=ok inherited FD: VERIFY_PASS ``` 这证明干净源目录可以从网络固定 pin 重建 RMUX、构建产品、运行真实端到端套件,并通过继承 FD/PTY/SDK 验收。完整日志保留在上述 `/tmp/opencode` 文件;测试临时 runtime 由各套件自行清理。 主 agent 最终独立审计确认 `scripts/check.sh` 与干净目录一致、`src/` 一致,并在原仓库再次运行: ```sh scripts/check.sh ``` 结果为 exit 0,最终打印 `CHECK_PASS`;日志: ```text /tmp/opencode/kuruwa-final-primary.log ``` 该复跑覆盖与干净 checkout 相同的固定 RMUX 构建/回归、cargo 格式/构建/单测/clippy、M2–M5 真实套件和继承 FD 验收。 ## 6. 已知限制 - **平台**:Linux 验证;其他平台未验证。 - **隔离强度**:bwrap 示例是 mount namespace 弱隔离,不是安全边界。同 UID 进程仍可能通过 `/proc`、ptrace、开放 FD 等旁路控制面。 - **权限边界**:host 实例的 shell 具有主 daemon 启动环境的实际权限。租户入口暴露、不同 OS UID 的目录/socket 所有权、mount/namespace 组合由部署者负责;0600 socket 不自动提供跨 UID 隔离。 - **运行态**:实例、终端、输出、grant 和旧连接不跨主 daemon 重启恢复;实例 daemon 异常退出不自动替换。 - **崩溃孤儿**:不保证崩溃孤儿自动回收;这是 MVP 明确非目标。 - **输出**:`transcript` 只读取 RMUX 当前保留的 raw PTY 输出,受输出环容量限制;不是持久日志,不承诺自创建以来的完整记录。 - **attach**:管理入口或目标实例 owner;成功后 exec 宿主原生 RMUX 客户端,调用者拥有该环境的实际控制能力。终端 grant 不返回 endpoint/session。 - **网络/服务**:没有网络监听、数据库、独立授权服务、持久任务系统或 agent 框架集成。 - **构建**:首次固定 RMUX 构建依赖网络和 C 链接器/系统构建环境;干净构建不复用原仓库 target。 ## 7. 品牌资产 `assets/logo.svg`、彩色/单色终端资产及相关生成脚本是品牌与展示材料,不是 `kuruwa` 或 `rmux` 的运行依赖。构建、部署和验收不需要生成或安装这些资产;可选生成也不属于 M1–M6 行为验收。 ## 8. 状态 `scripts/check.sh`、本文和部署说明已按干净 checkout 与主 agent 最终复跑结果落地。M0–M6 MVP 已验收完成;干净构建日志为 `/tmp/opencode/kuruwa-m6-clean.log`,主 agent 原仓库复跑日志为 `/tmp/opencode/kuruwa-final-primary.log`,两者均 exit 0 并打印 `CHECK_PASS`。