Files
memind/docs/goose-v149-103-cutover-runbook.md
T
john 570ecbd1b0 feat(wechat): add WX gate evidence and v1.49 103 cutover runbook
Prioritize scheduled-task intent over page.generate for automation phrases, add run-wechat-gate-evidence.mjs for WX-01..13, and document 103 maintenance-window steps for Goose v1.49.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-10 15:01:32 +08:00

17 KiB
Raw Blame History

Goose v1.49 · 103 生产切换 Runbook

状态: 草案(本地 v1.49 证据已齐;未授权在 103/105 执行任何操作)

适用范围: 10358.38.22.103 / Mac Studio arm64)将 goosed 运行时从 1.41 native 升级到 v1.49 TKMind 补丁树

不包含: Portal runtime 整包发版(见 portal-release skill)、105 nginx 灰度(见 release-canary-103.md)、Memory owner 切换(见 TKMIND_V1_49_MIGRATION.md


1. 目标与边界

1.1 要达成什么

目标 说明
9 实例 goosed 升级到 v1.49 仍监听 1800618014,与现网 TKMIND_API_TARGETS / h5_user_sessions.goosed_target 兼容
保留 TKMind 定制 tkmind_compat REST、PG Session 共享、sandbox-fs MCP、harness、计费 relay、微信/页面 fail-closed
用户数据零丢失 RDS、PG memind_sessions、MindSpace 磁盘、Redis 路由键不删库
可回滚 15 分钟内回到 1.41 native 或 Docker standby

1.2 明确不做(除非单独批准)

  • 修改 RDS schema / 跑未审批 migration
  • 切换 Memory 写入 owner 到 upstream v1.49
  • 拆除 :18036 DeepSeek no-think 代理
  • 在本 runbook 内顺带发 Portal runtime(可同维护窗,但须独立 Gate + 脚本)
  • 从本机 Mac 直接 rsync 二进制到 103(须在 103 上 clone + vendor + 编译,或交付已审计的 release tar

1.3 与 native 1.41 迁移的关系

2026-07-30 已完成 goosed-native-103-migration-plan.mdDocker → native 1.41)。

本 runbook 是 第二次运行时升级native 1.41 → native v1.49。目录可沿用 /Users/john/Project/tkmind_go-native 的 launchd 模式,但二进制与启动命令改为 goose serve(见 goose-v149-local-phase0-manifest.md)。


2. 准入闸门(全部满足才申请维护窗)

2.1 Memind 仓库

# 命令 / 标准
1 v1.49 补丁已 review tkmind_go-v149 · 分支 upgrade/v1.49-tkmind · commit 记录在 Phase 3 清单
2 Memind 侧脚本/文档已进 main check-release-ready.sh、canary 脚本、WX gate 脚本
3 Phase 3 本地证据 node scripts/run-goosed-v149-phase3-offline.mjsGOOSE_V149_PHASE3_OFFLINE_OK
4 完整 LLM smoke(可选但推荐) GOOSE_V149_ALLOW_REAL_LLM=1 + run-goosed-v149-phase3.mjsGOOSE_V149_PHASE3_OK
5 Memory manifest 无 drift node scripts/compare-goose-v149-memory-manifest.mjs
6 WX 单测 + 本地 webhook node scripts/run-wechat-gate-evidence.mjsrun-wechat-scenario-test.mjs poem-page
7 用户明确批准 合并 main、103 维护窗、本 runbook 执行

2.2 103 只读基线(维护前 24h 内采集)

103 上只读执行,保存到本机 test/_103_baselines/pre-v149-YYYYMMDD/

ssh john@58.38.22.103 '
  date -u +%Y-%m-%dT%H:%M:%SZ
  cat /Users/john/Project/Memind/.release-manifest.txt
  grep -E "^(TKMIND_API_TARGETS|GOOSED_RUNTIME|GOOSED_MCP_|GOOSE_SESSION|MEMIND_DEEPSEEK)" /Users/john/Project/Memind/.env | sed "s/=.*/=***/"
  /Users/john/Project/tkmind_go-native/goosed --version 2>/dev/null || ls /Users/john/Project/tkmind_go-native/releases/
  for p in $(seq 18006 18014); do
    printf "goosed_%s=" "$p"
    curl -kfsS --connect-timeout 3 "https://127.0.0.1:${p}/status" || echo FAIL
  done
  curl -fsS http://127.0.0.1:8081/api/status
  curl -fsS http://127.0.0.1:8082/mindspace/v1/contract | head -c 400
'

记录:release_idGOOSED_TAGDocker standby)、九个 launchd label 状态、Portal git_head


3. 103 资产清单(不能遗漏)

3.1 目录与仓库

路径 用途 v1.49 动作
/Users/john/Project/Memind Portal live + MCP 脚本 不删;确认 mindspace-sandbox-mcp.mjs 与 runtime manifest 一致
/Users/john/Project/tkmind_go-native 当前 1.41 native 池 备份后部署 v1.49 binary;保留旧 releases/goosed-* 回滚
/Users/john/Project/tkmind_go-v149 v1.49 源码(103 上需 clone 见 §4
/Users/john/Project/tkmind_go-v141-prod-prep/.hermit/... Rust git vendor 缓存 见 §4.2;或从本机 tar 传到 103
/Users/john/Project/goosed-prod Docker standby 保留停机的 compose + 原 GOOSED_TAG
/Users/john/MindSpace MindSpace 服务 不动
~/Library/LaunchAgents/cn.tkmind.goosed-native-1800*.plist 9 实例 更新 ProgramArguments 指向 v1.49
~/Library/LaunchAgents/cn.tkmind.memind-deepseek-no-think.plist :18036 必须保持运行

3.2 持久化(备份,禁止覆盖)

release-portal-runtime-prod.sh manifest 一致,额外

资产 备份
阿里云 RDS goose 控制台快照
PG memind_sessions @ :5432 pg_dump
PG mindspace_userdata_prod @ :5433 pg_dump
tkmind_go-native/ 整目录 tar.gz
tkmind_go-v149/(首次 clone 前无) 首次 build 后备份 target/release/goose
Portal .env 单独拷贝(含 secret,不进 Git)
105 nginx m.tkmind.cn / wechat.m.tkmind.cn 发布脚本同款备份

3.3 服务依赖(切换后仍须全绿)

组件 端口 说明
Portal 8081 cn.tkmind.memind-portal
MindSpace 8082 独立服务
memind_adm 8085 智趣/Cursor 后台白名单在此配置,非 .env
DeepSeek no-think 18036 native goosed 自定义 provider 指向
PostgreSQL 5432 / 5433 Session + userdata
Redis 6379 worker 路由(可重建,但切换前记录)
imgproxy launchd 页面缩略图

4. 103 上从零拉齐 GitHub / 离线依赖

本机 Mac 已有缓存 不等于 103 已有。以下在 103 SSH 会话内执行(或维护窗预演)。

4.1 Goose 源码

# 在 103 上
cd /Users/john/Project

# upstream 基线 tag(对照用)
# https://github.com/aaif-goose/goose/releases/tag/v1.49.0

# TKMind 补丁树(与本地一致的分支/commit)
git clone git@git.tkmind.cn:tkmind/tkmind_go.git tkmind_go-v149   # 或已有 remote 的实际 URL
cd tkmind_go-v149
git fetch origin upgrade/v1.49-tkmind
git checkout upgrade/v1.49-tkmind
git rev-parse HEAD    # 必须与 Phase 3 记录的 commit 一致

若使用 worktree,路径固定为 /Users/john/Project/tkmind_go-v149(与 GOOSE_V149_ROOT 默认一致)。

4.2 Rust / cargo vendorGitHub 不稳定时)

依赖 来源 103 命令
rust-sdk hermit 缓存 bash /Users/john/Project/Memind/scripts/ensure-goose-v149-vendor.sh
cudaforge hermit 缓存 同上
rusty_v8 GitHub release bash /Users/john/Project/Memind/scripts/ensure-goose-v149-v8.sh

Hermit 根目录默认:/Users/john/Project/tkmind_go-v141-prod-prep/.hermit/rust/git/checkouts/

若 103 无 hermit 树,从本机传输(维护窗前):

# 本机
tar -czf /tmp/goose-v149-hermit-vendor.tgz -C /Users/john/Project/tkmind_go-v141-prod-prep .hermit
scp /tmp/goose-v149-hermit-vendor.tgz john@58.38.22.103:/tmp/
# 103
mkdir -p /Users/john/Project/tkmind_go-v141-prod-prep
tar -xzf /tmp/goose-v149-hermit-vendor.tgz -C /Users/john/Project/tkmind_go-v141-prod-prep

v8 直链见 goose-v149-offline-downloads.md

4.3 工具链

# 103 上确认
uname -m    # arm64
rustup show # 需 1.96.1
/opt/homebrew/opt/node@24/bin/node --version
/opt/homebrew/opt/postgresql@17/bin/pg_isready -h 127.0.0.1 -p 5432

4.4 编译 v1.49103 本机)

cd /Users/john/Project/Memind
export GOOSE_V149_ROOT=/Users/john/Project/tkmind_go-v149
bash scripts/ensure-goose-v149-vendor.sh
bash scripts/ensure-goose-v149-v8.sh
GOOSE_V149_BUILD_MODE=codemode bash scripts/build-goosed-v149-local.sh
# 日志:/tmp/goosed-v149-build.log
/Users/john/Project/tkmind_go-v149/target/release/goose --version   # 期望 goose 1.49.x
strings .../goose | grep -q platform_extensions::code_execution && echo code-mode OK

禁止使用 GOOSE_V149_BUILD_MODE=minimal 上生产。

4.5 安装 release 二进制(推荐)

STAMP=$(date +%Y%m%d-v149-m1)
install -m 755 /Users/john/Project/tkmind_go-v149/target/release/goose \
  /Users/john/Project/tkmind_go-native/releases/goose-${STAMP}
# 更新 run-goosed-native.sh 或各 .env.1800N 中的 GOOSE_BIN 指向该 release

保留上一版 releases/goosed-20260729-v141-m1(或当前 live)用于回滚。


5. 推荐切换策略

5.1 两阶段(推荐)

阶段 范围 端口 目的
A. Canary goosed 单实例 :18015 release-canary-103.md 候选 goosed 对齐;Portal 灰度用户(如唐 wx_ul610et8
B. 全池切换 9 实例 :18006:18014 维护窗内替换全部 launchd

阶段 A 可在 替换 1800618014 的情况下验证 v1.49 + sandbox-fs + DeepSeek + 微信。

5.2 全池切换(维护窗)

参考 goosed-native-103-migration-plan.md Phase 12,替换为 v1.49 启动参数。


6. 单实例配置模板(v1.49

18006 为例;1800718014 复制并改 GOOSE_PORT / launchd label。

6.1 环境变量(.env.18006 或 launchd EnvironmentVariables

GOOSE_PORT=18006
GOOSE_HOST=127.0.0.1
GOOSE_TLS=true
GOOSE_SERVER__SECRET_KEY=<与 Portal TKMIND_SERVER__SECRET_KEY 同步>
GOOSE_DISABLE_KEYRING=1

# 生产 Session PG(不是本地 goose_sessions_v149_dev
GOOSE_SESSION_DB_URL=postgresql://<user>@127.0.0.1:5432/memind_sessions

# MCP — 宿主机路径,必须与 Portal .env 一致
GOOSED_MCP_NODE_PATH=/opt/homebrew/opt/node@24/bin/node
GOOSED_MCP_SERVER_PATH=/Users/john/Project/Memind/mindspace-sandbox-mcp.mjs
PORTAL_RUNTIME_DIR=/Users/john/Project/Memind
MINDSPACE_STORAGE_ROOT=/Users/john/MindSpace/data/mindspace

# Memory — 强制 legacy owner(禁止 upstream 写 MySQL
MEMORY_BACKEND=legacy
MEMORY_VECTOR_ENABLED=0
MEMORY_AGENT_INJECTION_MODE=off
MEMORY_LIFECYCLE_ENABLED=0
MEMORY_CANDIDATE_ENABLED=0

# XDG 每实例隔离(避免 9 实例争用同一 state)
XDG_CONFIG_HOME=/Users/john/Project/tkmind_go-native/state/18006/config
XDG_DATA_HOME=/Users/john/Project/tkmind_go-native/state/18006/data
XDG_STATE_HOME=/Users/john/Project/tkmind_go-native/state/18006/state
XDG_CACHE_HOME=/Users/john/Project/tkmind_go-native/state/18006/cache

6.2 启动命令

v1.49 不再使用 goosed agent,改为:

exec /Users/john/Project/tkmind_go-native/releases/goose-<STAMP> serve \
  --host 127.0.0.1 --port 18006 --tls

legacy REST/agent/start/sessions/{id}/reply)由 tkmind_compat 在 v1.49 内提供;切换后必须跑:

node /Users/john/Project/Memind/scripts/check-goosed-v149-all.mjs   # 在 103 上针对 localhost:18006 预演

6.3 Portal .env 核对项

变量 要求
TKMIND_API_TARGETS 九个 https://127.0.0.1:1800618014 URL
GOOSED_RUNTIME native
GOOSED_MCP_* 宿主机绝对路径,且文件存在
MEMIND_DEEPSEEK_DISABLE_THINKING 1
DeepSeek provider URL http://127.0.0.1:18036/v1(非 host.docker.internal
Memory 开关 因 v1.49 默认开启 upstream Memory

7. 维护窗执行清单

建议窗口: ≥ 45 分钟(9 实例 + provider 同步 + P0 回归)

Phase 0 — 备份(可先执行)

  • RDS 快照
  • pg_dump memind_sessionsmindspace_userdata_prod
  • Portal persist tar + tkmind_go-native tar
  • 记录当前 releases/goosed-* 文件名

Phase 1 — 切流量

  • 105 维护页或阻止新会话(见 native 迁移计划 drain
  • 可选 soft drain Redis memind:runtime:worker:goosed-N:drain
  • 超时后停 cn.tkmind.memind-portal(或仅 block 新 session,视 drain

Phase 2 — 替换 goosed 二进制与 launchd

  • 确认 :18036 DeepSeek 代理仍 active
  • launchctl bootout 九个 cn.tkmind.goosed-native-1800N
  • 部署 v1.49 goose release + 更新 run 脚本
  • launchctl bootstrap 九个实例
  • 九个 /status 返回 ok
for p in $(seq 18006 18014); do
  echo -n "$p: "
  curl -kfsS --connect-timeout 3 "https://127.0.0.1:$p/status" || echo FAIL
done
  • Provider 同步到全部 9 个 targetAdmin 模型中心 / 103 既有流程)
  • sandbox-fs 冒烟:node scripts/check-goosed-v149-sandbox-fs.mjs(指向 18006

Phase 3 — Portal

若无 Portal 代码变更:

  • 重启 cn.tkmind.memind-portal(读 .env
  • 跳过 Docker remount

若同窗发 Portal runtime

  • bash scripts/check-release-ready.sh
  • Gate report 绑定 commit + artifact SHA
  • bash scripts/release-portal-runtime-prod.sh --yes(或 canary 流程)

Phase 4 — P0 回归(103 localhost + 105 外网)

优先级 场景 验证
P0 Portal /api/status 200
P0 /auth/login 错误密码 401 + 正确文案
P0 新建 H5 对话 goosed_target 落在 1800618014
P0 旧 session 续聊 维护前存在的 session /reply 成功
P0 sandbox-fs 落盘 page.generate → public/*.html 200
P1 微信真实回调 WX-0113;非仅 health
P1 DeepSeek 工具轮次 reasoning_content 裸奔错误
P1 imgproxy / MindSearch 生产 URL

Gate:维护窗 commit 须绑定 Core + Impact Gate reportproduction-release-guardian.md)。

Phase 5 — 恢复流量

  • 105 nginx → 58.38.22.103:8081(或灰度 19082 路径)
  • 外网 https://m.tkmind.cn/api/status

Phase 6 — 观察 2472h

  • GOOSED_RUNTIME=native node scripts/runtime-worker-metrics.mjs sample
  • monitor-goosed-fds.mjs 覆盖 1800618014
  • 续聊 / 页面 / 微信投诉

8. 回滚

触发: 九 target 非全绿、旧 session 批量续聊失败、P0 回归失败、FD 泄漏

目标: < 15 分钟

步骤 操作
1 105 保持维护
2 launchctl bootout 九个 v1.49 native 实例
3 恢复 launchd 指向 1.41 releases/goosed-*
4 或紧急:cd goosed-prod && docker compose up -d(原 GOOSED_TAG,仅 18006 standby
5 Portal .env 恢复备份
6 若 Portal 已发新版:按 archived_source / backup release_id 回滚
7 九路 /status + /auth/login + 旧 session 续聊抽样

回滚不需要: 恢复 RDS / PG(若切换中未改库)。

本地 canary 回滚(仅开发机):bash scripts/switch-goose-v149-canary.sh rollback


9. 与 Portal 发版的关系

动作 独立? 说明
Goose v1.49 全池 本 runbook
Portal runtime release-portal-runtime-prod.shartifact 含 mindspace-sandbox-mcp.mjs
105 灰度 可组合 先 canary goosed :18015 + 灰度 Portal
Memory owner 禁止绑在 v1.49 包内 单独审批

推荐顺序: Memind 合并 main → 103 上 build v1.49 → canary18015 + 唐)→ 全池维护窗 →(可选)Portal Gate 发版。


10. 证据附件(维护窗结束后归档)

保存到 test/_103_baselines/post-v149-YYYYMMDD/

文件 内容
goose-version.txt goose --version × 9
status-loop.txt 1800618014 /status
portal-manifest.txt .release-manifest.txt
gate-report.json Core + Impact,绑定 commit
phase3-offline.log 本机 GOOSE_V149_PHASE3_OFFLINE_OK
wechat-smoke.log 本地 run-wechat-scenario-test103 真实 WX 另补)
rollback-pointer.txt 1.41 release 文件名 + Docker GOOSED_TAG

11. 相关文档

文档 用途
TKMIND_V1_49_MIGRATION.md 决策表、Memory 闸门
goose-v149-phase3-closeout.md 本地证据与合并前闸门
goose-v149-offline-downloads.md v8 / vendor 直链
103-runtime-topology.md 端口与服务拓扑
goosed-native-103-migration-plan.md 1.41 native 迁移(已执行)
production-release-guardian.md Gate 场景
发包必看.md Portal 发版强制项

12. 变更记录

日期 说明
2026-09-10 初稿:103 clone/vendor/build/9 实例/回滚清单;本地 Phase 3 证据已齐,待用户批准执行