Files
Cyrene_v2/AGENTS.md
T
AskaEth a4efbffe60
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
docs(架构): 插件开端口的四条护栏转为「已确认采纳」
主人 2026-10-07:「其他几个选项按你的最优解来」⇒ 四条护栏正式采纳,
去掉 AGENTS.md §9 与契约 v0.88 里的「待主人逐条确认」字样。

护栏内容不变:显式配置 / 默认绑 127.0.0.1 / 日志与审计 / 不得绕过身份判定。
2026-10-07 16:16:29 +08:00

87 lines
15 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.
# 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`(工作树内容不丢)。