claude-mem Server Beta 发布就绪验证:独立 BullMQ 观测运行时的 Phase 13 终局门禁
本文基于 claude-mem 仓库中的发布就绪报告 docs/server-release-readiness.md,系统拆解 Server Beta(独立 BullMQ 观测运行时)如何通过 Phase 13 终局验证门禁:从全量测试回归分析、反模式 Grep 守门、Docker E2E 全生命周期断言,到构建与类型检查基线对齐,最终给出“可发布(带已记录延期项)”的判定依据。读完本文,你将掌握一套可复用的“发布就绪验证”方法论,并能对照仓库源码逐条核验该结论的出处。
1. 验证对象与总体结论
报告验证的是分支 server-beta-phase-4-event-pipeline 上的 Server Beta 运行时,其参考计划为 plans/2026-05-07-server-beta-independent-bullmq-observation-runtime.md 中的 Phase 13(Final Verification Gate)。验证于 2026-05-08 由只读验证模式(read-only verification mode,不做任何实现改动)的 Phase 13 Final Verification 子代理完成。
Phase 13 的定位在计划文档中写得很明确:“Phase 13 不是一个实现阶段,而是证明独立实现的 Server beta 运行时完整、持久、且仍与遗留 worker 运行时兼容的最终发布门禁”(计划文档 Phase 13 一节)。
总体结论(Verdict):READY TO SHIP — with documented deferred items(可发布,附带已记录的延期项)。支撑该结论的四个支柱:
- Phase 13 全部退出标准(exit criteria)满足;
- 相对
main基线,零新增测试回归; - Docker E2E 通过完整生命周期:事件提交 → 观测生成 → 重启持久化 → 吊销密钥拒绝 → 无 worker 进程断言;
- Server-beta 运行时不包含任何对遗留 worker 运行时的导入。所有延期项均为显式范围界定的后续跟进项,不阻塞独立运行时门禁。
2. 测试结果矩阵
2.1 全量扫描(bun test tests/)
| 分支 | pass | skip | fail |
|---|---|---|---|
main(基线) |
1665 | 9 | 55 |
server-beta-phase-4-event-pipeline |
1749 | 19 | 45 |
该分支净增 84 个测试,并把失败数减少 10 个——它修复了 main 上失败的两个套件:summarizeHandler — privacy tag stripping 与 Version Consistency > worker-service.cjs。
2.2 回归分析
对去除计时后缀后的失败名集合做差集比较:
- 分支有而 main 没有的失败(真回归):
0 - 分支修复的失败(main 有、分支上消失):
10
其余 45 个分支失败全部在 main 上同样存在,属于预存基线失败(pre-existing baseline failures),不是回归。它们按套件聚簇为:
| 聚簇 | 数量 | 状态 |
|---|---|---|
GeminiProvider 套件 |
7 | 预存 API 表面不匹配 |
CORS Restriction > preflight CORS headers |
6 | 预存 |
parseAgentXml |
10 | 预存 |
server REST API v1 routes |
5 | 预存 |
Schema repair on malformed database |
3 | 预存 |
Logger Usage Standards |
2 | 预存 |
redis queue config、SessionManager queue integration、SearchRoutes Welcome Hint、SettingsDefaultsManager、WelcomeCard、ensureWorkerStarted、export-memories、updateFolderClaudeMdFiles |
12(杂项) | 全部预存 |
2.3 定向区域与 Server-beta 专属套件
- 定向区域
tests/server tests/storage/postgres tests/services tests/hooks tests/servers tests/compat tests/cli:350 pass / 12 skip / 7 fail,且这 7 个失败全部落在上表预存基线集合内,无一触及 server-beta 运行时、jobs、generation 或 storage 模块。 - Server-beta 专属套件
bun test tests/server/runtime/ tests/server/jobs/ tests/server/generation/ tests/storage/:68 pass / 9 skip / 0 fail。对应测试文件可见 tests/server/jobs/(job-id.test.ts、payload-schema.test.ts、server-job-queue.test.ts)与 tests/storage/postgres/。 - 兼容面套件
bun test tests/compat/sessions-observations-adapter.test.ts tests/hooks/server-client.test.ts:15 pass / 1 skip / 0 fail。前者对应 Claude Code PostToolUse payload 经兼容适配器进入 server 的路径(tests/compat/sessions-observations-adapter.test.ts),后者验证 hook 路由到 Server beta 的客户端行为(tests/hooks/server-client.test.ts)。
3. 四条必查 Grep:把“反模式”变成可执行断言
Phase 13 计划文档定义了四条必查 Grep(见计划文档 “Required Greps” 一节),其本质是把架构决策——“Server beta 不得依赖 WorkerService、worker HTTP 路由、worker 队列消费者或 worker 进程生命周期”——转成可在 CI 中重复执行的文本断言。报告中的执行结果:
| # | Grep | 预期 | 结果 |
|---|---|---|---|
| 1 | rg -n "new WorkerService|services/worker-service|services/worker/http/routes" src/server |
无匹配 | PASS — 输出为空 |
| 2 | rg -n "PendingMessageStore|SessionQueueProcessor" src/server |
无 server-beta 运行时导入 | PASS(带注记) — 当时有 6 处匹配,全部位于 src/server/queue/ 下实现 SQLite 引擎的类文件中,这些类由遗留 worker 经 src/services/worker/SessionManager.ts 消费;对 src/server/runtime、jobs、routes、generation、compat、mcp、services、middleware、auth 做交叉 grep 结果为空,即 server-beta 运行时路径不会拉入这些类 |
| 3 | rg -n "CLAUDE_MEM_AUTH_MODE=local-dev|ALLOW_LOCAL_DEV_BYPASS" docker docs/server.md |
文档中不存在“推荐”用法 | PASS — 所有匹配都是明确的拒绝声明:docs/server.md 的环境变量表将其列为 Docker 中不得设置的取值;“Do not enable …” 警告块;以及 local-dev 在 Docker 内被拒绝的说明 |
| 4 | rg -n "POST /v1/events|generationJob|wait=true" docs README.md |
文档描述了生成语义 | PASS — docs/api.md 记录了 POST /v1/events、POST /v1/events/batch、wait=true 查询参数与 generationJob 响应字段;docs/server.md 明确 POST /v1/events?wait=true 返回 generationJob 描述符;docs/server-parity-map.md 将遗留路由映射到 /v1/events |
3.1 源码级佐证:这些断言不是纸面文章
Grep 1 与当前源码状态一致。 在当前仓库的 src/server/ 中执行同样检索,唯一命中是 src/server/runtime/create-server-service.ts 里的一条注释——“We mirror the worker's pattern (src/services/worker-service.ts)”——是设计说明而非导入,印证了“无运行时依赖”的结论。
Grep 3 的拒绝逻辑在启动校验器中真实存在。 src/server/runtime/create-server-service.ts 显示:当处于 Docker 环境时,CLAUDE_MEM_AUTH_MODE=local-dev 会直接产生启动错误 “CLAUDE_MEM_AUTH_MODE=local-dev is not allowed in Docker. Set CLAUDE_MEM_AUTH_MODE=api-key and create a key with claude-mem server api-key create”,CLAUDE_MEM_ALLOW_LOCAL_DEV_BYPASS 为真时同样被拒绝。docs/server.md 也解释了原因:loopback 旁路依赖请求来自监听器的 127.0.0.1,这一边界在容器内没有意义,因此启动校验器会以非零退出码拒绝该组合。
Grep 2 的“注记”反映了架构边界。 需要说明:当前仓库 src/server/queue/ 目录现在只含 queue-health-types.ts 与 redis-config.ts,验证报告提到的 SQLite 引擎文件已不在 server-beta 运行时目录中——这与门禁目标(server-beta 不消费遗留 SQLite pending 队列)的方向一致,属于报告之后仓库演进的进一步收敛。
4. Docker E2E:一次可复现的全生命周期证明
结果:PASS。 执行命令为 bash scripts/e2e-server-docker.sh,它拉起 Phase 10 完整栈(Postgres + Valkey + server-beta + worker 容器)。
scripts/e2e-server-docker.sh 的头部注释即断言清单:所有断言均为 fatal,任一失败脚本即非零退出。关键实现包括:
assert_no_worker_process(脚本):先检查docker compose ps --services中不存在名为worker的遗留服务(新世代生成 worker 命名claude-mem-worker是允许的),再分别在 server 与 worker 容器内pgrep -af 'worker-service\.cjs',确保遗留 worker 进程不在任何容器里运行;assert_local_dev_rejected_in_docker(脚本):以CLAUDE_MEM_AUTH_MODE=local-dev+CLAUDE_MEM_ALLOW_LOCAL_DEV_BYPASS=1临时拉起 server-beta 容器,要求其启动失败且 stderr 包含 “local-dev is not allowed in Docker”——用“预期失败”反证启动校验器生效。
报告附带的最后一次运行输出(节选):
[e2e] phase1 starting (1778273299-31577)
[e2e] phase1 passed session=dcef676a-... event=2239a1ad-... job=629abbe8-...
[e2e] revoking read-only key inside server container
[e2e] restarting server container to verify persisted state and queue durability
Container ...claude-mem-worker-1 Started
Container ...claude-mem-server-1 Started
[e2e] verifying no legacy worker process is running
[e2e] no legacy worker processes detected
[e2e] running phase2 persistence and revoked-key checks in test container
Container ...postgres-1 Healthy
Container ...valkey-1 Healthy
[e2e] phase2 after restart starting (1778273299-31577)
[e2e] phase2 passed session=854c5a46-... event=21d53585-...
[e2e] verifying anti-pattern guards
[e2e] verifying local-dev auth is rejected inside Docker
[e2e] local-dev auth correctly rejected
[e2e] Docker server beta E2E passed for run=1778273299-31577
覆盖的验证维度:API key 认证、通用事件提交与观测生成、带 BullMQ 持久化的 server 重启、吊销密钥后的拒绝、Docker 内 local-dev 认证拒绝、无遗留 worker 进程。docs/server.md 的 “End-to-end test” 一节与之一一对应:wait=true 返回 generationJob 描述符、流中重启 claude-mem-server/claude-mem-worker 不丢数据、吊销密钥后 401/403、任一容器内无 worker-service.cjs 进程、local-dev 在 Docker 内被拒绝。
5. 手动验证清单(9 项逐条核对)
| # | 项目 | 状态 | 证据 |
|---|---|---|---|
| 1 | Worker 在遗留模式下仍可用(health、观测流) | N/A — DEFERRED LIVE | worker 定向单元/集成测试(tests/services/worker/、tests/worker/http/、tests/services/sqlite/)除 7 个与 server-beta 无关的预存基线失败外全部通过。本次验证环境无 provider 凭据,未做 live 回环;Phase 7 提交已注明 worker 回环集成测试延期(需 Redis),功能上由 Docker E2E phase1 覆盖 |
| 2 | 停止 worker — 无 PID 文件 | N/A | 本次验证未启动 worker;由 Docker E2E 在 phase1、phase2 中两次执行的 [e2e] no legacy worker processes detected 断言覆盖 |
| 3 | 带 Valkey 启动 server-beta | PASS | Docker E2E 中 claude-mem-server-1 与 valkey-1 容器均达到 Healthy |
| 4 | 提交通用 REST 事件 | PASS | Docker E2E phase1:event=2239a1ad-7983-49f3-b361-e712d29f5e7f |
| 5 | worker 未运行时观测仍出现 | PASS | Docker E2E phase1:在 [e2e] no legacy worker processes detected 状态下 job=629abbe8-... passed |
| 6 | Claude Code PostToolUse payload 经兼容适配器提交 | PASS | tests/compat/sessions-observations-adapter.test.ts + tests/hooks/server-client.test.ts:15 pass / 0 fail(Phase 9 兼容面) |
| 7 | 兼容路径下 worker 未运行仍出现观测 | PASS | 同一套件——适配器映射的事件提交在测试中端到端执行;Docker E2E 在相同事件流下确认无 worker 进程 |
| 8 | 在 provider 调用中途重启 server-beta — 作业重试 | PASS | Docker E2E phase2(重启后):session=854c5a46-... event=21d53585-... phase2 passed,BullMQ 状态存活于重启 |
| 9 | 作业恰好生成一次(幂等性) | PASS | Docker E2E phase2 确认 phase1 的事件/观测 ID 已持久化;幂等性由 tests/server/jobs/job-id.test.ts 与 tests/server/jobs/payload-schema.test.ts 覆盖并通过 |
6. Phase 13 退出标准(7 项全部达成)
| # | 标准 | 状态 | 证据 |
|---|---|---|---|
| 1 | Worker 停止时 Server beta 仍能生成观测 | YES | Docker E2E phase1+phase2,伴随显式 [e2e] no legacy worker processes detected |
| 2 | Docker Server beta 镜像不派生 worker | YES | E2E 断言无 worker 进程;Phase 10 提交已从 server 镜像中移除 worker 派生 |
| 3 | /v1/events 可入队并生成观测 |
YES | E2E phase1;tests/server/v1-routes.test.ts 与 tests/server/jobs/server-job-queue.test.ts 通过 |
| 4 | 健康时 hook 路由到 Server beta 可生成观测 | YES | tests/hooks/server-client.test.ts 通过(15/15) |
| 5 | BullMQ 队列状态存活于重启且重试安全 | YES | E2E phase2 覆盖重启后行为;server-job-queue.test.ts 覆盖重试安全 |
| 6 | Postgres server 存储是观测与生成作业的唯一事实源 | YES | tests/storage/postgres/ 通过;E2E 全程仅使用 Postgres |
| 7 | Worker 作为独立稳定运行时继续可用 | YES | tests/services/worker/、tests/worker/http/ 继续通过(仅剩基线已知失败);worker 容器在 E2E 栈中正常构建 |
退出标准第 6 条对应的是计划文档中的核心架构决策:Postgres 是观测的唯一事实源,Redis/Valkey 只是作业、重试、并发与可观测性的运行时基础设施,绝不存储规范观测记录。这也正是 Grep 断言“不用遗留 SQLite pending 队列做 server-beta 生成”的动机。
7. 构建与类型检查:与 main 基线严格对齐
npm run build— 干净通过(✅ All build targets compiled successfully!),4 个 cjs 产物全部生成:worker-service.cjs、server-service.cjs、mcp-server.cjs、context-generator.cjs。npm run typecheck— 24 个错误,数量与位置与main基线完全一致。错误集中在src/services/worker/http/routes/CorpusRoutes.ts、src/services/sqlite/SessionStore.ts、src/services/worker/http/BaseRouteHandler.ts、src/services/integrations/CursorHooksInstaller.ts、src/services/infrastructure/WorktreeAdoption.ts、src/shared/find-claude-executable.ts、src/npx-cli/commands/install.ts。src/server/内零错误,Phase 4–12 未引入任何类型检查回归。
这里体现的方法论值得注意:发布门禁不要求“全仓库类型检查为零错误”,而是要求与基线严格等值(identical count and locations)——只要错误集合不发生变化,就说明本次分支没有引入新的静态问题;存量问题单独跟踪、不阻塞发布。
8. 已知问题与延期项(8 项)
来自 Phase 4–12 提交信息的汇总,全部为显式范围界定的延期项:
- Live
/api/health回环集成测试 — 延期(CI 需要 Redis);功能上由 Docker E2E 覆盖; - Stalled event live 集成测试 — 延期(需要 Redis);单元测试层面已有覆盖;
- 在观测行上存储
request_id— 按 Phase 1 模式属范围外,非必需; - 冗余的
generation_job.queuedaudit_log 行 — 已由 Phase 1 模式拆分中的observation_generation_job_events生命周期日志覆盖;兼容适配器设actor_id=null但透传api_key_id; - 语义上下文注入(UserPromptSubmit hook) — 仍为 worker 独占;server-beta 尚未暴露
/v1/context/semantic,hook 回退到 worker 的路径保持完好; - ModeManager — 使用稳定的回退观测类型列表;summary 与 reindex 队列车道尚未在 server-beta 中接入;
- 预存基线测试失败 — 45 个,与
main不变;独立跟踪,不阻塞 server-beta 独立性; - 预存类型检查错误 — 24 个,与
main不变;全部位于遗留 worker / 共享模块,src/server/内为零。
9. 建议的后续步骤
合并前:独立运行时门禁本身无任何必需项——所有 Phase 13 退出标准已满足。
合并后:
- 待 CI 具备 Redis 服务后,为延期 live Redis 集成测试(上述第 1、2 项)开跟进票;
- 为
/v1/context/semantic开跟进票,移除最后一个 UserPromptSubmit-hook → worker 依赖(第 5 项); - 为清理预存基线测试失败与遗留 worker/共享路径的 24 个类型检查错误开跟进票(与 server-beta 无关);
- 排期一次基于 Phase 10 Docker compose 栈的生产冒烟部署。
10. 小结:一份发布就绪报告的可核验性来自哪里
docs/server-release-readiness.md 的价值不在“我们测过了”这句话,而在于每个结论都可沿三类证据回查:
- 数字证据:测试矩阵与
main基线做差集而非绝对计数,把“45 个失败”精确归类为 0 回归 + 10 修复 + 45 预存; - 可重复执行的断言:四条 Grep 与
bash scripts/e2e-server-docker.sh是任何人可重跑的一行命令,且断言(如assert_no_worker_process、assert_local_dev_rejected_in_docker)直接编码了计划文档中的反模式清单; - 源码落点:Docker 内 local-dev 拒绝、
wait=true→generationJob语义、Postgres 作为事实源等关键行为,分别能在 src/server/runtime/create-server-service.ts、docs/server.md、docs/api.md 与 tests/storage/postgres/ 中找到对应实现与文档。
对 claude-mem 这类“双运行时(遗留 worker + 独立 server-beta)并存”的项目,这套门禁回答了发布前最尖锐的三个问题:新运行时是否真的独立(Grep + 无 worker 进程断言)、是否真的持久(重启后 BullMQ 状态与 Postgres 数据存活)、旧的会不会被破坏(worker 套件基线等值通过)。三者皆证,方可 READY TO SHIP。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00