# Cyrene v2 开发铁律(AGENTS.md) > 本文件是**项目级开发铁律**,由运行环境在**每次工作会话时自动注入**。即使发生上下文压缩/丢失,以下约束仍会强制生效。**必须遵守**,违反即偏离。 ## 1. 先读设计,再写代码 - 动任何代码**前**:先读 `DevDocs/开发时间线.md`(当前里程碑 + §3 功能状态清单),确定这一步属于哪个里程碑/功能。 - 具体功能实现:先读对应 `DevDocs/design/*.md`,**按其规格实现,不得自行发挥**(design/01~13 是权威设计)。 ## 2. 按里程碑推进,不跳步、不漂移 - 严格按 **M0 → M12** 顺序。每个功能的依赖与归属见时间线 §2/§3。 - 不得「想到什么做什么」。**新需求/新想法:先写入设计或时间线清单,再开发**,不脱离清单。 - 上下文压缩后:**先读 `DevDocs/工作小结/00-当前态.md`** 恢复锚点,再继续,**不得凭印象跳走**。 ## 3. 每阶段审查并勾选 - 阶段完成:后端 `go build ./...` + `go vet ./...` + `go test ./...` 全绿;前端 `tsc --noEmit` + `vite build` 通过。 - 在 `DevDocs/开发时间线.md` §3 勾选状态:`✅ 已完成` / `⚠️ 未完成/阻塞`(⚠️ 必须记录原因与延后里程碑)。 - 与 `DevDocs/design/*` 比对:不一致时以设计为准——先改设计文档或修正代码,**不允许带着偏离堆叠**。 ## 4. 改动前确认归属 - 修改任一文件/功能前,明确它在哪个里程碑、对应哪份 design 文档;改完同步该文档(若设计变了)。 ## 5. 实时同步工作小结 - 每完成一步,更新 `DevDocs/工作小结/00-当前态.md`:当前里程碑 / 进度 / 已完成+未完成 / 关键决策 / 变更日志。 ## 6. 小步提交 + 频繁验证 - 小粒度 commit;每步 build/test 通过再提交;提交信息按 Git 规范(feat/fix/refactor/docs/chore,scope 用模块名)。 ## 7. 不信任记忆,信任清单 - 关键决策、架构铁律、用户红线(如身份识别靠元数据、不靠提示词)都记录在 `DevDocs/工作小结/00-当前态.md` 的「关键决策」区;压缩后回读,不得丢失。 ## 8. 上下文保护:可并行项交给后台子代理,主会话当监工 - **相互独立、不依赖主会话开放状态**的开发任务(如 M0 地基各件、层 1 并行件),用 `Agent(run_in_background=true)` 派后台子代理**并行实现**。 - 主会话**只当监工**:等子代理回报 → 验收(`go build/vet/test`)→ 更新 `DevDocs/工作小结/00-当前态.md` + 时间线 → 小步 commit → 派下一批。**不在主会话里重复子代理已做的搜索/实现**。 - 子代理 prompt 必须**自包含**:写清目标、已知信息、精确文件路径、必须遵守的编码约束(02-development-constraints.md)、验收命令;不要让它去搜已经知道的东西。 - **只有真正独立才并行**;有依赖的串行。避免两个子代理同时改 `go.mod/go.sum`——若都要改,指定其中一个负责或先把依赖拉好。 - 目的:防主会话上下文超限触发压缩;压缩后靠本文件 + `DevDocs/工作小结/00-当前态.md` 恢复锚点,继续当监工。 ## 9. 全球红线(跨里程碑,必须遵守;违反即架构偏离) - **单二进制、单端口 `:8080`、零跨进程 IPC**(🔴 **本条约束的是 Cyrene 框架自身,不约束扩展插件**):框架模块间同步走**进程内接口 + 依赖注入**(直接方法调用),异步走**进程内 `bus`**;**框架自身不另开监听端口、不 HTTP 互调**。 - 🆕 **2026-10-07 主人口径补充(原「豁免」升格为一般规则)**:**扩展插件不受本条约束** —— `plugins/` 下的渠道适配器与工具、MCP server、以及插件自己拉起的本地伴随进程/服务,**可以开自己的监听端口、可以有自己的进程形态**。这**不是「例外」,是插件的正当能力**;原先只为 `qq-obv11` 登记的那条例外,**随之由「例外」变为本条一般规则的一个实例**(该渠道规格仍见 `design/08 §4`)。 - 🔴 **插件开端口的四条护栏(主人 2026-10-07 确认采纳)**:① 端口/地址**必须由配置显式给出**,**不得默认开启、不得写死**;② **默认绑 `127.0.0.1`**,要对外暴露必须由 `.env` 显式决定(与框架暴露面同一套口径);③ **必须登记日志来源与审计**(谁开的、绑在哪);④ **端口不得成为绕过身份/权限判定的入口** —— actor 元数据 + 白名单 + 策略引擎仍是唯一判据,端口不是后门。 - 「**零跨进程 IPC**」的原意**仍然有效**:**框架内部模块**不得为解耦而拆成多进程/多服务、不得 HTTP 硬编码 URL 互调(详见 `DevDocs/00-overview.md`)。**框架与插件之间的边界通信不在本条约束内**;但框架**不得**因此把自身模块拆出去变成插件。 - **身份识别靠 channel 层强类型 `actor` 元数据 + 策略引擎**,**绝不靠提示词/LLM 判断**(主人/群聊/陌生人判定与权限永远由 actor 元数据 + 白名单 + policy engine 决定)。 - **人格 = 身份**(**不限制能力**);**行为模式 = 呈现**(≠边界,可热切换、不构成能力边界);**能力全局全能**;**前端(Web)是第一公民**。 - **IM 是镜像**:只 chat 文本,Web 不回流 IM;输出一律 chat 文本。 - **前端(用户端 + 管理面板)统一 Miuix 设计语言**(小米 HyperOS Miuix / Miuix Console),实现须对齐六大核心(Smooth Corner/多层 Surface/弹簧动效/深色优先/毛玻璃/Liquid Glass),不混用其他 UI 语言。 - **存储**:SQLite 默认 + PG/pgvector **可选增强**;**配置了增强必须真实走语义/向量路径**(非空壳)。 - **工具循环上限 8 轮**;任务:后台声明 / 前台 2s 转后台 / 消息队列回输出。 - **记忆三类作用域隔离**:用户习惯(全局共享)/ 角色日常(他角色只读)/ 项目(人人读写 + 项目索引分层);**群聊 / 陌生人:查记忆只读不写、不入主会话上下文、不泄露主人敏感信息**。 - **敏感操作主代理代审 + 审计日志 + 前端小字**(「xxx 想要干什么,我审查后批准了」)。 - **模型**:per-role 路由 + 接口报错自动降级(主→备→本地);多模态/流式。 - 🔴 **后端常驻(主人 2026-10-04 追加要求)**:在**下一次构建产物就绪之前,正在运行的后端(`cyrene.exe`,`:10942`)不准关**,除非出现**恶性 Bug**(进程致命错误/必须阻断的严重故障)。推论:① **禁止**为「跑全树验收 / 重启清理 / 图省事」而停它——`go test`/`go build`/`git` 都不需要停后端;② 换二进制**只允许**在**新产物已构建好之后**一次性 `restart`(即「先 build 到位,再一次切换」,不得留空窗);③ **启动后端不许用前台阻塞式命令**(`scripts\ctrl.bat start` 会守着进程不返回)——必须确认它**脱离工具进程**,否则工具超时会**连带杀掉后端**(2026-10-04 实测:`TaskStop` 掉阻塞包装后进程存活、PID 文件已写 `757788`,属脱离式启动);④ 上下文压缩/会话中断后:**先探活**(`netstat -ano | grep 10942` + `curl /api/v1/health`)再决定,不要凭印象以为它停了。 ## 9.5 学习成熟开源实现,禁止闭门造车(⚠️ 用户强制红线) - **已成熟的能力/模块,必须优先学习并复用现有开源项目的业务逻辑与交互范式**,**严禁闭门造车/按设计文档凭空推演**。对照基准(按 design 主题): - **agent 工具循环 / 工具分发** → Claude Code、OpenClaw、Cursor(工具 schema、循环上限、权限门、流式输出) - **子代理编排 / 隔离上下文 / 审计代审** → Claude Code 的 subagent、OpenAI Swarm、CrewAI - **MCP** → **官方 Model Context Protocol SDK**(Go/Python/TS 客户端接入、工具自动发现) - **WS 实时协议 / 流式 token** → OpenAI/Anthropic 官方 SDK 的流式惯例、Claude Code 的实时事件 - **checkpoint 恢复 / 长任务持久化** → Claude Code 的 resume / Cursor 的会话恢复 - **跨平台渠道接入(QQ/微信/Telegram)** → OneBot v11、Telegram Bot API、微信 iLink 既有客户端 - **管理面板 / 前端交互** → Miuix Console(本项目设计基准)、以及成熟 admin 面板范式 - **实现前**:先在该主题的 design 文档下**补一行「开源对照」**——列出参考项目 + 借鉴点(模板:`## 开源对照(实现前必读)`)。实现时逐点对齐其成熟逻辑。 - 若某个能力**已有成熟开源实现**而项目选择了自研,必须**写明理由**(如协议差异、单二进制约束),不得默认自研。 - 上下文压缩后:**本铁律强制生效**;每个模块补全前**先查 `DevDocs/开源对照清单.md`**(集中记录各主题的参考项目与已完成对照),未对照不得开工。 ## 10. 代码与流程硬性规范(压缩后仍需遵守) - 🔴 **文件 ≤500 行、函数 ≤80 行**;**模块按职责拆成多个源文件,严禁把整个模块塞进一个超大文件**;**三次复制必须抽取**共享。 - 🔴 禁 `interface{}`(用 `any`)、禁包级全局变量(除 `var ErrXxx`)、禁裸 `return err`、禁魔法数字;错误一律 `%w` wrap;SQL 全参数化、主键 `id`、时间戳 `created_at/updated_at`、索引 `idx_{table}_{col}`(♢ **已登记例外(主人 2026-10-04 裁决)**:表名**统一用复数**、以既有迁移为准——本条原「表名单数」**不再作为硬约束**,命名口径以 `DevDocs/design/13`/`design/16` 为准);敏感信息打日志。 - 🔴 **日志必须标来源**:模块/子功能用 `internal/logger.WithSource`/`Scoped`(`source=module/subfeature`)标注,跨模块可追溯定位;**禁止无来源裸日志**。 - 🔴 **客户端 API 契约先行**:REST `/api/v1` + WS `/ws` + admin `/api/v1/admin/*` 统一**版本化契约**,供跨平台客户端(Web/移动/IM bridge)接入与治理;JSON 响应 `{data}` / `{error:{code,message}}`。 - 🔴 **用户侧 API 文档随实现更新**:每实现/变更一个 REST 端点、WS 事件、admin API,**立即同步更新 `Docs/api-client.md`**(用户侧跨平台客户端 API 文档),供后期原生客户端开发;契约变更版本化。 - 🔴 **`.env` 冻结(主人 2026-10-06,二次收口后为最终口径)**:`.env` 只保证「**最小化功能可跑**」——**基础键已经定好了,以后不准改**(**不加、不改、不删**;模板 `.env.example` 与 `.env` 同进退)。 ① **新配置一律不进 `.env`**:调优/门槛/上限/开关类参数走 **`$DATA_DIR/config/**`(面板可改)+ 代码默认值**; ② **既有基础键与既有 `env:` tag 保持现状**(不迁移、不改默认值、不删键); ③ 原协同 `E6`「新 env 键必须同步 `.env.example`」**作废**; ④ **凡文档里写「新增 env 键须同步 `.env.example`」的段落一律是过期文本**,按本条改正(口径全文见 `design/13 §2.1`)。 - 🔴 **每次模块/功能改动「前」与「后」都推仓库**(用户红线,留恢复误操作余地):改动前若工作树有未推改动,先 `git push origin dev` 存一个干净基线;改动完成验收通过后,立即 `git commit` + `git push origin dev` 存档。**绝不攒一堆改动到阶段末一次性推**——坏操作可随时 `git reset`/`rebase` 到任一推过的 commit 回滚。每个模块/功能提交(或里程碑归档)后均 `git push origin dev` 同步远端。 - 🔴 **压测纪律(2026-10-04 实测事故,必守)**:子代理做负载/竞态验证时**不许**用无界进程风暴占机(如 `yes` ×30、`sleep` 风暴)—— 实测一次「`yes` 没杀干净」把 12 核占满约 **15 分钟**,期间所有 `go build/test` 近乎停滞,并把工具链误判成死锁。规矩:① 负载**限核**(`GOMAXPROCS`/单包并行/`-p`)或**限时**(几分钟级),优先用「可控对抗条件 + 注入时钟 + 门控」而不是堆进程;② 压测结束**必须确认无残留进程**(`Get-Process yes` 之类计数为 0)再出证据;③ 出现「整机变慢/命令不动」先查**是不是自己刚起的压测进程**,再怀疑工具链。 - 🔴 **仓库根产物卫生(2026-10-04 实测事故,必守)**:`go build ./cmd/cyrene/...` 这类**单 main 包**命令会把可执行文件写到**当前工作目录** ⇒ 实测**静默覆盖**了正在用的发布产物 `cyrene.exe`(且不带 `-ldflags "-s -w"`,体积 39.3 MB → 49.1 MB)。规矩:**子代理一律不许跑会在仓库根产出可执行文件的构建** —— 只跑 `go build ./...`(多包 ⇒ 丢弃产物)、`go build ./<非 main 包>/...`、`go vet`、`go test`。**换二进制只允许**「`scripts\ctrl.bat build`(唯一权威构建,带 strip)+ **一次** `restart`」,且必须在**整树验收通过之后**执行(对齐「后端常驻」红线:换产物不留空窗)。 - 🔴 **等待子代理:不许用长 `WaitFor` 阻塞回合(主人 2026-10-04 反馈)**:主会话在 `WaitFor` 里等子代理时,**主人无法给任何补充输入** —— 等于把主人锁在门外。规矩:**派完就结束回合**(子代理的完成通知会自动唤醒主会话);确需同回合内等,**单次 `WaitFor` ≤ 60s**,且只用于「马上就要用它的结果」;等待期间若有并行工作,**先做工作再结束回合**,不要空等。 - 🔴 **遇到开发文档冲突 / 意义不明 / 规格矛盾时**:**阻塞会话**,用 `AskUserQuestion` 询问主人,**不得自行猜测**;文档清、不冲突则自主推进。 - 🔴 阶段验证:后端 `go build ./...` + `go vet ./...` + `go test ./...` 全绿 + windows/darwin 交叉编译;前端(M9+)`tsc --noEmit` + `vite build` 通过。 - 🔴 **换二进制前先确认前端是否变更(2026-10-05 登记)**:`scripts\ctrl.bat build` **只跑 `go build`,不含前端**。若本次改动触及 `frontend/web/**`,必须先在 `frontend/web` 跑 `npm run build`(会把 `dist` 拷到 `internal/webui/dist`),**再** `ctrl.bat build` + **一次** `restart`;否则后端产物里带的是旧前端。反过来:**纯前端改动不需要重启后端**(运行时优先读磁盘 `frontend/web/dist`),刷新浏览器即可。 - 🔴 **裁定必须带完成状态(2026-10-05 登记)**:凡是给主人 / 给安卓端的裁定、承诺、回执,**每一条都必须标注「已完成 / 在办 / 未开始」**;标「已完成」须附 commit 号或验收证据,且**完成后回原条目处补记「已完成 + commit」**——不得只在别处口头称完成。**禁止把「未验证」表述成「已修好」**。 - 🔴 **提交一律逐文件 `git add <显式路径>`(2026-10-05 实测事故)**:**禁止**在「同一目录下有多路在途切片」时用 `git add -A -- <目录>` —— 实测它会**把别的子代理的在途文件一起吞进提交**(本次误把 237 的 `sessionenv.go` 提交并推了)。修复套路:`git reset --soft HEAD~1` → `git restore --staged <误入文件>` → 重新 commit → `git push --force-with-lease origin dev`(工作树内容不丢)。