Gogs 仓库的 AGENTS.md 工程协作规范全解读:从编码到提交的完整开发约定
说明:本文将基于 AGENTS.md 这份仓库级开发协作手册,结合 Gogs(自托管 Git 服务)当前仓库的实际源码、构建配置与测试代码,逐条解读其对 AI 开发助手与人类开发者提出的工作准则,包括核心协作原则、Go 与前端编码规范、本地化流程、可访问性要求、构建与代码提交纪律。读者读完可以掌握在该仓库中高效协作的正确姿势,以及每条规范背后的仓库实现依据。
一、AGENTS.md 是什么:给代码协作者的“行动总纲”
在 Gogs 仓库根目录中,AGENTS.md 是一份面向代码编写者(尤其是 AI Agent)的工程协作手册。它与普通的贡献指南不同:内容高度浓缩,条条都是可执行的硬性约束,覆盖了从“接到任务后如何推进”到“写错代码时如何自纠”,再到“文案、国际化、UI、提交”的全链路约定。
该文件与仓库中其他文档(如 web/DESIGN.md)形成“总纲 + 细则”的关系:AGENTS.md 负责定义适用于全仓库的通用规则,并引用专门的模块文档作为补充约束。理解它,等同于理解这个仓库当前"被期望如何被维护"。
二、核心协作原则:一次做对,尊重现状
文档开篇即强调两条贯穿始终的核心原则:
- 停止无意义的附和,一次做对:不要用“你说得对”这类空话回应,而要在第一次尝试时就做正确,并在改动后进行事实核查与自我复查;如果不确定,就主动求助。
- 以当前版本为新的起点:当发现超出自己知识范围的既有改动时,不要盲目覆盖,而是把它当作新起点,尊重周边上下文中已经形成的模式。
这两条原则的实际价值在于:Gogs 是一个长期演进的成熟代码库(覆盖 cmd/、internal/ 下的 app、auth、context、database、route、repo 等大量子包,以及 web/ 前端工程),任何机械化的“重写式”改动都极易破坏既有约定。文档明确要求 Agent 在改动前先以现有代码为锚点,改动后先自查再交付,这与仓库中大量配套测试(例如 internal/database 下几乎每个模块都有同名 _test.go)的工程质量要求是一致的。
三、Style and mechanics:全仓库通用文案规则
该规范适用于所有面向用户的文本,包括但不限于 UI 文案、文档与代码注释。核心规则包括:
- 采用 sentence case(句首大写、其余小写),但品牌名保留原始大小写;
- 完整句子必须以句号结尾;
- 正文中禁止使用 em dash(
—)与 en dash(–),应改写为逗号、句号、冒号或括号;唯一的例外是作为 UI 设计中的视觉分隔符(例如标题与描述之间); - 不要过度使用分号,两个短句通常比一个用分号连接的长句更清晰;仅当两个子句耦合极强、拆分会丢失含义时才使用分号;
- 注释应解释代码无法直接表达的意图,而不是复述代码行为;优先使用更具描述性的命名。此规则优先于“跟随既有模式”;
- CHANGELOG 条目只描述用户视角的可见影响,不写入实现细节(可对照仓库根目录的 CHANGELOG.md 的写作风格);
- 使用
e.g.,与i.e.,时必须带尾随逗号。
这些细节对中文社区团队同样有借鉴意义:在提交信息、Release 说明与界面文案上保持一致的句式风格,能显著降低多语言维护与后续机器翻译的成本。
四、Coding guidelines:Go 侧的三条硬规范
4.1 错误处理统一使用 cockroachdb/errors
文档规定所有 Go 代码的错误处理统一使用 github.com/cockroachdb/errors。该要求与当前仓库的依赖声明完全一致:go.mod 第 9 行声明了 github.com/cockroachdb/errors v1.13.0。
从源码看,这一约定已被大面积落实。例如在 internal/database 的 actions.go、attachment.go、comment.go、database.go、issue.go 等实现中均大量使用 errors.New、errors.Wrap 系列调用,为错误链保留原始上下文。选用该库的价值在于其丰富的堆栈信息保留能力,便于在 Gogs 这类需要精确追踪数据库与 Git 操作失败原因的服务端代码中快速定位根因。
4.2 测试断言统一使用 stretchr/testify
测试必须使用 github.com/stretchr/testify 进行断言,同时要审慎选择 require 与 assert:当断言失败后测试无法继续有意义地执行时,应当使用 require(立即终止),反之才使用 assert(继续执行)。
该约定同样有仓库证据支撑:go.mod 第 45 行声明 github.com/stretchr/testify v1.11.1;典型示例如 internal/database/access_tokens_test.go,其中大量使用 assert.Equal、assert.True、assert.False 组合校验 token 的时间戳与使用状态字段。选择 assert 而非 require 的场景通常是同一实体多个字段的独立校验,单点失败不影响其他断言继续执行;反之,若后续断言依赖前一步结果,则应使用 require 尽早暴露问题。
4.3 5xx 错误必须在 handler 内直接记录日志
文档规定:每一个 5xx 响应都必须在 handler 内部直接记录错误日志,不要在共享 helper 中统一打日志。从源码结构看,这正对应 internal/context/context.go 提供的 Error、NotFoundOrError 等上下文方法:路由层在调用它们时同时传入人类可读的描述(例如 internal/route/home.go 中的 c.Error(err, "search repository by name")),从而让错误日志携带具体的业务语义,而不是在底层共享封装里打出一堆无法区分场景的堆栈。这种“语义化日志下沉到调用点”的模式,直接服务于 Gogs 生产环境下的问题定位效率。
五、Localization:本地化文件的“编辑主权”边界
本地化是 Gogs 这类国际化项目的高频改动点,文档给出了明确的权限边界:
- 只能编辑 conf/locale/locale_en-US.ini(英文基准语言文件);
- 其他
locale_*.ini由社区维护,严禁增删或改写其中的键,即使是删除 Go/模板侧已经失效的死键也不允许。
仓库现状与该约定吻合:conf/locale/ 目录下共存有 32 个语言文件(含 locale_zh-CN.ini、locale_ja-JP.ini、locale_ko-KR.ini 等),其中 locale_en-US.ini 是唯一由主仓库维护者直接掌管的基准源。这条规则的工程意义在于:避免主分支与社区翻译仓库之间因键名不一致产生合并冲突,保证自动化提取与回填流程(可参考 web/scripts/extract-locales.mjs 这类脚本的同步基础)永远以 en-US 为准。
六、UI guidelines:移动优先与无障碍底线
前端工作必须遵守三条相辅相成的约束:
- 移动优先设计:每个 UI 都必须在窄视口下先做好做对,再通过响应式断点增加桌面端精化;在约 375px 宽度下验证通过,才能视为完成。
- 至少满足 WCAG 2.2 AA,具体量化要求包括:
- 每个交互控件都有可辨识的可访问名称(可见 label 或
aria-label); - 颜色不能作为信息的唯一载体(必须配文字、图标或形状);
- 正文与有意义图标相对背景满足 4.5:1 对比度(大号文字与 UI 组件为 3:1);
- 焦点始终可见且不会被困住;
- 触摸目标至少 24×24 CSS px(优先 40×40)。
- 拿不准时,宁可选择更高对比度、更大目标与更明确的标签。
- 每个交互控件都有可辨识的可访问名称(可见 label 或
web/下的工作必须遵循 web/DESIGN.md 中记录的排版、颜色层级、表面装饰、文件命名与无障碍细则;当一个模式在两处被使用时,就应当回写更新该文档。
6.1 服务端数据的获取位置:route loader 而非 useEffect
文档对数据获取给出了一条非常具体的前端架构约束:当页面需要服务端数据渲染时,必须在 TanStack Router 路由的 loader 中获取,让页面只在响应返回后才挂载;严禁在页面组件内部用 useEffect 触发该请求,否则会造成数据到达前先闪烁出空 UI。
该约束在仓库中有清晰的实现对应:web/src/router.tsx 基于 TanStack Router 构造路由树(createRootRouteWithContext、createRoute),并为根路由配置 defaultErrorComponent: ServerError;而 web/src/routes/repo.tsx 就是典型实践:其路由节点定义了 loaderDeps 与异步 loader,在 loader 内完成请求并发起错误响应,例如返回 404 而不浪费一次拉取。仓库中 web/src/pages/NotFound.tsx、web/src/pages/ServerError.tsx 等组件则承担路由错误渲染。
七、Build instructions:用 moon 统一构建与质量门禁
当前仓库的前后端构建统一通过 moonrepo 的任务编排完成,仓库根目录 moon.yml(Go 后端,项目 id 为 gogs)与 web/moon.yml(TypeScript 前端,项目 id 为 web)定义了全套任务。文档要求:
- 尽量使用
moon run <project>:<task>而不是裸的go/pnpm命令,例如moon run gogs:build、moon run web:dev; - 需要绕过缓存时传入
--force; - 改完 Go 代码后必须运行
moon run gogs:lint,改完前端代码后运行moon run web:lint,并修复全部 linter 错误。
两个 moon 配置文件中的关键任务对应关系整理如下:
| 任务 | 后端(moon.yml) | 前端(web/moon.yml) |
|---|---|---|
| 安装依赖 | install:go mod tidy + go generate ./... |
install:pnpm install(在工作区根执行) |
| 格式化 | format:golangci-lint fmt |
format:pnpm run format |
| Lint | lint:golangci-lint run |
lint:pnpm run lint |
| 测试 | test:go test -cover -race ./... |
— |
| 构建 | build:go build -v -trimpath 并注入 BuildTime/BuildCommit 到 .bin/gogs |
build:pnpm run build 输出到 /public/dist |
| 开发运行 | server:cd .bin && ./gogs web |
dev:pnpm run dev |
| 全量产物 | build-prod:以 -tags prod 构建,依赖 web:build |
被后端 build-prod 依赖 |
值得注意的实现细节:build 任务通过 -ldflags "-X 'gogs.io/gogs/internal/conf.BuildTime=...' -X '...BuildCommit=...'" 把编译时间与当前 commit 注入 internal/conf 包,这意味着每次构建产物的版本信息都可在运行时追溯;而 build-prod 会额外携带 -tags prod 并串联前端 web:build,构成前后端一致的生产构建链路。此外根 moon.yml 还提供了 portless、dev、prod 等组合任务,用于把本地服务暴露到 gogs.localhost 开发域名。
八、Tool-use guidance 与 Source code control:工具纪律与提交纪律
8.1 工具使用
- 访问 GitHub 上非公开的信息时使用
ghCLI; - Chrome DevTools MCP 必须以 headless 模式运行,避免抢走用户前台浏览器焦点;任务结束后用
pkill -f chrome-devtools-mcp清理所有残留进程。
8.2 源码控制纪律
- 从 fork 推送 PR 变更时使用 SSH 地址,且不要添加 remote;
- 除非被明确要求,绝不直接提交到
main分支;一次“允许”只对应 main 分支上的一次提交动作; - 绝不擅自 amend 提交,除非被明确要求;
- 创建 git worktree 时,worktree 目录名必须与其分支名一致,不得使用随机或生成的后缀。
最后一条对多分支并行开发极具实操价值:目录名 = 分支名的约定让本地多个 worktree 之间可以靠路径名直接辨别分支归属,避免 gogs-fix-a1k2 这类无法识别的随机目录堆积。结合“不直推 main”“不 amend”两条纪律,可以推断该仓库期望的协作流是:功能分支或 fork 分支 → 提交 → PR 审查合并,历史保持线性与可追溯。
九、小结:把规范变成可执行的协作清单
将 AGENTS.md 的要点压缩为 AI 助手与贡献者的每日行动清单:
- 改动前先读周边代码,以当前实现为起点;改动后自查并验证,不空口附和;
- 文案一律 sentence case、句末带句号、正文不用 em/en dash、少用分号;注释写意图而非复述代码;
- Go 错误处理一律走
cockroachdb/errors,测试断言用testify,require只在无法继续执行时使用;5xx 的错误日志留在 handler 内记录; - 本地化只改
locale_en-US.ini; - 前端先做移动端再上桌面端,任何 UI 都须达到 WCAG 2.2 AA;需要服务端数据的页面一律在路由
loader中取数;前端模式遵循 web/DESIGN.md; - 优先用
moon run gogs:build、moon run web:dev等任务;改完代码先跑对应lint并清零告警; - 提交遵循 SSH + 不直推
main+ 不 amend + worktree 目录名与分支名一致。
这份文档的价值在于:它把 Gogs 仓库多年沉淀的工程品味,显式化为机器可读、可判罚的规则。无论你是人类贡献者还是 AI 编码助手,遵循 AGENTS.md 都是在以仓库维护者认可的姿势推进改动,从而让每一次提交都更接近一次通过。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00