host
9d986becaf
feat(chv): 完整 Chromium 改装数据盘
...
根盘只剩 ~600MB,playwright install chromium 装根盘 109 秒后
ENOSPC 失败(2026-11-08 构建 #8 驱动实证)。完整版改装数据盘
/home/chv/workspace/.chv-browsers(9.3G 空闲),仍不 bake 进
base、按需;full 引擎启动时直接传 executable_path(channel 与
executable_path 互斥,且驱动进程启动时才读 env,运行中改 env
无效);status 增 full_browsers_dir,mount 失败报错给数据盘
安装命令。驱动的安装步同步改数据盘并 chown 给 chv-browser。
2026-11-08 09:45:00 +00:00
host
435664925e
fix(chv): cell 不再把 /run/chv 的组改回 root
...
chv-cell 每次跑 cell 都 _ensure_bind_source(BROKER_DIR, uid=0,
gid=0),把 /run/chv 的组改回 root,抹掉 tmpfiles 的 chv-browser
组;之后 chv-browser 重启时 os.remove(browser.sock) 报
Permission denied、无限 crash-loop(构建 #8 客机 62 次重启才
被发现,03:42 驱动两次跑 cell 正好在补丁后、重启前)。改:组
改取 chv-browser 的 gid(不存在回落 0);serve() 删 socket
失败时报错说清修法,不再只剩裸 traceback。
2026-11-08 09:45:00 +00:00
host
0bfb00ab1b
fix(chv): 快照改走 page.aria_snapshot()
...
Playwright 1.64.1 已移除 page.accessibility,真实快照一路报
AttributeError(P2 假实现用的旧 API,单测一直没抓到;2026-11-08
构建 #8 驱动 live 抓到)。新版 aria_snapshot() 返回字符串,
超 64KB 截断;旧版 accessibility.snapshot()(dict)只作回落。
驱动的 a11y 断言接受 str 或 dict。
2026-11-08 09:45:00 +00:00
host
7361b0654f
fix(chv): _load_playwright 须返回 sync_playwright() 实例
...
返回函数本身则无 __enter__,真实启动路径从未跑通过(P2 假实现
掩盖;2026-11-08 构建 #8 驱动 live 抓到)。回归测试钉死该契约。
2026-11-08 09:45:00 +00:00
host
eb495892e1
fix(chv): 阶段 3 live 根因——浏览器 socket 与数据盘 profile 的两处权限
...
- /run/chv 0755 root:root 时 chv-browser 建 browser.sock 报
PermissionError、服务无限 crash-loop(P2 遗留,阶段 2 从未验
过 browser.sock):tmpfiles 改 0775 root:chv-browser。
- /home/chv 默认 0750,chv-browser 穿不过家目录,ismount 判假、
profile 静默回落本机盘:chv-data-mount 挂载成功后 chmod 0751
/home/chv(只放行穿过,不放行列表)。
- 驱动:等 cloud-init done + 四服务 active 再验浏览器。
- 回归 97 项全过(新增 2 项接线断言)。
2026-11-08 09:45:00 +00:00
host
1188e4b000
feat(chv): 阶段 3 浏览器服务化——持久 profile + CDP + 多会话 + JPEG 截图 + 双浏览器
...
- chv-browser:launch_persistent_context,profile 固定数据盘
/home/chv/workspace/.chv-browser-profile(未挂载回落本机盘并明说);
CDP --remote-debugging-port 9222(op cdp 返回 webSocketDebuggerUrl);
多会话每会话一页;截图 JPEG q70、viewport 宽封顶 1280、diff_only
整帧相同跳过;mount_full/unmount_full 切 full/shell 引擎,full
未装或起不来回落 shell 并明说。
- chv-data-mount:挂载后预建 profile 目录(chv-browser:chv-browser 0700)。
- build.sh:chv-browser 单元 Restart=always、After cloud-final.service。
- chv-execd:codex 环境白名单加 CHV_BROWSER_ 前缀。
- 测试:新增 test_chv_opt_stage3.py(20 项);P2 假实现改为持久
上下文 + JPEG;stage2 的 Restart=always 计数 3→4。
- 全量回归 2032 过 skipped=8。
2026-11-08 09:45:00 +00:00
host
6a65c94254
fix(chv): execd 单元 KillMode=process(构建 #6 驱动实证)
...
缺 KillMode 时 systemd 默认 control-group,kill -9 execd 主进程
后重启会 SIGTERM 整个 cgroup,sleep 任务同 pid 存活的要求被破、
新 execd 认领时 pid 已死记 unknown,驱动 kill 相断言失败。
KillMode=process 只信号主进程,任务在重启后同 pid 存活认领;
stop 仍干净停 daemon 本身。回归测试
BuildWiringTest.test_build_sh_execd_unit_keeps_tasks_on_restart。
2026-11-08 09:45:00 +00:00
host
42adbd047f
fix(chv): 79-chv-cell.network 改回 root:root 644(构建 #5 驱动实证)
...
virt-customize --copy-in 保留构建宿主 uid/mode,79 文件在客机
落盘成 chv:chv 640,networkd 不认它、改配 80-container-ve.network、
刷掉 10.200.0.1,cell _iface_has_ip 复核失败、codex --help rc=1。
构建时显式 chown root:root + chmod 644 并断言属主与权限;
回归测试 BuildWiringTest.test_build_sh_fixes_cell_network_file_owner。
2026-11-08 09:45:00 +00:00
host
1cbaf7c1d5
chv-cell: networkd 不管 ve + 单元内 DNS 修复
...
- systemd-networkd(/usr/lib 80-container-ve.network,匹配 ve-*)
会在 veth 建好后几秒内刷掉静态 10.200.0.1、改 DHCP/链路本地,
致单元网关不可达、TCP/UDP 全灭(FORWARD/NAT 计数器恒 0;
早先一次 curl 403 是刷掉前的窗口期偶发)。修法:镜像内置
/etc/systemd/network/79-chv-cell.network(Unmanaged=yes),
须排在 80 之前(99 会被 80 抢走,已实测);build.sh copy-in
+ 校验、BASE_CONTENTS 与两处 DECLARED_SOURCES 登记。
- run_cell 配网后复核 ve 上确有 10.200.0.1(_iface_has_ip),
不见即大声失败、不跑无网单元(第二道防线)。
- 单元内 DNS:/etc/resolv.conf 是 127.0.0.53 stub,单元独立
netns 里自己的 lo 上没有 resolver;把上游
/run/systemd/resolve/resolv.conf 绑到 /etc/resolv.conf
(解析 symlink 后挂真实目标)。live 验证:DNS-UDP-OK、
getaddrinfo 解析成功、curl https://gitea.tose.top 200。
- 单测:CellResolvTest + _iface_has_ip 真实 lo 断言 + 规约
dns_resolv_conf 字段;P2 + 阶段 2 共 74 项全过。
2026-11-08 09:45:00 +00:00
host
4b5f2f124f
chv-cell: ns 内 setuid 修复 + 单元内 DNS(上游 resolv.conf 绑定)
...
- 中间进程不再先 setuid(1000) 再 unshare:真机对照实测那样
后续 unshare(CLONE_NEWNS) 得 EPERM;改为保持 root 外层身份
unshare(creator caps 在),孙进程在 ns 内 setgid/setuid(0)
切到内 0(映射到外层 chv 1000)。
- 单元内 DNS:客机 /etc/resolv.conf 是 127.0.0.53 stub,单元
独立 netns 里自己的 lo 上没有 resolver;把上游
/run/systemd/resolve/resolv.conf 绑到 /etc/resolv.conf
(解析 symlink 后挂真实目标),只在单元私有 mount ns 里。
- 单测:CellResolvTest(bind 参数/symlink 解析/缺失回落)
+ 规约 dns_resolv_conf 字段;P2 + 阶段 2 共 73 项全过。
2026-11-08 09:45:00 +00:00
host
afbb7772c5
fix(chv): cell 映射改由父进程写,中间进程先 setuid(1000)
...
两个真机教训(2026-11-07):
- 子进程自己写不进 uid_map:unshare 后 euid 变 overflow,
连 /proc/self/uid_map 的 open 都 EPERM——改由父进程
(仍在初始 ns 的 root)经 /proc/<pid>/uid_map 写。
- 映射按外层 uid 翻译:中间进程外层是 root(0) 时
“0 1000 1” 盖不住它、新 ns 里仍是 overflow——中间进程
须先 setgroups/setgid/setuid(1000) 再 unshare(实测
chv 身份 unshare 在客机上可行,AppArmor 不挡)。
另:中间进程异常加 traceback(调试用);userns 单测改测
父写映射真实路径(映射行按 split 比,内核会多空格对齐)。
2026-11-08 09:45:00 +00:00
host
a2a5624736
fix(chv): cell 后端由 nspawn 改为纯 stdlib userns 启动器
...
nspawn --directory=/ 在 systemd 255.4 上走不通(2026-11-07 真机
实测,修一个冒一个):裸 --no-new-privileges 被当成要值吞掉
下一个参数;--directory=/ 被根目录检查挡住;--volatile=state
又要 /run/host/os-release 挂载点与空 /dev(--tmpfs=/dev 不
生效)。cell 从未 live 跑通过(阶段 1 只测参数表纯函数)。
bwrap 作 chv 被 AppArmor userns 门挡住,newuidmap 客机未装。
新后端(同文件、同 CLI、同调用方):root 起进程,中间进程
unshare 用户 ns 并自己写 uid_map/gid_map(内 0 → 外 chv
1000),再进 mount/pid/net ns、挂 fresh /proc、/tmp tmpfs、
遮蔽敏感路径(目录盖 tmpfs、文件绑 /dev/null)、设
no_new_privileges + seccomp(禁 io_uring 三件套)+ 丢
capability,最后 exec payload;父进程配 veth/NAT、等退出码、
清 NAT。veth/NAT/nsenter 流程与旧版一致,seccomp BPF 与
capability 语义与 P2 设计一致。无新依赖、无 sysctl 改动。
2026-11-08 09:45:00 +00:00
host
42b295fc71
fix(chv): 阶段 2 syncd 改走 systemd RuntimeDirectory=/run/chv-syncd
...
tmpfiles 行 d /run/chv/syncd 0755 chv chv 没用:tmpfiles-setup
跑在 cloud-init 建 chv 用户之前,属主解析失败整行被跳过,
客内 /run/chv/syncd 根本不存在(2026-11-07 真机实测:镜像
里有这行、目录没有,syncd 反复退出、restart counter 57)。
改走单元 RuntimeDirectory=chv-syncd(服务启动时由 systemd
按服务用户建目录,不依赖启动时序);状态写失败改为记日志
不杀进程;daemon 与驱动的 syncd 路径同步改到
/run/chv-syncd/。
2026-11-08 09:45:00 +00:00
host
8013431f63
fix(chv): 阶段 2 syncd 写路径改到 chv 所有的 /run/chv/syncd/ 子目录
...
/run/chv 是 0755 root:root,chv 身份的 syncd 写不进状态文件
与 socket,_atomic_write 抛错致进程反复退出、systemctl 长期
activating(2026-11-07 真机实测)。socket 与状态文件改到
tmpfiles 预建的 /run/chv/syncd/(0755 chv:chv,与 chv-browser
的 shots 同款);daemon 的 sync 摘要读同一路径;驱动的
syncd socket 路径与 ls 检查同步更新;另修驱动 SSH poller
线程残留(daemon=True + wake 失败也 set 事件)。
2026-11-08 09:45:00 +00:00
host
9d77ae55a7
feat(chv): 阶段 2 客机运行时三分 daemon/execd/syncd + restore 留 seed.iso + tap 退避
...
- 客机三分(chv-guest/chv-daemon.py、chv-execd.py、chv-syncd.py,
仅标准库;systemd Restart=always;build.sh 拷入 + 单元 + enable;
buildinfo/check/generate lockfile 登记):
daemon=心跳/资源上报/快照配合(prepare-snapshot 问 execd,
有运行中任务或联系不上即拒绝);execd=shell/文件读写/codex
托管(chv-cell 起 host.py,setsid 脱离,任务登记落盘,
重启按 pid 认领;SO_PEERCRED 只认 uid 0/1000;codex env
白名单);syncd=常驻循环只调 chv-sync pull/push,规则一条
不改(先 pull --ff-only 再 push,分叉即停、不 --force、
不 rebase;仓不存在记 needs-boot 不擅自 clone)。
host.py 仍是唯一任务/codex 引擎,broker/browser/cell 分工
不变,不另起第二套 agent。
- 阶段 1 遗留修复:restore_vm 失败路径 stop_vm(keep_disk=True),
seed.iso 与任务盘都留,重试有输入;vm.boot/restore 的 tap
触点遇 Resource busy 等 tap 空闲后重试一次(_wait_tap_idle
看 ip link state,_ch_remote 报错带 stderr 尾巴以便识别);
诊断不用 pgrep -x(15 字符上限)。
- 单测 cloud/tests/test_chv_opt_stage2.py 25 项;P2 干跑夹具
与 enable 行断言随构建接线更新。
- 全量 cloud/tests 2001 全过(skipped=8)。
2026-11-08 09:45:00 +00:00
host
a5f836e9fd
feat(chv-guest): 阶段 1 数据盘独立持久(客内挂载)
...
- 新增 chv-guest/chv-data-mount.sh:按 LABEL=CHVDATA 找盘
(不依赖 /dev/vd? 固定名;seed ISO 与根盘排除),无 fs
即 mkfs.ext4 -L CHVDATA,挂到 /home/chv/workspace,幂等;
无数据盘即静默退出 0(copy 模式旧 VM 不报错)。
- build.sh:缺脚本即失败(与 chv-sync.sh 同款门);拷入
镜像 /usr/local/bin/chv-data-mount;99-chv-sync.cfg
runcmd 在 chv-sync boot 之前调它(工作区先挂好再 clone)。
- buildinfo.py BASE_CONTENTS 与两 lockfile DECLARED_SOURCES
登记 chv-data-mount(repo_commit,随 P2 三脚本先例)。
- tests:test_chv_opt_stage1.DataMountScriptTest(脚本内容、
构建接线、lockfile 登记);P2 干跑夹具补新文件。
回归:discover test_chv_*.py 与 test_cloud_hypervisor.py 全过。
不推、不合、不部署;只本地分支。
2026-11-08 09:45:00 +00:00
host
c904ae9358
carry-over: 在途 V-9 根因修复 + Muse P2 对齐原样带入(未改一行业务逻辑)
...
来源:feat-chv-muse-p2 @ c918d69 的 6 个未提交文件(+157/-29):
build.sh(GT 哈希轮换 + 99-chv-sync.cfg runcmd chown)、
check_lockfile.py / generate_lockfile.py(DECLARED_SOURCES 加
chv-cell/chv-broker/chv-browser)、executor.py(_wait_guest_env_usable)、
hostkeys.py(guest-env owner 恒 root:root)、test_chv_v3_fixes.py。
单测:python3 -m unittest cloud.tests.test_chv_v3_fixes 38/38 通过。
本提交只搬运,不含阶段 1 改动;阶段 1 另起提交。
2026-11-08 09:45:00 +00:00
host
65504ae8cb
fix(chv): V-3/F1/F2 真机缺陷修复 + V-1/V-4 附带修复
...
V-3 快照/restore:
- snapshot 改传裸 URL(source_url= 是 restore 的键,服务端
Could not extract path from URL);快照产物是目录,校验
改为目录非空,登记计量/剪枝同步支持目录
- restore 起 VMM 前补 _restore_prepare:杀旧 VMM(登记的 +
未登记跨实例扫描)并清旧 socket,与 _wake_prepare 对等
- hibernate 评估结论:快照 config.json 引用原盘,旧 stop 删
盘致 restore 必失败;hibernate 的 stop 改 keep_disk=True,
GC 不删有登记快照的 VM 的盘,restore 前预检快照引用的盘
(snapshot_disk_missing fail-fast)
F1:re-wake 删旧盘——H5 删私钥致 re-wake 必然生成新 key 对,
旧盘复用时 cloud-init 不重应用新 seed,sshd 仍呈旧 key 而
known_hosts 钉新 key;wake 本就是冷启动,旧盘不是要保留的状态
F2:stop_vm 跨实例按 socket 进程扫描杀未登记 VMM
(/proc cmdline 精确 socket + VMM 二进制名 + 跳过自身/pid 1,
绝不误杀 ch-remote 与他人 VMM)
V-4:remote_command source 失败改 || exit 126 fail-fast;
guest-env 条目 owner 改归 SSH 用户(0600 不变),root 仍 root:root
V-1 附带:build.sh 预建 /app/work(1777 粘滞位 + stat 断言);
host.py default_codex_bin() 改 shutil.which,裸名不再让
health 报 ok:false
测试:新 test_chv_v3_fixes.py 23 项;旧快照测试按目录产物改写;
test_chv* 458 全过,全量 cloud 套件 1930 全过(skipped=8)
2026-11-08 09:45:00 +00:00
host
ef206cf554
feat(chv-guest): 对齐 Muse P2——nspawn 单元 + broker + 浏览器子代理
...
- chv-cell:systemd-nspawn 单命令单元,--private-users=1000:65536
(单元 root → 客机 chv),丢 8 项能力(含 SYS_PTRACE/NET_ADMIN),
syscall 过滤扣 io_uring,遮蔽 /etc/chv 与 playwright,
--network-veth(10.200.0.0/24 + NAT),白名单环境透传
- chv-broker:Unix socket + SO_PEERCRED(uid 范围 + pid ns 对照),
白名单 ping/sync/browser;sync 只调 chv-sync(runuser -u chv)
- chv-browser:单元外独立进程,只暴露 open/snapshot/screenshot/
close/ping,返回无障碍树快照(截断);evaluate/content 拒绝
- build.sh:装 systemd-container/iproute2/iptables,拷入三脚本,
建 chv-browser 用户与两个 systemd 单元;vsock_notify 条件拷入
- buildinfo:内容项加 P2 四项,支持可选 extra_contents
- 测试:cloud/tests/test_chv_muse_p2.py 40 项全过;broker/browser
真实 socket 回路冒烟通过(root 连 broker 被拒)
- 差距表:docs/chv-muse-p2-gap.md;真机验证待测试机空闲(round 11)
本地做,不推、不合、不部署
2026-11-08 09:44:59 +00:00
host
fb609acb50
feat(chv-guest): M4 Chromium 单独钉死 + /app 收紧为最小集
...
- Chromium 钉死:CHROMIUM_HEADLESS_SHELL_REV(纯数字修订号)
设即钉死,buildinfo.py 校验读回的 ms-playwright 缓存目录名
须恰好是该修订号,否则构建失败;generate/check 的 --verify
也复核;未设时只记录、构建输出明说未钉死,BUILDINFO 记 null
- /app 最小集:build.sh 不再把整个 $REPO_DIR/cloud/ 拷进客机,
只拷 host.py(只用标准库,不依赖 cloud/);REPO_DIR 预检
不再要求 cloud/ 存在
- generate_lockfile.py 只读 BUILDINFO.versions 一事已在 to10 轨
改写,本棒以合成 BUILDINFO 干跑复核(假版本 9.9.9 进 lockfile,
宿主 git 1:2.43.0 未混入)并补钉死复核;真实 lockfile 产出
仍待 V-9 真机构建,不编造版本号
2026-11-08 09:44:59 +00:00
host
af64f31138
feat(chv-guest): seed 附加项供客机用户与静态网络(wake 路径前置)
...
wake_vm 在 WSL 台架上跑通需要客机身份与网络:镜像本身不建
用户、tap 无 DHCP,缺 users 块的 VM 登不进去、缺 network-config
的 VM 拿不到静态 IP。最小补法(复用 write_seed 机制):
- hostkeys.write_seed 新增 user_data_extra(原样追加进
user-data,供 users: 块)与 network_config(写 seed
network-config 文件,0600);附加项含 runcmd: 即 ValueError
- config _seed_fragment:CHV_SEED_USER_DATA_EXTRA_FILE /
CHV_SEED_NETWORK_CONFIG_FILE(只存路径)
- executor._seed_extras 在 wake 起 VMM 前读入,缺失即
ChvFailure seed_extra_missing;provision_host_key 透传
- README §7 残留更新:guest-env 集成已做
- 测试:test_chv_gitea_sync 新增 5 项(写盘/禁 runcmd/
配置映射/wake 带附加项/缺失 fail-closed)
2026-11-08 09:44:59 +00:00
host
706fe88f46
fix(chv-guest): seed user-data 不再自带 runcmd,防顶掉镜像钩子
...
sync-test 首轮实测:seed 的 runcmd 整体替换了镜像
/etc/cloud/cloud.cfg.d/99-chv-sync.cfg 的 runcmd(cloud-init
不跨配置类型合并,merge_how 救不了 conf.d),chv-sync
boot 钩子静默不跑、启动 clone 没跑。
- hostkeys.build_seed_user_data 不再发 runcmd;chmod 600
已由 write_files 0600 保证;sshd 重启搬到镜像自己的
runcmd(cloud-final,sshd 首次启动之后)。
- build.sh:99-chv-sync.cfg 的 runcmd 增加 restart ssh
一行(在 chv-sync boot 之前)。
- README §5 同步硬性要求;回归测试 2 项(无 runcmd、
带 secret 仍单 write_files 列表无 runcmd)。
- 针对性 147 项全过(test_chv_to10/gaps/secfix/fix/
arch95plus)。
本地提交,未推未部署。
2026-11-08 09:44:59 +00:00
host
e8cf356616
fix(chv-guest): 首启缺 key 时才生成 host key(B-23)
...
Minimal 底座 cloud.cfg 不含 ssh 模块,build.sh 又写
ssh_genkeytypes: [] 彻底关掉首启生成:客机无 host key、
sshd -t 失败、ssh.service 连败 5 次,SSH 全程不通(真机
冒烟 131s 未通,console 已到 login、ping 通、tap 正常)。
修正:99-chv-hostkey.cfg 改写首启 bootcmd,只在缺
ed25519 key 时 ssh-keygen -A;ssh_deletekeys: false 保留,
绝不重生成已预置的 per-VM key(bootcmd 跑在 seed
write_files 之前,预置 key 随后覆盖生成值)。README §5
同步修正;新增 BuildScriptTest 回归断言。
2026-11-08 09:44:59 +00:00
host
39c76c2e43
fix(chv-guest): 浏览器装系统路径(B-22)
...
Round 7 构建本身成功,但 BUILDINFO.versions.chromium 为空:
virt-customize 的客机 shell 里 HOME=/,Playwright 默认缓存
~/.cache/ms-playwright 落到根目录 /.cache(实测浏览器在
/.cache/ms-playwright/chromium_headless_shell-1248),而
build.sh 读的是 /root/.cache/ms-playwright(不存在),ls 读回
空文件;buildinfo.py 当时不校验 chromium 非空,静默放过,
事后 check_lockfile / generate --verify 兜底报未覆盖(exit 1)。
改:安装与读回都走 PLAYWRIGHT_BROWSERS_PATH=
/usr/local/share/ms-playwright(agent 运行时也须设同一变量,
否则 chv 用户在家目录找不到浏览器);buildinfo.py 加
playwright_browsers_path 字段,并校验 playwright=1 时
versions.chromium 非空;README 同步。
2026-11-08 09:44:59 +00:00
host
c94bb02881
fix(chv-guest): apt 用 --no-install-recommends(B-21)
...
Round 6 真机构建在 Playwright 步 ENOSPC 失败:--install 默认装
Recommends,python3-pip 连带拉入 python3-dev → gcc/g++/
build-essential 全套,根分区 2.4G 用到 2.2G(95M 空闲),
headless-shell 下到 70% 写满。改走 --run-command apt-get
install --no-install-recommends,必需项显式列出(fontconfig、
openssh-client),两轮 apt 后 apt-get clean + 清 lists 收尾。
buildinfo contents 与 README 同步加 openssh-client/fontconfig。
2026-11-08 09:44:59 +00:00
host
7900b4b7b4
fix(chv-guest): gt 用绝对路径调用(B-20)
...
Round 5 真机构建在 gt 安装步失败:install.sh 已装好
/usr/local/bin/gt,但 virt-customize 的客机 sh 里 PATH 不含
/usr/local/bin,同一 --run-command 链里的 gt version 报
command not found,整个 virt-customize 退出非 0。
改两处为 /usr/local/bin/gt version(安装断言 + 版本读回文件)。
install.sh 自身的 SHA256 校验与二进制下载均已通过,不是下载问题。
2026-11-08 09:44:59 +00:00
host
7674f7396b
feat(chv-guest): 轻量镜像 + Gitea 双向同步(停全量版,改 Ubuntu Minimal)
...
- build.sh 改轻量:Ubuntu Minimal 底座、apt 精简(git/ssh/cloud-init/
python3/pip/curl/ca-certificates/xz-utils/fonts-wqy-microhei)、
Playwright + chromium-headless-shell、去 B-16 +12G 扩盘;
加 git + gt 1.0.0(官方 install.sh + SHA256 校验,GITEA_CLI_VERSION
钉 1.0.0)与 chv-sync 启动钩子(cloud-init runcmd)
- B-19(新发现):dpkg freeze 的 ${Package} 会被客机 shell 展开
成空,284 行全空白;加反斜杠转义,探针实测已出真实版本
- buildinfo.py:轻量 contents、chromium-headless-shell、gt_version
- generate/check_lockfile.py:gt/chv-sync 声明来源、headless-shell 映射
- chv-sync.sh(新):boot/pull/push/status,分叉/脏树失败关闭,
凭证走 seed 盘 guest-env,不进镜像
- README §1/§2/§3/§4 改轻量口径,新增 §7 Gitea 双向同步
- tests:ChvSyncTest 6 项(本地 bare 仓当远端);针对性测试 144 项全过
2026-11-08 09:44:59 +00:00
host
b83c5b2d8d
fix(chv-guest): B-18 virt-get-kernel -o 是目录不是文件
...
- 第三轮真机构建:virt-customize 全程通过(Playwright 步已过),
随后 virt-get-kernel -a disk.raw -o $OUT/vmlinux 失败;手动
查 --help 确认 -o 是 output directory——旧写法会在 OUT 里
建出 vmlinux 目录,后面的 test -s 文件校验必然失败,即使
下载成功构建也会失败。
- 修复:-o 改为 $OUT,下载 vmlinuz-<ver> 与 initrd.img-<ver>
后把 vmlinuz-* 移为 vmlinux 文件;initrd.img-* 留在 OUT 里
作配套产物(与任务产物清单一致)。
- 同轮里 virt-get-kernel 首跑另报过一次 "file receive
cancelled by daemon",同一盘手动重跑即成功(瞬时故障),
此处失败重跑一次,与 B-05/B-06 重试口径一致。
2026-11-08 09:44:59 +00:00
host
e656f63e6d
fix(chv-guest): B-17 Playwright 安装加 --break-system-packages
...
- 第二轮真机构建实测:单次 virt-customize 在 playwright 步
失败,pip3 install --no-cache-dir playwright 在 Ubuntu 24.04
上报 PEP 668 externally-managed-environment 而拒绝安装;
随后 python3 -m playwright 报 No module named playwright。
此前 PLAYWRIGHT 默认 0,该步从未在默认构建里跑过,缺口
被默认开启暴露出来。
- 修复:playwright 的 pip 安装与第一处 pip 安装同款口径
(--break-system-packages,失败回落无 flag 再试),且只有
pip 成功才跑 python3 -m playwright install --with-deps
chromium(括号分组 + &&,失败即停,不再以 ; 带病续跑)。
- 第二轮中间证据:B-10 步已过(sshd -t 完成、99-chv.conf 与
cloud-init hostkey 配置已写入、客机 /etc/ssh 无残留 host
key;dpkg/pip freeze 已写 876/92 行)。
2026-11-08 09:44:59 +00:00
host
018bcda046
fix(chv-guest): B-16 真机构建扩根分区(云镜像根分区仅 2.4G 会写满)
...
- 首轮真机构建实测:单次 virt-customize 在 playwright
--with-deps 装 g++/make 时报 No space left on device,
根分区 /dev/sda1 仅 2.4G、已用 97%。
- 修复:qemu-img resize +12G 后 sgdisk 只扩 1 号分区
(起始扇区实测取,不写死;14/15/16 不动),再 guestfish
resize2fs;实测根分区 2.4G→14G、可用 12G、编号仍为 sda1。
- 不用 virt-resize:实测它重写分区表、把根分区从 1 号重编号
为 4 号,而执行器默认 cmdline 是 root=/dev/vda1,重编号后
无法启动。工具检查清单加 sgdisk、guestfish。
2026-11-08 09:44:59 +00:00
host
3b5dd7a473
test(chv-guest): 构建脚本测试夹具跟进 B-09 新契约
...
- 假 codex 二进制须报出版本号(codex --version 核对)
- 假仓库改为真 git 仓库,REPO_COMMIT 取其实测短 hash
(旧 test123 非 hex,B-03 格式校验本应拒绝)
- 干跑行补 BUILDINFO.json 字样(断言依赖)
另:79ba56b(并行轨)已把 Playwright 改默认开启、单次
virt-customize、补 fonts-noto-cjk,本提交只补测试与干跑
文案,不动构建逻辑
2026-11-08 09:44:59 +00:00
host
b8d68bd94c
feat(chv-guest): Playwright 默认开启、单次 virt-customize、补 fonts-noto-cjk
...
- virt-customize 3 次调用合并为 1 次(VC_ARGS 数组按序执行;
PLAYWRIGHT=0 时仍可显式关掉,freeze 步骤保留兜底)。
- PLAYWRIGHT 默认 0→1:浏览器常驻复用;最终 freeze 在
Playwright 安装之后(B-08),BUILDINFO.versions.pip 含
playwright,chromium 目录名照常记录。
- apt 清单加 fonts-noto-cjk(浏览器 CJK 渲染字体,不是 LaTeX;
xelatex 仍不装)。
- 针对性测试:to10+gaps+secfix 94 项,91 过;3 项失败为
7f18c2d 已有 fixture 陈旧(REPO_COMMIT=test123 非 hex),
与本次改动无关,改前改后一致。
2026-11-08 09:44:59 +00:00
host
bfc1010a24
fix(chv-guest): 客机镜像构建缺口补齐(B-02/B-03/B-04/B-05/B-06/B-07/B-08/B-09/B-10/B-13/B-15)
...
- B-10(实测):virt-customize chroot 里 sshd -t 必败,双因:
无 host key(exit 1)+ 缺 /run/sshd(exit 255);修为
mkdir -p /run/sshd + ssh-keygen -A 临时生成,断言通过后
立删临时 key,镜像仍不带 host key(已在 WSL 真机预演验证)
- B-08:Playwright 装在第二次定制,须重写 pip freeze 否则
BUILDINFO 里无 playwright;Chromium 以 ms-playwright 缓存
目录名记录进 guest-versions-chromium.txt
- B-09:codex --version 须含 CODEX_VERSION;REPO_COMMIT 须
等于 HEAD 短 hash;工作树脏即拒绝构建
- B-02/B-13:BUILDINFO 生成抽成 buildinfo.py(可单元测试),
补 disk.raw/vmlinux sha256+大小、ubuntu 镜像 sha、cmdline、
playwright 开关、image_sha256 字段
- generate_lockfile.py 改写:版本唯一来源改为
BUILDINFO.versions(客机读回),codex 三件套取
codex_version、/app/host.py 取 repo_commit、chromium 取
versions.chromium;不再查构建宿主 dpkg/pip(旧方法不成立)
- check_lockfile.py 补强:条目格式、contents 全覆盖、冻结
清单双向比对
- B-03/B-04 输入格式校验、B-05 curl 重试、B-06 哈希不符
删文件重下、B-07 磁盘预检、B-15 set -euo pipefail
- 同步改 test_chv_to10.py:generate 不再查宿主,改断言客机
版本来源 + 不回落宿主
2026-11-08 09:44:59 +00:00
host
f42c1f2b9b
feat-chv-to10:往 10 分方向提升(类型/lint 清零、worker 适配抽取、审计落盘、lockfile 生成脚本、前端四态与统一文案、就绪清单 §13)
2026-11-08 09:44:59 +00:00
host
56a6241bbe
feat(chv): 架构与代码质量 9.5+ 提升——长函数清零、WarmPool facade、#215 对齐、审计计数、只读 VM 字段、ADR-8~11
2026-11-08 09:43:59 +00:00
host
6a74d0182c
feat(chv): 安全审计修复 High/Medium/Low(堆叠于 #239)
...
审计报告 ~/workspace/chv-security-audit/REPORT.md(No-Go,
Critical 0 / High 7 / Medium 8 / Low 5)代码层修复,mock
测试覆盖,真机动态验证一律未做、只列清单(见
docs/chv-production-readiness.md §11)。
High:
- H1 egress 代码门:代理地址校验、直连显式允许+审计、
每 VM 独立 tap/mac/ip 校验、net 字段白名单;宿主防火墙
列为部署清单,代码门+防火墙缺一不可。
- H2 网关 key 移出 argv:provisioned seed 盘客内文件
/etc/chv/guest-env(0600)投递,传输层密钥进 argv 直接
ValueError;keyscan 模式密钥投递 fail-closed。
- H3 任务盘删除:stop/recycle/cleanup 删 disk.raw(保留期
0)+ 残留盘 GC,删失败审计+脏标记。
- H4 默认值改 provisioned:keyscan 只作显式 opt-in。
- H5 seed.iso 生成即 0600;宿主私钥 seed 盘建好后即删;
崩溃残留扫描 cleanup_stale_secrets。
- H6 state_dir 默认出 /tmp(~/.local/share/.../chv-vms,
preflight 保 0700);api-socket 组/其它可写即 fail-fast。
- H7 tap 隔离校验:net.json 登记+stop 释放,共享即拒绝审计。
Medium:M1 shlex 远程转义;M2 清理失败即拒起(脏标记);
M3 配额默认 50GB + 快照数/总量/保留期上限;M4 SHA256 必填
+ BUILDINFO versions 实测记录(事前 lockfile 列清单);
M5 host key/ preflight/失败审计补齐;M6 reuse 须声明单租户
项目;M7 容量计数只认连通 socket;M8 sshd 加固进 build.sh
断言。Low:L1 链接不跟随;L2 路径白名单;L3 失败审计;
L4 双变量警告+字段白名单;L5 预热盘/任务盘对应关系定义。
旧测试:实验室默认值与生产默认值区分标注;行为已变的旧
测试按新语义更新(容量死 socket、快照白名单、磁盘路径
白名单、网关 argv、reuse 租户声明)。
测试:新 test_chv_secfix 39 项;旧 117 项 + 2 项新增断言 =
158 项;worker 相关 129 项;前端 vitest 9 项;cloud 全量
1588 项(skipped 4)。
2026-11-08 09:43:17 +00:00
host
7320d693ba
feat: CHV 审核修复 P2(范围恢复为全做)
...
P2-1:preflight reuse/CPU/内存校验块小提取为
_preflight_config_checks(纯移动,深耦合处如实停)。
P2-2:build_vm_command 降级为私有 _build_vm_command;
Docker goal 内联解析顶部加正典分叉说明 + 同步检查清单。
P2-3:gaps grep 文本断言改成真实 Worker._run_attempt
行为断言。P2-4:README/build.sh 口径对齐(章节顺序、
BUILDINFO 名字列表、Node.js 不装写实)。P2-5:stop_vm
删除失败记审计。P2-6:CPU/内存校验统一进 preflight。
测试:原 84 + 新增 33 = 117 项,mock,无真 VM。
2026-11-08 09:40:32 +00:00
host
f8f2034265
feat: CHV gap fill — worker breakpoint wiring, pool reconcile, per-VM host keys, egress validation, guest build script
...
Stack: #216 -> #221 -> this. Worker breakpoint branch now calls any
executor providing goal_resume_breakpoint_task (Local keeps its
original path, gateway tasks still loud-fail); WarmPool
reconcile_orphans is called on CHV worker startup and close with
audit-on-failure; per-VM SSH host keys are provisioned before VMM
start via cloud-init NoCloud seed (keyscan kept only as weak
fallback, CHV_HOST_KEY_MODE=provisioned|keyscan); CHV_NET_JSON is
validated in preflight and explicit direct egress is audited;
chv-guest/build.sh is now real steps with --dry-run and fails fast
without /dev/kvm. Tests: new test_chv_gaps.py (18), cloud full
1514 OK (skipped=4). No real VM verification: no KVM host.
2026-11-08 09:40:09 +00:00
host
250c511bce
feat: Cloud Hypervisor 执行器生产级 v1(cloud-hypervisor)
...
单任务单 VM:API 唤醒(preflight→vmm.ping→vm.create→vm.boot→SSH 就绪)、
暂停/快照/休眠等价/关闭/回收、预热快照池、每任务磁盘 copy、容量与磁盘配额门、
受控 egress fail-closed、VM 事件审计与分类失败;worker/server/autoscaler 接线
(executor=cloud-hypervisor,任务内 LLM 不可自选);默认关闭,不进生产路由。
未做真实 VM 验证:生产主机与本 VM 均无 /dev/kvm、无嵌套虚拟化,验证为 mock +
干跑命令 + 单元测试;真 VM、快照恢复、压测、安全审计见
docs/chv-production-readiness.md。CI 账单故障仍是硬门禁,本提交只到 PR OPEN。
2026-11-08 09:39:12 +00:00