1d165bc6e3
Expand Goose v1.49 smoke coverage (memory chat, portal resume, page e2e, multiturn provider), add canary memory policy lock, refresh baselines, and ignore one-off evidence artifacts. Document headroom-based context runtime fusion plan; include auth, scheduled-task, and wechat intent fixes on branch. Co-authored-by: Cursor <cursoragent@cursor.com>
689 lines
34 KiB
Markdown
689 lines
34 KiB
Markdown
# 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 <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 |
|