首页
/ claude-mem Server Beta 发布就绪验证:独立 BullMQ 观测运行时的 Phase 13 终局门禁

claude-mem Server Beta 发布就绪验证:独立 BullMQ 观测运行时的 Phase 13 终局门禁

2026-09-06 15:21:14作者:房伟宁

本文基于 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(可发布,附带已记录的延期项)。支撑该结论的四个支柱:

  1. Phase 13 全部退出标准(exit criteria)满足;
  2. 相对 main 基线,零新增测试回归;
  3. Docker E2E 通过完整生命周期:事件提交 → 观测生成 → 重启持久化 → 吊销密钥拒绝 → 无 worker 进程断言;
  4. 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 strippingVersion 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 configSessionManager queue integrationSearchRoutes Welcome HintSettingsDefaultsManagerWelcomeCardensureWorkerStartedexport-memoriesupdateFolderClaudeMdFiles 12(杂项) 全部预存

2.3 定向区域与 Server-beta 专属套件

  • 定向区域 tests/server tests/storage/postgres tests/services tests/hooks tests/servers tests/compat tests/cli350 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.tspayload-schema.test.tsserver-job-queue.test.ts)与 tests/storage/postgres/
  • 兼容面套件 bun test tests/compat/sessions-observations-adapter.test.ts tests/hooks/server-client.test.ts15 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/runtimejobsroutesgenerationcompatmcpservicesmiddlewareauth 做交叉 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 文档描述了生成语义 PASSdocs/api.md 记录了 POST /v1/eventsPOST /v1/events/batchwait=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.tsredis-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-1valkey-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.tstests/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.tstests/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.cjsserver-service.cjsmcp-server.cjscontext-generator.cjs
  • npm run typecheck — 24 个错误,数量与位置与 main 基线完全一致。错误集中在 src/services/worker/http/routes/CorpusRoutes.tssrc/services/sqlite/SessionStore.tssrc/services/worker/http/BaseRouteHandler.tssrc/services/integrations/CursorHooksInstaller.tssrc/services/infrastructure/WorktreeAdoption.tssrc/shared/find-claude-executable.tssrc/npx-cli/commands/install.tssrc/server/ 内零错误,Phase 4–12 未引入任何类型检查回归。

这里体现的方法论值得注意:发布门禁不要求“全仓库类型检查为零错误”,而是要求与基线严格等值(identical count and locations)——只要错误集合不发生变化,就说明本次分支没有引入新的静态问题;存量问题单独跟踪、不阻塞发布。

8. 已知问题与延期项(8 项)

来自 Phase 4–12 提交信息的汇总,全部为显式范围界定的延期项:

  1. Live /api/health 回环集成测试 — 延期(CI 需要 Redis);功能上由 Docker E2E 覆盖;
  2. Stalled event live 集成测试 — 延期(需要 Redis);单元测试层面已有覆盖;
  3. 在观测行上存储 request_id — 按 Phase 1 模式属范围外,非必需;
  4. 冗余的 generation_job.queued audit_log 行 — 已由 Phase 1 模式拆分中的 observation_generation_job_events 生命周期日志覆盖;兼容适配器设 actor_id=null 但透传 api_key_id
  5. 语义上下文注入(UserPromptSubmit hook) — 仍为 worker 独占;server-beta 尚未暴露 /v1/context/semantic,hook 回退到 worker 的路径保持完好;
  6. ModeManager — 使用稳定的回退观测类型列表;summary 与 reindex 队列车道尚未在 server-beta 中接入;
  7. 预存基线测试失败 — 45 个,与 main 不变;独立跟踪,不阻塞 server-beta 独立性;
  8. 预存类型检查错误 — 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_processassert_local_dev_rejected_in_docker)直接编码了计划文档中的反模式清单;
  • 源码落点:Docker 内 local-dev 拒绝、wait=truegenerationJob 语义、Postgres 作为事实源等关键行为,分别能在 src/server/runtime/create-server-service.tsdocs/server.mddocs/api.mdtests/storage/postgres/ 中找到对应实现与文档。

对 claude-mem 这类“双运行时(遗留 worker + 独立 server-beta)并存”的项目,这套门禁回答了发布前最尖锐的三个问题:新运行时是否真的独立(Grep + 无 worker 进程断言)、是否真的持久(重启后 BullMQ 状态与 Postgres 数据存活)、旧的会不会被破坏(worker 套件基线等值通过)。三者皆证,方可 READY TO SHIP。

登录后查看全文
热门项目推荐
相关项目推荐