Files
memind/TKMIND_V1_49_MIGRATION.md
T

17 KiB
Raw Blame History

TKMind Goose v1.49 迁移决策表

目标与边界

本次升级的目标是“升级运行时基线 + 选择性吸收 upstream”,不是把 TKMind 变成 vanilla Goose。

  • Layer 0PG Session、多实例 affinity、9 实例拓扑——保留。
  • Layer 1goosed 运行时、安全修复、agent loop——跟随 upstream v1.49。
  • Layer 2:通用能力的 platform extensions——优先改为薄封装,逐项退役重复实现。
  • Layer 3tkmind_compat、harness、sandbox-fs MCP——保留,确保 Portal/H5 契约与业务语义不变。
  • Layer 4Portal、微信、计费、MindSpace、Page Data——保留,属于产品层。

迁移完成的判定不是“upstream 代码已合入”,而是:新旧运行时在受保护业务路径上行为等价,且每个可退役定制都有 canary 证据与可执行回滚。

Memory 无缝迁移硬闸门

Memory 不能作为普通 extension 随运行时升级一起替换。这里必须分别保护四类状态,不能只比较“能否召回”这一项:

状态层 当前事实/责任 v1.49 原则
Goose Session PG 共享 session、agent_session_id、SSE/Finish 状态 只适配 runtime API;不得让 upstream 本地 SQLite 成为隐式第二份真相。
业务记忆 MySQL h5_conversation_messagesh5_user_memory_itemsh5_episodic_memory_items 保持原表、原 ID、原 user/session/evidence 关联与原写入语义;upstream 不得接管 owner。
V2 候选/生命周期 h5_memory_v2_candidates 及 promotion/expire/forget 继续由 Portal policy 控制;off 必须零写入,所有操作按 user scope 严格隔离。
语义索引/项目记忆 memory_embeddings、可选向量后端、harness bootstrap/remember 只能是可重建派生数据或受控项目记忆;必须保留来源 ID、embedding 版本和回填水位,不能反向覆盖业务记忆。

以下条件未全部满足时,Memory owner 必须保持现有 conversation-memory / Portal 链路,v1.49 只能旁路 shadow 观察:

  • 同一 userId 能在旧运行时、新运行时、Portal 和所有 Memory adapter 中稳定映射;不能用 display name、邮箱或临时 session ID 代替。
  • agent_session_idsource_session_idevidence_message_id、memory idmemory_hash 的映射已导出并逐项对账;不能因 session ID 重建造成重复记忆或丢 evidence。
  • 迁移期间只有一个业务记忆写入 owner。禁止旧链路和 upstream 同时写入同一事实,避免重复提取、hash 冲突和不可逆覆盖。
  • 新 runtime 先双读/对照旧结果,再考虑切换 resolve;writecompact、promotion、expire、forget 仍走旧 owner,直到对账稳定。
  • 已建立按用户的 count、ID 集合、hash、状态、更新时间、来源 session 和 evidence 外键对账;总数相同不能替代逐用户逐 ID 对账。
  • 已覆盖增量追平:固定 cutover watermark,回填期间捕获 watermark 之后的新写入;不能依赖从 updated_at=0 开始的有限批次。
  • 向量索引记录 embedding provider/model/version/dimensions、文本规范化版本、来源 memory ID 和写入时间;维度或模型变化必须新建 namespace/table 或完整重建,禁止混索引。
  • 向量不可用、索引落后、embedding 失败、upstream 超时或结果不一致时,必须 fail-open 回到 legacy exact/recent recall;不得阻塞聊天或删除原记忆。
  • remember-recent 使用原始用户消息(优先 h5_agent_runs.user_message_json),不得把注入的 [Memory Context] 再提取成新记忆;空数组必须表示“无需保存”。
  • 回滚只切回 resolve/write/compact owner 与 feature flag,不删除候选表、向量表或原始记忆;回滚后仍能从原始表重建派生索引。

Memory 数据不对接上的常见盲点

  1. 只迁 goosed session,不迁业务记忆关联session 恢复成功不代表 userId → source_session_id → evidence_message_id 仍然成立。
  2. 把向量库当主库:向量结果是派生索引,不能替代 MySQL 事实、状态和 forget/expire 语义。
  3. 双写但没有幂等键:必须以稳定的业务 memory ID/hash + user namespace 幂等 upsert;不能用每次 embedding 的随机 ID。
  4. 只比总数不比内容:同数但 user 串线、status 丢失、evidence 外键断裂或更新时间截断,都会表现为“数据在但接不上”。
  5. 忽略提取输入污染:新 runtime 注入的 Memory Context 可能被再次保存,造成旧记忆复制和权重膨胀。
  6. 把 schema/DDL 当启动副作用:本地可以显式建空表并验证;生产 schema、备份、回填和 owner 切换必须是独立审批步骤,本次升级禁止触碰 103。

本地优先与生产隔离规则

本次迁移只能在本地 loopback、隔离数据库和临时 workspace 开始。未获得新的明确授权前,禁止:

  • 连接 103、105 或任何生产数据库、生产 goosed、生产 MindSpace 服务;
  • 执行生产发布、runtime/artifact 生成、远端迁移、远端 backfill、远端 schema DDL 或生产重启;
  • 使用生产 DATABASE_URLGOOSE_SESSION_DB_URL、Memory provider key 或生产数据做测试;
  • 将 upstream Memory backend 接入 Portal 主路径,或修改 production profile 的 Memory 开关。

本地测试必须使用显式 loopback 地址和隔离数据库名,例如 127.0.0.1 的 MySQL/PG;测试启动前应打印并检查目标 host、database、runtime profile,命中 103105、公网数据库或 production profile 时直接失败。优先使用脱敏 fixture 或本地数据副本,测试结束删除临时用户/会话/索引,但保留可复核的对账报告。

决策规则

判断问题 Replaceupstream 替代 Keep:保留定制 Thin wrapper:薄封装 upstream
是否 TKMind 独有? 部分独有
upstream 是否明显更成熟? 否或不对等 是,但缺 TKMind 钩子
替换后 H5/微信契约是否不变? 不适用 需要 adapter 层
是否绑定 MindSpace、计费或权限? 部分绑定

只有“非独有 + upstream 更强 + 契约可不变”同时成立时,才直接 Replace。任何涉及用户空间、发布、计费、权限、微信 ACK 或 PG Session 的能力,默认先 Keep;若能复用 upstream 内核,采用 Thin wrapper。

定制项决策表

状态含义:Candidate 表示建议方向,尚未凭 canary 取得退役资格;Keep 表示本次不以 upstream 替代;Wrapper 表示保留入口与契约,内部逐步换内核。

定制项 决策 v1.49 迁移动作 退役/切换门槛 回滚点
platform_extensions/web.rsDuckDuckGo + fetch Wrapper → Replace 保留现有 extension 名与 H5 调用入口;内部优先转发 upstream web-search / browser-use skill。 搜索、抓取、超时、fallback、权限与结果格式回归通过;无 TKMind 专属域规则回归。 切回旧 extension 实现。
session-reply-wait 与 Portal 侧 DeepSeek workaround Wrapper / Keep(分阶段) 先在 v1.49 保留等待、Finish、重试与游标适配;对 upstream reasoning 修复做独立 canary。 工具调用后的 reasoning_content、SSE Finish、断线续播、重复消息与超时回归通过。 保留 session-reply-wait 与旧兼容链路。
DeepSeek no-think 代理(:18036 Wrapper → Pass-through 先保留独立代理与端口;验证 v1.49 原生兼容后,再将代理改为 pass-through,最后才评估停用。 生产同构工具轮次通过,候选失效时可自动回落稳定版本;不得仅凭版本号拆除。 恢复旧 :18036 no-think 处理。
billing-token-state 粗估价 Candidate Replace / Simplify 优先读取单条消息 usage/cost 与 cache tokenaccumulated_cost 稳定时,Portal 仅保留缺失字段时的保守估算。 Finish 稳定带完整累计成本;账单、margin、补偿与幂等回归通过;不能出现超扣。 恢复 Portal 估算逻辑。
部分 message sanitize 补丁 Candidate Replace 对比 v1.49 provider message 处理与本地补丁 diff;只删除已被 upstream 覆盖且契约等价的分支。 DeepSeek、多模态隔离、工具轮次、历史消息显示回归通过。 恢复对应 sanitize 分支。
PG Session 多实例共享 Keep 移植到 v1.49 session/runtime 接口;保持 PG、9 实例 affinity 与共享 session 语义。 多实例并发、重启恢复、session 一致性与故障切换通过。 保留旧 PG adapter / 配置。
tkmind_compat/sessions 等 REST adapter Keep 仅适配 upstream v1.49 内部 API;对外 REST/H5 契约不变。 Portal、H5、微信客户端不需要改请求格式;旧客户端回归通过。 切回旧 goosed adapter。
tkmind_memoryharness bootstrap/remember Keep / Wrapper 保留项目记忆与 capability 门控;若 upstream 有 projects/memory 原语,只在内部复用,不改变 TKMind 入口。 bootstrap、remember、权限边界与项目级记忆回归通过。 使用现有 harness 实现。
sandbox-fs MCPMindSpace、Page Data、generate_image Keep 按 v1.49 extension/MCP 生命周期接口移植;保持路径隔离、页面落盘、缩略图 fallback 与图片策略。 发布/改页、Page Data、图片生成、私有路径隔离、Transport closed 重试回归通过。 保留现有 sandbox-fs 子进程与 Portal fallback。
aider / openhands platform extensions Keep 保持 coding_router、微信与 agent-run 策略;只适配运行时加载接口。 coding 路由、模型名映射、权限与失败回退不变。 保留旧 extension。
custom_tkmind_relay_deepseek Keep 保留计费、margin、Admin 模型中心绑定;若 upstream provider 足够,只替换内部传输实现。 provider/key/model 目录、计费归属、margin 与 canary 策略回归通过。 切回 custom relay。
capabilities.mjs + extension policy Keep / Wrapper 保留用户权限、canary、微信策略;可将通用 extension 解析委托给 upstream。 capability 不越权,sandbox-fsread_image 等关键策略不回归。 使用现有 policy builder。

明确不替换的产品契约

以下能力不能因为 upstream 1.49 提供了相似原语就直接删除:

  • MindSpace 页面发布、edit_file 落盘、Finish 合并与 Page Data 交付。
  • sandbox-fs 的 workspace 路径隔离、图片生成、缩略图 fallback 与 MCP 失败兜底。
  • 微信 5 秒 ACK、消息路由、页面链接验证与定时任务投递。
  • 计费、usage/cost、margin、provider/model 权限与 canary 策略。
  • PG Session 共享、9 实例 affinity、Portal/H5 /sessions 等兼容 REST。
  • SSE 断线续播、Portal replay ID 与 Goose Last-Event-ID 的映射。
  • 私有 MindSpace 页 noindex、confirmed public 才可收录的 SEO/GEO 策略。

分阶段迁移清单

Phase 0:冻结基线

  • 记录当前 1.41/现生产候选的 commit、runtime artifact、配置与端口。(见 docs/goose-v149-local-phase0-manifest.md
  • 拉取 upstream v1.49.0;创建 upgrade/v1.49-tkmind worktree/Users/john/Project/tkmind_go-v149)。
  • 本地隔离 PG 库 goose_sessions_v149_dev;启动脚本 scripts/run-goosed-v149-local.sh(端口 18049)。
  • 建立旧版与 v1.49 的 canary 开关,以及一键回落路径(scripts/switch-goose-v149-canary.sh + docs/goose-v149-canary-runbook.md)。
  • 保存关键业务场景的输入、SSE 事件、Finish 状态、usage/cost 与产物校验结果(node scripts/capture-goose-v149-baseline.mjs + node scripts/check-goosed-v149-all.mjs)。
  • 导出本地基线 Memory manifest:每用户 memory ID/hash/status/source session/evidence、候选状态、向量 namespace/versionnode scripts/export-goose-v149-memory-manifest.mjs)。
  • 记录 schema 版本、索引版本、回填 watermark、时区和字符规范化规则(见 manifest schemaVersion / cutoverWatermarkMs / textNormalization 字段)。

Phase 1:运行时升级

  • 将 upstream v1.49 安全修复、agent loop 与 provider 变更移植到 Layer 1(基线已在 v1.49.0 tag)。
  • 适配 tkmind_compat、PG Session、harness 的加载/生命周期接口(P0 路由 + PG 双后端)。
  • 适配 sandbox-fs 的加载/生命周期接口(extension_overrides + /agent/tools 验证)。
  • 自定义 provider 路由(/config/custom-providers/config/upsert+ custom_tkmind_relay_deepseek 本地 reply Finish smoke。
  • aider / openhands platform extensions + deploy/coding_router.shcheck-goosed-v149-executors.mjs)。
  • v1.49 初始配置强制 MEMORY_BACKEND=legacyMEMORY_VECTOR_ENABLED=0、lifecycle/promotion/injection 为 off/shadowrun-goosed-v149-local.sh + check-goosed-v149-memory-policy.mjs)。
  • 先验证旧 owner 在 v1.49 上完成“写入 → compact → 新 session resolve”的本地闭环(check-goosed-v149-memory-loop.mjs)。
  • 保持 Layer 34 对外接口不变(Portal canary 联调 POST /agent/resumeGET /sessions/{id} 带 conversation、restart 返回 extension_results 已补齐 smoke)。

Phase 2:逐项 canary

  • web/searchTKMind platform/web 已移植至 v1.49check-goosed-v149-web-smoke.mjs);upstream web-search skill 对照仍保留。
  • DeepSeek:工具调用 Finishcheck-goosed-v149-deepseek-tools.mjs);reasoning 保留单测(check-goosed-v149-thinking-preservation.mjs );:18036 no-think 代理与 Portal replay 仍保留。
  • upstream web-searchload_skill 路径 smokecheck-goosed-v149-skills-smoke.mjs);TKMind platform/web 仍为主 H5 契约。
  • costusage、cache token、accumulated_cost、估算回退与账单金额对照(check-goosed-v149-cost-smoke.mjsdocs/baselines/goose-v149-cost-evidence-*.json)。
  • message sanitizeprovider 层单测 v1.41≈v1.49compare-goose-v149-message-sanitize.mjs );Portal 多模态/历史展示路径仍保留对照。
  • Memory 对账:逐用户逐 ID/hash/status/source/evidence 对照(compare-goose-v149-memory-manifest.mjs )。
  • Memory 故障演练:legacy owner 超时 fail-open 不中断(check-goosed-v149-memory-failopen.mjs);向量→legacy 自动回退待 pgvector canary 时再验。
  • 每项记录“通过 / 保留 / 回滚”,不得一次性批量删除(台账:docs/goose-v149-phase2-evidence.md)。

Phase 2 聚合入口: node scripts/run-goosed-v149-phase2.mjs

Phase 3 收口入口: node scripts/run-goosed-v149-phase3.mjs · 清单:docs/goose-v149-phase3-closeout.md

Phase 3:退役与收口

  • 只删除已取得 canary 证据的重复逻辑(当前:无删除项;见 Phase 3 清单)。
  • 保留薄封装入口、feature flag 与回滚说明(canary runbook + switch-goose-v149-canary.sh)。
  • 更新 runtime 文档、证据链接与 Phase 3 合并闸门(docs/goose-v149-phase3-closeout.mddocs/baselines/README.md)。
  • 本地连续验证 + Memory manifest 无 driftrun-goosed-v149-phase3.mjs);不授权 103 操作。
  • 合并前运行影响域 verify;完成测试后再讨论 commit、合并或发布(须用户明确批准)。

必须通过的回归守卫

涉及受保护路径时,至少执行仓库约定的:

npm run verify:mindspace-publish-guards
npm run verify:mindspace-publish-guards:full
npm run verify:mindspace-page-sync-guards
npm run verify:h5-session-patches
npm run verify:seo-geo
npm run verify:seo-discovery
npm run verify:page-data

DeepSeek 兼容链路还必须覆盖 release-gate/deepseek-production-parity.test.mjs 及对应生产影响域场景。任何守卫失败时,结论只能是“保留定制并修复适配”,不能以“upstream 已支持”为理由继续退役。

Memory 本地最低验证集:

npm run check:memory-v2-contracts
npm run check:memory-v2-config
npm run check:memory-v2-session
npm run check:memory-v2-stack
node --test conversation-memory.test.mjs conversation-repair.test.mjs \
  memory-v2-personal-store.test.mjs memory-v2-lifecycle.test.mjs \
  memory-v2-pgvector-backfill.test.mjs memory-v2-runtime.test.mjs

以上命令只验证本地代码/fixture;若要使用真实本地 MySQL/PG,必须先确认连接字符串是 loopback 隔离库,并把 count、ID/hash、关联和 watermark 对账结果作为附件保存。任何测试失败、数据 drift、owner 不明确或无法证明回滚时,Memory 迁移保持 blocked,不得进入生产。

一句话结论

跟随升级,但不做 upstream 全量替换:通用能力(搜索、浏览器、hooks、cost 追踪、DeepSeek 兼容)按证据逐步 Replace 或 WrapperMindSpace、Page Data、微信、计费、权限、PG 多实例与 H5/Portal 契约必须 Keep。