AI 开发,本质是一场文档的生命周期管理

前言

周末在家继续搞我的 简历生成智能体项目,打开 CodeBuddy,让它帮我修个对话历史记录的 bug。好家伙,还没开始干正事呢,先看了下上下文消耗------文档读取占了我将近 40% 的上下文窗口 😭。我这额度可是薅羊毛搞来的,属实心疼。

于是我顺着这个线索往下查,发现项目文档已经膨胀到 170KB,AI 每次对话都要先把这堆东西全吞进去。P0 阶段实现的"工具注册机制"细节,在我做 P4 暗色主题切换时,还在占着上下文位子------但它跟当前任务一毛钱关系都没有。

这篇文章就是我从 170KB 瘦身到 12.8KB 的完整复盘。

项目背景

先交代下项目。ResumeHarness 是我在开发的一个简历智能体------用户上传简历 + 岗位 JD,AI 自动生成针对性优化简历,支持评分、多轮优化、模板切换、PDF 导出。前端 Next.js,后端 FastAPI,接 DeepSeek API。整个项目用 CodeBuddy 做主力开发工具,从零到现在已经跑了 P0 到 P4 五个迭代,40 多个功能点。

早期的文档结构:简单,但好使

项目刚起步那会儿,我没有任何文档架构的预设,就是跟着直觉走,按信息类型分了几个文件:

bash 复制代码
docs/
├── 已实现功能.md       # 42KB --- 所有迭代的功能实现记录
├── 迭代规划.md         # P0 到 P5 的全部规划
├── 缺陷修复记录.md     # 所有阶段的 bug 记录
├── 扩展规范.md         # Skill/MCP/模板开发规范
├── 项目架构.md         # 23KB --- 完整架构文档
├── 详细设计.md         # 42KB --- 完整设计文档
└── plans/
    ├── active/         # 进行中的需求规划
    └── done/           # 已完成的需求规划

说实话,P0-P2 阶段这结构挺好使的。每个文件就几 KB,AI 一次加载全部文档也毫无压力。信息密度高、没噪音------模型拿到的是完整的项目认知,不需要什么导航逻辑。

对人类也友好------一个文件看全貌,不用跳来跳去。"实现记录归实现记录,规划归规划",很自然。

后来我复盘这个阶段,发现"全量加载"在早期不仅没问题,反而是优势------AI 对项目没有任何先验知识,你给它越完整的上下文,它对项目的理解就越准确。信息全量 = 认知完整,这在项目初期是成立的。

但这个"自然演化"的结构,藏着一个隐患:它假设信息量不会膨胀。而信息量一旦过了某个阈值,全量加载会从优势翻转为负担。 这个翻转不是线性的------不是说信息多了 10% 效果就差 10%,而是在某个拐点上,噪音突然压过了信号,AI 开始被无关信息干扰决策。至于这个拐点在哪,取决于两个东西:你用的模型的上下文窗口有多大,以及单次任务的复杂度有多高。我的体感是,当文档总量超过上下文窗口的 15%-20% 时,就该警惕了。

膨胀失控:到了 P3 我开始难受了 📈

到 P3-P4 阶段,几个问题一起冒出来了。

第一个,线性膨胀。 已实现功能.md 从几 KB 涨到 42KB,每次对话 AI 都得先把 P0-P3 的实现细节全过一遍。我在做暗色主题,它脑子里装着工具注册机制的完整实现------纯噪音。

更严重的是,这种噪音不只是浪费上下文空间,还会误导 AI 的决策。我遇到过一次:P2 阶段我重构了 API 客户端的错误处理方式,但 P0 的旧实现细节还躺在文档里。AI 在帮我修一个连接超时的 bug 时,参考了 P0 的旧逻辑,给我生成了已废弃的错误处理代码。如果它没读到那段过时信息,反而会直接参考当前代码,不会犯这个错。

第二个,语义冲突。 我有个 plans/active/ 目录放进行中的需求规划。但"active"这个词在项目语境里有了歧义------plans/active/ 指的是某个需求的状态是"进行中",而项目层面的"active"又让人联想到"当前活跃文档"。

这个歧义不只是概念上的混淆,它直接传导到了 AI 的行为上。有一次我让 AI 归档 P3 的文档,它搞混了"归档 active 下的需求规划"和"归档当前活跃文档",漏操作了 plans/active/ 里的文件。归档这种操作,一旦漏了什么,后面很难发现。

第三个,归档没边界。 P3 做完想切 P4,发现 已实现功能.md 里 P0-P3 的内容混在一起,没有天然的分隔线。手动拆?太痛苦了。于是我就没拆,让历史信息继续堆着。堆着堆着就更不想拆了。

后来我想明白为什么拆不动------深层原因是按类型组织的文档天然没有时间维度的标记 。你在 已实现功能.md 里甚至分不清哪行是 P0 写的哪行是 P3 写的,因为没有"迭代边界"这个概念。内容是按"这是实现记录"归类的,不是按"这是哪个阶段实现的"归类的。两个维度交叉在一起,手动拆分本质上是在给一个本来没有时间索引的文件补索引------当然痛苦。

第四个,参考文档的陷阱。 项目架构.md(23KB)+ 详细设计.md(42KB)= 65KB,每次都全量加载。但 AI 大部分时候只需要知道"数据流怎么走的"这类概要,65KB 换来不到 5% 的有效利用率。

这个"5%"不是精确统计,是我观察 AI 实际行为后的估算------大部分对话中 AI 根本没有引用架构文档里的具体内容,只有涉及架构调整的任务才会用到。说白了就是图个安全感------"万一要用呢?"这种心理模式其实在 AI 辅助开发里很普遍:怕 AI 信息不够就全塞,结果信息越多反而越容易让 AI 在无关细节上钻牛角尖,适得其反。

以为刚开始自己想的好好的,但是做着做着,就会有新的想法冒出来,这个在公司开发中应该更常见,每个人都喜欢 微操 下🎆🎆🎆

说到底,按信息类型组织的文档,天然不适合按时间阶段推进的迭代节奏

我看了社区方案,但没采用

动手重构之前,我先看了下社区里有没有现成的方案。比如 OpenSpec------一个 AI 原生的规范驱动开发系统,GitHub 3.4 万 Star。它的思路是:需求用结构化 Markdown 文件存,修改只描述"变化"(Delta Spec 机制),还有三层验证确保 AI 理解和人一致。

说实话挺心动的。特别是 Delta Spec------修改需求时只需描述"新增/修改/删除了什么",不用重写整个规范。这个"增量"思路跟我要解决的问题其实有交汇:都在试图减少 AI 需要处理的信息量。只不过 OpenSpec 的增量粒度是需求级别的(每次只看变了什么需求),而我的增量粒度是迭代级别的(每次只看当前迭代)。

粒度不同,适用场景就不同。OpenSpec 更适合需求频繁变更、需要精确追溯每次变更的场景------比如团队协作时,产品经理和开发需要就"需求到底改了什么"达成共识。而我的痛点是迭代间的信息隔离------P0 的实现细节不应该污染 P4 的上下文。这是两个不同层次的问题。

另外 OpenSpec 有一套比较重的规范体系(SPEC / DELTA SPEC / CHANGE / SCHEMA 四种文件类型),每次变更都要写结构化的 Delta Spec,还有 YAML 定义工作流依赖。对于我这种个人项目 + 快速迭代来说,学习成本和流程成本都有点高------我写个需求规划的习惯是开个 md 随手写,不是先想好用 ADDED 还是 MODIFIED 标记。如果团队协作、需要严格的需求追溯,这套规范就有价值了。

我自己的感觉是,每个人都需要根据自己的开发习惯和项目阶段选择合适的文档组织架构。没有银弹,只有最适合自己的。

重构:以迭代为轴心

想清楚之后,我做了这么个结构:

bash 复制代码
docs/
├── current/                        # 日常加载区(~12.8KB)
│   ├── roadmap.md                  # 当前迭代任务清单 + 进度
│   ├── changelog.md                # 当前迭代实现记录
│   ├── bugs.md                     # 当前迭代缺陷记录
│   └── plans/                      # 当前迭代的需求规划
│       └── P4-01-xxx.md            # 状态在文件内标记,不靠目录
│
├── archive/                        # 历史归档(仅回溯时读取)
│   ├── P0/                         # P0 的 roadmap + changelog
│   ├── P1/
│   ├── P2/
│   ├── P3/
│   └── design/                     # 初始设计文档(已过时)
│
└── reference/                      # 跨迭代参考(按需读取)
    ├── specs.md                    # 5.9KB 扩展规范
    └── architecture.md             # 5.7KB 精简架构概要

加载逻辑的变化

当前迭代只关心当前迭代的逻辑,如果有需要,再去查看历史的文档

这是整个重构里最核心的变化------不是文件结构变了就完事了,是 AI 读取文档的规则变了

CodeBuddy 的文档加载机制是:AI 根据规则文件里的文字指示去读取对应的文件,不是框架自动扫描。所以规则怎么写,AI 就怎么读。改动规则文件,相当于改了 AI 的"出厂设置"。

旧结构下 ,我在 projectConfig.mdc 规则文件里写的是:

markdown 复制代码
## 文档体系
- docs/已实现功能.md 是功能实现记录,开发任务需参考
- docs/迭代规划.md 是迭代规划,开发任务需以其为基准
- docs/缺陷修复记录.md 是缺陷记录,修复缺陷时参考
- docs/扩展规范.md 是扩展规范,涉及 Skill/MCP 开发时参考
- docs/项目架构.md 是架构文档,涉及架构调整时参考
- docs/详细设计.md 是详细设计,涉及核心模块修改时参考

6 个文档并列排列,没有优先级区分,没有加载条件。AI 看到这些指示,每次对话开始就 read_file 把 6 个文件全读了。为什么全读?因为当规则里没有优先级和条件判断时,AI 的安全策略是"宁多勿少"------既然没说不需要,那就都读。这是 AI 编程助手的一个普遍倾向:保守加载。你不在规则里明确排除,它就不会主动排除。

所以不管当前任务是改个前端样式还是修个后端 bug,170KB 照单全收。

新结构下,规则变成了:

markdown 复制代码
## 文档体系
5、docs/current/ 是当前迭代的全部活跃文档,日常任务只需加载此目录
6、docs/current/roadmap.md 是任务清单,开发任务需以其为基准
7、docs/current/changelog.md 是实现记录(最高基准),完成任务后更新
8、docs/current/bugs.md 是缺陷记录,修复缺陷后更新
9、docs/current/plans/ 是需求规划目录,新需求先创建规划文件再开发
10、docs/reference/specs.md 是扩展规范,涉及 Skill/MCP/模板/工具/提示词/记忆 开发时参考
11、docs/reference/architecture.md 是架构概要,涉及架构调整时参考
12、docs/archive/ 是历史迭代归档,仅回溯时按需读取,日常不加载

变化不只是文件名变了,是规则的语义结构变了

  • 第 5 条是"总纲" ,明确说了"日常任务只需加载此目录"------这是一条加载白名单,AI 只读 current/ 下的文件就够
  • reference/ 下的文件标注了"涉及 xxx 时参考"------这是条件加载,AI 会在需要时才按需读取
  • archive/ 明确说了"仅回溯时按需读取,日常不加载"------这是加载黑名单,AI 不会主动去翻历史

白名单 + 条件加载 + 黑名单,三层规则把 AI 的加载行为从"全量"变成了"精准"。 这比只改文件结构重要得多------文件结构是静态的,规则才是驱动 AI 行为的动态指令。

从 170KB 到 12.8KB,不是删了信息,是让模型在正确的时机看到正确的信息。

plans 归属迭代,不再独立管理

旧结构里 plans/active/plans/done/ 有自己的生命周期,跟迭代节奏不同步。归档时得两处操作。

这个"不同步"不只是归档时要操作两个地方,更麻烦的是跨迭代需求的归属问题 。我在 P3 开始规划了一个"简历版本管理"的需求,放在 plans/active/ 里,但实际开发拖到了 P4。P3 结束归档时,这个需求规划算 P3 的还是 P4 的?移到 done/?它还没开发完。留在 active/?但 已实现功能.md 里 P3 的记录已经归走了,这个规划跟 P3 的上下文脱节了。需求的 lifecycle、迭代的边界、文档的分类维度,三条时间线纠缠在一起

新结构里 plans/ 直接归到 current/ 下,归档时跟着迭代一起走。需求的状态在文件内用 emoji 标记------🟡 规划、🔵 开发中、✅ 已完成------不靠目录位置区分。一个维度管到底,不用操心同步问题。

跨迭代需求也好处理------归档时未完成的规划随 current/ 一起移到 archive/P{n}/,然后在新的 roadmap.md 里重新登记,继续推进。它始终跟着"当前迭代"走,不会悬空。

归档协议化,一句话切换迭代 🎉

我在 CodeBuddy 的规则文件里加了个 iteration-archiving.mdc

markdown 复制代码
## 迭代归档流程

当用户声明当前迭代完成(如"P4 完成"或"进入 P5")时,执行以下步骤:

1. 将 docs/current/ 整体移动到 docs/archive/P{n}/
2. 创建新的 docs/current/ 目录结构
3. 更新 projectConfig.mdc 中的迭代编号

现在我做完 P4,只需要说一句 "P4 完成,开始 P5" ,AI 自动完成全部归档操作------current/ 整体迁移到 archive/P4/,然后创建新的 current/ 写入 P5 的内容。

之所以能做到这么简单,核心是 current/archive/P{n}/ 的目录结构完全一致。这个结构同构是有意为之的设计------归档就是搬家,不用拆分不用重组,AI 不需要理解任何新的目录含义,就是把 A 搬到 B。如果 archive 下的结构和 current 不同(比如按类型再拆),AI 就需要额外的理解成本,出错概率也上升。

反过来想,旧结构为什么归档简直是噩梦? 根本原因就是信息按类型组织,而归档需要按时间拆分------两个维度交叉,没有自动化拆分的天然边界。你在 已实现功能.md 里甚至无法程序化地识别出"P3 的内容到此结束,P4 从这里开始"。没有边界标记,AI 也不知道该怎么拆。所以我一直拖着没归档,文档就越堆越胖。

效果对比

维度 旧结构 新结构
日常加载量 ~170KB(6 个文件全加载) ~12.8KB(current/ 3 个核心文件)
膨胀控制 无,持续增长 每轮归档清零
迭代切换 手动拆分 5+ 文件 一句话自动归档
架构参考 每次加载 65KB 全量 按需读 5.7KB 精简版

几条经验(和教训)

第一,文档结构要跟着上下文预算走,不是跟着人的阅读习惯走。 人可以跳读、可以忽略、可以凭经验筛选,但模型不行。冗余信息占位越多,留给当前任务的推理空间越小。12.8KB 和 170KB 的区别不是"更简洁",是给模型留出了更多有效推理空间。

第二,按迭代阶段分区比按信息类型分区更合理。 AI 每次对话的核心问题是"现在要做什么",不是"之前做过什么"。历史信息有价值,但它的价值在"回溯时按需读取",不在"每次全量加载"。这跟数据库冷热分离是一个逻辑------热数据常驻内存,冷数据按需加载。

第三,归档机制要协议化。 文档结构再好,没有归档机制就会重新膨胀。把归档协议写进规则文件,让 AI 理解什么时候该归档、怎么归档------这不是炫技,是把文档治理变成开发流程的一部分,而不是流程之外的负担。

但也要警惕过度缩减。 有一次我在 P4 修改一个 P1 设计的会话池模块,current/ 里只有 P4 的实现记录,没有当初为什么要用"共享单例 + 每会话独立"这个设计决策的上下文。AI 不清楚历史设计意图,差点给我改成完全独立的会话实例------这在多租户场景下是个回归 bug。后来我手动让 AI 去读了 archive/P1/ 的 changelog,才避免了这个问题。

这说明 current/ 压得太狠也有风险。我的应对方式是在 changelog.md 里保留关键的设计决策记录------不只是"做了什么",还有"为什么这么做"。这样 AI 在修改旧模块时,至少能看到当初的设计意图,判断是否需要回溯完整历史。

最后,说下这套方案的适用边界。 我的项目是个人开发、5 个迭代、单分支,这套"current/archive/reference"三区架构够用了。但如果是团队 10 人协作、20 个迭代、多分支并行开发,文档治理的复杂度会上升------不同分支可能处于不同迭代阶段,"当前迭代"这个概念本身就不唯一了。到那个规模,可能需要引入分支感知的文档分区,或者像 OpenSpec 那样更正式的规范体系。但在当前阶段,简单有效比全面规范更重要。

本质是上下文治理 💡

现在大家聊 AI 辅助开发,关注点多半在"怎么写更好的 prompt"、"怎么选更强的模型"上。Prompt engineering 当然重要,但我从这轮实践中感受到的是------上下文治理是比 prompt engineering 更底层的问题

Prompt 决定了你"怎么问",但上下文决定了 AI"看到了什么"。再精巧的 prompt,喂进去的上下文是噪音,输出也好不了。这跟一个道理:你给一个顶级厨师再好的烹饪指令,食材是坏的,做出来的菜也好不了。

有人可能会说:现在模型上下文窗口越来越大了,Gemini 都 100 万 token 了,还需要操心这个吗?我的判断是仍然需要。上下文窗口大,只是能"装下"更多信息,但不等于"有效利用"更多信息。噪音始终会稀释 AI 的注意力、降低输出质量------窗口越大,噪音的绝对量也可以越大,问题不会因为窗口变大而消失,只是变得不那么紧迫了。

所以我说,AI 时代,代码开发的本质是一场上下文治理行动。你喂给 AI 的每一行文档,都在塑造它的认知边界。

治理好你的上下文,就是治理好 AI 的认知。


本文基于 ResumeHarness 项目的真实开发实践,项目从 P0 到 P4 累计 40+ 功能点,文档架构从"大一统"演进到"迭代轴心",日常上下文加载量从 170KB 降至 12.8KB。后续迭代过程遇到问题我会继续补充完善此文档,感兴趣的可以点个关注

相关推荐
AI技术控1 小时前
论文解读:AE-TCN-SA——基于自编码器、TCN 与自注意力机制的锂电池内短路诊断方法
人工智能·python·深度学习·算法·机器学习·自然语言处理
一切皆是因缘际会1 小时前
AI技术新风口:边缘计算与智能体协同,解锁产业落地新范式
大数据·人工智能·安全·ai·架构·语音识别
我要出家当道士1 小时前
AICoding 编码范式参考
人工智能·aicoding·编码范式
郭龙飞9801 小时前
OpenClaw 飞书机器人搭建指南 远程 AI 操控电脑配置
人工智能·windows·机器人·飞书
Volunteer Technology2 小时前
Spring AI MCP 案例-WebFlux SSE传输模式 (九)
java·数据库·人工智能·spring
酿情师2 小时前
小龙虾(OpenClaw)本地部署详细教学:从 0 到跑通 AI 本地助手
人工智能
Hyyy2 小时前
普通前端自救记录——第0周
前端
极品小學生2 小时前
从零到一:打造属于自己的高可用 AI 接口中转站
人工智能
HIT_Weston2 小时前
83、【Agent】【OpenCode】bash 工具提示词(commit 注意事项)(一)
人工智能·agent·opencode