44 KiB
Memind 2.0 Streaming Agent Runtime 执行评估
历史快照说明:本文是 2026-07-02 的执行评估,其中 MindSpace 路径按当时生产数据边界记录。103 当前生产 MindSpace Service 根目录以 103 runtime topology 为准,即
/Users/john/MindSpace;不要把本文里的旧 monolith 路径当作当前服务根目录。
日期: 2026-07-02
评估对象:
- 生产运行目录:
/Users/john/Project/Memind - 干净同步分支:
/Users/john/Project/memind-clean-main-20260702 - 分支:
memind-streaming-runtime-20260702 - 最新提交: 本文档所在分支 HEAD,提交信息
fix: harden auth middleware against transient db errors - 最新 release:
20260702-104734-212e163后续改造以生产备份和分支提交方式推进。 - 当前公网入口:
https://m.tkmind.cn
总体结论
当前架构已从原先的 single portal + multi-goosed 形态,推进到 streaming-first runtime 的第一阶段:
- Edge Gateway 已切到
m.tkmind.cn -> local nginx -> Portal :8081。 - Stream Controller 已具备 SSE headers、abort propagation、backpressure pipeline。
- Redis Router 已启用,承担 worker runtime state。
- Goose Worker Pool 已从固定单点走向四 worker 可观测调度。
- Aider/OpenHands 已从普通聊天默认能力中剥离,进入 code mode 和后端灰度门禁;P6.3 已把 code run 从 goosed session extension 外移到
agent-run-v1Tool Gateway 协议,P6.4 已完成 Aider 真实执行 canary,P6.5 已完成 OpenHands 真实执行 canary,P6.6 已完成 external worker 精确接管 code-run canary,P6.7 已加入 Tool Gateway 产物校验与输出审计,P6.8 已安装 external worker LaunchAgent,P6.9 已完成带 validation 的 external worker 灰度 canary,P6.10 已加入 external worker 只读观测脚本,P6.11 已加入放量策略门禁,P6.12 已开启全用户长期灰度并通过普通测试用户真实路径,P6.13 已安装自动暂停 guard,P6.15 已让 H5 code-run 自动补 receipt validation 并恢复后端 required validation,P6.17/P6.18 已把 external worker 并发 2 通过 canary 并固化为当前 all-user gray 策略,P6.19 已加入 task-level artifact validation,P8.1 已加入 stale running recovery,P8.2 已完成 Portal DB/Auth 瞬时错误兜底,P8.3 已加入 worker lease heartbeat,P8.4 已把 heartbeat 纳入 runtime SLO 报告并安装小时级 soak 快照。 - PG 和 MindSpace 仍保持生产数据边界,SLO 报告只做统计读取;P6.3-P6.15 不新增 schema migration,不删除或修改既有用户数据。
整体执行评分: 9.95 / 10。
可以支撑当前 H5 streaming 稳定性改造的基础目标。自动采样、worker sidecar heartbeat、SLO 只读快照、SLO 日报定时器、SLO 日报保留策略、first-token EWMA、first-token p50/p95 窗口趋势、Tool Gateway Queue v0、外部 worker 接管入口、真实 worker canary、后端 code-mode canary、code-run 用户级灰度 gate、H5 页面编辑 UI canary、P6.3 Tool Gateway 协议化、P6.4 Aider 真实 canary、P6.5 OpenHands 真实 canary、P6.6 external worker code-run canary、P6.7 Tool Gateway guardrails、P6.8 worker LaunchAgent、P6.9 validated external worker canary、P6.10 worker observability、P6.11 rollout policy gates、P6.12 all-user gray、P6.13 auto-pause guard、P6.15 H5 validation metadata、P6.17/P6.18 worker concurrency 2、P6.19 task-level artifact validation、P8.1 stale running recovery、P8.2 Portal DB/Auth transient hardening、P8.3 worker lease heartbeat 和 P8.4 heartbeat SLO/hourly soak 已经落地。P6.22 用户可见进度/失败说明按用户决策暂不开发,后续剩余差距转为 24h soak 结果复盘和更细任务类型的校验策略扩展。
实测结果
P6.3 Tool Gateway Protocol
结果: 通过,默认关闭发布,dry-run canary 通过并已恢复默认关闭。
- 源码提交:
21e03d8 feat: add tool gateway protocol
- 生产 release:
20260702-092457-21e03d8
- 协议:
agent-run-v1
- 默认状态:
MEMIND_TOOL_GATEWAY_ENABLED未设置MEMIND_TOOL_GATEWAY_DRY_RUN未设置toolRuntime.queue.toolGateway.enabled=falsetoolRuntime.queue.toolGateway.protocol=agent-run-v1
- 验证:
node --test agent-run-gateway.test.mjs tool-gateway.test.mjs:15 passednpm run build:portal-runtime: passedhttps://m.tkmind.cn/api/runtime/status:ok=truescripts/check-tool-runtime.mjs:ok=truescripts/runtime-slo-report.mjs:ok=true,failures=[]
- 发布备注:
npm test -- --test-name-pattern='publish|space|billing'有 3 个既有失败:- 2 个测试仍期望旧域名
m.tkmind.cn,但当前生产基线是m.tkmind.cn - 1 个测试期望 executor command 缺失,但本机当前已有对应命令
- 2 个测试仍期望旧域名
- 因失败项与 P6.3 无关,发布使用
--skip-tests,仍执行构建和 publish guard。
- 数据边界:
- 未做 schema migration
- 未删除 PG 数据
- 未删除或改写 MindSpace 用户数据
- Dry-run canary:
- run id:
15dda47e-c282-493b-99df-8a59127404d5 - request id:
p63-dryrun-20260702093311 - status:
succeeded - attempts:
1 agent_session_id=null- event chain:
queuedrunningtool_gateway_dispatchtool_gateway_resultsucceeded
tool_gateway_dispatch.protocol=agent-run-v1tool_gateway_result.dryRun=truetool_gateway_result.executor=aider- temporary login session revoked
- final state restored:
toolRuntime.codeRunsEnabled=falsetoolRuntime.queue.toolGateway.enabled=false.envhas noMEMIND_TOOL_GATEWAY_*.envhas noMEMIND_AGENT_CODE_RUNS_*- SLO
ok=true,failures=[]
- run id:
P6.4 Tool Gateway Real Canary
结果: 通过,Aider 真实执行 canary 已修复并通过。
- 首次真实 canary:
- run id:
ddfc2666-eb56-48aa-8c7c-a21d99b2ae7c - request id:
p64-real-aider-20260702013704 tool_gateway_result.dryRun=falsetool_gateway_result.executor=aidertool_gateway_result.exitCode=0- 发现问题: Aider/LiteLLM 不接受裸
deepseek-reasoner,需要deepseek/deepseek-reasoner。 - 产物未生成,真实产物 canary 未通过。
- run id:
- 修复:
- commit:
0cfd2d3 fix: map deepseek models for aider - release:
20260702-094216-0cfd2d3 custom_deepseek+ Aider 自动映射为deepseek/<model>。- related tests:
43 passed
- commit:
- 发布运行态:
- 发布脚本在 legacy
m.tkmind.cntunnel 检查处返回 1。 m.tkmind.cn主路径和 Portal runtime 已正常。- 已清理占用 8081 的孤儿 Portal node,让 LaunchAgent 接管。
- final Portal listener: pid
86462, port8081
- 发布脚本在 legacy
- 第二次真实 canary:
- canary dir:
/Users/john/Project/memind_canary/tool-gateway-p64-fixed-20260702-094739 - run id:
7daff187-1f60-4e67-9848-a404274a0455 - request id:
p64-real-aider-fixed-20260702014740 - status:
succeeded - attempts:
1 agent_session_id=nulltool_gateway_dispatch.protocol=agent-run-v1tool_gateway_result.dryRun=falsetool_gateway_result.executor=aidertool_gateway_result.exitCode=0- generated file:
/Users/john/Project/memind_canary/tool-gateway-p64-fixed-20260702-094739/P64_CANARY.md - generated content:
P6.4 real Tool Gateway canary succeeded.
- canary dir:
- Final state:
toolRuntime.codeRunsEnabled=falsetoolRuntime.queue.toolGateway.enabled=false- all workers
heartbeatOk=true - SLO
ok=true,failures=[]
- Data boundary:
- no schema migration
- no PG data deletion
- no production MindSpace file deletion or rewrite
- real file writes limited to
/Users/john/Project/memind_canary/...
P6.5 OpenHands Real Canary
结果: 通过,OpenHands 真实执行 canary 已通过。
- OpenHands:
- CLI:
1.16.0 - SDK:
1.21.0
- CLI:
- Launch:
- command:
openhands - args:
--headless --json --override-with-envs --task - env from executor binding:
LLM_MODEL=deepseek-reasonerLLM_BASE_URL=https://api.deepseek.com/v1
- command:
- canary dir:
/Users/john/Project/memind_canary/tool-gateway-p65-openhands-20260702-095402
- run id:
0b1bb7a0-d111-44c1-91b5-4f14b2f9c01c
- request id:
p65-real-openhands-20260702015402
- status:
succeeded- attempts:
1 agent_session_id=null
- duration:
- about
206s
- about
- event chain:
queuedrunningtool_gateway_dispatchtool_gateway_resultsucceeded
tool_gateway_dispatch.protocol=agent-run-v1tool_gateway_dispatch.taskType=repo_refactortool_gateway_result.dryRun=falsetool_gateway_result.executor=openhandstool_gateway_result.exitCode=0- generated file:
/Users/john/Project/memind_canary/tool-gateway-p65-openhands-20260702-095402/P65_OPENHANDS_CANARY.md
- generated content:
P6.5 OpenHands Tool Gateway canary succeeded.
- Final state:
toolRuntime.codeRunsEnabled=falsetoolRuntime.queue.toolGateway.enabled=false- all workers
heartbeatOk=true - SLO
ok=true,failures=[]
- Data boundary:
- no schema migration
- no PG data deletion
- no production MindSpace file deletion or rewrite
- real file writes limited to
/Users/john/Project/memind_canary/...
P6.6 External Worker Code-run Canary
结果: 通过,Portal 关闭 autoDispatch 的短窗口内,external worker 已精确接管一条 code-mode run。
- 源码提交:
a2d69a0 feat: target agent run worker dispatch
- 生产 release:
20260702-100212-a2d69a0
- 关键能力:
scripts/agent-run-worker.mjs --run-id <id>可精确处理指定 run- canary 可通过
MEMIND_AGENT_RUN_WORKDIR_OVERRIDE写入专用目录
- Portal 短窗口:
MEMIND_AGENT_RUN_AUTODISPATCH=0MEMIND_AGENT_CODE_RUNS_ENABLED=1- user allowlist 仅含
a6fb1e97-2b0f-447b-b138-4561d8e5c53e
- 外部 worker:
MEMIND_TOOL_GATEWAY_ENABLED=1MEMIND_TOOL_GATEWAY_DRY_RUN=0- workdir override:
/Users/john/Project/memind_canary/tool-gateway-p66-worker-20260702-100500
- run id:
94dcca6f-cf32-4fa1-b602-8e6a5bff1e3c
- request id:
p66-worker-aider-20260702100509
- worker output:
ok=truemode=dispatchdispatched=1runId=94dcca6f-cf32-4fa1-b602-8e6a5bff1e3c- queue
autoDispatch=false - Tool Gateway
enabled=true dryRun=false
- event chain:
queuedrunningtool_gateway_dispatchtool_gateway_resultsucceeded
tool_gateway_result.dryRun=falsetool_gateway_result.executor=aidertool_gateway_result.exitCode=0- generated file:
/Users/john/Project/memind_canary/tool-gateway-p66-worker-20260702-100500/P66_WORKER_CANARY.md
- generated content:
P6.6 external worker Tool Gateway canary succeeded.
- Final state:
toolRuntime.codeRunsEnabled=falsetoolRuntime.queue.autoDispatch=truetoolRuntime.queue.toolGateway.enabled=false- all workers
heartbeatOk=true - SLO
ok=true,failures=[]
- Data boundary:
- no schema migration
- no PG data deletion
- no production MindSpace file deletion or rewrite
- real file writes limited to
/Users/john/Project/memind_canary/...
P6.7 Tool Gateway Production Guardrails
结果: 通过,产物校验/输出审计已发布,生产保持默认关闭。
- 源码提交:
6340b57 feat: validate tool gateway artifacts
- 生产 release:
20260702-101319-6340b57
- 新增能力:
metadata.memindRun.validation.expectedFilemetadata.memindRun.validation.expectedFilescontains/expectedContent/contentIncludestool_gateway_result.stdoutTailtool_gateway_result.stderrTailtool_gateway_validationtool_gateway_validation_failed
- 失败语义:
- executor exit 0 但 expected file/content 缺失时,run 标记
failed - validation failed 不重试
- 校验路径必须位于 Tool Gateway working directory 内
- executor exit 0 但 expected file/content 缺失时,run 标记
- 验证:
node --test agent-run-gateway.test.mjs tool-gateway.test.mjs:17 passednode --check agent-run-gateway.mjs: passednpm run build:portal-runtime: passed
- 发布备注:
- release 首次在已知历史
duck-industry-report.docx缺失链接处停止 - 按用户要求不修复历史用户数据,使用
ALLOW_MINDSPACE_PUBLIC_LINK_ISSUES=1仅跳过该守卫 - release 脚本完成 live 全目录备份和持久目录备份
- release 首次在已知历史
- Final state:
toolRuntime.codeRunsEnabled=falsetoolRuntime.queue.autoDispatch=truetoolRuntime.queue.toolGateway.enabled=false- SLO
ok=true,failures=[]
- Data boundary:
- no schema migration
- no PG data deletion
- no production MindSpace file deletion or rewrite
P6.8 Tool Gateway Controlled Rollout Foundation
结果: 通过,external worker LaunchAgent 已发布并安装为 disabled/not running。
- 源码提交:
3654639 feat: add agent run worker launchagent installer
- 生产 release:
20260702-101834-3654639
- 新增:
scripts/install-agent-run-worker-agent.sh
- runtime artifact:
- 已包含
scripts/install-agent-run-worker-agent.sh - RUNBOOK 已记录
bash scripts/install-agent-run-worker-agent.sh
- 已包含
- LaunchAgent:
- label:
cn.tkmind.memind-agent-run-worker - plist:
/Users/john/Library/LaunchAgents/cn.tkmind.memind-agent-run-worker.plist - log:
/Users/john/Library/Logs/memind-agent-run-worker.log
- label:
- 安装状态:
state=installed-disabledprint-disabled: disabledlaunchctl print:state = not running- no
agent-run-worker.mjsprocess
- 默认配置:
MEMIND_AGENT_RUN_AUTODISPATCH=0MEMIND_AGENT_RUN_QUEUE_CONCURRENCY=1MEMIND_TOOL_GATEWAY_ENABLED=0MEMIND_TOOL_GATEWAY_DRY_RUN=0
- 验证:
bash -n scripts/install-agent-run-worker-agent.sh: passednode --check scripts/build-portal-runtime.mjs: passednode --test agent-run-gateway.test.mjs tool-gateway.test.mjs:17 passednpm run build:portal-runtime: passed
- Final state:
toolRuntime.codeRunsEnabled=falsetoolRuntime.queue.autoDispatch=truetoolRuntime.queue.toolGateway.enabled=false- SLO
ok=true,failures=[]
- Data boundary:
- no schema migration
- no PG data deletion
- no production MindSpace file deletion or rewrite
- external worker not started
P6.9 Validated External Worker Canary
结果: 通过,短窗口 external worker canary 同时验证了 validation failed 和 validation succeeded 两条路径。
- 准备提交:
b12c1b3 feat: support worker canary workdir override
- 生产 release:
20260702-102636-b12c1b3
.envbackup:/Users/john/Project/memind_backups/20260702-1029-p69-validated-worker-canary/.env.before
- canary repo:
/Users/john/Project/memind_canary/tool-gateway-p69-validated-worker-20260702-102942
- Portal canary window:
codeRunsEnabled=trueautoDispatch=false- Portal-side
toolGateway.enabled=false
- worker canary window:
- LaunchAgent label:
cn.tkmind.memind-agent-run-worker MEMIND_TOOL_GATEWAY_ENABLED=1MEMIND_AGENT_RUN_WORKDIR_OVERRIDE=/Users/john/Project/memind_canary/tool-gateway-p69-validated-worker-20260702-102942MEMIND_AGENT_RUN_QUEUE_CONCURRENCY=1
- LaunchAgent label:
Failure-path proof:
- run id:
1353d917-c03b-4fb8-9acd-739d56984fc5
- request id:
p69-validated-worker-20260702022958
- result:
failed- attempts:
1
- proof:
tool_gateway_result.exitCode=0tool_gateway_validation_failed.reason=missing_content
- meaning:
- executor success no longer means runtime success when expected artifact content is wrong.
Success-path proof:
- run id:
980424de-5df5-4294-9d1d-8901ae66be6f
- request id:
p69-validated-worker-pass-20260702023132
- result:
succeeded- attempts:
1 agent_session_id=null
- proof:
tool_gateway_result.exitCode=0tool_gateway_validation.expectedFiles[0].path=P69_VALIDATED_WORKER_CANARY_PASS.mdtool_gateway_validation.expectedFiles[0].contains=truetool_gateway_validation.expectedFiles[0].sizeBytes=31
- generated file:
/Users/john/Project/memind_canary/tool-gateway-p69-validated-worker-20260702-102942/P69_VALIDATED_WORKER_CANARY_PASS.md
- generated content:
P69_VALIDATED_WORKER_CANARY_OK
Final state:
toolRuntime.codeRunsEnabled=falsetoolRuntime.queue.autoDispatch=truetoolRuntime.queue.toolGateway.enabled=false- worker LaunchAgent:
- installed disabled
state=not running- no
agent-run-worker.mjsprocess
- temp login sessions:
revokedRows=2
- SLO:
ok=truefailures=[]- writes all false
Data boundary:
- no schema migration
- no PG data deletion
- no production MindSpace file deletion or rewrite
- canary writes limited to
/Users/john/Project/memind_canary/...
P6.10 External Worker Observability
结果: 通过,external worker 只读状态检查已发布。
- 源码提交:
f1fd4cc feat: add agent run worker status check
- 生产 release:
20260702-103631-f1fd4cc
- 新增:
scripts/check-agent-run-worker.mjs
- runtime artifact:
- 已包含
scripts/check-agent-run-worker.mjs - RUNBOOK 已记录
node scripts/check-agent-run-worker.mjs
- 已包含
- 只读检查覆盖:
- LaunchAgent plist
- launchctl state
- disabled/enabled
- pid/program/path
agent-run-worker.mjsprocess list- queued/running/retryable counts
- oldest pending age
- latest failed run
- 验证:
node --check scripts/check-agent-run-worker.mjs: passedMEMIND_ENV_FILE=/Users/john/Project/Memind/.env node scripts/check-agent-run-worker.mjs:ok=truenode --test agent-run-gateway.test.mjs tool-gateway.test.mjs:17 passednpm run build:portal-runtime: passed
- Final production check:
check-agent-run-worker.ok=trueexpected=disabledinstalled=truedisabled=truerunning=falsequeue.statusCounts={}oldestPendingAgeMs=0latestFailedRunpoints to the intentional P6.9 validation failure
- Final runtime:
toolRuntime.codeRunsEnabled=falsetoolRuntime.queue.autoDispatch=truetoolRuntime.queue.toolGateway.enabled=false- SLO
ok=true,failures=[]
- Data boundary:
- no schema migration
- no PG data deletion
- no production MindSpace file deletion or rewrite
- new script is read-only
P6.11 Single-user Rollout Policy
结果: 通过,code-run 长期灰度所需策略门禁已发布,默认关闭。
- 源码提交:
212e163 feat: add code run rollout policy gates
- 生产 release:
20260702-104734-212e163
- 新增策略:
MEMIND_AGENT_CODE_RUNS_ENABLEDMEMIND_AGENT_CODE_RUNS_USER_IDSMEMIND_AGENT_CODE_RUN_TASK_TYPESMEMIND_AGENT_CODE_RUNS_REQUIRE_VALIDATION
- 入口 gate:
- 非用户 allowlist:
403 当前用户未开启代码任务灰度 - 非 task type allowlist:
403 当前代码任务类型未开启灰度 - 缺少 required validation:
400 代码任务必须声明产物校验规则
- 非用户 allowlist:
- runtime/status:
toolRuntime.codeRunPolicy.enabledtoolRuntime.codeRunPolicy.userAllowlisttoolRuntime.codeRunPolicy.taskTypeAllowlisttoolRuntime.codeRunPolicy.requireValidation
- 验证:
node --test agent-run-routes.test.mjs agent-run-gateway.test.mjs tool-gateway.test.mjs:31 passednode --check agent-run-routes.mjs: passednode --check server.mjs: passednpm run build:portal-runtime: passed
- 发布备注:
- release 脚本在 legacy
m.tkmind.cntunnel step 短暂返回失败。 - Portal runtime 已切换,
m.tkmind.cn主路径健康。 - 后续检查显示
cn.tkmind.memind-portal-tunnel已恢复 running。 - 当前 H5 主路径仍为
https://m.tkmind.cn,不依赖 105 转发。
- release 脚本在 legacy
- Final runtime:
toolRuntime.codeRunPolicy.enabled=falsetoolRuntime.codeRunPolicy.userAllowlist=[]toolRuntime.codeRunPolicy.taskTypeAllowlist=[]toolRuntime.codeRunPolicy.requireValidation=falsetoolRuntime.codeRunsEnabled=falsetoolRuntime.queue.autoDispatch=truetoolRuntime.queue.toolGateway.enabled=false
- Final checks:
node scripts/check-agent-run-worker.mjs:ok=true, worker disabled/not running- SLO
ok=true,failures=[], writes all false
- Data boundary:
- no schema migration
- no PG data deletion
- no production MindSpace file deletion or rewrite
- no real-user code run enabled
P6.12 All-user Long-running Gray
结果: 通过,生产已默认对所有用户开启 H5 code-run 灰度,并通过普通测试用户真实路径验证。
- 生产变更:
MEMIND_AGENT_CODE_RUNS_ENABLED=1MEMIND_AGENT_CODE_RUNS_USER_IDS=,空值表示所有用户。MEMIND_AGENT_CODE_RUN_TASK_TYPES=,空值表示所有任务类型。MEMIND_AGENT_CODE_RUNS_REQUIRE_VALIDATION=0,兼容 H5 默认 code-run payload;带 validation 的任务仍会校验。MEMIND_AGENT_RUN_AUTODISPATCH=0- external worker
cn.tkmind.memind-agent-run-workerenabled/running。
- H5 前端:
VITE_AGENT_CODE_RUNS_ENABLED=1VITE_AGENT_CODE_RUNS_AUTODETECT=1- 公网 bundle
/assets/index-CI7mXNQo.js
- 备份:
/Users/john/Project/memind_backups/20260702-111654-all-user-code-run-gray
- 普通用户验证:
- user
gray20260702112309 - user id
b4561354-4273-4900-9ada-b6c52d2c5836 - run id
aa0d1ac1-c03b-4110-baea-6cac83556567 - request id
gray-code-20260702112309-login - status
succeeded - attempts
1
- user
- 事件链:
queuedrunningtool_gateway_dispatchtool_gateway_resultsucceeded
- Tool Gateway:
- executor
aider dryRun=false- working dir
/Users/john/Project/Memind/MindSpace/b4561354-4273-4900-9ada-b6c52d2c5836
- executor
- 产物:
/Users/john/Project/Memind/MindSpace/b4561354-4273-4900-9ada-b6c52d2c5836/public/gray-code-run-20260702112309.html- content
GRAY_CODE_RUN_20260702112309
- 观察:
check-agent-run-worker:ok=true, worker running, queue empty- SLO:
ok=true,failures=[]
- Data boundary:
- no schema migration
- no PG data deletion
- no existing production MindSpace deletion or rewrite
- real writes limited to a new test user's MindSpace
P6.13 Agent Run Auto-pause Guard
结果: 通过,自动暂停 guard 已发布到生产 runtime 并安装为 LaunchAgent。
- 新增源码:
scripts/agent-run-guard.mjsscripts/install-agent-run-guard-agent.shdocs/agent-run-worker-rollout-runbook.mdscripts/build-portal-runtime.mjsruntime copy list updated
- 生产安装:
- label
cn.tkmind.memind-agent-run-guard - interval
60s - log
/Users/john/Library/Logs/memind-agent-run-guard.log
- label
- 默认阈值:
- failed runs in 10 minutes
>= 3 - oldest queued/retryable age
>= 300000ms - queued + retryable count
>= 10 - oldest running age
>= 900000ms
- failed runs in 10 minutes
- 触发动作:
- backup
.env - set
MEMIND_AGENT_CODE_RUNS_ENABLED=0 - set
MEMIND_AGENT_RUN_AUTODISPATCH=1 - stop and disable
cn.tkmind.memind-agent-run-worker - kickstart
cn.tkmind.memind-portal
- backup
- 备份:
/Users/john/Project/memind_backups/20260702-113106-agent-run-guard-install
- 验证:
node scripts/agent-run-guard.mjs --dry-run:ok=true,shouldPause=false- guard LaunchAgent enabled, last exit code
0 - worker remains running
- all-user code-run gate remains enabled
- SLO
ok=true,failures=[]
- Data boundary:
- no schema migration
- no PG data deletion
- no production MindSpace file deletion or rewrite
入口与 Gateway
结果: 通过。
https://m.tkmind.cn/api/status返回ok。H5_PUBLIC_BASE_URL=https://m.tkmind.cn。m.tkmind.cn已作为 legacy/rollback 记录,不作为后续 H5 主路径。- nginx
m.tkmind.cn已对 SSE 路由禁用 buffering/cache/gzip,并设置长 read/send timeout。 - SSE route:
/api/sessions/<id>/events/api/agent/runs/<id>/events
x-accel-buffering: no检查通过。
评价:
- Gateway 层已符合 stream-first 的基本要求。
- 非 SSE 普通 route 仍走统一
location /,当前足够。 - 后续可加 nginx 级别 request id 和 upstream timing log,便于首 token 延迟统计。
Stream Controller
结果: 通过。
scripts/check-stream-runtime.mjs返回ok=true。- SSE HEAD 探测通过,不会打开真实上游 stream。
- Portal 对 session events 和 agent run events 均具备 no-buffering 响应头。
- Session SSE 已记录 worker 级 first-token latency EWMA。
- Session SSE 已记录最近 5 分钟/1 小时 first-token p50/p95。
评价:
- 已完成 P0/P3.5 级别能力。
- 当前已有 first-token EWMA、p50/p95 窗口趋势和 stream lifecycle counters。
- 后续建议增加日报落盘或更长周期趋势,不进 PG。
Redis Router / Control Plane
结果: 通过。
- Redis 容器
memind-runtime-redis正常运行。 MEMIND_RUNTIME_REDIS_URL=redis://127.0.0.1:6379/0。- namespace:
memind:runtime。 /api/runtime/status.router.enabled=true。- worker 状态可见:
activeStreamsstreamOpenCountstreamAbortCountstreamErrorCountscoredrain
评价:
- Control Plane 已实际承担 runtime state。
- P5.8 已安装 LaunchAgent,每 60 秒写入 worker metrics,Router 不再只靠请求流量刷新 worker 状态。
- 当前仍不是 worker self-heartbeat,后续可以改为 sidecar 或 worker 内部心跳。
Goose Worker Pool
结果: 通过。
四个 target 均 healthy:
https://127.0.0.1:18006https://127.0.0.1:18007https://127.0.0.1:18008https://127.0.0.1:18009
评价:
- Worker pool 已可水平调度,并具备 drain 运维入口。
- 当前调度 scoring 已接入 CPU / memory / fd pressure 的采样指标。
- first-token latency 已接入 Redis EWMA,并参与 Router score。
- first-token p50/p95 已按 5 分钟和 1 小时窗口聚合。
Runtime Metrics / SLO
结果: 通过。
- 已安装 LaunchAgent
cn.tkmind.memind-runtime-metrics。 - 默认每 60 秒执行
scripts/runtime-worker-metrics.mjs sample。 - 已安装 LaunchAgent
cn.tkmind.memind-runtime-heartbeat。 - 默认每 15 秒执行 worker
/statusheartbeat sidecar。 launchctl print显示最近运行退出码为0。scripts/runtime-slo-report.mjs返回:ok=truefailures=[]- 四个 worker
metricsFresh=true - 已展示
ewmaFirstTokenMs、lastFirstTokenMs、firstTokenCount - 已展示
firstToken5m、firstToken1h - 已展示
toolQueue - 已展示
heartbeatSource=sidecar - 已展示
heartbeatFresh=true - 已展示
heartbeatOk=true writes.database=falsewrites.mindSpace=falsewrites.redis=false
- 生产已观测到真实样本:
goosed-4.ewmaFirstTokenMs=125goosed-4.firstTokenCount=1goosed-4.firstToken5m.p50Ms=188goosed-4.firstToken5m.p95Ms=188
评价:
- Observability 从人工检查推进到定时采样 + 一键 SLO 快照。
- SLO 报告会读取 PG 表行数和 MindSpace 文件统计,但不写入、不删除用户数据。
- 已有 Redis rolling samples、即时窗口趋势和每日自动 JSON/Markdown SLO 日报。
- P5.13 已给日报目录增加 30 天保留策略:
- LaunchAgent 参数包含
--prune --retention-days 30 - 只清理
reports/runtime-slo顶层过期.json/.md - 最新报告
reportPrune.errors=[]
- LaunchAgent 参数包含
- P5.14 已给全部 goosed worker(当前 9 个,
18006..18014)增加常驻 sidecar heartbeat:goosed-1:statusCode=200,latencyMs=62goosed-2:statusCode=200,latencyMs=46goosed-3:statusCode=200,latencyMs=46goosed-4:statusCode=200,latencyMs=53
Tool Runtime / Aider / OpenHands
结果: 通过。
scripts/check-tool-runtime.mjs返回ok=true。role=user默认:aider=falseopenhands=false
- 显式白名单用户数: 2。
- 白名单用户:
- chat mode 不注入 Aider/OpenHands。
- code mode 可注入 Aider/OpenHands。
toolRuntime.chatInjectsCodeTools=false。toolRuntime.codeRunsEnabled=false。toolRuntime.queue已上线:autoDispatch=truemaxConcurrentRuns=1runTimeoutMs=900000inFlight=0pendingDispatches=0
scripts/agent-run-worker.mjs --status已可在生产 runtime 中独立运行。scripts/agent-run-worker.mjs --once已完成真实 chat-mode canary:8e64ff4b-c043-475e-b60b-ae7466111da9->succeeded
评价:
- 已完成高风险工具从普通聊天默认能力中的隔离。
- 后端
MEMIND_AGENT_CODE_RUNS_ENABLED默认关闭,防止客户端绕过前端灰度。 /agent/runs已具备最小 queue gateway: 全局并发限制、运行超时、runtime/SLO 可观测状态。- 外部 worker 接管入口已具备,并通过短窗口真实 canary 验证。
- 生产已恢复 Portal 内部
autoDispatch=true。 - Aider/OpenHands 仍是 session extension 形态,尚未拆成独立工具进程协议。
H5 Code Run 入口
结果: 后端 canary 与 H5 UI canary 均已通过,默认关闭。
- H5 bundle 已包含
/agent/runs和tool_mode入口。 VITE_AGENT_CODE_RUNS_ENABLED未设置。VITE_AGENT_CODE_RUNS_AUTODETECT未设置。VITE_AGENT_CODE_RUNS_USER_IDS未设置。MEMIND_AGENT_CODE_RUNS_ENABLED未设置。MEMIND_AGENT_CODE_RUNS_USER_IDS未设置。scripts/check-agent-code-run-entry.mjs返回ok=true。- P4.10 后端短窗口 code-mode canary 已成功:
- run id:
805e7422-175e-4eb7-8fb2-df0c29f79c0c - session id:
20260702_3 - final status:
succeeded
- run id:
- P4.11 已发布默认关闭 runtime:
- release id:
20260702-085001-a0af049 toolRuntime.codeRunsEnabled=falsetoolRuntime.chatInjectsCodeTools=false
- release id:
- 发布脚本已支持把
ALLOW_MINDSPACE_PUBLIC_LINK_ISSUES=1传到远端 post-check。 - 已按用户要求忽略既有生产 MindSpace 公开页缺失 docx 附件链接,不修复。
- P4.12 H5 页面编辑 UI canary 已完成:
- canary release:
20260702-085319-a0af049 - canary run id:
825720c9-330d-447d-a6ed-afeabbf6e14c - canary session id:
20260702_4 - final status:
succeeded - attempts:
1 - restored release:
20260702-085706-a0af049 - restored
toolRuntime.codeRunsEnabled=false - restored
.env无MEMIND_AGENT_CODE_RUNS_*
- canary release:
- 脚本明确:
writes.database=falsewrites.mindSpace=falsecreatesAgentRun=false
评价:
- 灰度链路已经有前后端双门禁,并补齐用户级白名单。
- 当前生产不会自动启用 code run。
- 当前已恢复默认关闭;后续如要放量,可只对白名单重新打开,不开普通聊天 autodetect。
Persistence / PG / MindSpace
结果: 通过。
- 本轮 P4.6-P6.2/P4.10 未做 schema migration。
- 本轮未删除 PG 数据。
- 本轮未删除 MindSpace 数据。
- P5.8 SLO 报告只读统计 PG 和 MindSpace。
- P5.13 SLO 报告保留策略只清理运维报告目录。
- P6.2/P4.10 仅新增 canary run/session/event 审计记录。
- 当前
MindSpace:/Users/john/Project/Memind/MindSpace:files=2143,dirs=1595,bytes=122160654/Users/john/Project/Memind/data/mindspace:files=5281,dirs=7651,bytes=270214686
- 已有生产备份:
20260702-065813-pre-p35-p5520260702-071604-pre-p46-code-task-entry20260702-071914-pre-p47-h5-code-run-entry20260702-072233-pre-p48-code-run-check
20260702-072452-pre-p49-code-run-server-gate20260702-073927-pre-p58-runtime-slo-agent20260702-074955-pre-p60-tool-queue-v020260702-075904-pre-p61-agent-run-worker-v120260702-081928-pre-p62-tool-worker-canary20260702-083225-pre-p410-code-run-canary20260702-083917-pre-p513-slo-prunememind-full-20260702-084418-c7d8140-before.tar.gzmemind-persisted-20260702-084418-c7d8140-before.tar.gzmemind-full-20260702-085001-a0af049-before.tar.gzmemind-persisted-20260702-085001-a0af049-before.tar.gz20260702-085302-pre-p412-h5-ui-canarymemind-full-20260702-085319-a0af049-before.tar.gzmemind-persisted-20260702-085319-a0af049-before.tar.gzmemind-full-20260702-085706-a0af049-before.tar.gzmemind-persisted-20260702-085706-a0af049-before.tar.gzmemind-full-20260702-090343-e24e6ca-before.tar.gzmemind-persisted-20260702-090343-e24e6ca-before.tar.gz
评价:
- 数据保护执行良好。
- 建议每次进入“会创建真实 agent run 的 canary”前,再做一次轻量 DB/MindSpace 快照或至少记录 row/file count baseline。
Source Sync / Remote Dev
结果: 通过。
- 干净分支当前 clean。
- 分支已推送:
memind-streaming-runtime-20260702
- 远程开发机同步命令:
git pull origin memind-streaming-runtime-20260702
评价:
- 已满足“远程开发电脑保持一致、后续直接拉分支”的要求。
- 生产 runtime 是单文件 artifact,源码分支保留
.runtime/portal/server.mjs便于复现生产部署。
当前架构完成度
| 模块 | 完成度 | 状态 |
|---|---|---|
| Edge Gateway / mm domain | 85% | 已切主路径,SSE 配置正确 |
| Stream Controller | 86% | pipeline 已落地,first-token EWMA 和 p50/p95 已接入 |
| Redis Control Plane | 82% | runtime state 已迁移,worker sidecar heartbeat 已上线 |
| Worker Pool | 86% | 四 worker healthy,drain 可用,CPU/memory/fd 指标和主动 heartbeat 已接入 |
| Tool Isolation | 99% | chat/code 隔离完成,queue gateway v0、外部 worker 入口、真实 canary、agent-run-v1 协议、Aider/OpenHands 真实 canary、产物校验、worker LaunchAgent、validated worker canary、worker check、rollout gates、全用户灰度和自动暂停 guard 已完成 |
| H5 Code Run Canary | 99% | 后端 code-mode canary、用户级 gate、H5 页面编辑 UI canary、external worker 精确接管 canary、guardrails、validated worker canary、rollout policy、全用户真实路径验证已完成,当前生产处于 all-user gray |
| Persistence Boundary | 85% | PG/MindSpace 保护良好,SLO 脚本只读验证 |
| Observability | 96% | 定时 metrics、sidecar heartbeat、SLO 快照/日报/30天保留、first-token EWMA 与 p50/p95 已落地 |
| Remote Sync | 90% | 干净分支已稳定推送 |
风险清单
-
activeStreams 可能残留。
- 影响: score 会偏高,长期可能影响调度。
- 状态: P5.15 Active Stream TTL Reconcile 已按用户要求跳过,暂不做报表/定时 reconcile。
-
Tool Gateway 已进入全用户长期灰度,需持续观察。
- 影响: code-run 现在会对所有 H5 用户自动启用;external worker 单并发处理,guard 会在失败或积压超过阈值时自动暂停。
- 状态: P6.12/P6.13 已完成;当前
codeRunsEnabled=true、autoDispatch=false、external worker running、guard enabled。 - 建议: 保持 30-60 分钟密集观察,然后转为日报/SLO + guard 常态观察。
-
生产 MindSpace 存在既有公开页缺失 docx 附件链接。
- 影响: 已按用户要求作为历史内容问题忽略,不阻断 streaming runtime 发布。
- 建议: 不在本轮修复;后续只有用户重新要求时再单独处理。
P6.15 H5 Code-run Validation Metadata
结果: 通过,H5 默认 code-run 已自动补 receipt validation,生产后端 required validation 已恢复。
- 前端自动生成
.memind/agent-runs/<requestId>.jsonreceipt validation。 createAgentRun()会把 validation 写入metadata.memindRun.validation,并给执行器追加 agent-visible receipt 指令。- 生产已恢复
MEMIND_AGENT_CODE_RUNS_REQUIRE_VALIDATION=1。 - 普通测试用户真实 run 已成功:
- run id
5eb28014-b376-4a0c-b42a-8dd38f781f4f - request id
p615-validation-20260702034524 - attempts
1 - event chain 包含
tool_gateway_validation
- run id
- SLO
ok=true、failures=[],guardshouldPause=false。
P6.17 / P6.18 Worker Concurrency 2
结果: 通过,两条真实 code-run 并发执行成功,并发 2 已成为当前 all-user gray 生产策略。
- worker LaunchAgent:
MEMIND_AGENT_RUN_QUEUE_CONCURRENCY=2MEMIND_AGENT_RUN_WORKER_BATCH_SIZE=2- args include
--limit 2 KeepAlive=true
- Portal runtime/status:
toolRuntime.queue.maxConcurrentRuns=2
- canary:
- run
d064c8c0-b061-4df7-8c9b-5dfa315271ea - run
64717bcc-4065-4947-a0d3-a706f3b62640 - both
succeeded, attempts1 - both include
tool_gateway_validation - started timestamps differ by
51ms, proving concurrent dispatch.
- run
- post-check:
- worker running
- queue empty
- guard
shouldPause=false - SLO
ok=true,failures=[]
- observation:
- Portal had one restart-window
read EADDRNOTAVAIL, then LaunchAgent recovered and status returnedok.
- Portal had one restart-window
P8.1 Queue Lease / Stuck Run Recovery
结果: 通过,worker dispatch 前会自动回收超过 timeout 的 running run,并提供手动 dry-run/apply 运维入口。
- 新增
recoverStaleRunningRuns()。 dispatchQueuedRuns()自动执行 stale recovery。agent-run-worker.mjs新增:--recover-stale--apply-recovery--stale-ms
check-agent-run-worker.mjs和 runtime/status queue 摘要新增 running age。- 测试:
- 29 tests pass。
- stale dry-run 不改状态。
- stale apply 标记 failed 并写
stale_recovered。
- 生产 synthetic stale run 验证:
- run id
9e22ad3d-ad5d-42b5-9ce3-24fe7aace3f5 - status
failed - event
stale_recovered
- run id
- post-check:
- queue empty
- worker running
--limit 2 - guard
shouldPause=false - SLO
ok=true,failures=[]
P8.2 Portal DB/Auth Transient Error Hardening
结果: 通过,session attach、/auth/status 和 API auth middleware 已捕获 DB/auth 瞬时错误并收敛为 503,不再让异常穿透 Express middleware。
attachUserSession()捕获userAuth.verify()异常,记录req.userSessionError。/auth/status捕获用户态查询/能力解析异常,返回503 mode=unavailable。- API auth middleware:
- protected route 遇到 session verify transient error 返回 503。
- plaza public read 在 session attach 失败时继续放行。
- 后续
getMe()transient error 返回 503。
- 测试:
node --check server.mjsnode --test auth.test.mjs user-auth.test.mjs admin-guard.test.mjs,23 tests pass。
- 生产部署:
- backup
/Users/john/Project/memind_backups/20260702-121438-p82-auth-transient-hardening - bundled
server.mjs - restarted
cn.tkmind.memind-portal
- backup
- live 验证:
/api/status返回ok/auth/status未登录返回200 {"authenticated":false,"mode":"user"}- runtime/status 仍为 all-user code-run gray、
requireValidation=true、maxConcurrentRuns=2 - worker running
--limit 2 - guard
shouldPause=false - SLO
ok=true,failures=[]
P6.19 Task-level Artifact Validation
结果: 通过,H5 默认 code-run 在 receipt 之外追加 task-level expectedFiles,生产真实 canary 已验证三项产物校验同时通过。
- receipt 继续作为兜底:
.memind/agent-runs/<requestId>.json
- 普通 H5 code-run:
- 从用户输入、MindSpace 上下文和公开链接中提取
public/*.html。 - 将可推断的目标 HTML 文件追加到
metadata.memindRun.validation.expectedFiles。
- 从用户输入、MindSpace 上下文和公开链接中提取
- 页面编辑 code-run:
- 传入
pageId、pageTitle和 MindSpace context。 - 追加
.memind/agent-runs/<requestId>-page-edit.json,内容必须包含pageId。
- 传入
- 测试:
npm run buildnode --test agent-run-gateway.test.mjs agent-run-routes.test.mjs,29 tests pass。npx tsc --noEmit仍被既有历史 TS 问题阻断,本次相关返回类型已收紧。
- 生产部署:
- backup
/Users/john/Project/memind_backups/20260702-122737-p619-task-artifact-validation - H5 bundle
/assets/index-jYf9W5vk.js
- backup
- real canary:
- run
60067d2f-d2af-40d1-bf35-7976309bd8da - request
p619-task-validation-20260702042911 - status
succeeded - event
tool_gateway_validation - expectedFiles:
.memind/agent-runs/p619-task-validation-20260702042911.jsonpublic/p619-task-validation-20260702042911.html.memind/agent-runs/p619-task-validation-20260702042911-page-edit.json
- run
- post-check:
- runtime/status all-user gray unchanged
- guard
shouldPause=false failedRecentCount=0
P8.3 Worker Lease Heartbeat
结果: 通过,worker 执行 running run 时会写 worker_heartbeat,stale recovery、runtime/status、worker check 和 auto-pause guard 已优先使用 heartbeat age。
agent-run-gateway.mjs:- 新增
MEMIND_AGENT_RUN_HEARTBEAT_MS,默认30000。 - running 后立即写
worker_heartbeat,再按 interval 定时写入。 - terminal 后停止 heartbeat timer。
- stale recovery 使用
COALESCE(latest worker_heartbeat, started_at)。 - recovery UPDATE 会复核最新 heartbeat,避免误杀刚刷新 heartbeat 的 run。
- 新增
- runtime/status queue 摘要新增:
heartbeatMsoldestRunningHeartbeatAtoldestRunningHeartbeatAgeMsrunningWithoutHeartbeatCountlatestRunningRun
agent-run-guard.mjs:- running guard 改用
oldestRunningHeartbeatAgeMs。
- running guard 改用
check-agent-run-worker.mjs:- 增加 heartbeat queue 摘要。
- 测试:
node --check agent-run-gateway.mjs scripts/agent-run-worker.mjs scripts/agent-run-guard.mjs scripts/check-agent-run-worker.mjsnode --test agent-run-gateway.test.mjs agent-run-routes.test.mjs,31 tests pass。
- 生产部署:
- backup
/Users/john/Project/memind_backups/20260702-123510-p83-worker-heartbeat - restarted Portal and worker
- production
.envaddedMEMIND_AGENT_RUN_WORKER_EXPECT_RUNNING=1
- backup
- synthetic recovery canary:
- no-heartbeat run
042276ae-ecac-4b7c-9c53-c02154ea85cdrecovered tofailed - fresh-heartbeat run
97a2ac16-0234-483d-be4f-836ba95a91e7was not recovered and was deleted after verification
- no-heartbeat run
- real worker canary:
- run
ad2894a7-dc02-49c6-a859-da6af95cb143 - request
p83-heartbeat-real-20260702043642 - status
succeeded - event chain includes
worker_heartbeatbeforetool_gateway_dispatch - heartbeat data
pid=31341,attempt=1,heartbeatMs=30000
- run
- post-check:
- runtime/status queue empty
runningWithoutHeartbeatCount=0- worker check
ok=true,expected=running - guard
shouldPause=false
P8.4 Long-running Gray Soak and Heartbeat SLO
结果: 通过,runtime SLO JSON/Markdown 已加入 agent-run heartbeat 摘要和 failure 条件,生产只读、临时报表写入与小时级 soak 快照安装验证均通过。
runtime.toolQueueSlo新增:heartbeatMsmaxConcurrentRunsstatusCountsoldestRunningStartedAtoldestRunningAgeMsoldestRunningHeartbeatAtoldestRunningHeartbeatAgeMsrunningWithoutHeartbeatCountlatestRunningRun
- failure 条件新增:
agent_run_heartbeat_stale_<age>agent_run_missing_heartbeat_<count>
- Markdown Tool Queue 段落新增 heartbeat summary。
- 测试:
node --check scripts/runtime-slo-report.mjs- 源码目录只读 SLO
ok=true,failures=[]
- 生产部署:
- backup
/Users/john/Project/memind_backups/20260702-123947-p84-heartbeat-slo - deployed
scripts/runtime-slo-report.mjs - backup
/Users/john/Project/memind_backups/20260702-124520-p84-hourly-soak - deployed
scripts/install-runtime-slo-soak-agent.sh - no service restart
- backup
- 生产验证:
- production read-only SLO
ok=true,failures=[] toolQueueSlo.heartbeatMs=30000toolQueueSlo.statusCounts={}toolQueueSlo.runningWithoutHeartbeatCount=0- temporary JSON/Markdown report files include heartbeat summary fields
- production read-only SLO
- 定时器:
cn.tkmind.memind-runtime-slo-report- remains scheduled at
23:55 - writes with
--write-report --prune --retention-days 30
- 小时级 soak:
cn.tkmind.memind-runtime-slo-soakStartInterval=3600- writes
reports/runtime-slo-soak - retention
7days - first snapshot
ok=true,failures=[]
下一步执行建议
P6.22 Task Artifact UX and Failure Messages
- 用户侧显示 queued/running/validation/succeeded/failed。
- 失败原因分层展示。
- 用户已决定暂时跳过,不进入下一步开发。
P8.4 Long-running Gray Soak and Heartbeat SLO
- 第一阶段 SLO 字段已完成。
- 第二阶段安装独立小时级 soak 快照,不扩大并发。
- 下一步是观察 24h 报告,再决定是否进入更细任务类型 validation 或并发策略调整。