Gitea AGENTS.md 深度解析:让 AI 编程 Agent 遵循项目规范的 20 条硬规则
2026/9/7 5:38:41 网站建设 项目流程

Gitea AGENTS.md 深度解析:让 AI 编程 Agent 遵循项目规范的 20 条硬规则

【免费下载链接】giteaGit with a cup of tea! Painless self-hosted all-in-one software development service, including Git hosting, code review, team collaboration, package registry and CI/CD项目地址: https://gitcode.com/GitHub_Trending/gi/gitea

Gitea 仓库根目录的 AGENTS.md 是一份专为 AI 编程 Agent(以及希望模仿 Agent 行为的贡献者)定制的协作规范:它约束了 PR 描述写法、Conventional Commits 类型选择、Agent 署名 trailer、注释哲学、前后端代码风格、lint 命令与测试运行方式。读完本文,你将掌握 Gitea 对 AI 辅助开发设定的全部 20 条规则、每条规则背后的仓库实现依据(如 Makefile 目标、locale 同步机制、e2e 测试脚本),以及如何在实际贡献中准确执行这些约束。

1. 文档定位与总则

AGENTS.md 采用极简的逐条规则(bullet rule)格式,共 20 条,可归纳为五个主题域:

主题域覆盖规则
事实与版本控制纪律先验证再断言、不重写 git 历史
信息与文档导航make help列开发目标、读docs目录
PR 与提交规范PR 描述、issue 引用、Conventional Commits、Agent 署名
代码风格注释哲学、版权头、locale、TS 非空断言、Go 现代特性、Tailwind 工具类
质量保障lint/生成命令、修复根因而非禁用检查、单测运行与性能预算

1.1 先验证,再断言(Never assume, verify before claiming)

第一条规则即"不要假设,先验证再下结论"。这是对 Agent 最常见的幻觉式输出(凭空声称某函数存在、某参数默认值是多少)的针对性约束。在 Gitea 仓库中,验证手段是明确的:用 Makefile 提供的make help目标查看全部开发目标——该目标通过awk解析 Makefile 中带##注释的行来生成帮助输出(见 Makefile#L183-L187),还会额外打印test-e2etest-backend[#TestSpecificName]test-integration[#TestSpecificName]三个参数化目标的用法说明。因此规则要求 Agent 在声称"某命令可以执行"之前,先运行make help核实目标确实存在。

1.2 文档导航:docs目录是权威来源

第二条规则要求 Agent 在动手前阅读docs目录中的开发者文档。当前仓库docs目录包含以下文件,构成完整的开发文档体系:

  • development.md:从源码构建 Gitea 与日常开发工作流(make build依次执行frontendbackend两个子目标);
  • testing.md:四类自动化测试(单元测试、集成测试、e2e 测试、迁移测试)的运行方法;
  • guidelines-backend.md、guidelines-frontend.md、guidelines-refactoring.md:分领域的编写与重构指南;
  • community-governance.md、release-management.md:社区治理与版本发布管理。

这条规则实际上把 AGENTS.md 与docs目录建立了一个两级文档结构:AGENTS.md 管"Agent 行为",docs管"项目事实",Agent 必须以后者为准来回答技术性问题。

1.3 不重写 git 历史

规则明确:除非被要求,绝不重写 git 历史;更新 PR 一律通过追加新提交并正常git push完成。这避免了 Agent 使用rebase/amend后强推(force-push)造成的协作事故,也符合 CONTRIBUTING.md 中"PR 会被 squash-merge、PR 标题即最终提交信息"的合并流程——历史整洁由合并方保证,贡献方只需线性追加提交。

2. PR 与提交信息规范

2.1 PR 描述:最小化,只写 what 与 why

规则要求 PR 描述保持最小:只说明"做了什么"和"为什么",禁止罗列任务清单或文件列表;UI 变更必须附截图,修改既有 UI 时须附 before/after 对比;目标控制在 1000 字符以内。这与 CONTRIBUTING.md 的 PR 章节完全一致:PR 标题描述"问题"而非"修法",首条评论作为 PR 摘要,功能 PR 的截图与"用法说明 + 测试说明"是合并的硬性前提。

2.2 引用 issue 与 PR 必须用完整 URL

规则要求通过完整 URL 而非编号引用 issue/PR。对 Agent 而言这是可检索性约束:编号#1234脱离仓库上下文后无法被外部 LLM 或搜索引擎解析,完整 URL 则自含项目、平台与定位信息。

2.3 Conventional Commits 与 Gitea 专属的enhance类型

规则要求提交信息与 PR 标题使用 Conventional Commits 格式,并特别指出用户可见的小型增强应使用 Gitea 专属的enhance类型。CONTRIBUTING.md 给出了完整类型表(buildcichoredocsfeatenhancefixperfrefactorrevertstyletest),其中enhance的定义是:

小型或琐碎的用户可见改进或 UX 打磨(如措辞修改、颜色调整、间距/边距微调、占位符、小的 UI 行为改进)。

它与feat(较大的用户可见功能)构成大小之分。示例包括:

fix(web): prevent avatar upload crash on empty file feat(api): add pagination to repo hooks list enhance(repo): improve diff toolbar spacing ci(workflows): lint PR titles in CI

实现层面的佐证:CI 会对合法 Conventional Commits 标题自动打type/…标签——feat/enhance/fix/docs/test前缀会分别获得对应标签(例如enhance(web): …获得type/enhancement),且标签随标题编辑保持同步;其他前缀则不自动打标,由合并者负责。可见enhance不是文档约定而已,而是与 CI 打标管线、changelog 生成直接联动的机制。

2.4 Agent 署名:Assisted-bytrailer,而非Co-Authored-By

规则规定:提交信息中必须添加形如下式的 trailer:

Assisted-by: AGENT_NAME:MODEL_VERSION

并明确禁止使用Co-Authored-BySigned-off-by来表达 Agent 参与。这一设计的含义是:

  • 人类作者仍是唯一的Author/Co-Authored-By主体,Agent 贡献以独立的Assisted-by元数据记录,格式固定为"代理名:模型版本"两段,便于后续按工具与模型维度统计 AI 辅助情况;
  • 不用Signed-off-by是因为 DCO 签名语义上声明的是"本人有权提交此代码",把 Agent 放进该 trailer 会混淆责任主体。

2.5 Issue/PR 评论中的署名位置

在 issue 与 PR 的评论中,Agent 署名必须放在单行结尾(trailing line),不得作为 PR 描述的一个章节。这避免了署名块喧宾夺主,也与 PR 描述"最小化"的原则保持一致。

3. 代码风格规则

3.1 注释哲学:几乎不写注释

规则对注释的约束极强:

  • 几乎不写注释;要写就写短的、尽量同行(same-line)的,为未来读者解释"为什么";
  • 绝不复述代码本身、变更过程或生成该代码的 prompt("Never narrate code, the change or the prompt"——后者是专门针对 Agent 生成代码时习惯留"这是根据用户要求 X 生成"类注释的现象);
  • 保留仍然适用的既有注释;
  • 如果需要写段落级注释,说明实现大概率过于复杂,应当重新设计。

这一条与 Gitea 后端指南的基调一致,核心是"复杂度的告警器":长注释通常不是文档不足,而是实现有问题的信号。

3.2 新.go文件的版权头

新建.go文件须写入当年年份的版权头。CONTRIBUTING.md 给出了标准格式:

// Copyright <current year> The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT

且此后仅当版权主体变化时才修改。AGENTS.md 将其细化为 Agent 的操作性指令:"加入当前年份"。

3.3 locale:只编辑locale_en-US.json

规则规定在options/locale目录下只能编辑 locale_en-US.json,其他语言的 locale 文件由 Crowdin 同步流程自动覆盖更新,手动修改其他语言文件会在下次同步时被冲掉。CONTRIBUTING.md 的 Translation 章节确认了这一点:仓库内只维护英文翻译,其余语言达到约 25% 的翻译覆盖率后回同步进仓库。Agent 如果"好心"顺手修了其他语言的文案,属于无效甚至有害的改动。

3.4 TypeScript:值必存在时用!而非?./??

前端规则要求:当某个值在类型与运行时逻辑上必然存在时,使用非空断言!而不是可选链?.或空值合并??。其语义是:?./??会对读者暗示"这里可能是空",如果实际不可能为空,防御式写法反而掩盖了真实不变量;!则把不变量显式声明出来,把防御留给真正可空的边界。

3.5 Go:优先使用现代语言特性

规则要求在 Go 代码中尽可能使用现代语言特性。结合 go.mod 声明的语言版本可推断,这指向for range int循环、min/max/clear内置函数、泛型等随新版 Go 引入的能力——即新代码不应停留在旧式写法(如手写 64 位整数取模的循环、临时变量交换等)。

3.6 Tailwind:tw-*工具类优先于内联样式与子项边距

前端样式规则:

  • 优先使用tw-*(Tailwind)工具类,而非内联style
  • 优先使用flex-*(如tw-gap-*间距类)而不是给每个子元素逐一加tw-ml-*/tw-mr-*边距;
  • 当需要提升优先级时,才回退到带!importanttw-*写法。

这与 Gitea 前端"全面 Tailwind 化"的方向一致,gap优先于逐项 margin 也是响应式布局更稳健的通用实践。

4. Lint、格式与生成命令

4.1 四条"改完就跑"的命令

规则将常见改动类型映射到固定的收尾命令:

改动类型必须执行的命令说明
编辑.go文件make fmt格式化 Go 与模板代码
编辑go.modmake tidy运行go mod tidy并重新生成 license 文件
API 变更make generate-swagger从代码注释重新生成 swagger 规范
有 diff 的任意文件make lint-go/lint-js/lint-css/lint-templates对改动范围做 lint

这些目标均可在 Makefile 中逐一验证存在:

  • fmt(Makefile#L199)实际是golangci-lint fmt加上对templates*.tmpl的 sed 规整(去掉{{(后与}})前的多余空白);配套的fmt-checkgit diff检查是否还有未格式化的差异并让 CI 失败;
  • tidy(Makefile#L420)执行go mod tidy -compat=<go.mod 声明版本>,还包含一段针对上游 Go issue 的 workaround(tidy 丢失toolchain行时用go mod edit -toolchain恢复),随后重新生成 license 清单;
  • generate-swagger(Makefile#L228)调用go-swagger从 Go 源码注释生成规范,并把非go:前缀的输出行视为告警直接失败——即生成过程不干净就不算成功;
  • lint 目标族(Makefile#L276-L363):make lint汇总了lint-frontendlint-backendlint-templateslint-swaggerlint-spelllint-mdlint-actionslint-jsonlint-yamllint-shell,AGENTS.md 只要求 Agent 按改动范围挑对应的细分目标(lint-jslint-csslint-golint-templates),避免全量 lint 的噪音与耗时。

4.2 修复根因,而非禁用检查

规则要求:遇到问题时修复原因本身,而不是禁用 linter 或削弱测试;确不可避免时,使用最小作用域并附行尾注释说明理由。这是对 Agent 常见"绕过行为"(加nolint、注释掉断言、放宽期望值让测试变绿)的直接封杀,最小作用域 + 行尾理由两个约束保证了例外可审计。

5. 测试规则

5.1 三类测试的单测运行方式

规则给出了 Gitea 三种自动化测试各自的单测命令,全部可在仓库中核实:

# Go 单元测试:精确匹配测试名 go test -run '^TestName$' ./modulepath/ # TypeScript 单元测试(Vitest):按路径过滤 pnpm exec vitest <path-filter> # Playwright e2e:只跑指定测试文件 GITEA_TEST_E2E_FLAGS='<filepath>' make test-e2e
  • Go 侧使用^...$锚定正则防止误匹配其他测试;
  • make test-e2e的实现链为test-e2e -> playwright frontend backend,最终由 tools/test-e2e.sh 消费GITEA_TEST_E2E_FLAGS环境变量,并自动在本地与容器两种 Playwright 运行模式间探测(非 Ubuntu/Debian 的 Linux 上自动回退到容器模式);
  • Makefile 还提供了参数化目标的替代写法:make test-backend#TestXxx会经$(subst .,/,$*).转换为/后传给-run(Makefile#L404-L406),集成测试同理有test-integration#%目标。

5.2 测试数量、速度与确定性预算

规则最后两条是量化与定性结合的测试纪律:

  • 数量与速度:写"最少、最快"的测试来覆盖行为,能扩展现有测试就不要新建;逻辑可隔离时优先单元测试。仓库层面有对应支撑——单元测试通过GO_TEST_PACKAGES过滤掉modelmigrationtests等重量级包(Makefile#L112),且集成测试默认走 SQLite(非 CI 环境下GITEA_TEST_DATABASE缺省为sqlite,见 Makefile#L30-L36),无需外部数据库服务;
  • 性能预算:单个集成测试目标 < 2 秒,单个 e2e 测试 < 4 秒。这是硬性的单测耗时预算,超出即视为实现或测试设计有问题;
  • 确定性等待:等待条件满足必须等待确定性条件(如元素出现、请求完成、日志就绪),禁止sleep硬等待——这与 e2e 脚本中wait_for_container采用"轮询端口 + 30 秒超时上限"的模式(tools/test-e2e.sh)是同一哲学;
  • 语义化定位器:e2e 测试优先使用getByRole/getByLabel一类语义定位器,而非脆弱的 CSS 选择器或 XPath,保证 UI 样式类名变化不会击穿测试。

6. 规则落地的完整工作流

把 20 条规则串起来,Agent(或贡献者)在 Gitea 仓库完成一次合规改动的完整闭环是:

  1. 核实make help确认目标存在;阅读docs下对应指南;引用外部对象一律完整 URL;
  2. 实现:Go 用现代特性、新文件带当年版权头;TS 用!表达不变量;样式用tw-*flex-*;注释几乎不写、只解释"为什么";
  3. 文案:只改 locale_en-US.json;
  4. 收尾命令:按改动面执行make fmt/make tidy/make generate-swagger,再跑对应的lint-*目标;
  5. 测试go test -run '^TestName$' ./modulepath/pnpm exec vitest <path-filter>GITEA_TEST_E2E_FLAGS='<filepath>' make test-e2e定向验证,遵守 2s/4s 预算与确定性等待;
  6. 提交:Conventional Commits 标题(用户可见小改进用enhance),追加提交而非重写历史,提交信息尾部加Assisted-by: AGENT_NAME:MODEL_VERSION
  7. PR:最小化描述(what/why,<1000 字符),UI 变更附 before/after 截图,评论中的 Agent 署名放在单行结尾。

这套规范的工程价值在于:它把"人类评审者不会重复提醒的隐性知识"(哪些命令必须跑、哪个 locale 文件不能碰、Agent 该怎么署名、测试有多快才算合格)显式化为机器可消费的规则集,使 AI 辅助产出在进入人工评审前就满足 Gitea 的格式、标签与流程预期,从而降低 PR 往返成本。

【免费下载链接】giteaGit with a cup of tea! Painless self-hosted all-in-one software development service, including Git hosting, code review, team collaboration, package registry and CI/CD项目地址: https://gitcode.com/GitHub_Trending/gi/gitea

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询