chv
29d3a5a474
feat(chv-muse-round11): build.sh 补 P3 authd 进镜像 + gt 脚本哈希轮换
...
- authd 三件套 copy-in(chv-guest/authd.py 与 git-credential-chv-authd
-> /usr/local/bin/ 并 chmod +x,chv-authd.service ->
/etc/systemd/system/),云端叶子模块 cloud/chv/authd.py 与
sentinel.py + 两个 __init__.py -> /usr/local/lib/chv-authd/,
systemctl enable chv-authd;99-chv-sync.cfg runcmd 在 chv-sync
boot 之前加 systemctl start chv-authd;缺件即 fail-fast
- buildinfo BASE_CONTENTS 登记新增件;P2 干跑夹具补 P3 文件并断言
authd 步骤出现在干跑输出里
- GT_INSTALL_SH_SHA256 cf82... -> 49ffe090...:上游 2026-11-07
06:44 轮换,V-9 已核实(WSL fresh curl 与失败镜像内残留逐字节
一致;新脚本全文已读,只从 dl.gitea.com 取 1.0.0 二进制并验 hash)
- vsock_notify 条件拷入在合入后生效(cloud/chv/guest/vsock_notify.py
已在仓里,干跑不再报缺失警告)
- 定向单测 P1/P2/P3/chv_fix 172 项全过;全量套件仍在跑
2026-11-06 23:08:40 +00:00
host
73176e135c
feat(chv-muse-round11): 执行器接 nspawn 单元(P2 差距表 §4)
...
客内 host.py 调用改为 chv-cell run -- python3 /app/host.py
--state /home/chv/.codex/host-state.json --codex-home
/home/chv/.codex --sandbox danger-full-access …,其余原参数
原样保留。--sandbox 放全局参数最后(argparse 后胜出),
单元内恒为 danger-full-access,调用方 read-only 不得盖回
bwrap;非单元路径(本地/Docker/冷启动回落)不动。
开关 CHV_CELL_ENABLED:只认 0/1,默认 1 开;非法值
ValueError(_to_switch 同款口径)。关时走原命令,给
lite10 及更早无单元的旧镜像留逃生口。
测试:新 test_chv_muse_round11_cell.py 7 项(开/关 argv、
原参数保留、sandbox 只在单元路径、非法值报错、SSH 层
接线);test_host_command_options_identical_across_executors
显式关单元测三执行器参数全等,断言本身未动。
全量 cloud 套件 2011 OK(skipped=8)。
2026-11-06 21:58:01 +00:00
host
304707b372
merge(chv-muse-round11): 合入 P3 authd 替身凭证 + Sentinel 出口审批 ( a90cf78)
...
冲突解决(3 处,均为并集保留,双方改动无一丢弃):
- cloud/chv/executor.py _copy_config_fields:P1 的 balloon/
vsock/vsock_cid 与 P3 的 sentinel_allow_hosts 合并进同一元组
- cloud/tests/test_chv_arch_maint_fe.py EXPECTED_FIELDS:P1 三字段
+ P3 sentinel_allow_hosts;len 断言 41/39 → 42(并集)
- cloud/chv/config.py 自动合入:P3 sentinel_allow_hosts(网络
片段内)+ P1 _balloon_vsock_fragment 均保留;仅更新
build_chv_config docstring 注明字段集含 P3 字段
2026-11-06 21:36:56 +00:00
host
3209f59cd6
merge(chv-muse-round11): 合入 P2 nspawn 单元 + broker + 浏览器子代理 ( c61484a)
2026-11-06 21:35:53 +00:00
host
55f6d7ad6c
merge(chv-muse-round11): 合入 P1 常驻 VM + 气球 + vsock ( 78098c5)
2026-11-06 21:35:51 +00:00
host
78098c5594
feat(chv-muse-p1): 常驻 VM + WarmPool 扶正 + 气球 + vsock,对齐 Muse
...
每用户一台常驻 VM(暂停态,resume 到 SSH 5 秒内为待验证目标),
池空/失败回落冷启动;CHV 配置加 virtio-balloon + free-page-reporting
与 vsock notify 最小实现(SSH 仍是命令通道与就绪判定)。
新模块 resident_pool.py / vsock.py + 客内 vsock_notify.py;
_config 增加 CHV_RESIDENT_IDLE_MINUTES / CHV_BALLOON / CHV_VSOCK;
worker_adapter 接常驻孤儿清理 facade;ADR-17 差距表见
docs/chv-muse-p1-gap.md。
恢复收尾(分离后回归,见 gap.md §4):VmDeathTest 死亡模拟改杀
实际跑命令的 VM;两处冷路径旧测试显式关常驻;_balloon_vsock_payload
与 listen_notify 拆到 50 行内;resident_pool.py:208 mypy 修掉。
executor.py out 未注解与 marker_tools.py:142 是基线旧错,未动。
测试:全量 cloud 套件 1934 OK(skipped=8);mypy 在改动文件上
干净(仅基线旧错 4 处)。真机验证待第三棒让出 WSL 测试机。
2026-11-06 21:31:48 +00:00
host
a90cf78d84
feat(chv): 对齐 Muse P3 收尾——authd 替身凭证 + Sentinel 出口审批
...
- 新测试 cloud/tests/test_chv_muse_p3.py 30 项:替身过期、真 token
泄露面、SSRF 挡截、deny/ask 路径、authd-seed 拆分、wake 预审、
客内 authd 守护进程、git credential helper 端到端(真 git fill)
- 8 个旧测试按新 authd 行为改写(未删测试、未放宽断言):
GITEA_TOKEN 改走 authd-seed,build_ssh_command 不再 source 进
codex 环境;wake 测试补 Sentinel 白名单 + 假解析器
- 7 处超 50 行函数拆到 50 行内(不改行为);补 authd/sentinel
公共 API 注解,mypy 在改动文件上干净
- 真问题修复:git 默认不把 path 发给 helper,chv-sync boot 加
credential.useHttpPath=true,否则 authd 路径每次都拒绝
- 全量 cloud 套件 1897 项 OK(skipped=8)
真机待验证(未做,等第三棒让出 WSL 测试机):见
docs/chv-muse-p3-gap.md §3.6 清单
2026-11-06 21:21:55 +00:00
host
c61484aa68
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-06 20:53:15 +00:00
host
06c3e172fe
fix(chv): restore 路径补 H7 net 校验+登记,seed 暂存文件走 atomic_file
...
restore_vm 此前既不校验 net 冲突、也不登记 net.json:
已登记 VM 的 tap/mac/ip 会被恢复出的 VM 静默复用,且
恢复出的 VM 自身不登记、后来的 wake 也看不到它,两边
都漏判。现与 wake 同款:_validate_restore 在起 VMM 前
校验冲突(net_tap_conflict + vm_failed 审计),
_restore_boot 在 restore 成功后登记 net.json,登记失败
审计 net_registry_write_failed + 拒绝恢复(P2-19 语义,
stop_vm 清半恢复 VM)。
hostkeys.write_seed/_apply_seed_extras 的 meta-data、
user-data、network-config 改走 atomic_file(mkstemp 0600
→ 写 → fsync → rename):user-data 含 host 私钥明文,
直接写 + 事后 chmod 会在 chmod 前以 umask 权限短暂可读;
半截文件本身到不了 ISO(唯一消费者 genisoimage 只在
write_seed 返回后跑),原子写同时堵住权限窗口与半截残留。
回归测试 6 个:restore 冲突拒起/恢复后登记/登记失败
拒起/无 net_json 不登记;seed 走原子写(0600、无 tmp
残留)/写失败不留半截文件。CHV 全套件 395 测试通过。
2026-11-06 19:32:41 +00:00
host
f448ecb74b
docs(chv): L4/M6 取舍定案 + 部署核对清单
...
- L4:保持警告不改硬拒(CHV_NET 是手动直接启动命令透传值,
与 API 的 CHV_NET_JSON 是两条路径;硬拒会断手动运维,
误配代价只是 API 模式忽略 CHV_NET);写清兼容影响与
将来改硬拒的前置条件;部署核对只设 CHV_NET_JSON
- M6:确认声明 + 审计就是本项机制,不假装已校验;部署核对
加人工项(部署记录写明已核对租户数 = 1 与项目名一致,
并复核 disk_reuse_experiment_allowed 审计)
- §11.4 加环境变量核对与残留尾巴审计抽查项
(net_registry_write_failed / dirty_marker_write_failed /
vm_net_registry_delete_failed 任一出现即先修宿主再启用)
2026-11-06 18:41:56 +00:00
host
2ad29eeb1f
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-06 18:41:56 +00:00
host
c39715659e
fix(chv): P2-20/P2-19/P2-17/P2-18 残留收尾 + NO_PROXY 合并
...
- P2-20:_guest_env_delivered 加专用锁,读写只走
_delivered_secrets/_mark/_clear 三个入口,并发 hammer 测试钉死
- P2-19:_record_net_entries 失败发 net_registry_write_failed
独立审计并返回 False;_boot_vm 见 False 即拒起(wake 随后清半醒 VM)
- P2-17:net.json 删失败发 vm_net_registry_delete_failed 审计;
_write_dirty_marker 失败发 dirty_marker_write_failed 审计并返回
False,stop 不抛的契约不变
- P2-18:新增 cloud/chv/atomic_file.py(mkstemp 随机名 + 文件
fsync + rename + 目录 fsync),net.json/known_hosts/
snapshots.json/pool registry/脏标记/spill 全部走它,固定 .tmp 清零
- H1 附带:NO_PROXY 实测确有覆盖 bug(env 重复赋值以后者为准,
调用方 NO_PROXY 被 egress 的 localhost 值静默覆盖),改为合并
单条发出;egress 已设时调用方代理变量(含小写)一律不发
- 测试:新增 cloud/tests/test_chv_residual.py(23 项),旧 closeup
两处钉死旧语义的测试按新语义更新
2026-11-06 18:41:50 +00:00
host
ba5df980bf
fix(chv): known_hosts 22 端口写裸 host 行,修 provisioned 钉死失效
...
OpenSSH 默认端口只查裸 host 名、非默认端口只查
'[host]:port':known_hosts_line 对 22 端口也写
'[192.168.10.10]:22',ssh 永远匹配不上,报 Host key
verification failed、wake fail-closed 关 VM。keyscan
TOFU 输出裸行,lite9 没暴露。非 22 端口仍用括号形式。
2026-11-06 17:59:53 +00:00
host
4f3a176771
fix(chv): CHV 54 VmConfig 形态——payload.kernel/cmdline 纯字符串 + 磁盘显式 image_type Raw
...
真机 CHV 54.0.0 实测:旧顶层 kernel:{path}/cmdline:{args}
create 时 204 照放、vm.boot 400 'No bootitem provided';
补 payload 后又报 'Image type required for disk'(raw 盘
无魔数、探测失败),磁盘须显式 image_type,枚举原名
Raw(JSON 写小写 raw 报 unknown variant)。
2026-11-06 17:59:53 +00:00
host
5b6514d019
fix(chv): api_client 接受 204 无 Content-Length 响应
...
WSL 真机实测(CHV 54.0.0):vm.create 成功回 204 No Content,
且不带 Content-Length、无体;严格校验(P1-6)把合法成功当
失败拒掉,wake_vm 卡在 vm.create。204/304 按 HTTP 语义体长
恒为 0,不要求长度、不读体(keep-alive 下读会等到超时);
其它状态仍严格(无长度/截断/chunked 均拒绝)。
测试:test_chv_cover100 新增 3 项(204 成功、200 无长度仍拒、
_parse_status)
2026-11-06 17:43:54 +00:00
host
d7cc482ed5
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-06 16:58:27 +00:00
host
e7f699c62b
feat(chv-guest): Gitea 同步变量经 seed 进 guest-env(执行器集成)
...
- 新增 cloud/chv/gitea_sync.py:6 键白名单,三源合并
(宿主 CHV_GITEA_* < 任务 gitea_sync < extra_env),
必填 4 键缺失即 fail-closed,空即不同步
- ssh_transport:GITEA_TOKEN 进密钥集(argv 拒绝),其余
5 键进 guest-env 集(split_guest_env)
- hostkeys.write_seed:guest_env 与 secret_env 合并写同一
条目,仍无 runcmd、0600
- config:_gitea_fragment 产 gitea_sync_env(函数内 import,
叶子模块顶层只许标准库)
- executor.wake_vm:起 VMM 前合并+校验(gitea_sync_incomplete),
guest-env 随 seed 投递;provision_host_key 透传 guest_env
- worker:_run_attempt 仅对 CHV 执行器把同步变量并进 gateway_env
- 测试:cloud/tests/test_chv_gitea_sync.py 20 项
- 边界:tasks 表无 JSON 列,DB 往返丢任务 gitea_sync;
生产主来源是宿主 CHV_GITEA_* 环境变量
2026-11-06 16:55:32 +00:00
host
67ca0b86cd
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-06 16:35:14 +00:00
host
cbd5ab7c0b
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-06 12:05:43 +00:00
host
dcb0824f78
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-06 10:55:02 +00:00
host
4c8e4eac7b
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-06 10:29:59 +00:00
host
5206dfbc43
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-06 10:09:02 +00:00
host
4d09518338
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-06 09:47:54 +00:00
host
9e60d5dfaa
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-06 09:01:20 +00:00
host
b5e75f156d
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-06 08:34:14 +00:00
host
368bccd16e
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-06 07:59:29 +00:00
host
3b41f864e8
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-06 15:34:06 +08:00
host
79ba56bd51
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-06 07:25:15 +00:00
host
7f18c2d13b
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-06 15:13:23 +08:00
host
8c8d62f70d
test(chv): 补齐 chv 模块剩余覆盖到 100%(生产与实验分开计分)
2026-11-01 07:00:21 +00:00
host
e718f0f326
test(chv): 修复 isWorkerAlive 边界测试抖动(精确边界改确定性字段测)
2026-11-01 00:44:12 +08:00
host
54f20dfe55
feat-chv-closeup:收尾(executor 覆盖到 100%、合并/灰度准备,堆叠于 #264)
...
- 后端新增 cloud/tests/test_chv_closeup.py 85 项:唤醒失败
(vm.create/vm.boot/API 超时/guest 就绪超时/host key 不匹配/
provisioned 缺钉死)、恢复与快照失败、取消与清理(残留
socket/登记/磁盘/密钥、脏标记)、中途死亡分类、只读
execute 归类、入口校验、preflight 事后改写、防御性
except、worker_adapter 剩余分支;executor.py 覆盖 100%。
- 前端新增 src/api/chv.closeup.test.ts 13 项:显式 false、
undefined、可用性优先级、Workers 旧 bug 文案不复发、
120 秒边界;控制按钮与新页面仍不做。
- 新增 tools/chv_merge_precheck.py(只读):逐个核 base/head/
mergeable/CI/链衔接,实测 11 个 PR 全 NOT-READY(CI 全
FAIL、mergeState 全 UNSTABLE),退出码 1,绝不合并。
- docs/chv-production-readiness.md 新增 §14:审计落盘运维
runbook(定位/轮转/读取/清理,ADR-14 取舍不变)、mypy
默认口径 2 错评估(沙箱验证过的标注修法,本轨不改
其它链文件)、灰度三阶段可执行清单、V-1~V-9 检查表
(全部未验证)、逐项评分。
- 安全语义不变:egress、key seed 投递、磁盘删除、默认
provisioned、tap 校验、前端不绕后端白名单均未放宽。
- 只到 PR OPEN,不合并、不部署;CI 账单仍是硬门禁。
2026-10-31 12:15:56 +00:00
host
2f3ff8b3ec
feat-chv-to10:往 10 分方向提升(类型/lint 清零、worker 适配抽取、审计落盘、lockfile 生成脚本、前端四态与统一文案、就绪清单 §13)
2026-10-31 10:20:42 +00:00
host
df8c64bd64
feat(chv): 架构/可维护性/前端只读侧推进——生产实验分离、配置片段化、VM 只读展示
...
架构:WarmPool 从 cloud/chv/pool.py 移到 experimental_pool.py,
生产残留清理彻底分文件到 cloud/chv/orphans.py(facade 直接读
registry 文件清理,不构造池、不碰 prewarm/acquire/release);
cloud/chv 与 cloud/sandbox 不再导出 WarmPool,旧路径一律
ImportError(CHV 未合并、无生产用户,兼容保留已无保留理由);
worker 改走 orphans facade,不再持有 _warm_pool;#215 对齐从
接口形状推进到 REPLACEMENT_POINTS 替换清单(R1/R2 可机械替换、
R3 永不替换,#215 模块当前不存在由测试钉住)。
可维护性:build_chv_config 拆成 base/ssh/network/quota/disk/
timeout 六片段(组装只做 dict 合并,键冲突即报错;38 字段集
与取值不变,单项非法报错文案逐字一致);ADR-12 模块职责图
与禁 import 清单(AST 钉住);cloud/chv/ 公开 API 全量类型
标注、无 Any 逃逸,并修正三处旧标注错误;死代码扫一遍
(删实验池已无调用的 _quarantine 委托与未用 _LOGGER)。
前端(只读侧,不做控制按钮):chv.ts 新增纯逻辑谓词与文案
(执行器精确匹配、附件守卫、VM 状态文案、列表徽标);列表
行新增 VM 已报告死亡徽标;详情对全部 CHV 任务显示 VM 行
(已报告死亡/未报告死亡,不猜 live);WorkersSection 与成本
卡沿用已有数据,不新开池管理/成本页;服务端未新增第二个
生命周期字段(持久化事实只有三项,chv_vm_dead 已是完整派生),
只把派生抽成 _chv_vm_dead_from_row 并补 goal 回落形态测试。
2026-10-31 06:55:26 +00:00
host
42de20da68
feat(chv): 架构与代码质量 9.5+ 提升——长函数清零、WarmPool facade、#215 对齐、审计计数、只读 VM 字段、ADR-8~11
2026-10-31 06:20:12 +00:00
host
c908a0147a
feat(chv): 架构与代码质量提升——WarmPool 定案、长函数提取、严格测试替身、Docker 同步守卫、配置统一校验、类型注解与 ADR
...
堆叠于 #246(feat-chv-secfix),只到 PR OPEN,未合并、未部署。
安全语义不变:egress、key seed 投递、磁盘删除、默认 provisioned、
tap 校验一律保留;前端零改动。
- WarmPool 定案为实验性(ADR-5):dispatch 永远冷启动,
wired_to_dispatch 恒 False,acquire/resume 只保留实验接口,
worker 仍调 reconcile_orphans 清理残留。
- 长函数提取:preflight 126→31、wake_vm 135→36、__init__ 69→31、
build_chv_config 159→58;错误文案逐字不变。
- 严格测试替身:fake API 校验 VmConfig(任务盘+seed 盘、net
无重复),fake SSH 校验 known_hosts 钉死;新增 5 项测试。
- Docker 同步守卫:8 个真实标记用例下 Docker 内联版与正典
parse_goal_result 状态全等,改分叉即 fail。
- 配置统一校验:preflight 以 config_invalid 统一兜底端口/配额/
超时/快照/host-key 模式(构造时已校验正常值,preflight 兜底
事后改写);CHV_NET 与 CHV_NET_JSON 双设仍警告不硬拒。
- 类型与 lint:chv 叶子模块公开 API 补类型注解;stdlib 扫描
揪出 executor 内 1 个真死 import(host_key_paths)并删除。
- ADR:docs/chv-architecture.md(ADR-1 至 ADR-7)。
测试:CHV 163 项全过;cloud 全量 1593 项三跑结果为 8 errors
(首跑详细日志因 tail 截断丢失)、全过、1 失败(浏览器代理
时序测试,与 CHV 无关),全量本身存在时序偶发,CHV 套件
确定性全过。
2026-10-31 05:50:56 +00:00
host
baf26beb78
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-10-31 03:02:10 +00:00
host
003ea357f9
feat(console): CHV production-grade frontend — worker availability, attachment guard, queue hint, build:console fix, vitest
2026-10-31 02:35:38 +00:00
host
036323e620
feat(console): CHV executor option in dispatch/env selectors + experimental note in detail/list
...
- DispatchSection: add cloud-hypervisor option (labelled experimental,
default off); default stays docker; hint states a KVM-host CHV worker
must claim the task (otherwise it stays queued; attachments are
rejected by the backend at creation) and that the frontend only passes
the executor value through, never bypassing the backend allowlist.
- EnvSection: same option, because the backend env-create allowlist
(local/docker/cloud-hypervisor) does allow it; note states env
allowlist excludes cloud.
- TaskListSection: add cloud-hypervisor to the executor filter so CHV
tasks are findable; list rows already showed executor.
- TaskDetailPanel: pure display note for cloud-hypervisor tasks
(experimental, default off, no VM controls); detail already showed
executor from the task API.
- README: document the CHV console entry, experimental marking, and
verbatim backend-error display.
- Rebuilt cloud/console.html from src (tsc + vite single-file build);
no backend change: executor is already returned by _task_to_dict.
2026-10-31 02:25:21 +00:00
host
445376743d
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-10-31 02:01:03 +00:00
host
9771ed9e8c
feat: CHV 审核修复(P0+P1,堆叠于 #230)
...
P0:seed 磁盘 CIDATA ISO 挂进 VmConfig 第二块只读盘;
restore provisioned 下复用钉死 known_hosts、缺失 fail-fast
绝不 keyscan;preflight 拦截 CHV_DISK_MODE=reuse(显式
实验二次确认 + 审计放行);SSH 目标选客机 IP 方案(显式
host > net 静态 ip > 显式转发宣称回环,三者皆无 fail-fast)。
P1:网关 extra_env 经 SSH env 前缀注入、worker 守卫收窄到
Local/CHV;取消/清理/看门狗接 CHV 通用路径;WarmPool
acquire 内 resume;容量门持久化计数;磁盘配额总量+余量
与已存在磁盘校验重拷;API 按 Content-Length 验完整性;
快照 file:// 验落盘再 shutdown;execute 死端口归类
vm_not_running。
P2 全部排除未做(用户范围收窄令,留待以后一轨)。
测试:原 84 + 新增 29 = 113 项,mock,无真 VM。
2026-10-31 01:54:13 +00:00
host
22b83f118a
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-10-31 01:30:52 +00:00
host
fde7bf4c3e
feat: CHV 执行器优化(拆模块/去重复/SSH 钉死/池持久化/中途死亡分类)
...
- 拆模块:CHV 从 cloud/sandbox.py 巨类拆到 cloud/chv/(executor/
pool/config/api_client/ssh_transport/disk/errors),sandbox 只留
兼容 re-export,旧导入路径与新路径是同一对象
- 去重复:goal 解析、host 顶层参数、runner 超时抽成共享 helper,
Local 与 CHV 在矩阵输入下结论全等(Docker goal-resume 变体
有意保留内联版,见 PR 描述)
- 安全:SSH host key 按 VM 钉死(state_dir/<vm>/known_hosts,
ssh-keyscan 首次捕获 TOFU),废除 no + /dev/null;CHV_SSH_USER
空串与 CHV_SSH_PORT 越界直接拒绝,不静默 fallback
- execute 语义:只读已运行 VM,未运行报 vm_not_running,不为
status 起 VM
- 预热池:registry 落盘、重启载入只当孤儿、reconcile 清理、
损坏 quarantine;条目仍一次性,绝不复用脏 VM
- 长任务:VM 中途死亡判 interrupted(断点可续跑);中途心跳
经评估不做(无客内进度信号可采)
- #215 未合并:只列复用清单,不复制模块
测试:原 42 项 + 新 24 项全过;相关旧套件与 cloud 全量 1496 项
全过(skipped=4)。验证仍是 mock + 干跑 + 单元测试,未做真机、
压测、安全审计;堆叠于 #216 之上,base 为 feat-cloud-hypervisor。
2026-10-30 19:45:33 +00:00
host
c371bbdf1e
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-10-30 18:54:16 +00:00
openqj
aebc6238a6
Merge pull request #201 from openqj/feat-platform-auto-resume
...
feat: auto-resume platform-interrupted non-goal tasks
2026-10-30 15:51:43 +08:00
host
4428a721a6
feat: auto-resume platform-interrupted non-goal tasks
...
Deploy restarts kill running tasks: the worker marks them
interrupted (worker_shutdown on graceful exit, sweep on stale
reclaim), and auto_resume_interrupted used to accept goal tasks
only, so every non-goal task killed by a deploy stayed
interrupted forever unless a human retried it (the 2026-10-30
demo task died this way).
Now worker_shutdown/sweep interruptions are re-queued for
non-goal tasks too: the platform killed the task, so the
platform re-queues it. The re-queue is a fresh run, not a
breakpoint resume: goal_resume_pending is forced to 0 and any
stale resume_message is cleared, so the new run cannot be
hijacked by the goal-resume path or an old continue message;
files in the same worktree persist. All existing guards stay:
user pause, coordinator orphans, quota (still goal-only),
backoff, the 3-strike stall guard (non-goal tasks have no
checkpoints, so each platform re-queue counts as no-progress),
and the auto_resume_max cap. Other non-goal reasons (NULL,
quota, user cancel) still do not auto-resume.
2026-10-30 15:39:55 +08:00
openqj
d6369154c2
Merge pull request #198 from openqj/feat-automation-edit
...
feat(console): automation panel edit and richer list
2026-10-30 15:38:59 +08:00
host
2d644f901b
feat(console): automation panel edit and richer list
...
- AutomationPanel rows now show title, prompt content (160-char preview with expand/collapse), repo_url, last/next run, run_once badge and cancelled time.
- Active automations get an inline edit form (name/prompt/interval/repo) that PATCHes only changed fields via the existing automation_update endpoint; backend semantics unchanged (no last_run_at reset, cancelled stays terminal).
- Rebuilt cloud/console.html with tsc + vite (build green); automation python tests 18/18 OK.
2026-10-30 15:31:21 +08:00
openqj
e2ce04ce4f
Merge pull request #197 from openqj/feat-stream-waiting
...
feat: browser stream waits through round gaps instead of disconnecting
2026-10-30 15:29:17 +08:00
openqj
92157ef421
Merge pull request #195 from openqj/feat-shared-home-mcp-sync
...
feat: sync shared-home MCP scripts on control-plane startup
2026-10-30 15:19:26 +08:00