Files
CyberGril/deploy/hel895-release-candidate.md
T
zonggongandmultica-agent 7c73d392b9 HEL-879 rework materials: hatchling cache correction with the offline mem0ai wheel actually built from the fixed source (sha256 698284b6..., zero downloads/installs, no 3.10 mixing, recorded in release-artifacts.json), hel895 release doc §0 now separates the historical HEL-895/896 candidate from the current hel-879-assembly candidate and §4/§5 carry the v3 snapshot semantics, budget §6.2.4 amended - a sealed library is never reopened by raising total_requests (contradiction removed), runbook §3.3/3.5/3.6/4.4/4.5 corrected (bounded cleanup ledger replaces the unproven rooms-die-naturally claim; assistant_interim kind; real-but-default-off proactive seam; single-owner dual launcher), one comment-only correction in web/src/voice/session.ts removing the unproven server-auto-cleanup claim (no logic/style change; CSS and JS bundle hashes byte-stable), CG-011 + her incremental subtitles now have a real minimal backend seam (voice/seam.py + worker/llm_chat_api wiring, proactive default off) with the precise frontend interface and acceptance list in docs/rework/hel879/voice-seam-interfaces.md, real-SDK check extended to 10 items (worker callback path on real SpeechHandle/SpeechCreatedEvent; interim seam through real LLMStream) and re-run on .12 ALL PASS, handoff-HEL-879.json appended with the rework scope; regression at this head: pytest 341/341, ruff clean except 1 pre-existing error identical at 7f0a739, web typecheck 0 errors / lint 0 errors 1 pre-existing warning / vitest 88/88 / build passes (CSS index-BpZaybfD.css unchanged), voice chain 8/8, budget split 10/10, release offline R1-R7, http pagination 7/7, real-service browser 9/9 with zero non-loopback outbound, pinned-SDK 16/16+12/12+6/6+7/7+12/12, requirements checks 4/4 (origin/main and c121c42, each with/without handoff)
Co-authored-by: multica-agent <github@multica.ai>
2026-10-27 04:27:04 +08:00

17 KiB
Raw Blame History

HEL-895 · 统一发布候选(离线核验过,未执行部署)

HEL-879 发布工具收口(2026-10-27,隔离候选分支 hel-879-assembly):按总管 对 HEL-896 的独立复核完成四项有限收口——①归档一致性:checkpoint 返回值必查、 源/快照行数不一致或 checkpoint busy 一律 CLI 非 0 且不形成可交付包,verify 拒绝 记录了 rows_match=False 的旧包(§5);②目录内真实 SQLite(history_root 的 mem0_public_history.db 等)停服口径走 checkpoint+逐表核对,在线模式只允许显式 单库 backup API、含 SQLite 的目录直接拒绝;③提前封账:tools/seal_budget_hel879.py 显式封账(真实用量保留、跨重启/归档拒绝,负例 S6);④安装入口唯一化:本文件 §2/§4 为唯一照抄入口(全 offline/no-index;mem0ai 只认固定源码轮),deploy/hel874-release.md §2/§4 已标注被取代。产物清单与精确提交见 docs/rework/hel879/sdk-audit/ 与 docs/rework/hel879/release-artifacts.json。不要用旧父提交(04eff61/152479b) 的说明冒充本候选 head:以交付评论与 handoff JSON 记录的精确提交为准。

HEL-896 修订(2026-10-27,正常追加 PR#11):按总管独立复审补齐——①浏览器 「真实服务 7/7」中 B3 原为已证实误报,测试已修为精确交互+严格断言(9 项检查, 含权限 API 调用计数与非回环出站守卫,证据 docs/rework/hel896/browser/); ②A/B/C 预算改为独立团队测试实例 + 全新用户实例的可执行分账 (docs/budget-package-hel895.md §6);③固定 SDK 缺项勘误为 41 项闭包清单 (§4);④归档/回退改为一致性快照口径(§5)。候选 head 与交付物不变,未部署、 未合并、未写权威账。

状态:候选。审核通过与预算/部署授权前不启动面向用户的真实循环、不部署、不合并 PR、不交体验地址。 本文件把已通过独立复审的内核(HEL-894 @ 152479b)与 HEL-881 已审核的主动留言前端(bf234570)装成一个统一候选,给出精确 head、 交付物清单、安装命令、健康矩阵与停用回退。发布卡照抄即可执行;不触 8300–8350 与共享 ASR/TTS/口型,不访问 4080,不导入演示/测试档案为用户伴侣。

0. 精确 head 与整合方式

HEL-879 返修勘误(2026-10-27):本节以下原文记录的是 HEL-895/896 历史 候选(分支 hel-870-assembly,PR #11 未合并),其 299 pytest / 55 vitest 等 验证数字属于那个历史 head,不是当前发布候选。当前统一发布候选是分支 hel-879-assembly(在 7f0a739 之后正常追加返修提交,不强推、不并入 PR #11), 其精确 head、pytest/vitest/build 全量数字与证据以交付评论与 docs/requirements/handoff-HEL-879.json 记录为准;本文件的安装/检查入口 (§2/§4/§5/§6)继续适用于当前候选,产物清单见 docs/rework/hel879/sdk-audit/ 与 docs/rework/hel879/release-artifacts.json (rework_head 字段)。历史叙述保留原样,不冒充、不改写。

  • 候选 head:见交付评论(分支 hel-870-assembly,PR #11 的正常追加提交, 未强推、未合并)。第一父为 HEL-894 通过复审的 152479b3503c3d1ab27681170e6bfd592c54380a, 合并入 HEL-881 已审核的 bf234570c0b6595a72f8dbc79e42c63685e08e01 (origin/hel-880-inbox-continuation,与 origin/hel-875-proactive-wiring 同点)。
  • 整合的机械性:母线 31970c4..152479b 从未触碰 web/(git diff 31970c4 152479b -- web/ 为空),合并只带入原作者六个前端文件与 handoff-HEL-875/880.json 共 9 个文件;src/tests/tools/config 相对 152479b 逐字不变。无重设计、无视觉决定;旧 b48d28b 测试合并未推送,由本候选取代。
  • 合成后验证(全部在本 head 实跑):299 pytest(3.11.16 venv + requirements.lock 离线)+ ruff 干净;web typecheck 0 错、lint 0 错/1 条既有警告、 vitest 55/55、build 通过且 CSS 仍为 index-DdDYzR5S.css(视觉零改动); 固定 SDK 回归:关闭所有权 16/16、关闭排队 12/12、处理中生命周期 6/6、语义恢复 7/7、真实接线 12/12;发布离线检查 15/15;真实 HTTP 分页合同 7/7 (tools/verify_http_pagination_hel895.py,真实服务 + 327 行播种 + fetchAfter 缺口游标移植对真实后端复验);真实服务浏览器 7/7(web/tests/hel895_real.mjs, Chromium CDP 对真实 API:留言卡、舞台播放、260 行缺口不跳留言、重启 epoch 去重、 零权限申请。HEL-896 勘误:原 7/7 中 B3 为已证实误报——兜底断言+点击 「日子与回忆」导航钮,stage=false 仍 PASS;修订版改精确交互+严格断言共 9 项 检查全过,含权限 API 调用计数 0 与非回环出站守卫 0,证据 docs/rework/hel896/browser/,原误报证据保留于 docs/rework/hel896/browser-before/)。双目标及实际母线需求检查各含/不含 handoff-HEL-895 共 6/6 通过(origin/main、原产品目标 de8874a3803b、实际母线)。

1. 交付物清单

交付物 位置/来源 说明
代码 分支 hel-870-assembly,精确 head 见交付评论 含本文件、docs/budget-package-hel895.md、tools/verify_http_pagination_hel895.py、web/tests/hel895_real.mjs
Python 依赖 requirements.lock(19 项固定版本,uv 离线可装) Python 3.11(发布机 3.11.16 实测)
前端产物 web/(原作者界面 + HEL-875/880 主动留言) npm ci && npm run build;CSS 哈希与已审核版一致
mem0 固定栈 deploy/mem0-stack.lock(mem0ai 2.2.1 / qdrant-client 1.20.0 / fastembed 0.9.1) 3.11 缺 41 项闭包,见 §4;缺项不阻塞其余发布
systemd 模板 deploy/cybergril-hel874-8360.service.example(PYTHONPATH=src 已内置) 独立单元/端口/数据目录模式
配置模板 config/models.yaml(预算全 0)+ config/semantic.example.yaml 批准值写入位置见 docs/budget-package-hel895.md(A 仅团队实例,§6)
预算执行包 docs/budget-package-hel895.md(含 §6 HEL-896 分账修订) A/B/C 一次批准核定稿,默认 0
HEL-896 工具 tools/verify_budget_split_hel896.py、tools/audit_sdk_offline_hel896.py、tools/release_snapshot_hel896.py、修订版 web/tests/hel895_real.mjs 分账切换验证、SDK 余缺只读审计、一致性快照/回退验证、严格浏览器检查

2. 安装命令(发布卡执行;本节是唯一照抄入口——HEL-879 收口)

# 全新目录,逐条照抄;任何一步失败即停。全部安装强制 offline/no-index:
# 缓存命中即装,缓存缺失即停并留证;联网补齐只发生在获批的发布窗口内,
# 逐项 sha256 留证(seq48–51 勘误教训:不写 offline 的安装发生过网络获取)。
# 2.1 服务账号与目录(独立可写数据路径,权限边界明确)
useradd --system --home-dir /opt/cybergril-hel874 --shell /usr/sbin/nologin cybergril || true
mkdir -p /opt/cybergril-hel874/data            # data 必须为空:新账从零初始化
chown -R cybergril:cybergril /opt/cybergril-hel874

# 2.2 代码 checkout:全新空目录 clone(空目录里没有仓库,不能直接 git fetch)
git clone ssh://git@192.168.200.36:222/leefer/CyberGril.git /opt/cybergril-hel874/current
git -C /opt/cybergril-hel874/current checkout <交付评论/handoff JSON 记录的精确head>

# 2.3 依赖与前端(uv/npm 一律 offline;缓存缺失即停)
cd /opt/cybergril-hel874/current
uv venv --python 3.11 .venv311
uv pip install --python .venv311/bin/python --offline -r requirements.lock
(cd web && npm ci --offline && npm run build)

# 2.4 服务单元(单元内已带 PYTHONPATH=<current>/src:requirements.lock 只装依赖,
#     产品代码经 PYTHONPATH 进程内可 import)
cp deploy/cybergril-hel874-8360.service.example /etc/systemd/system/cybergril-hel874.service
systemctl daemon-reload && systemctl enable --now cybergril-hel874
curl -s http://127.0.0.1:8360/api/health | python3 -m json.tool

发布前必过检查按 §6 与 deploy/hel874-release.md §6 的清单执行(该节仍有效), 另加本卡工具(真实 HTTP 分页合同、真实服务浏览器)在目标机重跑。

3. 健康能力矩阵(/api/health 预期)

与 deploy/hel874-release.md §3 一致:version=R4-assembly;backend mood/reach_out/semantic 接线;semantic_backend=stub(发布初期,真实 mem0 待 §4 与 B 部分预算);capabilities.proactive=true(生活循环开启时);voice/vision/ weather/materials/backup=false。主动留言前端已并入本候选:生活循环开启且产生 真实 reach-out 后,打开的页面每 20 秒读一次新行、回来立即读,未读有标记;该行为 已在本 head 用真实服务验证(§0)。

4. 固定 SDK(3.11)激活——唯一照抄入口(HEL-879 收口)

本节取代 deploy/hel874-release.md §4(历史文件,已标注被取代,不得再照抄)。 旧 4.1/4.2 按 deploy/mem0-stack.lock 的 mem0ai==2.2.1 向索引拉同名 wheel—— 索引同名 wheel 不能证明固定源码身份 2c81af3,这条路已废除。入口只有一条:

固定 tarball 哈希 → 固定源码构建轮 → 目标 cp311 依赖准备 → 仅本地轮安装 → 同进程 co-import。

  • 第 0 步 · 产物清单核对:docs/rework/hel879/sdk-audit/sdk-audit.json(本候选 精确提交上重跑)与 docs/rework/hel879/release-artifacts.json 记录闭包 55 项、 缺 41 项、缓存可复用 3 项与逐项哈希;发布卡先核对清单与目标提交一致。 事实口径(HEL-896 审计核定,HEL-879 重跑仍成立):三个顶层固定版本 (mem0ai 2.2.1 / qdrant-client 1.20.0 / fastembed 0.9.1)的 wheel 均为 py3-none-any 纯 Python;闭包按 3.11 Linux markers+extras 共 55 项,产品 3.11 venv 缺 41 项(28 纯 Python + 13 原生:grpcio/numpy/onnxruntime/ tokenizers/sqlalchemy/protobuf 等),这是闭包清单不是已完成的 cp311 下载结果。 seq48–51 pip 事件勘误保留:不写 offline 的安装发生过网络获取(uv 缓存取证), 故本入口全程 --offline/--no-index。
  • 第 1 步 · 固定 tarball 哈希核对(零下载):
    sha256sum <hel857-data>/mem0-2c81af3.tar.gz
    # 必须等于 deploy/mem0-stack.lock 记录的
    # 9dcef9303ebcec116eec6739f01b8b35bd24459de6a569686b4d19b9412dda23
    
    不一致即停;不得改用索引 mem0ai==2.2.1 wheel 冒充固定源(audit 已证明两者 身份不可互证)。
  • 第 2 步 · 固定源码构建轮(HEL-879 返修:已完成可离线构建):此前此处写 「hatchling 当前不在任何本机缓存、待补」——经总管只读核查与本卡复核勘误: uv wheels-v6/wheels-v7 均有 hatchling 1.32.4 缓存(release-artifacts.json build_backend 节逐路径留证)。固定源 tarball 已在 3.11.16 + uv build --wheel --offline 下离线构建出轮(零下载、零安装、不混 3.10 site-packages): mem0ai-2.2.1-py3-none-any.whl, sha256 698284b6083ab8b7761454d65876a6d1bb983d278ad21a7bee38d760cb20e9db。 发布卡在目标机重跑同一命令并核对该哈希:
    tar xzf <hel857-data>/mem0-2c81af3.tar.gz && cd mem0-2c81af3*/
    uv build --wheel --offline --python 3.11 -o wheels/
    sha256sum wheels/mem0ai-2.2.1-py3-none-any.whl
    
  • 第 3 步 · 目标 cp311 依赖准备:41 项缺项中缓存今天即可复用 3 项 (greenlet 3.5.6 cp311、pillow 12.3.0 cp311、truststore 0.10.5 py3-none-any, uv wheels-v6/v7 缓存实测,HEL-879 重跑核实仍命中);其余 37 项 由总管获批后发布窗口拉取(python3 -m pip download --only-binary :all: --implementation cp --python-version 3.11 --platform manylinux2014_x86_64 --abi cp311 -r <缺项清单> -d wheels/),逐项 sha256 留证;本卡零下载、零联网。 某固定版本若无 cp311 wheel,按 lock 注释如实上报缺项,不换版本号、不混 sdist。
  • 第 4 步 · 仅本地轮安装(--no-index 全程,目录里只有上两步产物):
    uv pip install --python .venv311/bin/python --no-index \
        --find-links <本地wheels目录> mem0ai==2.2.1 qdrant-client==1.20.0 fastembed==0.9.1 <41缺项>
    
    deploy/mem0-stack.lock 的 mem0ai 行只作版本记录;安装来源必须是第 2 步的 固定源码轮(同版本号不同来源不互认)。
  • 第 5 步 · 同进程 co-import 与模型落位:
    .venv311/bin/python -c "import cybergril.api, mem0, qdrant_client, fastembed; print('co-import ok')"
    
    fastembed 模型缓存(hel857-data/fastembed-cache,Qdrant/bge-small-zh-v1.5 + bm25 约 92MB,实测存在)拷入实例数据目录,真实 mem0 模式 cache_dir 指向它。

产品 venv 目前 import mem0/qdrant_client/fastembed 均缺、产品代码导入不受影响; 在 wheel 落位且 co-import 通过前,不得以 stub/FTS 冒充真实 Mem0 体验就绪。 真缺的下载(37 项运行闭包;hatchling 已勘误为缓存命中并完成离线构建,不在缺单) 仍待主卡授权,本卡不为补命令联网。

5. 停用与保留数据回退

与 deploy/hel874-release.md §5 相同:CYBERGRIL_SEMANTIC=off|stub 停语义层 (表保留、按后端区分续跑);CYBERGRIL_R2_ENABLED=0 停生活/主动联系;整实例 systemctl stop → 数据目录原样保留 → 切回上一 release/上一提交(R4 迁移全部 增量新表,旧代码可安全打开同一数据库);彻底撤销留数据档不删。

HEL-896 归档/回退修订 + HEL-879 收口(2026-10-27,v3 返修):在线库只复制主 .db 会丢 WAL 里已提交的资料(总管复现件连 companion 表都不在)。发布归档一律 二选一:停服务 + PRAGMA wal_checkpoint(TRUNCATE) 后整目录归档(推荐),或 在线用 SQLite backup API 对显式单库做一致性快照。工具已按收口语义强制执行 (v3;v2 的两处已证缺陷由总管独立复核提出并修复):

  • checkpoint 返回 busy≠0 或源/快照行数不一致 → CLI 非 0、不产生可交付归档 (「先停服」是前提,不是忽略失败结果的理由);
  • 目录内真实 SQLite(history_root 的 mem0_public_history.db、向量目录内库等, 按文件头魔数递归识别)在停服口径一并 checkpoint+逐表核对;
  • 在线模式只接受显式 --db(backup API);传入含 SQLite 的 --file 目录直接拒绝;
  • verify 要求三个计数直接相等(manifest 源行数 = manifest 快照行数 = 恢复 实测;rows_match 只是额外约束——v2 的 rows_match is True or … 允许记录值 绕过源计数比较,源 2/快照 1 仍 ok,已废除);回退演练按源路径映射实际恢复 到归档旁的持久独立目标树、打开恢复库核对行数与哈希,输出 rollback_plan;
  • 归档侧目标名无冲突映射:不同目录的同名 ledger.db 不再互相覆盖(v2 后写覆盖 前写仍先交成功包);同一源重复传入直接拒绝。

照抄命令:

# 覆盖范围:产品库(CYBERGRIL_DB)、语义向量目录 vector_root、推导史 history_root、
# 权威嵌入账 ledger_path(按部署实例 config/semantic.yaml 实际路径逐项代入)
# 停服口径(推荐;目录内 SQLite 一并一致性处理):
.venv311/bin/python tools/release_snapshot_hel896.py snapshot \
  --name <release-或阶段名> --db <产品库> [--db <权威账>] \
  --file <vector_root> --file <history_root> --out /opt/<实例>/archives/
# 在线兜底口径:仅显式单库(backup API),不得传含 SQLite 的目录:
.venv311/bin/python tools/release_snapshot_hel896.py snapshot --name <名> \
  --db <产品库> --out /opt/<实例>/archives/ --online
.venv311/bin/python tools/release_snapshot_hel896.py verify --archive <产物>.tar.gz

产物含逐文件 SHA256 清单、代码精确提交(快照时刻 git rev-parse HEAD)、 逐表行数核对与回退演练结果;不删档,旧归档永久保留。回退=停服务 → 解包快照到 新数据目录(按 rollback_plan 的源路径映射)→ 指回上一 release/上一提交 → 起 service → verify 通过后交付。本节是发布归档/回退要求,不冒充 R6(CG-009 每日自动备份/手动完整导出)完成。

6. 本候选不做的事

不合并任何 PR(PR #11 保持开放待总管/白栖知决定);不部署、不交体验地址; 零真实 LLM/嵌入/下载;不触 8300–8350、共享语音口型、GPU/4080;不导入演示测试 档案为用户伴侣;不替视觉作者改稿(前端内容以原作者六文件与 CSS 可追溯为准)。 R5(HEL-878/879 语音)、R6(天气/素材/完整备份)、R7(有条件视觉观察)未接入, 界面保持诚实文案,不冒充已运行。