Why: Second-instance writes stay closed until an independent replay or an admitted CI gate, plus a second host. Those remaining steps needed a durable spec. Evidence: Task-card evidence rows read the merged PRs, tree equality, CI runs 2783/2810/2816, and Dev main branch protection. Source SELF. Drills were not run. Impact: Docs and the task card only. Checklist grades stay SELF or not started. The collaboration proposal body stays r2.3. Refs: docs/release-multi-instance.md Co-authored-by: Cursor <cursoragent@cursor.com>
81 lines
7.7 KiB
Markdown
81 lines
7.7 KiB
Markdown
# 双实例放行前检查单(协作存储 U7)
|
||
|
||
协作存储方案 §5 U7 的放行出口要求:**单实例团队、双进程、双主机分别出具
|
||
结果;CI 身份/链接/SHA 或独立 REPLAY 可核验才用于放行,本地 SELF 只作辅助。**
|
||
本检查单列出每一放行条件、其证据来源与当前状态;未全部满足前,第二实例
|
||
不得承接写请求、双主机部署不得开工。
|
||
|
||
状态图例:✅ 已满足(证据可核验)|⏳ 入口就绪、待执行窗口|❌ 未开始。
|
||
|
||
## A. 正确性与故障矩阵(代码与 CI 可覆盖)
|
||
|
||
| # | 条件 | 证据(命令/测试) | 状态 |
|
||
|---|---|---|---|
|
||
| A1 | 单实例全链路(mock):认证/项目/会话/SSE/检索/卡片 | backend `go test ./...`(CI job `test`,SQLite 档 35+ 包) | ✅ CI 绿 |
|
||
| A2 | 真 PG/Redis 全量 | `make test-backend-pg`(CI job `test-pg`,AGENT_PG_TEST_DSN 必跑) | ✅ CI 绿 |
|
||
| A3 | 磁盘满清楚拒绝、零残留、可恢复 | backend `TestUploadRejectsCleanlyWhenObjectDirUnwritable`、`TestArtifactOverwriteRejectsCleanlyWhenObjectDirUnwritable` | ✅ CI 绿 |
|
||
| A4 | 恢复隔离(未知副作用不自动重跑) | backend `recovery_hold_test.go`(U3) | ✅ CI 绿 |
|
||
| A5 | 库级多实例语义(争抢/围栏/命令/跨实例 resolve 不落卡) | backend `runmgr/multi_instance_test.go`(真库门控) | ✅ CI 绿 |
|
||
| A6 | **双进程 HTTP 级验收**(跨实例读/SSE/409/HITL/取消/崩溃恢复/重启不变量) | `make test-multi-instance`(CI job `test-pg`;本地 `tests/integration/multi-instance/README.md`) | ✅ CI 绿 |
|
||
| A7 | 权限矩阵重放(撤权零泄漏:请求/SSE/检索/下载/工具) | backend `resource_authz_test`、`shared_*_test`、`sse_gap_test`、`pgvector_test`(U3/U6) | ✅ CI 绿 |
|
||
|
||
## B. 容量与负载合同(需要实测窗口,本地入口已就绪)
|
||
|
||
| # | 条件 | 证据(命令) | 状态 |
|
||
|---|---|---|---|
|
||
| B1 | 冒烟压测通过(入口可复核、不变量零违反) | `tests/load/collaboration/run_load.sh --profile smoke` | ✅ 已跑通(SELF,2026-10-12:读 P95<1ms、SSE P95≈18ms、对账 0 违反) |
|
||
| B2 | 阶梯负载 10→30→100 用户,读 P95≤300ms、P99≤1s、非预期失败≤0.1% | `--seed contract --profile ladder --instances 2`;results `20261012-064730`:读 P95≈15.5ms、P99≈44.3ms、fail=0 | ✅ SELF(2026-10-12);非 GATE/REPLAY |
|
||
| B3 | 60 分钟稳定负载 + 2 小时混合长稳 | `sustained60m` results `20261012-070510`(读 P95≈3.9ms);`sustained2h` results `20261012-081025`(读 P95≈6.2ms);均 fail=0、dup_seq=0 | ✅ SELF(2026-10-12);非 GATE/REPLAY |
|
||
| B4 | SSE 持久事件可见延迟 P95≤1s | 同上套件 sse_probe:ladder A/B ≈17.5/33.0ms;60m ≈5.7/4.4ms;2h ≈3.9/4.2ms | ✅ SELF(随 B2/B3) |
|
||
| B5 | 数据量档(100 万消息/10 万知识分块/多项目交叉授权) | 三段均 `--seed contract`(manifest:1e6 messages / 1e5 knowledge) | ✅ SELF(2026-10-12) |
|
||
| B6 | 数据库基线(pgbench 只测 DB 能力,不替代业务验收) | `tests/load/collaboration/run_pgbench.sh`;results `pgbench-20261012-131948`(scale 100,60s,`-M prepared`;100 客户端按 `max_connections` 余量封顶为 95)。select-only 10/30/95 的 P95 为 0.024/0.057/0.180 ms;TPC-B 类 10/30/95 的 P95 为 0.673/1.002/3.361 ms。失败事务 0。主机并不空闲,数字只作参考 | ✅ SELF(2026-10-12);无业务阈值;非 GATE/REPLAY |
|
||
| B7 | 容量数字绑定组件 SHA/配置/数据集归档 | [容量报告](../modules/documents/docs/records/2026-10-12-u7-capacity-window-report.md) + worktree `results/<ts>/` + 任务卡 evidence | ✅ SELF 报告已写 |
|
||
|
||
## C. 双进程与双主机放行(分布式出口)
|
||
|
||
| # | 条件 | 证据 | 状态 |
|
||
|---|---|---|---|
|
||
| C1 | 双进程共享 PG:正确性矩阵全过(A6) | `make test-multi-instance` | ✅ |
|
||
| C2 | 双进程**负载**下互相不拖累(热点会话/命令时延) | 上表 B2/B3 均 `--instances 2`(VU 粘滞 + 跨实例读 + 热点 409 入 expected_contention;非热点读阈值全过) | ✅ SELF(2026-10-12);非 GATE/REPLAY |
|
||
| C3 | 双主机(跨机网络)验证:同套验收在两台主机执行 | A6 的 AGENT_BIN/DSN 指向远端;需用户指定第二主机 | ❌ 待资源 |
|
||
| C4 | 故障演练:PG 断连/Redis 断连恢复(RTO≤15min) | `tests/ops/run_fault_drill.sh --fault all`;results `fault-20261012-142734`。pg-stop 与 pg-kill 的 F1–F5 均过,RTO 不到 1 秒且未重启应用。Redis:共享限额 20,断连期间按实例合计约 40,拉起后回到 20;无 5xx。G4 降级不可见、G5 启动时 Redis 不通则拒绝,记为发现 | ✅ SELF(2026-10-12);非 GATE/REPLAY |
|
||
| C5 | 备份恢复演练(RPO≤5min/RTO≤60min,pg_dump+物理备份) | `tests/ops/run_backup_drill.sh`。2026-10-12 `backup-20261012-153441` 的库恢复过、K4 因空 `*S3` panic 失败。2026-10-13 在 Backend `46073d30`(合入 `dc736e3`,同树)、Dev `a83588dd` 上重跑 `backup-20261013-013354`:K1–K7 过,RPO 65s,RTO 3s;K4 为 5 个工件 sha256 一致且跨用户项目/工件访问均为 404。静态加密、凭据演练记 N/A;归档与数据同盘 | ✅ SELF(2026-10-13);非 GATE/REPLAY |
|
||
|
||
## 放行结论(当前)
|
||
|
||
- **单实例团队档**:A1–A7 全绿 + B1–B5/B7 本机 SELF 容量窗口全过(见容量报告)。
|
||
功能验收成立;**容量数字仅为 SELF**,换机/真实模型须重测。生产承诺仍待独立 REPLAY 或 GATE。
|
||
- **双进程档**:正确性已证(A5/A6/C1),本机双实例负载 SELF 已过(C2)。C4 断连演练 SELF 已过。
|
||
**仍不放行第二实例承接写请求**——缺独立 REPLAY/GATE,C3 未做。C5 的工件恢复(K4)已有 2026-10-13 本机 SELF,不是 GATE。
|
||
- **双主机档**:未开始(C3),不放行。
|
||
|
||
## 下一步规格(2026-10-13,未执行)
|
||
|
||
上表的证据等级保持原样:C4 与 C5 仍是 SELF,C3 仍是未开始。
|
||
独立重放、CI 快速档和双主机都还没有做。可执行规格:
|
||
|
||
- [独立重放](u7-release-replay.md)
|
||
- [CI 快速档可行性](u7-release-ci-feasibility.md)
|
||
- [第二台主机清单](u7-release-c3-host.md)
|
||
|
||
PR、提交同树与 CI 运行的读取记录在任务卡
|
||
`.task/feature-u7-release-roadmap.md` 的证据表,来源 SELF。
|
||
`policy/facts.md` 仍只登记长期基础设施事实;上述 PR 与运行不写入该表,
|
||
因为它们不是长期事实,而且核验命令含管道与引号,不符合该表的命令格式。
|
||
|
||
协作存储方案正文仍是 Documents `05c13a42b14d70f878cc8a51c543e018a7f7a663` 的 r2.3。
|
||
本次没有改 Documents 仓,也没有推进 gitlink。下面这段是准备写入方案、尚未写入的修订:
|
||
|
||
> r2.4:2026-10-13 只补了放行规格,没有做独立重放,没有把 C4/C5 接进 CI,没有第二台主机。证据等级不变。第二实例写流量仍不开放。规格见 Dev `docs/release-multi-instance.md` 的「下一步规格」。
|
||
|
||
## 已知边界与诚实声明
|
||
|
||
- U7 期间经双进程验收发现并修复三个跨实例缺陷(详见
|
||
`tests/integration/multi-instance/README.md`):HITL resolve 落卡短路命令、
|
||
cancel 命令空会话 ID、CancelRun 假成功。修复均已入 CI 回归。
|
||
- 正式容量窗口使用 Homebrew 固定位 k6 v2.3.0。
|
||
- 容量详情与 SHA 绑定见 Documents
|
||
`docs/records/2026-10-12-u7-capacity-window-report.md`;原始
|
||
`results/<ts>/` 在测量 worktree(gitignore),不入库。
|
||
- B6 pgbench、C4 断连演练与 C5 备份恢复(含 K4 工件)已有本机 SELF。C3 双主机仍待第二台机器。证据等级仍缺独立 REPLAY 或 CI GATE。下一步规格见上文「下一步规格」,规格本身不提升证据等级。
|