Comment-Driven — 注释驱动开发
这只是一套本地的个人设计思路。读一读本 README 也好,参考别人的方案也好,实际本仓库的代码内容没有必要一定要读。内容只是讲解设计思路,不必照抄——毕竟并没有科学验证过这套思路是永久可行的,顺便说一下这个README也是ai写的,我自己也没怎么看,嗯,这句话也是,再顺便说一下其实我叫这个iflow框架的原因也是ai写的。本仓库压根不提供任何工具,项目内容也管理得混乱。
IntentFlow 是一套以 @intent 注释为核心契约的 AI 辅助开发工作流框架。本仓库只提供 skill 与设计思路,不提供任何工具——早期的 CLI、MCP Server、VS Code 与 Pi 扩展形态均已归档至 .archive/。
Prompt 和 Skill 的核心价值不是什么精巧的措辞技巧,它的本质很简单:把上下文中重复出现的相同文字提取出来,集成成一份可复用的规则说明。最标准的写法就是一套执行流程、一个阶段的说明。
随着 LLM 越来越强,很多 skill 里的技术性指令可能不再需要了。但有一件事无论模型怎么进化都绕不开——跟用户对齐。用户需求是个无穷底的黑箱,模型再精尖,不跟用户对齐那么最终的结果也只是个一团糟。
所以这套 skill 的核心目的不是"教模型做事",每一份 skill 都是可以被替代的,它们只是在开发流程的关键节点上建立模型与人的对齐锚点。
相关文件:
.dsh/skills/— 工作流 Skill 定义
前面说 skill 绕不开的核心是"跟用户对齐"。这条原则讲的是对齐动作发生在哪一刻。
agent 的思考链里有一个几乎必然出现的动作:把用户发来的话在内部重复一遍,再用自己的术语复述、归纳,然后据此猜测对方要什么。这不是需要修正的毛病,而是智能体理解语言的自然产物——它得先把输入翻译成自己能运算的形式,才能往下推进。既然这部分 token 无论如何都要花,那就不如让它花得规范一点。
术语显影规范的就是这个复述环节:当用户的表达缺少术语、或者指代不明时,这次理解重述必须显式输出,不允许只停留在内部推理里。输出形式是"术语重述 + 编号选项"——把这个描述对应的专业表述说清楚,再把可能指向的对象或属性列成编号,让用户只做选择题,不用重新描述一遍。
好处有两层。直接的一层:用户看到自己的话被翻译成了术语,能立刻判断翻译得对不对,误判在动手之前就被拦住。更深的一层:用户在这个过程中会不自觉地用上这些术语,之后的表达更准,需求质量更高——而需求质量决定了项目质量。
这条原则有一个失败的前身。更早的版本是让 agent 申明自己的"思考意图",用意图的自觉来提升质量。这个想法很快暴露了问题:agent 并没有真正的"理解",也没有对自身思考意图的"了解",让它申明一个它并不具备的东西,只是多生成一段没有约束力的文字。现在这版放弃了内省,改为约束可观察的输出——重述是实际发生的动作,术语是实际使用的词汇,两者都能被检查。
同一术语在同一会话里只显影一次,后续直接使用——把成本控制在第一次对齐上。
Requirement(需求) — .dsh/skills/requirement/SKILL.md
要把模糊想法结构化,最重点的事情是反复跟用户对话确定需求细节。侧面辅助手段是联网搜索——从问题角度看看别人怎么解决的,从功能角度看看同类功能解决了什么问题,或者直接随便乱搜找灵感。还有一个关键思路是测试前置:在需求阶段先模拟出一套验证流程,后续代码怎么写都得跟这套测试方法对齐,哪怕用户不会写代码,也能通过测试步骤体会到功能是否达标。
Design(设计) — .dsh/skills/design/SKILL.md
结构设计和需求分析本质上属于同一个阶段,但刻意拆成两个。原因是"结构设计"这件事在前后端、小脚本里有太多不同的做法,需要一个固定的框架来兜住。参考了 DDD 的分层概念,简化成三层:数据结构/接口/仓库放一层,应用逻辑/编排放一层,面向用户或外部接口的放一层叫适配。这套逻辑不分技术栈,前端后端小脚本大致都能套,因为它没讲什么高深的理论,只是一种代码的结构划分。划分的根本原因是——LLM 经常把代码全写在一个文件夹里,文件夹一长写着写着就跑偏了,所以要划分上下文、降低理解难度,人对代码的理解也是一样的道理。
需求+设计两个阶段会生成一份 change 产出,包含两个文档:需求文档和设计文档,作为本次开发的对齐基准。
这里面附带了一个小机制叫 later-on 备忘录——需求或设计阶段冒出了什么奇妙想法,但跟本次沾边不大或者太复杂,直接记进去,防止过度设计。
Execute(执行) — .dsh/skills/execute/SKILL.md
这是一个多 skill 编排的阶段,核心思路是隔离上下文——测试、写代码、审查三段彼此隔离。
多 agent 的上下文是统一的:写在文件里的 @intent 本身就是子 agent 需要读取和执行的内容。测试 agent 读 requirement 和 design 文档,同时主 agent 把每个文件的 @intent 作为该文件的规格派发给子 agent。子 agent 不需要再考虑"要设计哪些内容"——这些在主线程的上下文里已经满足。同理,写代码的 agent 和审查 agent 也是这样,各司其职,通过统一的 @intent 契约对齐。
Report(报告) — .dsh/skills/report/SKILL.md
接管 Git 对文件改动的关注,对需求理解做打包。通过 change 这一全局工作流阶段,把每次开发的意图沉淀为关账报告与模块现状(intent package)。后续更新改动时,优先查阅模块现状,方便模型搜索代码内容。
为什么这么设计?目前的 RAG 工具在实际反馈中,很多时候大语言模型宁愿用自己原生的那套 grep 也不愿意用 RAG 自带的代码分析工具。既然这样也就只好顺从——每次代码变动后遗存一份项目的备忘录/方向标,帮助模型分析自己的代码,在后续的设计和改动中提高代码质量。至少模型搜的时候有方向。
本质上,report 这一套就是工程规范中用来全局统一意志的上下文。
.dsh/skills/trim-change/SKILL.md
流水线会不断产出文档,但文档的寿命不一样。requirement/design 在关账后就完成了使命——它们的内容已经被 report 取代,留着只是让 agent 下次扫描时多读一遍已经过期的上下文。later-on 备忘录则相反,里面记的都是"当时没做、以后可能做"的事,需要按代码现状逐条重新判断。
trim-change 做的就是这件事:以当前代码为基准,判断 .intentflow/ 下存量文档的删留。已关账 change 的需求与设计文档直接删除;report 给建议、由人拍板;later-on 逐条划分为已完成/部分完成/无必要/条件未满足,分别删除、裁剪或保留。
它独立于四阶段之外,触发时机是阶段性积累之后——不是每次关账都要跑,而是文档攒到影响阅读时再整理。由于删文件不可逆,这条 skill 默认不进入模型目录(disable-model-invocation: true),需要人工显式触发。
.dsh/skills/asking-ui/SKILL.md + library-picks.md,UI 相关的需求对齐,独立于四阶段流程之外。
核心观点:市面上大多数 UI 需求并不依靠 skill 完成。前端组件库多如牛毛——2D 有 shadcn/MUI/Ant Design/Element Plus 那一大堆,3D 有 three.js 生态,“前端已死”在 AI 出现之前就被喊了多年,因为拼页面的能力早已被库工具化;到了 AI 时代,连调用库的代码都不用写了。所以对模型来说 skill 反倒不是很重要,重点在于知道去搜哪一些库。
asking-ui 因此只做三件事:问清楚颜色要什么样子的、搜索现成组件库做分流判断(能覆盖就直接代码层拼装)、确认配色方案。剩下的全是工程与逻辑层的事。它不画图——画布只用来平铺配色方案,供选定后记录为 token。
辅助决策项(产品方向、技术选择、字体层级/间距/阴影、三参数旋钮、无障碍约束、交互触发场景)保留在询问维度里——这些是市场验证过“需要问”的问题,不能因为思路简化就取消。
与四阶段的关系:asking-ui 是 Requirement 阶段的 UI 侧补充。产出需求清单后按分流结论走——库能覆盖的直接在代码层拼装,不进入设计流程;覆盖不到的才继续走设计。
逻辑代码中禁止"以防万一"式兜底。只处理确定会发生的路径,不存在的分支不需要防御。兜底 = 崩了不炸,不是优雅跑。测试未覆盖的兜底就是潜在的 bug。
一个个人观点(未经科学验证,仅作为设计出发点):代码文件对于大语言模型而言本质上是一份分析语料。文本形式的约束对模型来说本身就是好东西——机器看不懂的代码,模型同样可能看不懂。
尤其是一些接近底层的代码:效率越高、能力越强、越贴近硬件的写法,就越脱离模型知识库里的 token 分布。别说人看不懂,大语言模型想看懂代价也不小。这时候加上注释辅助,模型后续重复分析同一段代码时就能省下大量开销。
我的 @intent 思路默认了一个前提:AI 在理解代码时,并不会采用逐块分析的方式,而是先完整通读整个文件,后续需要修改时再分批处理。
PRD(产品需求文档)这类外部文档有一个绕不开的问题:文件腐烂。一旦代码和文档分开维护,就必须同时维护两份内容——代码本身和 PRD。但现实是,大多数人写完代码之后不会再去看文档,写代码之前也不看。PRD 对非专业人士是一种负担.
更现实的问题是:写着写着突然想到一个更好的优化方案,这时候是不是要同时改代码文件和 PRD?很麻烦。
所以不如把 PRD 分层打散,直接写进代码文件本身。这样大语言模型在读取代码语料的时候,顺手就能把 @intent 也一并改了,不存在"忘了更新文档"这回事。
每个文件头顶写一段自然语言 @intent,说明这个文件为什么存在、承担什么职责、边界在哪。人看了能理解,AI 看了也能理解,外部工具也能读取、追踪、聚类。这是整个框架的契约基础。
IntentFlow 里的输出文档(需求/设计/报告/模块现状)本质上是什么?是 AI 上下文的一部分,被截断保存下来,作为项目里一种可维护的记忆。
为什么需要截断保存?因为即使不保存,AI 在每次会话的思考过程中也会产生这些内容。区别在于:不保存,每次新 session 都要在黑盒里重新演算一遍;保存下来,后续 session 直接读取即可。
给输出文档定一个格式的意义:
- 统一共识——项目全局开发演进过程中,所有 session 共享同一份记忆,不会各说各话
- 省 token——让 agent 重复读取这些内容,上下文中的思考变成定量的,不需要每次重新演算黑盒中的思考内容
- 可干预——你可以手动修改文档,等于手动修改 AI 的思考方向和内容;文档是唯一看得见、摸得着、改得动的思考载体
本意一句话:通过约束和截断 agent 上下文里的内容,形成一种全局可维护的项目记忆。
至于维护成本——本项目需要维护的记忆极少:只有 .intentflow/_packages/ 里的模块现状导航需要维护,其余都是杂鱼,甚至可以不看。
记忆不是设计出来的,是长出来的。
治水不靠筑坝,靠疏导。在项目开始前先建立一份需要维护的全局规格(项目维护图、全局 spec),等于给水筑坝:坝越高,维护成本越大,而水总能找到缝。这套方案不预设全局规格,只让每次开发结束时的上下文截断自然沉积——沉积物就是记忆,不需要额外维护。
沉积的粗细刚好成金字塔:
_packages/*.yml—— 索引:有哪些模块、模块里有哪些文件(塔尖)- 文件头顶的
@intent—— 指导:这个文件为什么存在、边界在哪(中层) - 代码 —— 本体:唯一的既成事实(塔基)
- 需求/设计/报告 —— 土壤:过程上下文,被截断保存,供养上面三层
只有代码是事实,文档是记忆。 记忆可能过期、可能想错、可能比代码更早地存在于纸上。文档和代码冲突时以代码为准,改文档而不是改事实认定。让文档压过代码,等于让记忆覆盖现实——这是文档腐烂的根源。
维护成本因此极低:模块现状不要求描述未来,只要求如实记录当前;不要求先于代码存在,只要求事后沉淀。
report 本质上是 execute 阶段的输出文档——它本不是独立存在的内容,只因为需求必须反复与用户确认拍板、无法作为完整工作流嵌入开发,于是独立成了一个 skill。
它的设计经历过三次简化:
- 能力地图 webview——最初想基于范畴论设计一个能力地图/模块现状/项目模块图的 GUI 产品,后来意识到这玩意做起来太麻烦、做出来也不好用,放弃。
- 文件夹工程——又意识到:一个良好的架构,它的文件夹本身就已经能表露意图,不需要再用一个 GUI 结构重新表露一遍内容。
- 一个 report 就够——最后发现连文件夹工程都不用搞:每次维护结束之后,声明一遍自己做了什么,就足够了。把这件事集成成一个 skill 之后,反而意外地以项目工程的方式真正做了出来。
由此得到一个结论:所谓项目不可维护,本质上是缺乏工作经验、不会做每一次汇报——每次开发结束不沉淀,项目就逐渐脱离掌控。
至于"生成这么多文档真的合适吗"的疑虑——这些文档本质上只是上下文截断的内容,该生成的还是会生成。真正需要的只是一个指向全局的方向标:让 AI 每次读取时优先知道哪个该读、哪个不该读,而不是全面扫描。
这套记忆的字段因此只有三段,每段一个记忆层级:
- 此次更新了什么——局部记忆:当前 change 的总结
- 几个模块分别干了什么——分块记忆:模块如何组合成功能
- 每个文件改动了什么——文件级记忆:最重点的一层,它决定了模块现状是否可维护,决定了维护后能否生成能力地图,决定了 agent 能否通过能力地图而不是直接扫目录来获得项目的记忆
字段设计的目的很简单:可通过关键字检索,检索到的内容可分析、可查找。
与 git 的关系——git 记录的是变更的痕迹(代码层面发生了什么),report 记录的是语义(为什么这么改、模块怎么组合、结论是什么)。AI 读 git log 需要重新理解代码才能还原语义;读 report 直接拿到结论。git 回答"改了什么",report 回答"为什么这么改",两者不是同一层的信息。
与 spec 路线的根本区别:结论的时序。主流方案(spec 驱动)是在项目开始前先建立一套需要维护的全局规格,然后让代码去对齐它——规格先于代码存在,从第一天起就有维护负担。本项目的做法相反:在项目完成、代码确认能跑之后,才沉淀需要维护的结论(report 关账时产生)。因此 requirement/design 只是过程产物——代码跑通后它们就被 report 取代,根本不需要再看;只有 report 是结果结论,才需要维护。前者维护的是"承诺",后者维护的是"既成结论"。
独立化成长——report 沉淀的不是产品,是种子。任何项目想拥有贴合自己内部的意图流,不需要 fork 本仓库:只需通过 .intentflow/ 下 agent 产生的内容和 report.md 里的开发经验重新整合,修改自己的 skill 与工作流即可。核心机制越小越容易被重新实现,垂类内容由各开发者在自己的成长中自行沉淀——这也是本项目刻意保持精简的原因。
渐进式植入——这套方案不需要在项目开始时花大成本确定一份全局规格(项目维护图、全局 spec 之类):入场成本只有一个 .intentflow/ 文件夹和一个 skill。老项目的代码文件动辄几千几万个,就算要维护一份全局规格,最终也得分块描述——那不如一开始就分块。植入是渐进的:先在一个 change 上用起来,每次关账顺手给涉及的文件补上 @intent,随着项目成长,没有意图的内容逐步变成有意图的内容。像墨水在纸上洇开,每次关账就是一次扩散。
可抛弃性——模块现状不依赖本工作流存在:skill 如何更新、流程如何演进、甚至整个方案被抛弃,.intentflow/_packages/ 依然是有效的项目地图——它描述的是项目本身,不是流程。日常开发 AI 本就需要扫描目录,模块现状只是省去了这一步,没有增加任何实体。所以采用本方案没有沉没成本:最坏的情况,是留下一张比没有更好的项目地图。
核心九条:去人称化、过程式声明、极简无歧义、不角色扮演、不冗余、不兜底、流程描述衔接、不用表格、禁止思考链残余。
其中「禁止思考链残余」:文档只写当前职能、边界、结果,不残留推导经过、思考过程。
这些标准同样遵循上面的思路——随着模型越来越强,它们可能被替代,但"与人对齐"这个目标不变。
MIT