如何设计项目AI改造Skill
最近在 AgentInfra 里做了一个新的 Skill,名字叫 harness-builder。

这个 Skill 的目标不是帮某个项目生成一份漂亮的 AGENTS.md,而是做一件更实际的事:当我拿到一个新项目,或者一个已经跑了很久的老项目时,如何把它改造成一个 AI 更容易接手、也更不容易乱改的项目。
一开始我脑子里的需求其实有点大:
- 检查并优化项目里的
AGENTS.md; - 把 Karpathy 风格的编码约束放进去;
- 吸收一个已有项目里的
CLAUDE.md和.claude目录设计; - 把一篇关于 Claude Code 记忆系统的文章落地;
- 老项目还要跑一次整体代码体检;
- 最后生成项目文档导航,让后面的 AI 能快速进入状态。
这个需求如果直接写,很容易写成一个“万能改造器”。看起来很强,实际上大概率会很危险。
因为老项目最怕的不是没有规则,而是被一个看似懂项目的工具,直接重写了规则。
一开始容易走偏的地方
我最开始下意识会把这个 Skill 想成一个自动化工具:
给我一个项目路径,我自动扫描,自动生成
AGENTS.md,自动加 hooks,自动生成项目 skills,自动把外部文章重新读取并总结,最后自动改完。
这个方向看起来很顺,但里面有几个问题。
第一个问题是,项目改造不是纯生成任务。
一个老项目里原来可能已经有 AGENTS.md、CLAUDE.md、Cursor rules、CI、测试命令、团队历史约束。这些内容不一定写得好,但它们是项目事实的一部分。直接用模板覆盖,等于把历史上下文删掉。
第二个问题是,外部资料不能每次重新理解。
这次参考了三类材料:
multica-ai/andrej-karpathy-skills里的编码代理行为约束;- 一个 AimeClaw 项目里的
CLAUDE.md、rules、skills、hooks 示例; - 一篇关于 Claude Code 自我学习和记忆系统的文章。
这些材料的价值不是“每次执行时再去读一遍”,而是把里面稳定的设计原则提炼出来,变成 Skill 自己的固定参考资料。否则这个 Skill 每次运行都会带着不稳定输入,今天总结成这样,明天又总结成另一个样子。
第三个问题是,hooks 和记忆系统不能默认安装。
那篇记忆系统文章里有一个判断我觉得很对:Skill 依赖模型主动调用,Hook 更确定。比如工具调用前后记录 observation,会话结束后分析规律,下次会话开始前注入记忆,这些事情用 Hook 更合适。
但反过来,Hook 一旦安装,就是在改变用户的运行时环境。默认安装格式化、记录、Stop 分析、SessionStart 注入,听起来很完整,实际很容易变成新的干扰源。
所以最后的设计不是“自动安装记忆系统”,而是“默认生成轻量的项目记忆和 bug-pattern 机制,Hook 只作为模板和建议,用户确认以后再装”。
最后收敛成一个原则
这个 Skill 最后收敛成一个很简单的流程:
diagnose -> report -> confirm -> apply -> validate
先诊断,再报告,再确认,再落地,最后验证。
这里最重要的是前两步。项目 AI 改造不是上来就改文件,而是先回答几个问题:
- 这是新项目还是老项目?
- 有没有 Git 历史和已有代码?
- 有没有
AGENTS.md、CLAUDE.md、.cursor/rules之类的入口? - 有没有
docs/README.md这种文档地图? package.json里有没有test、lint、typecheck、build?- 有没有 CI?
- 有没有项目本地 skills?
- 有没有 hooks?
- 有没有明显的私有路径、secret 或运行时缓存风险?
这些问题不应该靠模型凭感觉回答,所以我给 Skill 加了两个脚本。
第一个是:
node capabilities/skills/engineering/harness-builder/scripts/scan-project.mjs <project-path> --json
它只读扫描项目,输出项目分类、入口文件、文档状态、包管理器、命令、CI、hooks、项目 skills 和风险标记。
第二个是:
node capabilities/skills/engineering/harness-builder/scripts/validate-harness.mjs <project-path> --json
它检查改造结果是否真的落地:
AGENTS.md是否存在;docs/README.md是否存在;docs/ai-harness/README.md是否存在;- 是否有日期化审计报告;
- 是否生成了最小项目 skill 组;
- skill frontmatter 是否有效;
- Markdown 和 skill 文件里是否出现
/Users/<name>/...这种私有路径; - 是否有类似 API key 的内容。
这一步很关键。没有验证脚本,Skill 很容易变成“写了一堆文件,看起来挺完整”。但下次 AI 进项目时,真正能不能用,其实没人知道。
AGENTS.md 不应该变成百科全书
这次设计里有一个我反复提醒自己的点:AGENTS.md 要短。
很多项目做 AI 改造时,最容易犯的错是把所有内容都塞进入口文件:
- 项目背景;
- 架构说明;
- 编码规范;
- 命令;
- 历史 bug;
- 外部文章摘要;
- 个人偏好;
- hooks 说明;
- skill 说明;
- TODO;
- 临时计划。
最后这个文件会越来越像垃圾桶。AI 每次进来都读,但读完也不一定抓得住重点。
所以 harness-builder 的默认设计是:
AGENTS.md只做主入口;docs/README.md做项目文档导航;docs/ai-harness/README.md记录 AI harness 状态;docs/ai-harness/audits/YYYY-MM-DD-harness-audit.md放诊断和改造报告;- 项目级重复流程放到
.agents/skills/。
这其实是把“入口”和“知识库”拆开。
入口文件只告诉 AI:
这个项目是什么,不能碰什么,常用命令是什么,进一步的文档在哪里。
更长的内容放到 docs 和 project skills 里。需要的时候再读,不需要的时候不要污染上下文。
为什么要生成项目本地 Skills
另一个设计选择是:改造项目时,不只是生成文档,还要生成一组最小项目 skills。
默认是五个:
.agents/skills/<project>-router/SKILL.md
.agents/skills/<project>-onboarding/SKILL.md
.agents/skills/<project>-dev-doctor/SKILL.md
.agents/skills/<project>-quality-gate/SKILL.md
.agents/skills/<project>-audit-followup/SKILL.md
这里我没有选择“生成一大包 Skill”。因为项目刚开始改造时,最需要的不是十几个花哨能力,而是几个稳定入口。
router 负责把常见任务路由到正确文档或技能。
onboarding 负责让 AI 先读项目地图、命令、架构、风险,不要一上来就改代码。
dev-doctor 负责本地启动、依赖、命令失败的诊断。
quality-gate 负责跑和解释项目已有的 lint、typecheck、test、build。
audit-followup 负责把审计报告里的问题拆成小的、可验证的整改任务。
这些 Skill 要跟项目走,所以默认放在项目里的 .agents/skills/,并且带项目名前缀。不要放到用户全局目录里。全局 Skill 放太多项目事实,后面一定会串味。
老项目必须先体检
对新项目来说,初始化一套 harness 问题不大。真正麻烦的是老项目。
老项目里已有代码、已有命令、已有文档、已有团队习惯。它可能没有 AI 规则,但不代表它没有规则。很多规则只是散落在 README、CI、测试文件、commit 历史和目录结构里。
所以这个 Skill 里定了一个比较粗但实用的判断:
非空 Git 仓库默认按老项目处理。
老项目先跑只读诊断。如果本机有 yulifeng-codebase-audit,就用这个 Skill 做更严格的整体体检;如果没有,就跑内置的轻量检查,并明确标注扩展审计不可用。
这里的重点不是“打分”,而是后续能不能根据报告继续自迭代。
一个好的审计报告应该告诉 AI:
- 当前项目最缺的证据是什么;
- 哪些规则入口不可靠;
- 哪些测试或质量门禁缺失;
- 哪些 hooks 只是建议,不能默认安装;
- 哪些问题应该本周修,哪些可以后面处理;
- 每个整改项的验收标准是什么。
没有这一步,后面的 AI 优化很容易变成“我觉得可以优化一下”,然后开始乱动。
外部资料怎么进入 Skill
这次有一个比较重要的处理:外部材料不原样塞进去。
Karpathy guidelines 进入 Skill 后,只保留几个稳定原则:
- 先说清假设;
- 保持改动小;
- 不做无关重构;
- 定义可验证目标;
- 需求不清先停下来问。
AimeClaw 的 CLAUDE.md 和 .claude 目录,也没有原样复制。里面有很多 AG-UI、适配层、shadcn、端口等项目专用内容,复制到别的项目就是污染。真正有价值的是结构:
- 入口文件说明项目职责边界;
- rules 单独拆文件;
- skills 编码重复流程;
- code-review agent 对照项目规则检查;
- hooks 做格式化或质量门禁,但本地配置不能变成通用模板。
微信文章里的记忆系统,也没有直接照搬成完整向量库方案。它真正给我的启发是:
- 规则要能长期积累;
- bug pattern 要能回流到项目;
- Hook 比 Skill 更适合确定性触发;
- 但默认改造必须轻量,不能上来就装一套 observation + embedding + Qdrant。
所以 harness-builder 里只把它转成轻量版本:项目记忆、bug-pattern、文档导航、可选 hook 模板。完整向量召回系统以后可以做,但不应该是默认路径。
又从 v3 workflow 里补了一刀
后来我又看了一份 v3.zip。
这里面有一套更完整的 AI coding workflow,从 Phase 0 到后面的实现、校验、交接都有。第一反应当然是:这么完整,是不是应该全塞进 harness-builder?
但仔细看完以后,我觉得不应该。
一方面,里面的 prototype-workflow/ 其实已经和 AgentInfra 里的 workflows/ai-coding-v3/ 对上了。也就是说,它不是一个缺失的新素材,而是已经存在的一套完整工作流。再把它复制进 harness-builder,只会让两个地方同时维护同一套东西。
另一方面,harness-builder 的定位不是“替项目安装一套完整 AI 开发流程”,而是先把项目变成 AI 能稳定接手的状态。它应该补的是项目的地基,不是直接规定每次开发都要走六个阶段。
所以最后只吸收了 v3 里最必要的三类东西。
第一类是 .docs4agents 上下文包。
它默认包含三个文件:
.docs4agents/codebase-inventory.md
.docs4agents/forbidden-list.md
.docs4agents/implementation-rules.md
这几个文件解决的是同一个问题:不要把项目事实只留在当前对话里。
codebase-inventory.md 记录组件、接口、路由、状态、hooks、工具函数这些项目地图。没有就写没有,不确定就写 unknown,而不是让 AI 猜。
forbidden-list.md 记录不能做的事情,而且必须带 Source 和 Verification。因为“不要动这个目录”本身不够,后面的 AI 还要知道这条规则从哪里来、怎么验证有没有违反。
implementation-rules.md 记录项目级实现边界,比如怎么改、怎么验、遇到不确定信息时放到哪里。
第二类是决策记录和开放问题。
新增两个文件:
docs/ai-harness/decision-log.md
docs/ai-harness/open-questions.md
decision-log.md 用 DEC-001 这种 ID 记录长期有效的决定,比如 hooks 为什么默认不安装、质量门禁以哪个命令为准。
open-questions.md 用 Q-001 记录没证据的问题,比如 CI 里的某个命令是不是本地也必须跑。这个文件很重要,因为 AI 最大的坏习惯之一就是“看起来很确定地补全未知信息”。把未知问题显式写下来,就是在给后面的 AI 留刹车。
第三类是验证门槛。
我没有只在文档里说“请创建这些文件”,而是把它加进了 validate-harness.mjs:
.docs4agents三件套必须存在;codebase-inventory.md至少要有组件、接口、路由等基本栏目;forbidden-list.md必须有Rule、Source、Verification;decision-log.md必须有DEC-*记录;open-questions.md必须有Q-*记录;- 审计报告不能只是观察,必须有风险、行动和验收标准。
这次补完以后,harness-builder 的边界更清楚了:它不复制 v3 的完整开发流程,只借它最实用的“文件化上下文”和“可验证交接”思想。
这也是我觉得做 Skill 时很容易被忽略的一点:看到好东西不要马上全加。先问一句,这个东西是在降低下一次接手项目的混乱,还是在给默认路径增加新的复杂度。
这个 Skill 最后长什么样
最终在 AgentInfra 里,harness-builder 是一个 core engineering skill。
它的结构大概是:
capabilities/skills/engineering/harness-builder/
SKILL.md
agents/openai.yaml
references/
source-digests.md
harness-output-spec.md
scripts/
scan-project.mjs
validate-harness.mjs
SKILL.md 负责流程和边界。
source-digests.md 固化前面几类参考材料,不让执行时每次重新联网理解。
harness-output-spec.md 规定目标项目应该生成什么、AGENTS.md 怎么合并、项目 skills 怎么命名、hooks 怎么处理、验收标准是什么。
scan-project.mjs 和 validate-harness.mjs 负责确定性检查。
同时它被注册到 manifests/assets.json 里,作为 core-engineering profile 的一部分。这样后续 AgentInfra 生成 Codex、Claude、Cursor 等目标适配时,它会跟着核心工程能力一起输出。
这一步也有一个设计边界:harness-builder 是 AgentInfra 的通用能力,但它生成的项目 skills 应该留在目标项目里。不要把某个项目的 onboarding、dev-doctor、quality-gate 全都装到用户全局目录。
自测为什么重要
这次不是只写了 Skill 文档,还给脚本补了测试。
测试里覆盖了几个场景:
- 空目录应该识别成新项目;
- 非空 Git repo 应该识别成老项目;
- 能识别
AGENTS.md、CLAUDE.md、CI、hooks、项目 skills; - 能识别
.docs4agents上下文包和 harness 决策记录; - 能从
package.json里识别test、lint、typecheck、build; - 完整 harness 应该通过验证,包括
.docs4agents、决策日志、开放问题和可执行审计; - 缺少 v3 派生的上下文记录时应该报错;
- 缺 docs 或出现
/Users/alice/...这种私有路径时应该报错。
最后跑的验证包括:
node --test tests/*.test.js
node scripts/agentinfra/inventory.js
node scripts/agentinfra/validate.js
node scripts/agentinfra/build-target.js --target codex --profile core-engineering --dry-run
git diff --check
这里还有一个小插曲:本机 shell 里没有全局 node,所以最后用的是 Codex runtime 里的 Node 路径。这个细节也提醒我,项目 harness 里不能假设环境一定完整。缺依赖、命令不存在,本身就是诊断结果的一部分。
这次的经验
这次做完以后,我对“项目 AI 改造 Skill”有几个比较明确的判断。
第一,Skill 不是大 prompt。
如果只是把一堆原则写进 SKILL.md,让 AI 自己发挥,那它不稳定。真正容易出错、容易重复的部分,要变成脚本或明确的验收规则。
第二,项目改造要先读项目,而不是先套模板。
尤其是老项目,原来的文档和规则可能很乱,但不能默认它们没价值。正确做法是保留项目事实,压缩重复内容,把入口变短,把长内容迁移到 docs 和 skills。
第三,hooks 要克制。
Hook 很强,但强就意味着风险也大。默认输出模板和建议,用户确认后再安装,比“一键全装”更稳。
第四,记忆系统应该先轻量落地。
先有项目记忆、bug-pattern、审计报告、整改清单。等这些基础东西真的用起来,再考虑 observation、embedding、向量召回。否则很容易为了“智能”引入一堆新的维护成本。
第五,最终要能验证。
AI-friendly 不是一个形容词。至少要能回答:
- 入口文件是否存在;
- 文档地图是否存在;
.docs4agents上下文包是否存在;- 决策日志和开放问题是否存在;
- 项目 skills 是否存在;
- 审计报告是否存在;
- 审计报告里有没有风险、行动和验收标准;
- 是否有私有路径和 secret 风险;
- 项目已有的质量命令有没有跑过。
如果这些都回答不了,那就还只是“看起来改造过”。
后面我如果继续优化这个 Skill,会继续看两件事。
一是让它生成更好的整改任务,把审计报告里的问题拆成一批小 PR 级别的任务。
二是补一套真实项目回放测试。拿几个不同类型的项目跑一遍,看它生成的 harness 是不是实际可用,而不是只在临时 fixture 里通过。
这类工具最后拼的不是概念,而是能不能减少下一次接手项目时的混乱。