From af5396c127fe5f776da29bab6ad03cd39080e2da Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 2 Jul 2026 12:08:49 +0800 Subject: [PATCH] docs: record worker concurrency rollout --- docs/agent-run-worker-rollout-runbook.md | 14 ++- ...2-runtime-execution-assessment-20260702.md | 66 +++++++++---- .../memind-2-streaming-agent-runtime-plan.md | 94 +++++++++++++++++++ 3 files changed, 153 insertions(+), 21 deletions(-) diff --git a/docs/agent-run-worker-rollout-runbook.md b/docs/agent-run-worker-rollout-runbook.md index 13f827e..6ee7666 100644 --- a/docs/agent-run-worker-rollout-runbook.md +++ b/docs/agent-run-worker-rollout-runbook.md @@ -70,7 +70,7 @@ All canary code writes must use `/Users/john/Project/memind_canary/...`. ## All-user Gray Profile -Current production rollout can use all H5 users by leaving the user and task-type allowlists empty. Validation metadata is accepted when present, but not required for the H5 default code-run path. +Current production rollout can use all H5 users by leaving the user and task-type allowlists empty. H5 default code-run now auto-attaches receipt validation, so required validation stays enabled. Portal `.env` additions: @@ -79,7 +79,9 @@ MEMIND_AGENT_RUN_AUTODISPATCH=0 MEMIND_AGENT_CODE_RUNS_ENABLED=1 MEMIND_AGENT_CODE_RUNS_USER_IDS= MEMIND_AGENT_CODE_RUN_TASK_TYPES= -MEMIND_AGENT_CODE_RUNS_REQUIRE_VALIDATION=0 +MEMIND_AGENT_CODE_RUNS_REQUIRE_VALIDATION=1 +MEMIND_AGENT_RUN_QUEUE_CONCURRENCY=2 +MEMIND_AGENT_RUN_WORKER_BATCH_SIZE=2 MEMIND_TOOL_GATEWAY_ENABLED=0 MEMIND_TOOL_GATEWAY_DRY_RUN=0 VITE_AGENT_CODE_RUNS_ENABLED=1 @@ -92,8 +94,8 @@ Worker installer environment: ```bash MEMIND_AGENT_RUN_WORKER_START=1 MEMIND_AGENT_RUN_WORKER_POLL_MS=3000 -MEMIND_AGENT_RUN_WORKER_BATCH_SIZE=1 -MEMIND_AGENT_RUN_QUEUE_CONCURRENCY=1 +MEMIND_AGENT_RUN_WORKER_BATCH_SIZE=2 +MEMIND_AGENT_RUN_QUEUE_CONCURRENCY=2 MEMIND_TOOL_GATEWAY_ENABLED=1 MEMIND_TOOL_GATEWAY_DRY_RUN=0 ``` @@ -104,12 +106,14 @@ Expected values: toolRuntime.codeRunPolicy.enabled=true toolRuntime.codeRunPolicy.userAllowlist=[] toolRuntime.codeRunPolicy.taskTypeAllowlist=[] -toolRuntime.codeRunPolicy.requireValidation=false +toolRuntime.codeRunPolicy.requireValidation=true toolRuntime.codeRunsEnabled=true toolRuntime.queue.autoDispatch=false +toolRuntime.queue.maxConcurrentRuns=2 toolRuntime.queue.toolGateway.enabled=false check-agent-run-worker.expected=running check-agent-run-worker.running=true +check-agent-run-worker.processes includes --limit 2 ``` ## Enable Procedure diff --git a/docs/architecture/memind-2-runtime-execution-assessment-20260702.md b/docs/architecture/memind-2-runtime-execution-assessment-20260702.md index 97abc7b..a4a41ad 100644 --- a/docs/architecture/memind-2-runtime-execution-assessment-20260702.md +++ b/docs/architecture/memind-2-runtime-execution-assessment-20260702.md @@ -19,12 +19,12 @@ - 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-v1` Tool 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。 +- Aider/OpenHands 已从普通聊天默认能力中剥离,进入 code mode 和后端灰度门禁;P6.3 已把 code run 从 goosed session extension 外移到 `agent-run-v1` Tool 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 策略。 - 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 已经落地。主要剩余差距转为更细粒度的任务级产物规范、用户可见进度/失败说明,以及后续是否提高 worker 并发。 +可以支撑当前 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 已经落地。主要剩余差距转为 running/stuck recovery、DB/session auth 瞬时错误收敛、更细粒度的任务级产物规范和用户可见进度/失败说明。 ## 实测结果 @@ -866,20 +866,54 @@ Data boundary: - event chain 包含 `tool_gateway_validation` - SLO `ok=true`、`failures=[]`,guard `shouldPause=false`。 +### P6.17 / P6.18 Worker Concurrency 2 + +结果: 通过,两条真实 code-run 并发执行成功,并发 2 已成为当前 all-user gray 生产策略。 + +- worker LaunchAgent: + - `MEMIND_AGENT_RUN_QUEUE_CONCURRENCY=2` + - `MEMIND_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`, attempts `1` + - both include `tool_gateway_validation` + - started timestamps differ by `51ms`, proving concurrent dispatch. +- 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 returned `ok`. + ## 下一步执行建议 -### P6.16 Task Artifact UX and Failure Messages +### P8.1 Queue Lease / Stuck Run Recovery -- 为 H5 code-run 增加用户可见状态: - - queued / running / validation / succeeded / failed - - 显示“正在执行代码任务”而不是普通连接态。 -- 失败原因分层: - - 执行器失败 - - 产物校验失败 - - 超时 - - 队列积压或 guard 暂停 -- 产物规范从 receipt 扩展到任务级: - - 页面编辑任务声明目标 public HTML。 - - 仓库/文件任务声明目标相对路径。 - - 无明确目标的通用 code-run 继续使用 receipt 兜底。 -- P6.16 完成并稳定后,再评估 worker 并发是否从 1 提到 2。 +- 为 `running` run 增加 lease / stale recovery: + - worker 启动和轮询时识别超过 TTL 的 running run。 + - 将超时 running 标记 failed 或 retryable,避免 worker/进程异常退出后永久卡住。 + - guard 同步读取 stale running 作为暂停依据。 +- 增加只读检查脚本输出: + - oldest running age + - stale running count + - recovery dry-run actions +- 同时修补 Portal auth/session DB 瞬时错误: + - `read EADDRNOTAVAIL` 不应作为 uncaught exception 杀掉 Portal。 + - session attach 失败应降级为 503/401 或跳过认证态,而不是进程退出。 + +### P6.19 Task-level Artifact Validation + +- receipt 继续作为兜底。 +- 页面编辑任务追加目标 `public/*.html` 校验。 +- 文件/仓库任务根据任务参数声明目标相对路径。 + +### P6.22 Task Artifact UX and Failure Messages + +- 用户侧显示 queued/running/validation/succeeded/failed。 +- 失败原因分层展示。 diff --git a/docs/architecture/memind-2-streaming-agent-runtime-plan.md b/docs/architecture/memind-2-streaming-agent-runtime-plan.md index 8f9d61c..39947d2 100644 --- a/docs/architecture/memind-2-streaming-agent-runtime-plan.md +++ b/docs/architecture/memind-2-streaming-agent-runtime-plan.md @@ -24,6 +24,8 @@ - P6.12 All-user Long-running Gray: 已完成,生产已默认对所有用户开启 H5 code-run 灰度,external worker running,普通测试用户真实 code-run 已成功生成 MindSpace 产物。 - P6.13 Agent Run Auto-pause Guard: 已完成,新增 `agent-run-guard.mjs` 和 LaunchAgent,按失败数/队列积压/running 超时自动关闭 code-run gate 并停 worker。 - P6.15 H5 Code-run Validation Metadata: 已完成,H5 code-run 自动声明 `.memind/agent-runs/.json` receipt 校验,生产已恢复 `MEMIND_AGENT_CODE_RUNS_REQUIRE_VALIDATION=1` 并通过普通测试用户真实路径。 +- P6.17 Controlled Worker Concurrency Canary: 已完成,external worker 短窗口提升到并发 2,两条真实 code-run 同时 running 并全部通过 receipt validation。 +- P6.18 Concurrency Rollout Policy: 已完成,生产 worker 和 Portal runtime/status 已对齐到并发 2,worker KeepAlive 保持开启,保留回滚备份。 - P5.15 Active Stream TTL Reconcile: 已按用户要求跳过,暂不做报表/定时 reconcile。 - P5 Worker Pool 运维化: 已完成第一步,Redis Router 支持 worker drain。 - P5.9 First-token Latency EWMA: 已完成,StreamController 会把首个 SSE chunk 延迟写入 Redis,SLO 报告已展示。 @@ -2642,6 +2644,98 @@ runtime/status: - `/Users/john/Project/memind_backups/20260702-114335-p615-validation-metadata` - worker KeepAlive 运维补强备份: `/Users/john/Project/memind_backups/20260702-115330-worker-keepalive` +### 2026-07-02 P6.17 Controlled Worker Concurrency Canary + +目标: + +- 在 required validation 和 auto-pause guard 已稳定后,短窗口验证 external worker 并发 2。 +- 不扩大 code-run gate,不改用户 allowlist,不改 task type allowlist。 +- 真实 canary 使用两个新测试用户,避免同一 MindSpace/git 工作目录互相锁住。 + +生产变更: + +- 备份: + - `/Users/john/Project/memind_backups/20260702-120520-p617-concurrency-canary` +- worker LaunchAgent 临时提升: + - `MEMIND_AGENT_RUN_WORKER_BATCH_SIZE=2` + - `MEMIND_AGENT_RUN_QUEUE_CONCURRENCY=2` + - `--limit 2` + - `KeepAlive=true` + +验证: + +- 两条真实 code-run 同时进入 running: + - run `d064c8c0-b061-4df7-8c9b-5dfa315271ea` + - user `916f1fe6-e9c8-44b5-9faa-2fc1bf146ab9` + - request `p617-concurrency-20260702040600-1` + - started `1782965163186` + - completed `1782965180346` + - status `succeeded`, attempts `1` + - run `64717bcc-4065-4947-a0d3-a706f3b62640` + - user `07f29934-8cf8-408a-af92-3c4276e579c8` + - request `p617-concurrency-20260702040600-2` + - started `1782965163135` + - completed `1782965186566` + - status `succeeded`, attempts `1` +- 两条 run 都写入: + - `tool_gateway_dispatch` + - `tool_gateway_result` + - `tool_gateway_validation` + - `succeeded` +- MindSpace 验证: + - 两个 receipt JSON 均包含 requestId。 + - 两个 `public/p617-concurrency-*.html` 均包含目标 marker。 +- worker log: + - `limit=2` + - `maxConcurrentRuns=2` + - `dispatched=2` +- P6.17 后复查: + - worker running + - queue empty + - guard `shouldPause=false` + - SLO `ok=true`, `failures=[]` + +### 2026-07-02 P6.18 Concurrency Rollout Policy + +目标: + +- 将 P6.17 的并发 2 从短窗口 canary 固化为当前 all-user gray 的可运营策略。 +- 让 worker LaunchAgent、Portal `.env` 和 runtime/status 对齐,避免状态面显示并发 1 但实际 worker 并发 2。 + +生产配置: + +- `/Users/john/Project/Memind/.env`: + - `MEMIND_AGENT_RUN_QUEUE_CONCURRENCY=2` + - `MEMIND_AGENT_RUN_WORKER_BATCH_SIZE=2` +- worker LaunchAgent: + - `MEMIND_AGENT_RUN_QUEUE_CONCURRENCY=2` + - `MEMIND_AGENT_RUN_WORKER_BATCH_SIZE=2` + - `--limit 2` + - `KeepAlive=true` + +验证: + +- `https://mm.tkmind.cn/api/status` 返回 `ok`。 +- `/api/runtime/status`: + - `codeRunPolicy.requireValidation=true` + - `toolRuntime.queue.maxConcurrentRuns=2` + - `toolRuntime.queue.statusCounts={}` +- worker check: + - running `true` + - process args include `--limit 2` +- guard dry-run: + - `ok=true` + - `shouldPause=false` + - queue empty +- SLO: + - `ok=true` + - `failures=[]` + +观察: + +- Portal 在一次重启窗口中出现 `read EADDRNOTAVAIL` 并由 LaunchAgent 自动拉起,随后 `/api/status` 和 `/api/runtime/status` 恢复 `ok`。 +- 后续建议优先做 running/stuck recovery 与 DB/session auth 异常不致命化,避免瞬时 DB/socket 错误扩大为进程退出。 + ## 回滚策略 - P0: 修改前保留 `server.mjs` 备份;如启动失败,恢复备份并 `launchctl kickstart` Portal。