Files
NixMsg/docs/TASKS.md
T

372 lines
27 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# NixMsg 开发任务拆分与多 Agent 协作
| 项 | 内容 |
|---|---|
| 版本 | 0.2 |
| 日期 | 2026-09-30 |
| 对应 | [PRD.md](./PRD.md) 0.5、[DEVELOPMENT.md](./DEVELOPMENT.md)(对应 PRD 0.5) |
| 仓库 | https://git.asio.asia/nixevol/NixMsg.git,主分支 `main` |
| 读者 | 总控 Agent、各开发线 Agent、负责人 |
## 1. 目标和交付标准
由多个 Agent 并行开发和测试,交付 NixMsg 服务端、管理后台、四种 SDK、Docker 镜像和文档。
下面全部满足才算交付:
1. `main` 上 `task check`(构建、代码检查、单元测试)和全部集成测试通过。
2. PRD 第 10 节 F01–F23 每条都有验收结果:通过;或未测,写明原因并经负责人认可。
3. 四种 SDK 都通过 DEVELOPMENT 第 9 节的接入清单。
4. DEVELOPMENT 第 13 节的弱网、崩溃、压测、端到端测试做完并有报告。
5. 二进制(`linux/amd64`、`linux/arm64`、`windows/amd64`)和 Docker 镜像(amd64、arm64)能按文档启动;镜像已推到 `git.asio.asia/nixevol/nixmsg`。
6. 和文档不一致的实现都写进 `docs/DEVIATIONS.md`,并经负责人确认。
7. 最终代码按第 7 节审核过,打上 `v0.1.0` 和 `sdk/go/v0.1.0` 标签并推送;npm、PyPI、Maven 三个 SDK 包已发布到 Gitea 包仓库。
## 2. 资料
- `docs/PRD.md`:产品行为,以它为准。
- `docs/DEVELOPMENT.md`:实现规范。第 5 节的库用法和第 15 节「不要这样做」必须看。
- `docs/TASKS.md`:本文件。
- MemRelay 项目记忆(项目 NixMsg,ID `25464650-ed5d-440e-b362-190f2852d451`):已确认的决定、技术栈选型、依赖库行为核对结论,以及各线的进度检查点。随时可以查。
- 文档没写清或互相矛盾时,停下来问总控;总控拿不准的问负责人。不要自己改 PRD 的产品行为。
## 3. 环境
- 本机是 Windows,已有 Git、Go、Node.js LTS、pnpm、Python、JDK 21、Docker Desktop 和 scoop。缺的工具用 scoop 装,例如 `scoop install task golangci-lint`;包名不确定时先 `scoop search`。
- 丢包模拟(netem)、多架构镜像等 Linux 相关的测试,在 Docker 的 Linux 容器里跑。toxiproxy 用它的官方 Docker 镜像。
- 多个 Agent 在同一台机器上同时跑测试,必须互不干扰:
- 测试里的服务一律监听随机端口(`:0`),数据放临时目录,不要写死 7443。
- Docker 容器、网络、卷的名字带上自己的线名前缀,用完删除。
- 不改全局配置:全局 git 配置、系统环境变量、全局 npm 配置都不要动。
- 推送 git.asio.asia 用本机 Windows 凭据管理器里已存好的账号,不要把账号密码写进仓库、脚本或命令行。
- 发布 SDK 包和推送镜像只在阶段 3 做,用 Gitea 个人访问令牌:总控用密码库条目 `git.asio.asia` 的账号在 Gitea 里创建一个只有 `package` 读写权限的令牌,立即存进 MemRelay 密码库,只写进本机用户级配置,不进仓库。
## 4. 协作规则
### 4.1 分支、工作树和提交
- `main` 只由总控合并,任何时候都要能构建、测试全绿。
- 每条线在自己的 git 工作树(worktree)里、自己的分支上工作,不共用目录。用 Cursor 代理窗口的工作树功能创建,或者自己建:
```bash
git fetch origin
git worktree add ../NixMsg-wt/<任务号> -b feat/<任务号>-<简述> origin/main
```
- 分支名:`feat/<任务号>-<简述>`,例如 `feat/n2-websocket-mochi`;修别人发现的问题用 `fix/<任务号>-<简述>`。
- 一功能一验证一提交:做完一个能验证的小功能,就补测试、跑 `task check`、提交,并推送到自己的远端分支。
- 提交信息:`type: 中文一句话描述`,type 取 feat、fix、refactor、style、docs、test、chore、revert。
- 不提交:构建产物、`web/dist`、数据库文件、证书和私钥、任何密码或令牌、`aidocs/`。
- 只改自己线负责的目录(第 5 节)。必须动别人的目录时,先告诉总控,改动尽量小。
### 4.2 共享文件
| 文件 | 规则 |
|---|---|
| `go.mod`、`go.sum` | 各线可以加依赖;冲突时以 main 为准重新 `go mod tidy` |
| `internal/protocol` | 总控在阶段 0 定好。之后要改先找总控,由总控改完合进 main,各线再 rebase |
| `internal/store/migrations` | `0001` 由总控在阶段 0 写好,包含全部表。之后要改表结构就加新文件,编号在 rebase 时取当时最大号加一 |
| `cmd/nixmsg/wire.go`(组装各模块) | 各线只加自己的注册代码;冲突时两边都保留 |
| `Taskfile.yml` | 总控维护;各线自己的任务写在 `taskfiles/<线名>.yml`,由主文件引入 |
| `docs/DEVIATIONS.md` | 按线分节,各线只写自己那节 |
| `docs/PRD.md`、`docs/DEVELOPMENT.md`、`docs/TASKS.md` | 只有总控改,而且要先得到负责人同意 |
### 4.3 合并进 main
1. 开发线:`git fetch` → `git rebase origin/main` → `task check` 和本任务的验证全过 → 推送分支 → 在 MemRelay 存一个检查点,标签 `ready-to-merge`,写清分支名、任务号、验证结果。
2. 总控:按第 7 节清单审阅差异 → 在主工作区 `git merge --ff-only <分支>` → 跑 `task check` 和集成测试 → 推送 main → 通知各线 rebase。
3. 不能快进(main 已经前进)时打回给开发线重新 rebase。冲突由开发线理解双方改动后解决。
4. 功能分支 rebase 后,用 `git push --force-with-lease` 更新自己的远端分支(负责人已同意,见第 9 节)。只能用在自己的 `feat/*`、`fix/*` 分支上,不许用于别人的分支;任何人都不许强推 `main`。
5. 如果仓库开了分支保护或合并请求审核,改成推分支、建合并请求,由总控合并。
6. 本期不做 CI(负责人决定)。合并前的全量验证由总控在本机执行,开发线的自测不能代替。
### 4.4 进度记录
- 各 Agent 按协作规则使用 MemRelay:开工前读项目上下文和最新检查点;完成一个任务、遇到阻塞、结束一次会话时存检查点,写明线名、任务号、分支、做了什么、验证结果、下一步。
- 不在仓库里另建进度文件,免得多条线同时改同一个文件。
## 5. 分工
| 线 | 负责目录 | 主要内容 |
|---|---|---|
| 总控 L | 根目录配置、`cmd/nixmsg/wire.go`、`internal/protocol`、迁移 `0001`、`test/harness`、`docs/` | 阶段 0、审阅合并、集成验证、最终验收 |
| 平台 P | `cmd/nixmsg`(`wire.go` 除外)、`internal/config`、`internal/store`(`0001` 除外)、`internal/auth` | 配置和命令、写入合并、密码哈希池、令牌和锁定计数、指标注册 |
| 连接 N | `internal/listener`、`internal/broker` | 端口识别、TLS、WebSocket、mochi、登录与会话令牌、连接表、握手 |
| 消息 M | `internal/app/message` | 提交、分发、推送、确认、撤回、回执、清理、启动恢复 |
| 身份 I | `internal/app/identity`、`internal/app/group`、`internal/app/presence` | 注册、自己的资料、对话密码、在线与目录、群、停用和删除 |
| 后台接口 A | `internal/admin`、`internal/httpx` | 管理接口、API 令牌、操作日志、指标接口的访问规则 |
| 后台网页 W | `web/` | Naive UI 后台和端到端测试 |
| SDK 一 S1 | `sdk/go`、`sdk/js` | Go、JS/TS SDK |
| SDK 二 S2 | `sdk/python`、`sdk/java` | Python、Java/Android SDK |
| 测试交付 Q | `test/`(`harness` 除外)、`deploy/`、`README.md` | 测试基础设施、验收用例、弱网和压测、Docker、发布、运维文档 |
## 6. 阶段和任务
```mermaid
flowchart LR
T0[阶段0 总控 骨架与契约] --> P[平台 P]
T0 --> N[连接 N]
T0 --> M[消息 M]
T0 --> I[身份 I]
T0 --> A[后台接口 A]
T0 --> W[后台网页 W]
T0 --> Q[测试交付 Q]
N --> S[SDK S1 S2 接入清单]
M --> S
I --> S
A --> W2[网页联调 W4]
P & N & M & I & A & S & W2 --> V[阶段2 验收 弱网 压测]
V --> Z[阶段3 总控 审核与交付]
```
- **阶段 0**(只有总控,串行):T0.1–T0.5。全部合进 main 并推送后才开阶段 1。
- **阶段 1**(并行):P、N、M、I、A、W、Q 同时开工,共 7 个 Agent。S1、S2 可以一起开工,先做不依赖服务端的部分(连接状态机、发送队列、去重、本地检查和单元测试),也可以等 N、M 合进 main 再开,看机器负载。
- **阶段 2**(联调和验收):N、M、I、A 的核心任务合进 main 后,S1、S2 跑接入清单,W 接真实接口做端到端测试,Q 跑验收、弱网、崩溃和压测。发现的问题开 `fix/` 分支,交回原负责线修。
- **阶段 3**(只有总控):全量回归、审核、偏差确认、打标签交付。
下面每个任务都要做到:代码、测试、文档依据里的规则都满足;验证项全部通过;`task check` 通过。
### 6.1 阶段 0:总控 L
**T0.1 仓库骨架** · 依赖:无
- 做:按 DEVELOPMENT 第 3 节建目录;`go.mod`(模块 `git.asio.asia/nixevol/NixMsg`);`Taskfile.yml`,目标至少有 `build`、`test`、`lint`、`check`(构建加检查加单元测试)、`web:dev`、`web:build`、`itest`(集成测试)、`docker`,并引入 `taskfiles/*.yml`;golangci-lint 配置;`web/` 用 Vite、Vue 3、TypeScript、Naive UI、Vue Router、Pinia 初始化,加 `web/embed.go`;`cmd/nixmsg` 先能 `version`,`serve` 先只打开库、跑迁移、在 `listen` 上提供 `/healthz`,端口为 0 时写 `listen.addr`;`deploy/config.example.yaml`;`.cursor/worktrees.json`,让新工作树自动执行 `go mod download` 和 `pnpm install`。
- 验证:Windows 上 `task check`、`task build` 通过,产物是嵌入了前端的单个可执行文件;在 Docker 的 Linux 容器里 `task check` 也通过。
**T0.2 协议包 `internal/protocol`** · 依赖:T0.1
- 做:DEVELOPMENT 第 6 节全部帧的 Go 类型,包括第 6.9 节注册的请求和响应、`session_token`、`self.logout`;第 6.10 节错误码常量;编码规则(不转义 HTML 和非 ASCII);字段校验(编号规则、正文和自定义字段大小、`send_at_ms` 和 `delay_ms` 互斥);第 7.3 节的请求指纹;整帧字节数计算。
- 验证:每种帧的编码、解码、校验都有表驱动单元测试;指纹对 `meta` 的键顺序不敏感。
**T0.3 数据库结构和存储接口 `internal/store`** · 依赖:T0.1
- 做:第 7.7 节的迁移执行器(有未应用版本时先 `VACUUM INTO` 备份);`0001_init.sql` 包含第 7.7 节全部表和索引;按第 7.7 节的 DSN 打开写连接和读连接池;写入队列的接口(提交一个写操作、拿到结果)和一个先不合并的简单实现,P2 再换成合并提交。
- 验证:空目录启动能建表;重复启动不会重复迁移;迁移前的备份文件存在;有单元测试。
**T0.4 模块接口和管理接口契约** · 依赖:T0.2、T0.3
- 做:`internal/auth` 和 `internal/app/*` 各服务的 Go 接口,以及测试用的假实现;broker 和 app 之间的接口(连接事件、上行帧分发、下行发布);`cmd/nixmsg/wire.go` 组装骨架;`docs/api/admin-api.md`,写清第 8 节每个管理接口的请求、响应、分页和错误格式,W 线据此先用假数据开发。
- 验证:`task check` 通过;契约文档覆盖第 8 节全部路由。
**T0.5 集成测试启动器 `test/harness`** · 依赖:T0.1
- 做:编译一次服务端;每个测试用随机端口、临时目录启动一个进程(配置里 `listen` 的端口写 0,服务端启动后把实际地址写进 `<data_dir>/listen.addr`,见 DEVELOPMENT 第 4.1 节,启动器读它),自动执行 `admin init` 拿到管理员密码;提供管理接口客户端和 MQTT 测试客户端(WebSocket 和 TCP 都支持,能收发第 6 节的帧);另外提供一个命令行启动器(例如 `go run ./test/harness/cmd/testserver`),在随机端口启动服务,把连接地址和管理员密码以 JSON 打到标准输出,收到 Ctrl+C 时退出并清理,给 JS、Python、Java 的集成测试用;测试结束时清理进程和目录。
- 验证:示例集成测试能启动服务、访问 `/healthz`,结束后进程和目录都清干净;两个测试并行跑互不干扰;命令行启动器能打出连接信息,退出后清理干净。
### 6.2 平台 P
**P1 配置和命令** · 依赖:T0.1、T0.3
- 做:第 11.1 节配置的加载和校验(`check-config` 拒绝 `max_body_bytes` 大于 262144);`admin init`、`admin set-password`、`backup`、`healthcheck`;`log/slog` JSON 日志;第 7.8 节的优雅停机。
- 验证:各命令有测试;`admin init` 的密码只在终端打印一次、不进日志,已初始化的库拒绝再次执行。
**P2 写入合并** · 依赖:T0.3
- 做:第 7.2 节的合并事务(最多 256 个操作或凑满 2 毫秒)、每个操作一个 SAVEPOINT、读连接池;写库失败时请求返回 `busy`,`/readyz` 返回失败。
- 验证:单个操作失败只回滚它自己;基准测试给出每秒能提交的写操作数,模拟每秒 200 条消息的写入量时队列不堆积。
**P3 认证工具 `internal/auth`** · 依赖:T0.1
- 做:argon2id 哈希池(第 12 节参数、PHC 格式、并发上限);会话令牌和 API 令牌的生成和哈希;锁定计数器(按键计数、时间窗口、到期解除、手动清除)。
- 验证:单元测试;并发池能限制同时运行的哈希数;锁定窗口到期自动解除。
**P4 指标注册** · 依赖:T0.1
- 做:用 `prometheus/client_golang` 建注册表,定义第 4.3 节列出的指标,给各线打点用;`/metrics` 的处理函数(访问规则由 A 线在路由里加)。
- 验证:单元测试能抓到指标文本。
### 6.3 连接 N
**N1 端口与 TLS** · 依赖:T0.1
- 做:第 4.1–4.3 节和第 4.5 节:首字节识别、TLS 和证书每小时重载、`admin_listen` 分离、通道 Listener、路由骨架、受信任代理的真实 IP。
- 验证:同一端口上明文 HTTP、TLS+HTTP、裸 TCP、TLS+TCP 都能识别;后台分离时的 404 规则;替换证书后新连接用上新证书;声明 ALPN `mqtt` 的客户端能完成握手。
**N2 WebSocket 与 mochi** · 依赖:N1、T0.2、T0.4
- 做:第 4.4 节;第 5 节的装配约束、连接代号、心跳校正、ACL、`OnPublish` 投进每端的串行队列(长度 256,满了形成背压);下行发布(整帧大小检查、QoS 选择、第 7.5 节的大帧并发名额)。
- 验证:浏览器页面从别的域名连 `/mqtt` 成功;子协议不对的连接被关闭;超过客户端上限的下行不发布,并回调上层;QoS 0 的事件不占 inflight。
**N3 登录、会话令牌和握手** · 依赖:N2、P3、T0.3
- 做:第 5 节「登录与会话令牌」和锁定(用 P3 的工具);内部故障时让 `OnConnect` 返回 error;顶号和连接表;第 6.1 节握手(返回 `session_token`、30 秒没握手就断开、没订阅 down 就断开);`self.logout`;`online_since` 和 `offline_since`;把上下线事件交给 I 线。
- 验证:F02 的全部验收(用测试启动器);数据库不可读时客户端连接被直接关闭,而不是收到 `0x86`。
### 6.4 消息 M
**M1 提交** · 依赖:T0.2、T0.3、T0.4
- 做:第 6.2 节和第 7.3 节:先查防重,再校验、查配额、写授权和回复授权,发送时刻已到的立即分发;请求频率桶(第 6.10 节)。
- 验证:表驱动测试覆盖防重命中、冲突、配额、授权、延迟和定时互斥。
**M2 分发与推送** · 依赖:M1、N2
- 做:第 7.4 节和第 7.5 节:调度器、`queue_full`、停用成员、推送窗口、确认计时和两种超时规则、`OnPublishDropped` 后重推、握手和断线时的投递调整、每秒清理循环。
- 验证:F08–F12 的状态机测试和集成测试。
**M3 确认、撤回、回执、状态** · 依赖:M2
- 做:第 6.3 节、第 6.4 节、第 7.6 节:确认、撤回结果的判定、回执写入和推送窗口、`revoked`、`status` 分页、收尾删正文、每小时清理(防重行按条件删、分批删、`wal_checkpoint`)。
- 验证:F13、F14、F18 的测试。
**M4 启动恢复** · 依赖:M2
- 做:第 7.8 节的启动恢复和写库失败处理。
- 验证:推送中杀掉进程再重启,不保留的消息在宽限内重连仍能送到;停机期间到点的定时消息在启动后发出。
### 6.5 身份 I
**I1 注册接口** · 依赖:T0.3、P3、N1
- 做:第 6.9 节:开关、安全码、锁定、跨域、字段规则、`source=self`;`settings` 表读写。
- 验证:F23 的全部验收。
**I2 自己的资料和对话密码** · 依赖:N3、T0.2
- 做:第 6.6 节的 `self.*`(改登录密码时返回新令牌)、`unlock`、授权表(版本、两种授权、回复授权)、按对方计总数的暂停。
- 验证:F15 的全部验收。
**I3 在线与目录** · 依赖:N3
- 做:第 6.5 节:`presence.get`、`presence.watch`(QoS 0 事件)、`directory.list`(分页和 `query`)。
- 验证:F03、F04 的验收。
**I4 群** · 依赖:M1、I2
- 做:第 6.7 节全部帧、群事件、成员上限、加人时的对话密码、退群、踢人、解散、转让,以及第 7.6 节表里的作废规则。
- 验证:F06、F16 的验收。
**I5 停用与删除** · 依赖:M3、I4
- 做:第 7.6 节表里停用、删除端的全部处理(清会话令牌、作废消息、转让群主、清理数据),提供给 A 线调用。
- 验证:F01 里停用和删除相关的验收;删除后用同一编号重新开通,不会串到旧数据。
### 6.6 后台接口 A
**A1 鉴权** · 依赖:T0.3、T0.4、P3
- 做:第 8 节的 Cookie 会话、`X-Nixmsg-Request` 头、管理员登录锁定、API 令牌鉴权和权限限制、令牌管理接口、操作日志。
- 验证:F17 里令牌相关的验收;用令牌调用改管理员密码和令牌管理接口被拒绝。
**A2 端管理** · 依赖:A1、I5、N3
- 做:列表(按来源、在线状态筛选)、开通、CSV 批量开通(整批校验、结果只给一次)、批量停用、启用、删除、编辑、重置密码、踢下线、`unlock`、设置对话密码。
- 验证:F01 的验收;导入 1000 行 CSV 成功。
**A3 其余接口** · 依赖:A1、I1、I4、M3、P4
- 做:注册设置、群管理、记录查询(筛选、分页、响应不含正文)、概览、只读设置、`/metrics` 的访问规则(第 4.3 节)。
- 验证:F17 和 F22 里指标相关的验收;在所有管理接口的响应里搜不到测试正文。
### 6.7 后台网页 W
**W1 框架** · 依赖:T0.1、T0.4
- 做:第 2.4 节的界面要求和 Naive UI 用法;布局、登录页、路由守卫、请求封装(CSRF 头、错误提示)、中文。先按契约用假数据开发。
- 验证:`vue-tsc` 类型检查、ESLint、Vitest 通过;页面在 1366×768 和 1920×1080 下没有重叠和遮挡。
**W2 端管理页** · 依赖:W1
- 做:列表、筛选、多选批量操作、开通和编辑弹窗、CSV 导入和结果下载、重置密码的结果只显示一次、解除锁定、设置对话密码。
- 验证:组件测试;假数据下主流程可用。
**W3 其余页面** · 依赖:W1
- 做:概览、注册设置、群、投递记录、API 令牌(创建后只显示一次)、改管理员密码、只读参数。
- 验证:组件测试;假数据下主流程可用。
**W4 联调和端到端测试** · 依赖:A2、A3
- 做:接真实接口;用 Playwright 走第 13 节的后台主路径(登录、开通、开启注册并设置安全码、建群、看到未完成记录),再加 API 令牌的创建和停用。
- 验证:端到端测试在 `task itest` 里通过。
### 6.8 SDK S1、S2
S1 先做 Go,再做 JS/TS;S2 先做 Python,再做 Java/Android。每种语言都按下面五个任务做,任务号带语言,例如 `S1-GO-1`、`S2-JAVA-3`。
| 任务 | 内容 | 依赖 |
|---|---|---|
| 1 连接和会话 | WebSocket(TCP 可选)、每次连接都带 Clean Start、握手、会话令牌(`onSession`、用令牌重连、`session_invalid`)、退避、停止重连的条件、连接超时 30 秒 | T0.2 |
| 2 收发 | 发送队列(上限 1000、在途 100、`rate_limited` 自动重交、`send_at_ms` 不重算)、去重和再确认、串行回调、自动和手动确认、`revoked`、本地大小检查 | 任务 1 |
| 3 其余接口 | 撤回、状态、回执、在线、目录、订阅、群、`self.*`、`logout`、注册 | 任务 2 |
| 4 接入清单 | 第 9 节的 15 条集成测试,用 T0.5 的启动器起真实服务端 | 任务 3,以及 N3、M3、I2、I4 已合进 main |
| 5 打包和文档 | 按 DEVELOPMENT 第 9 节设置包名、许可证信息和发布配置,用各工具的试运行方式确认能打包(真正发布在 Z3);写这种语言的 README 和最小示例 | 任务 4 |
各语言的要点在 DEVELOPMENT 第 2.3 节和第 9 节:Go 用 `ConnectPacketBuilder` 每次设 Clean Start;JS 同时支持浏览器和 Node,发 ESM 和 CJS,要测跨域;Python 同步为主,另给 asyncio 包装;Java 编译成 Java 8 字节码,写清 Android API 24 的用法。
### 6.9 测试交付 Q
**Q1 测试基础设施** · 依赖:T0.5
- 做:toxiproxy 和 netem 的 Docker 编排(名字带前缀);1000 连接的压测客户端;验收报告生成(F01–F23 对照表)。
- 验证:能对一个运行中的服务端注入延迟、丢包、断开;压测客户端能保持 1000 个连接。
**Q2 验收用例** · 依赖:各线的核心任务
- 做:PRD 第 10 节每条至少有一个集成测试;各线写过的算数,Q 负责补齐和汇总成报告。
- 验证:报告列出 F01–F23 每条的结果。
**Q3 弱网、崩溃、压测** · 依赖:Q1、Q2
- 做:DEVELOPMENT 第 13 节的全部相关测试,并出报告。
- 验证:报告里的数字满足 PRD 第 8 节。
**Q4 Docker 与发布** · 依赖:T0.1,最终在阶段 2 完成
- 做:第 11.4 节的多阶段、多架构镜像;compose 示例;三个平台的二进制;镜像冒烟测试;推送镜像的 Taskfile 目标(推到 `git.asio.asia/nixevol/nixmsg`,真正推送在 Z3);第 11.3 节 1Panel 证书说明。
- 验证:两个架构的镜像都能初始化、启动、通过健康检查。
**Q5 文档** · 依赖:各线完成
- 做:README(功能、构建、运行)、运维手册(配置、备份、升级、证书、时钟、指标)、SDK 文档汇总。
- 验证:按 README 在一台干净机器上能构建和启动。
### 6.10 阶段 3:总控 L
**Z1 全量回归**:在 main 上跑 `task check`、全部集成测试、端到端测试、四个 SDK 的接入清单、弱网和压测。
**Z2 审核**:按第 7 节清单逐项审核;做安全检查(日志和管理接口里没有正文、密码、令牌);检查依赖的许可证。
**Z3 交付**:汇总 `docs/DEVIATIONS.md` 并请负责人确认;打 `v0.1.0` 和 `sdk/go/v0.1.0` 标签并推送;按第 3 节创建发布令牌,把 npm、PyPI、Maven 三个 SDK 包发布到 Gitea 包仓库,把两个架构的镜像推到 `git.asio.asia/nixevol/nixmsg`(版本号标签和 `latest`);构建三个平台的二进制;写交付说明(功能清单、验收结果、已知问题)。
## 7. 审核清单
总控每次合并前和最终审核时都要过一遍:
- 行为和 PRD 一致,实现和 DEVELOPMENT 一致;不一致的已写进 `docs/DEVIATIONS.md`。
- 没有违反 DEVELOPMENT 第 15 节的任何一条。
- MemRelay 里「依赖库行为核对结论」涉及的点都做对了:`OnConnect` 和 `OnConnectAuthenticate` 的分工、`CodeSuccessIgnore`、下行大小自查、WebSocket 的 Origin 校验、TLS 的 `NextProtos`、每次连接都带 Clean Start。
- 所有写库都走写入队列;条件更新都检查了影响行数。
- 日志、错误信息、管理接口响应里没有正文、密码、令牌和注册安全码。
- 新代码有测试;测试用随机端口和临时目录。
- 没有引入技术栈以外的框架和中间件。
## 8. 负责人操作说明
用本地 Agent。仓库在自建的 Gitea 上,Cursor 的云端 Agent 只支持 GitHub、GitLab 等托管平台,而且用不了本机的 Docker。
1. 按 `Ctrl+Shift+P`,执行 `Open Agents Window` 打开代理窗口。每新建一个 Agent,先在输入框的模型选择器里选好 Grok 模型再发第一条消息。
2. 阶段 0:新建一个 Agent 当总控,就在主工作区 `e:\code\NixMsg` 里运行,发「总控提示词」。等它报告阶段 0 已经合进 main 并推送。
3. 阶段 1:每条线新建一个 Agent,让它在自己的工作树里运行(在代理窗口新建时选工作树;找不到这个入口就让 Agent 按第 4.1 节自己建)。发「开发线提示词」,把 `<线名>` 换成 P、N、M、I、A、W、Q。建议同时跑的不超过 7 个;S1、S2 在机器有余力时再开,或者等 N、M 合进 main 后再开。
4. 日常:在代理窗口侧栏看各 Agent 的进度和改动。某条线说可以合并时,告诉总控「合并 <分支名>」,或者让总控定期查 MemRelay 里标了 `ready-to-merge` 的检查点。Agent 提问时在它的对话里回答,拿不准的转给总控判断。
5. 阶段 2、3:N、M、I、A 的核心任务合进 main 后,让 S1、S2、W、Q 按任务表联调和验收;最后告诉总控「开始阶段 3」。
6. 注意:Cursor 默认整台机器最多保留 25 个工作树,超出会自动删掉最旧的,所以要各 Agent 勤提交、勤推送;需要时在设置里调大 `cursor.worktreeMaxCount`。
总控提示词:
```text
你是 NixMsg 的总控 Agent,在主工作区 e:\code\NixMsg 工作。先按协作规则读 MemRelay 项目记忆,再完整阅读 docs/PRD.md、docs/DEVELOPMENT.md、docs/TASKS.md。现在完成 TASKS.md 阶段 0 的 T0.1 到 T0.5:每个任务一个分支,一功能一验证一提交,全部验证通过后快进合并进 main 并推送。完成后向我汇报,并告诉我可以开启阶段 1。之后你负责按 TASKS.md 第 4.3 节和第 7 节审阅、合并各线分支并跑集成验证,最后执行阶段 3。
```
开发线提示词:
```text
你是 NixMsg 的开发线 <线名> Agent。先按协作规则读 MemRelay 项目记忆,再阅读 docs/TASKS.md(重点第 3、4、5 节和第 6 节里 <线名> 的任务)以及 PRD、DEVELOPMENT 的相关小节。在你自己的工作树和 feat/<任务号>-<简述> 分支上工作,只改本线负责的目录,按依赖顺序完成本线任务:一功能一验证一提交,并推送自己的分支。每个任务完成后 rebase 到 origin/main、跑全部验证,通过后在 MemRelay 存标签为 ready-to-merge 的检查点,然后告诉我。缺工具用 scoop 安装;文档有疑问先问我,不要自己改产品行为。
```
## 9. 负责人已确认的协作事项
- 2026-09-30:允许各开发 Agent 在 rebase 后用 `git push --force-with-lease` 更新自己的 `feat/*`、`fix/*` 远端分支;`main` 任何时候都不许强推。
- 2026-09-30:SDK 发布到 Gitea 包仓库,镜像推到 `git.asio.asia/nixevol/nixmsg`;本期不做 CI;许可证为专有,源码仓库和发布物公开可读(DEVELOPMENT 第 2.1 节、第 9 节、第 11.4 节)。
- PRD 第 9 节的默认规则 D1–D33 已全部确认,开发中不再等待确认;和文档不一致的实现按第 4.2 节写进 `docs/DEVIATIONS.md`。