- app_state.py: host_state_db_path() (host-level DB, distinct from per-VM state_db_path); kv_get/kv_put/kv_delete on meta (namespaced keys; kv_put skips the no-secrets guard by design — registry docs hold user prompts, documented); audit_trail table (P12 record shape + hash chain, seq explicit); counts()/backup() gain audit_trail. - swarm.py / presentation.py / browser_tasks.py: JSON-file backends replaced by KV rows (p8-swarm / p8-ledger / p8-browser-tasks); legacy JSON imported once on first load (renamed .migrated); corrupt row / unreadable store returns empty (fail-safe, same semantics as before; next successful save self-heals). - audit_trail.py: StoreAuditTrail (same record shape, hash chain, filters, export as JSONL version, backed by audit_trail table); migrate_jsonl_to_store() moves a chain verbatim (broken chain refused, divergent seq refused, re-run idempotent). JSONL class kept for reading old files. - P12 dict contracts now run against real P3/P5 code (ApprovalQueue.record -> build_approval_card -> card_matches_channel; CapabilityIssuer.issue -> describe -> PermissionRegistry.record_grant). - P6->P3 local protocol test: real PrivsepClient + real worker server + real git status; worker git argv carries the real P3 helper + useHttpPath; no token in argv/env/audit. runuser + HTTP pull stay real-machine-only (see gap docs). - Gap docs updated: P8 migration done, guest-side browser follow-up explicitly left for the real-machine track (no task_id in the browser protocol yet; lifecycle needs a real VM to verify); P6 wiring + P12 migration marked done; production-readiness.md gains §20 (round-12 integration). - Tests: new cloud/tests/test_chv_muse_round12.py, 24/24 OK; test_chv_muse_p8.py ledger corrupt test rewritten for the KV backend (+ legacy-import test). P7+P8: 95+1 tests OK.
9.4 KiB
对齐 Muse P8 差距表:后台工作(crons / 子代理群 / 回访通知 / 每任务浏览器子代理)
先写表再动手。口径分层:= Meta 安全文(security.muse.ai 2026-09-08)与产品 设计文(introducing.muse.ai)原文;= 媒体/评测转述;= 二进制拆解与用户 VM 观察。凡是 Meta 未公开的数值(cron 调度粒度、数量上限、失败重试 策略),一律写清是本项目自定,不得写成 Meta 官方值。
1. Muse 官方要求(出处:研究报告 §2.5)
| # | 要求 | 来源 |
|---|---|---|
| B1 | 关应用后继续工作;按计划与相关事件推进 | 设计文 |
| B2 | 完成后台工作后评估是否“值得呈现”,只在真正有新内容或需要输入时通知用户 | 设计文 |
| B3 | 启动成群的子代理、构建自己的工具、编辑自身;VM 需要足够存储、CPU 与内存来做真正的工作——如编译代理写的代码、开发自定义 Skills、处理并发子代理与 crons | 安全文 |
| B4 | 每个浏览器任务由专门浏览器子代理完成 | 安全文 |
| B5 | 定时任务(crons)与并发子代理并存 | 安全文(只提存在) |
| B6 | cron 的具体调度粒度、数量上限、失败重试策略 | Meta 未公开——本项目自定,见 §4 |
不在本轨官方口径内的东西: “目标工作器(objective workers)”一词只见于第三方 VM 观察,未见于官方页面原文,本轨不把它当官方术语用;长期目标的分派与通知步骤 用本轨的 swarm + presentation 实现,不挂这个名头。
2. 现状(基线 06c3e17,实测代码为准)
- crons,两套现成的、都不完整:
host.py run-due:host state JSON(name/task/repo/interval/last_run),now - last_run >= interval到期即派发 host 任务,跑完才回写 last_run。 无重试、无失败计数、无启用/停用(只有删定义)。cloud/automations.py:控制面 automations 表(SQLite/Postgres),claim_due_automation条件 UPDATE 抢单(同一间隔只一个执行器拿到), 配额门、automation_runs产出记录、分诊收件箱。无重试策略、无 paused 状态、无单项目上限。MIN_INTERVAL_SECONDS=60、MAX_INTERVAL_SECONDS=30d已有。- 子代理群:没有。 只有模型层的子代理名(
cloud/harness2.pysubagent_names,prompt 树里的名字),没有执行层的并行派发、没有隔离、 没有工具注册。 - 后台回访通知:没有“值得呈现”评估。
cloud/push.py dispatch_event按订阅派发终态(completed/failed/goal-unmet 等);自动化模块 docstring 已写明“不新写通知代码”。无去重、无节流——同一终态可重复派发。 - 每任务浏览器子代理:没有。 P2 的
chv-browser.py是常驻进程,close只关当前页、进程继续跑、等下一次 open;broker 固定转发到/run/chv/browser.sock。状态跨任务复用。
3. 改什么(本轨四个新模块 + 一处扩展)
| 模块 | 内容 | 归属 |
|---|---|---|
cloud/chv/crons.py(新) |
在 cloud/automations.py 之上加:启用/停用(paused 状态)、失败重试(指数退避 + 上限)、单项目并发上限与定义上限、tick 驱动(到期 + 重试到期统一认领) |
本轨 |
cloud/chv/swarm.py(新) |
子代理群:建群/派代理/生命周期;每代理独立任务 id + 独立工作区(resolve_inside 门,越界拒绝);工具注册与审计(只登记与审计调用意图,执行在代理自己的 VM 里走执行器);上限可配 |
本轨 |
cloud/chv/presentation.py(新) |
“值得呈现”评估(需要输入/失败需决策/有实质新内容才通知,常规完成只记日志)+ 通知账本(每任务每原因节流去重) | 本轨 |
cloud/chv/browser_tasks.py(新) |
每浏览器任务一个实例:建/绑/毁生命周期、单实例单任务(复用即错、毁后复用即错)、每实例独立状态目录;transport 接口注入(测试用 fake) | 本轨 |
cloud/automations.py(改) |
只加重试/停用所需的列与抢单入口(max_retries、retry_backoff_seconds、consecutive_failures、next_retry_at、paused 状态);host.py run-due 不动(host 侧唯一执行器,见该模块 docstring) |
本轨 |
P7 状态落点(更新 2026-11-07 06:39;迁移已完成,round-12 更新):
P7 已完成并提交(分支 feat-chv-muse-p7,提交 29fa0c8:每 VM
一个 SQLite 状态库 AppStateStore,0600 WAL,
tasks/goals/sessions/只追加 audit/meta)。round-12 已把三处登记
迁到 AppStateStore(分支 feat-chv-muse-round12):宿主级库
state_dir/app-state.sqlite(host_state_db_path,与 per-VM 库
同库不同文件),命名空间 p8-swarm / p8-ledger /
p8-browser-tasks,一行存整份登记文档;旧 JSON 文件首次加载时
自动导入并改名 .migrated;KV 行损坏/库打不开时回空结构
(fail-safe,下次成功保存即覆盖自愈)。测试钉在
cloud/tests/test_chv_muse_round12.py(P8MigrationTest)与
test_chv_muse_p8.py(损坏行恢复 + 旧文件导入)。crons 的状态
仍在 automations 表,未动。
客机侧跟进(本轨只写规约、不改 P2 的文件): 每任务浏览器实例的客机
进程拉起/销毁在 P2 的 chv-guest/chv-broker.py(browser 操作固定转发到
单例 socket)里改:每浏览器任务起一个全新的 chv-browser.py(每任务
socket),close 后杀掉进程。P2 的文件不在本分支基线里,本轨不复制、不
分叉,规约写进本表 §6,留给 round-12 集成时落在 P2 分支上。
客机侧跟进(round-12 决定:未做,留给真机轨): round-12 核实后未做,
原因三条:① chv-browser.py 的请求协议里没有任务 id 字段(只有
open/snapshot/screenshot/close/ping),broker 分不清请求属于哪个浏览器任
务,改 broker 之前须先改协议 + 调 broker 的调用方;② 进程拉起/销毁涉
及以 chv-browser 身份起进程、socket 就绪等待、close 后杀进程与僵尸回收、
broker 重启后的残留清理,在没有真机验证的情况下盲改,坏了就是每任务浏览
器全断;③ 本地只能用假浏览器进程测生命周期,真 Playwright + 真
chromium-headless-shell 的起停只能在真机上验。留给真机轨:先在真机上改
协议(请求加 task_id)→ broker 按任务拉起/杀进程 → 连续两任务端到端
(§6 第 4 项)。不许写成已做。
4. 自定数值清单(全部是本项目自定,非 Meta 官方值)
| 数值 | 本项目自定值 | 说明 |
|---|---|---|
| cron 最小间隔 | 60 秒(沿用现有 MIN_INTERVAL_SECONDS) |
已有,不新定 |
| cron 最大间隔 | 30 天(沿用现有 MAX_INTERVAL_SECONDS) |
已有,不新定 |
| 失败重试默认次数 | 3 次 | 超过即停,不再重试 |
| 重试退避 | 基数 60 秒 × 2^(n-1),上限 3600 秒 | n 为第几次重试 |
| 单项目并发 cron 执行 | 5 | tick 单轮最多认领 5 个 |
| 单项目自动化定义上限 | 100 | 超过建定义即 ValueError |
| 每群子代理上限 | 8 | 建群时可配,1–32 |
| 每项目群上限 | 10 | 超过建群即 ValueError |
| 通知节流窗口 | 同一任务同一原因 3600 秒内只通知一次 | 账本持久化 |
| 工具名长度上限 | 100 字符 | 与自动化名上限同款 |
5. 诚实边界
- B3 的“VM 需要足够资源”是容量要求,不是本轨能代码保证的:本轨只做上限与 隔离,宿主容量仍由部署方保障;群上限 8 是防炸宿主的默认值,不是性能承诺。
- swarm 层不执行工具:工具调用意图只登记与审计,真正执行在子代理自己的 VM/单元里(P1 常驻池 + P2 单元是底座)。“子代理构建自己的工具”在本轨指 注册进群内工具表、可被审计、可被别的代理复用调用名——不是沙箱外任意执行。
- “实质新内容”的判定是确定性规则(新产物/新改动文件/显式 notify 标志), 不是模型判断;模型觉得重要但规则判无新内容时,以规则为准、只记日志。
- cron 重试只针对 failed/interrupted 的执行;超配额跳过(skipped_quota) 不是失败,不进重试(沿用 automations 模块现有口径)。
- 通知账本先走原子 JSON 文件,P7 存储(
feat-chv-muse-p7提交29fa0c8的 AppStateStore)已落地,集成轨再迁移;迁移前账本丢了只 影响去重(可能重复通知一次),不影响任务执行本身。
6. 真机待验证清单(round-11 与 P4/P5/P6 之后,等通知)
- cron 端到端:定义在测试机上按间隔触发、失败重试 3 次后停、停用后不再触发。
- 群端到端:3 个子代理在各自 VM 里并行跑、互不可见对方工作区。
- 回访通知端到端:后台任务完成后有新内容才通知、无新内容不通知、同一原因 1 小时内不重复通知。
- 每任务浏览器实例端到端:连续两个浏览器任务各起全新实例、第二个看不到 第一个的截图与快照状态(需 §3 客机侧跟进先落地;round-12 未做,见 §3)。
- 账本迁移:已完成(round-12)——通知账本与另两处登记已迁到宿主级 AppStateStore(见 §3 更新),去重语义不变,测试钉住;真机上只需确认 升级后旧 JSON 文件一次导入、不丢去重状态。