本文是「AI 效能」系列的第四篇,讨论流程骨架与初始化加速之后,工程目录本身该怎么搭。流程骨架见 AI 效能流程总设计,初始化加速见 all-repos 本地镜像,能力边界见 AI 自动开发的架构设计。

先给出答案

简单工程不需要按任务复制工作区,一个长期存在的模板工程就够:模板 Git 管理 AGENTS.md、skills/、background/ 与 conventions/,代码统一放进 repos/,每个子目录是一个独立仓库。目录共享,Git 独立,.gitignore 只写一行 repos/。

关键要点

  • 这套结构的前提是业务域单一、仓库固定且数量不多。
  • 模板 Git 只记录上下文资产的变化,不跟踪任何代码。
  • repos/ 下每个目录都是独立仓库,保留自己的远端与发布节奏。
  • .gitignore 只写 repos/,模板历史不会带上代码。
  • 结构从简;出现反复重建环境的真实需求,再升级到仓库清单与初始化脚本。

适用场景

这套结构适合业务域单一、代码仓库固定且数量不多的工程:

  • 业务域只有一个,不需要按域拆分知识库和代码;
  • 代码仓库通常三到五个,长期不增减;
  • 一个工程长期使用,不需要为每个任务复制独立工作区;
  • 知识库只服务当前工程。

反过来,仓库多、体积大、需要频繁重建环境时,这套结构就不够用了:它没有仓库清单,也没有初始化脚本,跨机器复现全靠手工。那种场景应该走 all-repos 本地镜像 一类更重的方案。

目录结构

project/
├── AGENTS.md              # AI 入口:目录职责与硬约束
├── skills/                # 可复用的能力与工作流
├── background/            # 知识库:产品、领域、业务背景
├── conventions/           # 规范:文档、代码、协作
├── repos/                 # 代码:每个子目录一个独立仓库
│   ├── web/
│   ├── api/
│   └── shared/
└── .gitignore             # 忽略 repos/

模板工程以根目录为载体,代码统一放在 repos/ 下。目录名与仓库名保持一致,人和 AI 都按同一套路径定位:提到 web,指的就是 repos/web。

两层 Git

模板 Git

模板 Git 管理工程根目录的上下文资产:

  • AGENTS.md:AI 入口,说明目录职责、代码仓库列表和硬约束;
  • skills/:可复用的能力与工作流;
  • background/:产品、领域和业务背景;
  • conventions/:文档、代码和协作规范。

这些内容变更频率低,影响面却是整个工程,所以单独成层。模板 Git 的提交只记录上下文变化,历史的语义因此很干净:一次提交要么调整了规则,要么补充了背景,不会混进某个业务功能的实现细节。

代码 Git

repos/ 下的每个目录都是独立仓库:

repos/
├── web/.git
├── api/.git
└── shared/.git

每个仓库保留自己的远端、分支、提交历史和发布节奏。模板 Git 不跟踪它们的内容,.gitignore 只写一行:

repos/

这样模板工程的提交不会带上代码,代码仓库的提交也不会进入模板历史。目录共享,Git 不共享。

初始化

  1. 创建或 clone 模板工程。
  2. 在工程根目录创建 repos/。
  3. 把需要的代码仓库 clone 或拷入 repos/,目录名与仓库名一致。
  4. 确认 .gitignore 包含 repos/。
  5. 在 AGENTS.md 里写清目录职责和代码仓库列表。

初始化只做一次。之后代码仓库直接在各自目录里开发、提交、拉取;模板层的知识库和规范按正常 Git 流程维护。

第 5 步最容易被跳过,但它决定了 AI 能不能自己找到东西。目录职责和仓库列表写清楚,AI 就不需要每次靠对话临时推测哪个目录放什么。

日常使用

要改什么 在哪里改 用哪个 Git
AI 入口、skills、知识库、规范 工程根目录对应目录 模板 Git
业务代码 repos/<name>/ 对应仓库的 Git
新增代码仓库 repos/ 下 clone 或拷入 新仓库自己的 Git

模板层和代码层互不依赖。模板层改动不影响代码仓库的提交历史,代码仓库改动也不影响模板层。

约束

  1. 代码不进入模板 Git:repos/ 必须被忽略,避免历史丢失、副本漂移和模板膨胀。
  2. 模板 Git 不保存代码副本:模板只保留目录约定和仓库列表,代码始终由各自的仓库管理。
  3. 知识库默认放模板:background/、conventions/ 随模板 Git 版本化;需要跨工程共享时,再拆成独立仓库。
  4. 仓库名与目录名一致:repos/web 对应 web 仓库,路径即定位。
  5. 保持结构最简:不引入仓库清单、初始化脚本、子模块或本地镜像;这些只在需要反复重建环境时才出现。

这几条里最容易破的是第一条。一旦为了图方便把代码目录提交进模板历史,后续就会出现两份代码:模板里的副本和仓库里的真实代码。副本一旦漂移,AI 会优先相信它读到的第一份,问题就会以「改完没生效」的形式出现,排查成本很高。

什么时候需要更重的结构

情况 做法
需要为每个任务复制工作区,或在多台机器、CI 上反复重建 增加仓库清单和初始化脚本,或改用本地镜像作为克隆来源
仓库数量增长,开始按业务域拆分 在模板层增加路由,代码仓库仍保持独立
知识库需要跨工程共享 把 background/ 拆成独立仓库,挂到模板工程里
分支和发布策略变复杂 在代码仓库内部管理,不影响模板层

升级时目录结构不变,只替换具体的实现方式。

完成标准

  • repos/ 不出现在模板仓库的历史里,提交代码也不会把目录带进模板 Git;
  • 每个代码仓库在 repos/ 下能独立拉取与提交,远端地址正确;
  • 用新会话问 AI「这个工程有哪些代码仓库」,它能只凭 AGENTS.md 答出完整列表;
  • 在 repos/<name> 里做的改动,不会出现在模板 Git 的提交里。

常见问题

为什么不用子模块管理代码仓库?

子模块把目录结构和提交指针绑在一起,任何一次代码提交都会在模板历史里留下指针变化,模板层的语义就乱了。更直接的问题是:子模块的初始化和更新本身就是一套额外操作,与「结构从简」的目标冲突。

只有一个代码仓库时还需要 repos/ 吗?

需要。repos/ 的价值不是容纳多个仓库,而是把「当前目录属于模板还是代码」这件事固定下来。只有一个仓库时也照此放置,将来增加仓库不用改约定。

知识库什么时候该拆出去?

当它需要服务多个工程时才拆。单工程的知识库留在模板里,版本化和工程变更同步推进,比挂一个独立仓库省一次同步动作。

AGENTS.md 里要写多细?

写到 AI 不需要追问就能定位的程度:目录职责、代码仓库列表、哪些目录禁止写入。业务细节放 background/,不要堆在入口文件里。