docs: 初始化仓库,加入需求、开发说明和任务拆分

This commit is contained in:
Nixevol
2026-09-30 05:11:26 +08:00
commit 2ab09507ff
8 changed files with 2310 additions and 0 deletions
+367
View File
@@ -0,0 +1,367 @@
# NixMsg 开发任务拆分与多 Agent 协作
| 项 | 内容 |
|---|---|
| 版本 | 0.1 |
| 日期 | 2026-09-30 |
| 对应 | [PRD.md](./PRD.md) 0.4、[DEVELOPMENT.md](./DEVELOPMENT.md)(对应 PRD 0.4) |
| 仓库 | 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)能按文档启动。
6. 和文档不一致的实现都写进 `docs/DEVIATIONS.md`,并经负责人确认。
7. 最终代码按第 7 节审核过,打上 `v0.1.0` 标签并推送。
## 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 凭据管理器里已存好的账号,不要把账号密码写进仓库、脚本或命令行。
## 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. 如果仓库开了分支保护或合并请求审核,改成推分支、建合并请求,由总控合并。
### 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 节的帧);测试结束时清理进程和目录。
- 验证:示例集成测试能启动服务、访问 `/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 条集成测试,对真实服务端二进制运行 | 任务 3,以及 N3、M3、I2、I4 已合进 main |
| 5 文档和示例 | 这种语言的 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 示例;三个平台的二进制;镜像冒烟测试;第 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` 标签并推送;构建二进制和镜像;写交付说明(功能清单、验收结果、已知问题)。
## 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` 任何时候都不许强推。