# Context Runtime + Agent Harness 融合实施方案 > 状态:**方案已定稿;Context Runtime Phase 1–6 尚未授权产品代码改动**。v1.49 收口与 Phase 0 清理可并行推进(2026-09-09)。 > 生成日期:2026-09-09 > 关联规范:[AGENTS.md](../AGENTS.md) · [ENGINEERING_WORKFLOW_RULES.md](../ENGINEERING_WORKFLOW_RULES.md) · [PRODUCTION_RELEASE_RULES.md](../PRODUCTION_RELEASE_RULES.md) · [docs/production-release-guardian.md](./production-release-guardian.md) > 关联现状:[docs/memory-v2/README.md](./memory-v2/README.md) · [docs/goose-v149-phase3-closeout.md](./goose-v149-phase3-closeout.md) · [docs/goose-v149-canary-runbook.md](./goose-v149-canary-runbook.md) ## 0. 本方案要解决的问题 MeMind 当前不缺 Agent 执行能力,缺的是一层统一的 **Context Runtime**(这一刻 Agent 该知道什么)与可插拔的 **Agent Harness**(谁来组装、谁来裁决)。 Memory V2 在设计上明确**不是** context runtime: > Memory V2 is a facade and policy abstraction layer over existing Memind memory systems. > It is not a new memory system. > —— `docs/memory-v2/README.md` 因此 `Memory ≠ Context` 的分层是成立的:Memory 回答「过去有什么值得记住」,Context Runtime 回答「这一刻这个 Agent 为完成任务应该知道什么」。 ### 现存的四套并行上下文注入 | 管道 | 位置 | 现状问题 | |---|---|---| | Portal 编排注入 | `chat-intent-router.mjs` → `【Memind 任务编排】` | 与 Goose harness 内容可能重复 | | Goose harness | `session-reconcile.mjs` → `/agent/harness_remember` | 只覆盖 workspace 记忆,不管 tool output | | Direct Chat system prompt | `direct-chat-service.mjs` | 第三套独立 memory 解析 | | Session compaction | goosed 内部 | Portal 侧无 tool result index,压缩后状态丢失 | 四套互不知情,没有统一预算、没有去重、没有单一 trace。 --- ## 1. 关键可行性约束(必须先理解) ### 1.1 工具结果拦截边界 `context-mode` 的 98% 压缩来自 hook 在工具结果**进入模型上下文之前**拦截替换,前提是它与 agent 同进程并握有 `PreToolUse` / `PostToolUse` 钩子。 MeMind 的拓扑不同: ``` tkmind-proxy ──HTTP──> goosed ──> MCP tool 执行 │ │ │ 结果回 goosed │ ↓ │ goosed 内部拼 LLM 请求 ← 上下文在此已膨胀 ↓ SSE 事件流 ──> tkmind-proxy ← Portal 只在此看到,已是事后 ``` **推论:在 Portal 侧(`agent-run-gateway.mjs` / `tkmind-proxy.mjs`)建 tool result index,只能得到可观测性、replay、审计,拿不到任何 token 节省。** 真正能省 token 的只有两条路: | 路径 | 落点 | 版本依赖 | 可行性 | |---|---|---|---| | **B 路** | MeMind 自有 MCP 在 return 前自压缩 | 无 | **今天即可做** | | **C 路** | 改 goosed 加通用 hook | 绑 1.49 | 需 `tkmind_go-v149`,成本高 | MeMind 自有三个 stdio MCP server,由 goosed spawn 但代码在本仓库(见 `capabilities.mjs` 约 808–877 行): - `tkmind-search` → `tkmind-search-mcp.mjs`(`tkmind_search` / `tkmind_read` / `tkmind_research`) - `tkmind-excel` → `tkmind-excel-mcp.mjs`(`excel_inspect` / `excel_analyze` / `excel_chart` / `excel_report`) - mindspace sandbox → `mindspace-sandbox-mcp.mjs` `tkmind_read` 单次可返回 `TKMIND_SEARCH_READER_MAX_CHARS`(默认 12000)字符,`tkmind_research` 报告更大。这些结果**在 MeMind 自己的进程内生成**,可在 return 前压缩为「摘要 + handle」,goosed 拿到的就已经是小结果。 ### 1.2 受保护路径与 Gate 成本 `AGENTS.md` 受保护关键路径包含 `tkmind-proxy.mjs`、`server.mjs`、`wechat-mp.mjs`、`session-reconcile.mjs` 等。改动这些会触发 Core + Impact Gate 的影响域展开。 `tkmind-search-mcp.mjs` / `tkmind-excel-mcp.mjs` **不在**保护清单内,验证成本低一个量级。这是 B 路优先的第二个理由。 ### 1.3 现有技术栈约束 - MCP 协议为**手写 stdio JSON-RPC**(`tkmind-search-mcp.mjs` 用 `node:readline`),**无 MCP SDK 依赖** - `package.json` 依赖中**没有 SQLite**,但有 `redis` / `pg` / `mysql2` - 本机 Node v26 **推论**: - 若**自研**压缩器,全量存储用 Redis 或 PG,不引入 `better-sqlite3` 等原生依赖,避免污染 `release-portal-runtime-prod.sh` 的整包构建与跨平台交付 - 若**直接挂载**外部 MCP(见第 6 节),它作为独立 stdio 进程自带存储,不进 Portal 依赖树;Node ≥ 22.5 的项目会走内置 `node:sqlite`,同样无原生编译 ### 1.4 v1.49 定位澄清 v1.49 当前状态: - 分支 `feature/goose-v149-local-canary`,**4 个 commit 未进 `origin/main`** - `docs/goose-v149-phase3-closeout.md`:Phase 3 收口,**本阶段不授权 103/105 操作** - 生产仍是 1.41 stable(`:18006`–`:18014`),1.49 仅本地 loopback `:18049` - `goose-canary-memory-policy.mjs` **硬锁** canary 期 memory 为 legacy,vector / injection / lifecycle 全关 本方案的工作落在三个互相独立的变更面: | 面 | 仓库 | 版本依赖 | 内容 | |---|---|---|---| | **A. Portal 编排** | `Memind` | **版本无关** | Injection Budget、Recall Fusion、Harness plugin 化 | | **B. MeMind 自有 MCP** | `Memind` | **版本无关** | Tool result 压缩 | | **C. Goose 运行时** | `tkmind_go-v149` | **绑 1.49** | 通用 PreToolUse hook | > **设计原则 #0:A / B 面强制版本无关,必须能在 stable 1.41 上独立验证与独立上线,不等 1.49。** > 理由:1.49 本身未闭环,Context Runtime 又要动 memory 注入。两个未闭环大改动叠加会让故障归因不可能,且 `switch-goose-v149-canary.sh rollback` 回落 stable 时新层是否成立说不清。 --- ## 2. 设计原则 沿用 Memory V2 已在本仓库验证过的形状,**不另创范式**: 1. **旁挂不改主干** —— 新增独立模块,主干只加薄调用点 2. **默认全关** —— 所有开关默认 `off`,env + `memind_adm` 双控 3. **fail-open** —— 新层任何异常退回现有行为,绝不阻塞 4. **shadow 先行** —— 先只观测记录不改行为,拿到证据再 canary → active 5. **版本无关** —— A / B 面不引用任何 v149-only 接口 6. **不新增原生依赖** —— 存储复用 Redis / PG --- ## 3. 目标架构 ``` User → agent-run-routes │ ┌─────┴───────────────────────────────────┐ │ Context Runtime(新增,A 面) │ │ · Injection Budget 统一 token 预算 │ │ · Recall Fusion 三路召回合并去重 │ │ · Trace 单一可观测事件 │ └─────┬───────────────────────────────────┘ │ Agent Harness(重构 agent-run-gateway,A 面) │ tkmind-proxy → goosed │ ┌─────┴──────────────────────┐ │ MeMind 自有 MCP(B 面) │ │ · Result Compaction │ │ · handle + ctx_fetch │ └────────────────────────────┘ │ Compute Fabric(PAIR,Phase 6) ``` ### 落点对照 | 新能力 | 新增模块 | 薄调用点(现有文件) | 受保护路径 | |---|---|---|---| | Tool Result 压缩 | `mcp-result-compactor.mjs` | `tkmind-search-mcp.mjs`、`tkmind-excel-mcp.mjs`、`capabilities.mjs` | 否 | | Injection Budget | `context-budget.mjs` | `chat-intent-router.mjs`、`session-reconcile.mjs`、`agent-run-gateway.mjs` | 部分 | | Recall Fusion | `recall-fusion.mjs` | `chat-intent-router.mjs`、`temporal-recall-service/context-planner.mjs` | 否 | | Harness plugin 化 | `harness/` 目录 | `agent-run-gateway.mjs`(3235 行拆分) | 否 | | Personal KG | `user-model-service/graph.mjs` | 复用 dormant `memory-v2-neo4j.mjs` | 否 | | Compute Router | 配置层 | provider 配置 | 是 | ### 融合点:注入预算去重 当前两条独立注入路互不知情: - `agent-run-gateway.mjs` 约 1889 行 → `chatIntentRouter.resolveAgentMemoryContext()` → Portal 编排文本 - `session-reconcile.mjs` 约 310–337 行 → `buildSessionMemoryEntries()` → `/agent/harness_remember` 两者都从 memory 取数据(一条经 `resolveAgentMemoryContext`,一条经 `resolveUserMemories`),可能写入同类信息两遍。 `context-budget.mjs` 在两者之上做**单一预算裁决 + 内容指纹去重**,输出「本次注入什么、各占多少 token」,并产出统一 trace 事件。 > 注意:`MEMORY_AGENT_INJECTION_MODE` 默认 `off`,所以这条重复今天大概率**还未真正发生**。这是好消息——**在打开 injection 之前先把预算层建好**,比打开后救火便宜得多。 --- ## 4. 分期实施 ### Phase 0 · 前置清理(硬阻断) `AGENTS.md` 单一开发分支硬闸门要求:同时只允许一个未闭环开发分支 + 一个开发 worktree。当前状态违反: | 项 | 实测 | |---|---| | worktree 1 | `/Users/john/Project/Memind` @ `feature/goose-v149-local-canary` | | worktree 2 | `/Users/john/Project/Memind-health-p0` @ `feature/memind-health-p0` | | Memind dirty | ~192(34+ 已跟踪修改 + 大量未跟踪 evidence) | | Memind 未推送 | 4 commit | | Phase 3 聚合 | 最近一次 `GOOSE_V149_PHASE3_FAIL`(multiturn / page-e2e 超时;Phase 3 段 portal-resume 已通过) | | health-p0 dirty | 95(36 M + 59 ??) | | health-p0 | 领先 2 commit,落后 origin/main 20 commit | 详见第 5 节分类处置清单。 **产出**:干净 worktree、单一分支、`origin/main` 已同步。 **闸门**:`node scripts/run-goosed-v149-phase3.mjs` → `GOOSE_V149_PHASE3_OK`;push / 合 main 须取得明确批准。 --- ### Phase 1 · Tool Result 压缩(B 面 · 版本无关 · 优先级最高) **目标**:降低 goosed context 与 token 成本。 **已决策路线:`headroom` 独立 proxy 模式**(Apache 2.0)。决策依据见 6.4。 #### 1-A · headroom provider proxy(选定方案) **为什么是 proxy 而非 MCP**:headroom 的 proxy 拦截的是**发往 LLM 的请求本身**,而工具输出正是在 goosed 内部累积进该请求。这绕过了 1.1 节标记的「必须 fork Goose」约束,**不改 Goose 也能压到真实上下文**。 ``` goosed ──> headroom proxy ──> LLM provider ↑ 在此压缩 LLM 请求 ``` MeMind 已有同形插槽:`deepseek-no-think-proxy.mjs`(`:18036`)就是 provider 层代理,headroom 并列接入。 **必须用 standalone proxy,不要用 `headroom wrap goose`。** 尽管官方兼容矩阵中 Goose 标记为 ✅(`starts proxy + launches`),但 `wrap` 会:启动 agent 会话、自动安装 Serena、注入 agent 配置。这些对服务端部署全是错的。正确做法是 `headroom proxy --port ` 独立常驻,goosed 的 provider base URL 指向它。 **部署形态**:独立 Python 进程(Python 3.10+)或 Docker(`ghcr.io/headroomlabs-ai/headroom:latest`)。 **不进 Portal 依赖树**,不影响 `release-portal-runtime-prod.sh` 整包。 **官方基准(工具调用相关)**: | Benchmark | 类别 | 准确率 | 压缩率 | |---|---|---|---| | BFCL | **Tools** | 97% | 32% | | SQuAD v2 | QA | 97% | 19% | | GSM8K | Math | ±0.000 | — | BFCL 是唯一与 tool-call 保真度直接相关的项:**32% 压缩下 97% 准确**。即约 3% 的工具调用退化率——对 MeMind 的交付契约(Page Data、MindSpace publish)而言这不是可忽略的数字,必须按轮次类型分级启用。 **硬约束(与现有回归守卫冲突,必须遵守)**: | 项 | 要求 | 原因 | |---|---|---| | `HEADROOM_OUTPUT_SHAPER` | **必须保持 `0`(默认)** | 它会下调 thinking effort(`reasoning_effort` / `thinking.budget_tokens`),直接冲突 `check-goosed-v149-thinking-preservation.mjs` 与 `deepseek-no-think-proxy.mjs` 的 reasoning 保留策略 | | `headroom learn` | **禁止运行** | 会改写 `CLAUDE.md` / `AGENTS.md`,违反本仓库规则文件管理 | | `headroom wrap` | **禁止使用** | 会安装 Serena、注入 agent 配置、启动交互会话 | | `POST /admin/runtime-env` | 须限制为 loopback | headroom 的运行时配置热更新端点,103 上不得暴露 | | 页面生成 / code 任务轮次 | 首期**排除** | 交付契约对 tool-call 保真度零容忍 | **开关**:`MEMIND_HEADROOM_MODE = off | shadow | active`,默认 `off`。 shadow 期用 `HEADROOM_OUTPUT_HOLDOUT` 留对照组,取 measured 而非 estimated 数据。 **待验证项(Phase 1 前置)**: 1. **多租户** —— 一个 proxy 服务多用户并发,CCR store 是 local-first,需实测请求级隔离无串档 2. **保真度** —— 在 MeMind 真实轮次上复现 BFCL 级别准确率,特别是 `edit_file` / Page Data 工具链 3. **Python 3.10+ on 103** —— Mac Studio 环境确认;native wheel 覆盖 macOS Apple Silicon 4. **失败降级** —— proxy 不可用时必须直连 provider,不得阻塞(对齐 fail-open 原则) **观测**:`headroom doctor` / `headroom dashboard` / `headroom output-savings` **回滚**:goosed provider base URL 指回原 provider,proxy 进程独立停止,零代码残留。 #### 1-B · 自研 `mcp-result-compactor.mjs`(备选,仅在 1-A 验证失败时启用) - `compact(payload, { budget, kind })` → `{ summary, handle, stats }` - 全量存 **Redis**(复用现有 `redis` 依赖)+ TTL;无 Redis 时 fail-open 返回原始 payload - 新增 `ctx_fetch(handle)` 工具按需取回全量 - 记录 `rawBytes` / `sentBytes` / `savedRatio`,对齐 context-mode 的 savings 计量口径 **薄调用点**: - `tkmind-search-mcp.mjs` —— `tkmind_read` / `tkmind_research` / `tkmind_research_status` 结果过压缩器 - `tkmind-excel-mcp.mjs` —— `excel_report` / `excel_analyze` 同理 - `capabilities.mjs` —— `available_tools` 在开关开启时追加 `ctx_fetch` **开关**:`MEMIND_MCP_COMPACT_MODE = off | shadow | active`,默认 `off`。 shadow 只记录「本来会省多少」,不改返回值。 **验证**: ```bash node --test mcp-result-compactor.test.mjs # 新增单测 node scripts/check-goosed-v149-web-smoke.mjs # tkmind_search / read 路径 node scripts/check-goosed-v149-skills-smoke.mjs node scripts/check-goosed-v149-memory-policy.mjs # 守住 canary memory 硬锁 # 并在 stable 1.41 :18006 上重跑一遍,证明版本无关 ``` **回滚**:单一 env 置 `off`,MCP 返回原始 payload,零残留。 **不碰**:`tkmind-proxy.mjs`、`server.mjs`、`session-reconcile.mjs`。 --- ### Phase 2 · Injection Budget(A 面 · 稳定性收益最大) **目标**:在打开 memory injection 之前,先建立单一预算裁决与去重。 **新增** `context-budget.mjs`: - `plan({ memories, temporal, goal, harness, skillPrompt, policy })` → `{ blocks, droppedItems, totalChars, fingerprints }` - 内容指纹去重,跨 Portal 编排块与 harness 条目 - 硬上限 + 优先级降级:超预算时先丢什么有明确规则 **薄调用点**: - `chat-intent-router.mjs` —— `buildAgentOrchestrationAgentText` 前置调用 budget - `session-reconcile.mjs` —— `buildSessionMemoryEntries` 输出经同一 budget 过滤 - `agent-run-gateway.mjs` —— 新增 `context_budget_resolved` 事件,替代分散的 `agent_memory_resolved` / `runtime_context_resolved` 拼图 **开关**:`MEMIND_CONTEXT_BUDGET_MODE = off | shadow | active`,默认 `off`。 **验证**: ```bash node --test chat-intent-router.test.mjs # 补预算/去重用例 node --test session-reconcile.test.mjs node scripts/check-goosed-v149-session-reconcile.mjs node scripts/check-goosed-v149-harness.mjs node scripts/check-goosed-v149-memory-loop.mjs node scripts/check-goosed-v149-memory-chat.mjs node scripts/check-goosed-v149-memory-policy.mjs # 必须仍然通过 node scripts/compare-goose-v149-memory-manifest.mjs # manifest 无 drift ``` **硬约束**:Phase 2 **不得**打开 `MEMORY_AGENT_INJECTION_MODE`。预算层先建好、先 shadow 观测;打开 injection 是独立决策、独立审批。 --- ### Phase 3 · Recall Fusion + Hybrid(A 面) **目标**:memory / temporal / episodic 三路召回合并排序,激活语义检索。 **新增** `recall-fusion.mjs`:query 解析(时间 / 实体 / 关键词)→ 三路并行取候选 → 融合排序(借 zvec-grep 的 fuse 思路)→ 按预算截断 → 单一格式化。 **薄调用点**:`chat-intent-router.mjs`、`temporal-recall-service/context-planner.mjs` **可选**:激活 `memory-v2-pgvector.mjs` 的 `resolve()`(write / compact 仍走 legacy,与现有设计一致) **验证**: ```bash node --test memory-v2-runtime.test.mjs npm run check:memory-v2-contracts -- --include-pgvector-adapter node scripts/check-goosed-v149-memory-verbal-recall.mjs ``` **依赖**:Phase 2 预算层必须已就位,否则融合结果会直接撑爆上下文。 --- ### Phase 4 · Harness Plugin 化(A 面 · 重构 · 风险最高) **目标**:`agent-run-gateway.mjs`(3235 行)拆成 core + plugin slots,借 Cordis 的 service / event / reversible-effect 模型。 **新增** `harness/`: - `core.mjs` —— context + service registry + lifecycle - `plugins/memory.mjs`、`plugins/context-budget.mjs`、`plugins/skill-router.mjs`、`plugins/goose-execution.mjs`、`plugins/tool-gateway.mjs`、`plugins/telemetry.mjs` **方式**:**纯行为等价重构,先不加任何新功能**。每抽出一个 plugin 就跑全量 v149 smoke 对比,确认零行为变化再抽下一个。 **验证**:`node --test agent-run-gateway.test.mjs` 全绿 + `node scripts/check-goosed-v149-all.mjs` 前后输出一致 **时机**:1.49 完全闭环、Phase 1–3 已上生产并稳定运行之后。 --- ### Phase 5 · Personal KG(长期) 扩展 `user-model-service/` 的 entity 抽取(Person / Project / Intent / Event),借 codebase-memory-mcp 的 node/edge schema 与增量 watcher 模型,复用 dormant 的 `memory-v2-neo4j.mjs` slot。独立灰度,不进主聊天路径直到有明确收益证据。 类比映射: | codebase-memory-mcp | MeMind Personal KG | |---|---| | Repository | User Life Stream | | Tree-sitter AST | Event Parser(聊天 / 输入法 / 日历 / Agent trace) | | Function / Class 节点 | Person / Project / Intent / Event 节点 | | CALLS 边 | RELATES_TO / MENTIONED / SCHEDULED | | `get_architecture` | `get_user_context_snapshot` | --- ### Phase 6 · PAIR Compute Fabric(基础设施 · 可并行) 103 / 105 / home lab 试点 PAIR cluster,Goose provider 与 Direct Chat 指向 PAIR 的 OpenAI-compatible endpoint。 **关键约束(PAIR 官方明确)**:PAIR 按请求路由到单节点,**不做显存池化**、不跨机分片模型。大模型仍须单节点放得下。它解决的是并发请求分发。 与 Phase 1–4 无代码耦合,可独立试点。但涉及 provider 配置(受保护路径),需单独 Gate。 --- ## 5. Phase 0 分类处置清单 ### 5.1 Memind 主 worktree(163 项) #### A 组 · v1.49 核心交付(应提交) 已跟踪修改,与 4 个未推送 commit 同属 v149 canary 工作: ``` agent-run-gateway.mjs session-reconcile.mjs chat-intent-router.mjs session-reconcile.test.mjs chat-intent-router-rules.mjs tkmind-proxy.mjs chat-intent-router.test.mjs goose-message.mjs chat-skills.mjs memory-v2-runtime.mjs chat-skills.test.mjs memory-v2-runtime.test.mjs scripts/agent-run-worker.mjs scripts/check-goosed-v149-all.mjs scripts/check-goosed-v149-local.mjs scripts/check-goosed-v149-memory-policy.mjs scripts/check-goosed-v149-portal-resume.mjs scripts/check-goosed-v149-portal-smoke.mjs scripts/check-goosed-v149-session-reconcile.mjs scripts/compare-goose-v149-message-sanitize.mjs scripts/goose-v149-canary.mjs scripts/run-goosed-v149-phase2.mjs scripts/run-goosed-v149-phase3.mjs ``` 未跟踪新文件,同属 v149 交付: ``` goose-canary-memory-policy.mjs scripts/check-goosed-v149-memory-chat.mjs scripts/check-goosed-v149-memory-verbal-recall.mjs scripts/check-goosed-v149-multiturn-provider.mjs scripts/check-goosed-v149-no-think-evidence.mjs scripts/check-goosed-v149-page-data-evidence.mjs scripts/check-goosed-v149-page-e2e.mjs scripts/check-goosed-v149-session-affinity-evidence.mjs scripts/check-goosed-v149-wechat-evidence.mjs scripts/goose-v149-check-result.mjs scripts/goose-v149-check-result.test.mjs scripts/goose-v149-source-baseline.mjs scripts/run-goosed-v149-missing-evidence.mjs ``` 处置:与现有 4 commit 一并整理为 v149 收口提交。 #### B 组 · 与 v1.49 无关,需独立决策 ``` scheduled-task-executor.mjs scheduled-task-executor.test.mjs scheduled-task-worker.mjs user-auth.mjs user-auth.test.mjs wechat-intent-router.test.mjs wechat/intent/patterns.mjs ``` 处置:这 7 项混在 v149 分支里会污染 v149 的可追溯性。建议评估能否单独成 commit,或确认它们确实是 v149 适配的必要副产物。 #### C 组 · 一次性运维脚本(建议不入库或移出) ``` scripts/deploy-yaodingdang-teacher-day-103.mjs scripts/reactivate-icyxu-medication-reminder-103.mjs scripts/multiturn-ping-custom.mjs scripts/multiturn-ping-debug.mjs scripts/multiturn-ping-single.mjs scripts/assets/hulunbeier-travel-guide-202609.html scripts/assets/shenmei-teacher-day-tribute-2026.html ``` 处置:一次性投放 / 调试脚本与页面资产。建议移到仓库外或明确归档位置,避免长期堆积在 `scripts/`。 #### D 组 · 临时探针(应删除) ``` tmp-probe-run.mjs ``` #### E 组 · Baseline 证据文件(109 未跟踪 + 已跟踪 18 个时间戳文件) 实测: | 项 | 数量 | |---|---| | `docs/baselines/` 总文件 | 132 | | 已跟踪 | 24 | | 未跟踪 | 109 | | 目录体积 | 3.7 MB | | `.gitignore` baseline 规则 | **无** | `docs/baselines/README.md` 列出的**语义基线**是 `-latest.json` 与 `-current.json` 系列: ``` goose-v149-memory-latest.json goose-v149-memory-current.json goose-v149-message-sanitize-latest.json goose-v149-thinking-preservation-latest.json goose-v149-runtime-baseline-*.json ``` 而 `*-evidence-2026-*.json` 是**每次 smoke 的一次性产物**。当前已有 9 个 cost-evidence + 9 个 deepseek-tools-evidence 被跟踪(推测是早期误入库),另有 109 个未跟踪。 **建议处置**: 1. `.gitignore` 增加 `docs/baselines/*-evidence-*.json` 2. 保留 `-latest` / `-current` / `runtime-baseline` 作为可追溯语义基线 3. 已误入库的 18 个时间戳 evidence 文件评估是否 `git rm --cached` 4. `scripts/check-goosed-v149-all.mjs` 已有 `refreshMemoryBaselineAfterSmoke()` 自动刷新 `-latest`,与上述策略一致 > 注意:`docs/production-release-guardian.md` 的 Gate report 需要与 commit / runtime artifact 绑定的证据。移除 evidence 入库前,须确认 Gate 不依赖这些时间戳文件在 Git 中的存在。 ### 5.2 health-p0 worktree(95 项) ``` worktree: /Users/john/Project/Memind-health-p0 branch: feature/memind-health-p0 dirty: 95(36 M + 59 ??) 领先: 2 commit(health channel kernel + H5 health page/WeChat/observation API) 落后: origin/main 20 commit ``` 按 `AGENTS.md` 规则 3,需要明确处置:完成闭环并入 main,或登记为「禁止再次引用」后删除 worktree。落后 20 commit 意味着不能直接作为合并来源。 **这是唯一必须先做决策的项**——两个 worktree 并存本身就阻断新分支创建。 --- ## 6. 外部项目引入方式 **核心结论:五个 repo 中四个可以直接安装并挂进 MeMind 运行时。** 唯一卡点是 `context-mode` 的 ELv2 许可证,且那是商务/法务决策而非工程问题。 「借架构自研」只应用在**没有现成项目可装**的地方,而那个范围比初版方案估计的小得多(见 6.5)。 ### 6.1 为什么直接挂载是可行的 MeMind 的 Goose extension 机制本来就是**通用 stdio MCP 挂载点**(`capabilities.mjs` 约 808–850 行): ```js extensions.push({ type: 'stdio', name: 'tkmind-search', bundled: false, cmd: resolveSandboxMcpNodeExecPath(...), args: [ ...mcpServerPath ], envs: { TKMIND_SEARCH_USER_ID: userId, ... }, // ← per-user env 注入 available_tools: ['tkmind_search', 'tkmind_read'], // ← 生效的工具白名单 }); ``` 三个关键事实使直接挂载成立: | 事实 | 依据 | 解决的疑虑 | |---|---|---| | extension 按用户/会话动态构建,可注入 per-user env | `TKMIND_SEARCH_USER_ID`、`MINDSPACE_WORKSPACE_ROOT` 现成先例 | **多租户隔离** | | `available_tools` 是生效白名单 | `makeExtension('platform','developer',['read_image'])`;AGENTS.md「带图轮次必须摘掉 `read_image`」 | **危险工具可摘除** | | Node ≥ 22.5 自动用内置 `node:sqlite` | context-mode README;本机 Node v26 | **无原生编译依赖** | ### 6.2 逐项决策(修正版) | Repo | License | 决策 | 落点 | |---|---|---|---| | `headroomlabs-ai/headroom` | Apache 2.0 | **直接装(Phase 1 选定)** | provider proxy,goosed → headroom → LLM | | `DeusData/codebase-memory-mcp` | MIT | **直接装** | ① Cursor 开发工具;② 挂给 code 任务(`tool-gateway` aider/openhands 路径) | | `zvec-ai/zvec-grep` | Apache 2.0 | **直接装** | ① Cursor 开发工具;② 挂给用户 workspace 检索 | | `deepseek-ai/deepseek-harness` | MIT | **直接装(改用法)** | 作为第 4 个 code executor 并列,**不是**替换 goosed | | `NVIDIA/Personal-AI-Router` | Apache 2.0 | **直接装** | Phase 6 基础设施,103/105/home lab | | `mksglu/context-mode` | **ELv2** | **产品集成排除** | 见 6.4;仅可作个人开发工具 | | `Open330/context-compress` | 标称 MIT | **不采用** | 见 6.4 许可证风险 | ### 6.3 `deepseek-harness` 用法修正 初版按「替换 goosed」评估,成本极高。但 MeMind 已是多 executor 架构: ```js // tool-gateway.mjs const BASE_CODE_EXECUTORS = ['aider', 'openhands']; // cursor 后加入,走同一套 selectExecutor + launch plan + env 开关 ``` `cursor` 就是后加进来的。**加 `dsh` 是同一模式,不是重写 harness**: - `codeExecutorsForEnv()` 增加 `dsh`,默认关闭 - `MEMIND_TOOL_GATEWAY_DSH_TASK_TYPES` 按 task type 路由 - 复用现有 `assertRequiredCodeExecutorAvailable` 与 fallback 机制 风险:dsh 处于 developer preview,官方声明会有 breaking changes。对策:默认关闭 + 按 task type 白名单 + 现有 executor fallback 路径。 ### 6.4 `context-mode` 排除决策(已定) ELv2 限制条款原文: > You may not provide the software to third parties as a hosted or managed service, where the service provides users with access to any **substantial set of the features or functionality** of the software. **已决策(2026-09-09)**:MeMind 是带计费的托管服务(tkmind.cn / 103 生产 / h5 用户),其 `ctx_*` 能力经 Agent 提供给付费用户,**属于产品功能**,因此落入 ELv2 禁止范围。 **结论**: - `context-mode` **排除于 MeMind 产品集成**,不得挂进 goosed、不得进入任何 103 部署 - 个人本机开发工具用途属 ELv2 许可的 `use`,不受限 - **不得将其源码或实现逻辑抄进 MeMind**。ELv2 允许 derivative works,但要求「anyone who gets a copy of any part of the software from you also gets a copy of these terms」——抄代码会让 MeMind 相关部分继承 ELv2 - 自研 1-B 时只可参考其 README / 公开 benchmark 层面的**概念**(sandbox、handle、FTS5+BM25 检索),不读实现、不照搬结构 **`Open330/context-compress` 同样排除**:其 README 自述「Based on context-mode」,却标称 MIT。ELv2 衍生作品要求传递原条款,将其重新许可为 MIT 的合法性存疑。且该仓库仅 1 star,无生产可信度。 **替代方案**:`headroom`(Apache 2.0),见 6.4.1。 ### 6.4.1 为什么 `headroom` 是更优解 | 维度 | `context-mode` | `headroom` | |---|---|---| | License | ELv2(与托管服务冲突) | **Apache 2.0** | | Goose 支持 | 无 | **官方兼容矩阵 ✅** | | 拦截点 | MCP 工具层 | **LLM 请求层** | | Goose 无 hook 时节省 | ~60% | 不受 hook 限制 | | 需改 Goose | 通用覆盖需 fork | **不需要** | | 部署 | Node 进程 | 独立 Python 进程 / Docker | | Stars | 21.4K | 67.5K | 关键优势是**拦截点更靠后**:proxy 拦 LLM 请求,覆盖 goosed 内部已累积的全部上下文,包括上游 `platform/developer`、`platform/web` 等 MeMind 不拥有的工具输出。这正是 1.1 节标记为「C 路需 fork Goose」的部分,headroom 用 proxy 位置直接解决。 风险与硬约束见第 4 节 Phase 1-A。 ### 6.5 仍需自研的范围 **只剩 Injection Budget + Recall Fusion(Phase 2 + Phase 3)。** Phase 1 已由 `headroom` 覆盖。 原因:这两项要做的是「把 MySQL `h5_user_memory_items` 的 legacy memory + `temporal-recall-service` 时间线 + `episodic-memory` 三路合并去重、按 token 预算裁决,并同时约束 Portal 编排块与 `/agent/harness_remember` 两条注入路」。 这是 MeMind 特有的数据形状与特有的双注入拓扑。外部项目不知道 `h5_user_memory_items` 或 `/agent/harness_remember` 的存在,无法替代。 Phase 4(Harness plugin 化)仍是自研重构,但优先级可下调——若 `dsh` 作为 executor 验证顺利,其 Cordis 模型的价值可先在小范围观察。 ### 6.6 开发工具安装(Phase 0 之后) 装在本机、不触碰 MeMind 运行时,**不受发布闸门约束**,但建议 Phase 0 清理完成后再装,避免在脏工作区引入配置变更。 ```bash # zvec-grep(Apache 2.0,Node ≥22,本机 v26 满足) npm install -g @zvec/zvec-grep cd /Users/john/Project/Memind zg index --embedding local/potion-retrieval-32m # 索引落在 .zvec-grep/ # codebase-memory-mcp(MIT,原生二进制) curl -fsSL https://raw.githubusercontent.com/DeusData/codebase-memory-mcp/main/install.sh | bash # 重启 Cursor 后对 agent 说 "Index this project" ``` **必须同时处理**: - 两者都在项目根写索引目录(`.zvec-grep/` 等),需加 `.gitignore` - `codebase-memory-mcp` 的 `install` 会**改写 `~/.cursor` 下的 MCP 配置**,这是其设计意图,安装前应知情 ### 6.7 明确不做的事 - ❌ 用 `dsh` **替换** goosed —— 生产路径是 Goose + `tkmind-proxy`;作为并列 executor 可以,替换不行 - ❌ 把 `codebase-memory-mcp` 用于个人生活流 —— 它是 162 语言 tree-sitter parser,只适用于代码库;个人 KG(Phase 5)只借其 schema 思想 - ❌ 把 `zvec-grep` 当个人记忆主检索 —— 它是 workspace/file 导向;「我这周有什么重要事情」必须走 Personal Retrieval - ❌ 向端用户暴露 `ctx_execute` 或任何任意代码执行工具 —— 必须经 `available_tools` 白名单摘除 - ❌ 指望 PAIR 做显存池化 —— 官方明确不支持 - ❌ 将 `context-mode` 或其衍生实现引入 MeMind 产品(ELv2,已决策排除) - ❌ 使用 `headroom wrap` —— 会安装 Serena、注入 agent 配置、启动交互会话 - ❌ 运行 `headroom learn` —— 会改写 `CLAUDE.md` / `AGENTS.md` - ❌ 开启 `HEADROOM_OUTPUT_SHAPER` —— 会下调 thinking effort,冲突 reasoning 保留守卫 --- ## 7. 收益与风险 ### 收益 | 项 | 机制 | |---|---| | 上下文污染可控 | 单一预算裁决 + 指纹去重,替代四套并行注入 | | token 成本下降 | B 面 MCP 自压缩,直接减少 goosed 输入 | | 可观测性 | 单条 `context_budget_resolved` trace 替代分散事件拼图 | | 回滚粒度 | 每期一个 env 开关,独立回滚 | | 主干可维护 | 3235 行 gateway 拆成可测 plugin | ### 风险与对策 | 风险 | 对策 | |---|---| | 重构引入回归 | Phase 4 严格行为等价,逐个 plugin 抽取 + 全量 smoke 前后对比 | | 与 1.49 迁移互相干扰 | A / B 面强制版本无关,在 stable 1.41 上独立验证 | | 破坏 canary memory 硬锁 | 每期必跑 `check-goosed-v149-memory-policy.mjs` | | 触发大范围 Impact Gate | 优先改非保护路径;Phase 1 完全避开保护清单 | | 压缩丢关键信息 | shadow 期只观测;`ctx_fetch` 保留全量取回 | | 新增原生依赖污染整包 | 存储复用 Redis / PG,禁止引入 SQLite 原生模块 | --- ## 8. 待决策项 1. **health-p0 worktree 处置** —— 闭环入 main 还是登记禁用后删除(阻断所有后续工作) 2. **B 组 7 个非 v149 文件** —— 是否单独成 commit 3. **E 组 evidence 文件策略** —— `.gitignore` + 已入库 18 个是否 `git rm --cached`(须先确认 Gate 不依赖) 4. **是否接受 A / B 面不等 1.49** —— Phase 1–3 在 stable 1.41 上做完并可独立上生产 5. ~~`context-mode` 的 ELv2 许可证~~ —— **已决策 2026-09-09**:属产品功能,排除;Phase 1 改用 `headroom`(Apache 2.0) 6. **`dsh` 是否作为第 4 个 code executor 引入** —— developer preview 风险 vs 快速验证 Cordis 模型 7. **headroom 保真度门槛** —— BFCL 显示 32% 压缩下 97% 准确,约 3% 工具调用退化。需定义 MeMind 可接受阈值与分级启用范围(首期建议排除页面生成与 code 任务) ## 9. 变更记录 | 日期 | 变更 | |---|---| | 2026-09-09 | 初版:五 repo 评估,结论「零个进产品运行时」 | | 2026-09-09 | 修正一:四个可直接装。原生依赖、多租户、`dsh` 用法三处判断错误已纠正 | | 2026-09-09 | 修正二:`context-mode` 按 ELv2 排除产品集成;Phase 1 改为 `headroom` provider proxy | | 2026-09-09 | Phase 0 推进:`.gitignore` 排除 `*-evidence-*.json`;multiturn smoke 默认超时 90s→300s |