背景
使用cursor已经有半年,这种开发模式也叫vibe coding,也就是把prd贴过来给agent,基本上可以实现功能,但是总是需要返工,不是组件库写错版本导致死循环,就是写法完全让自己不满意。3月中旬直属领导跟我说他们最近在学习什么skill,期初我只当成是commands的升级版,大家可以共享可重复使用的提示词,就有点像抽象方法,或者写组件复用而已
但是当我在3.26 得知harness,我发现我的工时大幅度提升,原估时开发7pd,2天写完了前端,等接口文档出来,半天一天基本上就搞定了,等联调即可
概念
当ai写错时,不是去纠正它,而是提供正确的环境,这个就是harness最初概念
也就是说vibe coding模式下,我们总是去骂ai写错,像老板骂员工一样,其实是你没有提供精准的指令而已,也就是说当我们提供的指令足够精准,并且做一些禁止项。ai完全可以写正确
harness的最终状态就像openai发布的文章一样,缩短工时到原来的10%,3个人5个月写了100万行代码,经过我的实践,我发现是大概率有可能
思路
网上没人说过具体怎么实践,我也就是基于下面两个思路
- 当ai写错时,不是去纠正它,而是提供正确的环境
- harness就是给ai搭建流水线,自己写代码,自动自我检查
第一个思路是我看文章得到的,harness这个词的出现就是github有个人说了这句话,第二个是我认识的一个博主说自己已经实践了自动化流水线自己跑,并且我跟在字节的朋友,确认过他们很多业务已经在总结skill,以后我们的价值就是token时,我对harness这个概念大为相信
目标
目前我的实践仅限于读取prd->写代码,原因是我们组本身没有代码搭建单元测试,也没有打通代码平台(MCP),据说其他组已经打通,可以自动review自动提交自动评论
最终我的理想结果就是,ai自己分析prd->产出前端梳理->ai根据这份梳理写代码->ai根据梳理写自测->ai执行自测,修改代码->ai review代码,经过我看完验证没问题后提交,我还是比较认可人工把握每一行代码,这样才能保证质量
实践
1.读取prd
我们的prd(需求)是在confluence,可以通过下载html(附带图片),然后放在项目的文件下,我放在.docs/prd/{具体需求},然后skill通过读取文件,大体思路就是删掉废话,需求大纲,保留需求详细,删掉后端实现,最后对需求明细进行加工,对比代码已有实践,删掉已实现功能。最后写入文件.docs/前端梳理/{具体需求}
这个过程是最痛苦的地方,我用了一个一周多的需求,光调试“prd梳理成前端梳理”这个skill,就花了两天,不过也是值得的,也就是说只要需求足够明确,后面基本上调整很少,本着“当ai写错时,不是去纠正它,而是提供正确的环境”这个原则,只要ai梳理的我不满意,我立马改skill
2.书写代码
这部分其实就是vibe coding,我发现只要ai写错的,都是需求不够明确,举例:需求有句话是在某个列表加一个标签,这个标签要在某个已有旧标签下的右边,背景是这个列表有几种类型,也就是说代码有几个if else,只在某个if分支才有旧标签,按照人工理解,我们知道虽然需求没写,肯定就是在这个if分支去加新标签,但是ai的实现是所有if 分支都加上标签,因此当我发现这个问题,我立马修改“prd梳理成前端梳理”这个skill,让它必须遇到这种案例,就要只改有旧标签功能的这个分支
书写skill踩坑分享
ai处理人的语言,如果不够坚定,就会当成没必要实现,比如说优先、建议,ai大概率不会实现,因此以下原则各位可以参考
- 让ai必须读取案例
- 强制执行,而非优先、建议等说法,只要你想让ai实现了,语气需要坚定,如果是rule,则全部必须强制执行
- 多用禁止,禁止xxx,比如说禁止用跟本项目版本无关,否则ai很容易把你项目中组件库版本写错导致死循环调试半天
skill分享
根据prd前端梳理
1. **从 prd 识别提取文案**
- 文件地址在 `.docs/prd`,例如某需求对应目录为 `.docs/prd/短信工具提效优化`(**仅为路径示例**;其他需求替换目录名即可)。
- 本步骤产出:**完整** PRD 对应的 HTML 化内容(结构、表格行列、**图片标签**与原文层级尽量与源一致)。
- 若识别出表格:表头、行数列数、单元格合并关系 **尽量照搬**;表内 `<img>` **必须保留**。
- **功能模块 / 章节标题**:与 **PRD 正文实际用语** 一致(可能是 `h2/h3`、表格第一列标题等);**不要**强行改写成统一编号,除非 PRD 原文就是编号体例。
- 参考:`./步骤1` 的案例(如有)。
2. **初步过滤出详细需求:提取需求明细、删除与需求明细无关内容**
- **可删除**:需求背景、需求目标。
- 改动点章节默认不直接抄写;但若其中有在「需求详情」里缺失的有效需求,必须补充到对应功能模块,禁止漏项。
- **可删除**:PRD 中被删除线标记的内容(~~删除线~~)。
- 提取需求详细部分(如「3.2 需求详情」等):**该标题下的正文与表格须整段保留结构**;其中 **`<img>` 跟随所在行/块一并保留**。
- 参考:`./步骤2的案例.md`
3. **精细过滤:去掉无法指导前端开发的内容**
- 删除「纯后端」描述:**禁止自行发挥**,必须以 `./步骤3:精细过滤从详细需求过滤无法指导前端开发的需求/删除后端案例.md` 为准;案例未覆盖的 **一律不删**。
- 删除「总结性 / 无法编码」段落:**禁止自行发挥**,必须以 `./删除总结性需求案例.md` 为准。
- **注意**:本步骤删除的是**文字条目**;被删段落若在 PRD 中**仅有说明性文字而无独立截图**,才可整段消失;若该段内**含有截图**,删除总结性文字后 **`<img>` 仍应保留**并标注「待与下文要点对应」或合并到相邻需求块。
4. **把详细需求整理成前端需求**
- **案例**:`./步骤4-案例:把详细需求整理成前端需求.md`
- 结合 **PRD 图片与上下文** 理解后再改写为前端语言;**改写不等于删图**。
- 必须通过案例指导增删合并;**未在案例中出现过的删改理由,不得自行删**。
- 允许:PRD 上下文重复时去重;按案例做「无需前端实现」的剔除(剔除时仍遵守「图片继承链」)。
- 如果发现新增字段(筛选、列表等),且有图片时,务必识别出根据图片识别出新增字段所在位置,例如根据代码得知原来的筛选是人群圈选、创建时间、最后短信发送时间,而prd只写了新增短信任务id、人群类型、任务状态,图片画了短信任务id在人群圈选之前,则需要在短信任务id去备注:短信任务id(人群圈选之前)、人群类型(人群圈选之后)
- 如果某个需求当前页无法定位,需要读取图片,识别所在位置,例如短信任务列表模块,出现需求为“取消人群包有效期限制”,而代码是没有这个限制的,根据图片得知,这个限制在短信任务详情,因此需要将“取消人群包有效期限制”这句话,单独开一个“短信任务详情模块”,把图片+需求都挪过去
5. 加上前端语言
- 如果input识别是数字类型的,例如单位是万,则需要加上inputnumber,举例:发送数量,inputNumber,万
- 描述表单需求时,在每个item加上对应的输入框,例如input、select、时间选择器等
6. **过滤已实现的需求**
- **案例**:`./步骤5(过滤已实现的需求)-案例.md`
- 通过项目上下文(优先 `.docs/代码逻辑梳理`,**以代码为准**)检查步骤 4 内容:已实现的,删除对应**开发口径**描述;**截图与 PRD 证据尽量保留**(见「图片继承链」)。
- **禁止**:因「好像已上线」就删 whole 模块且无任何案例/代码依据。
7. 存在疑问的需求
寻找有疑问的地方,打上问号
**强制要求**:只能根据案例,相似类型才能打上问号,谨慎
**案例**:./步骤6(存在疑问的需求)—案例.md
8. 补充prd没提到的需求
强制要求,案例没提到的不允许随便补充
9. **写入文件**
- 路径示例:`.docs/前端需求整理/<需求名>-前端需求整理.html`
- 最终文件须**同时**包含:**证据**(`<img>` 或原文块)+ **前端可执行口径**(列表/表格均可,由 PRD 形态决定);不得只写后者。
根据代码梳理出逻辑
## 目标
把代码整理成前端逻辑,用前端语言,中文
## 适用边界
- 帮助ai或者人快速了解具体完整的前端逻辑细节
## 强制要求
必须先读取案例再结合步骤进行执行,只理解步骤,会导致理解会不准确,案例就是代码步骤的最准确意思
## 原则
如果字段能通过项目上下文得知什么意思,必须列出什么意思,案例:是否开启策略衰减(autoDecaySwitch)
## 执行流程
1. 读取文件,或者通过中文识别用户输入的业务是哪个文件下
2. 根据每个文件去整理,忽略css
3. 整理成简要逻辑
4. service文件查看案例,根据这个模版来输出,结合以service的url为纲,根据项目上下文,梳理出出参和入参
## 文档规范(强制检查输出文档)
参考./案例/文档规范案例.md
- 不要出现过多代码(代码只能是辅助,重要是用中文梳理逻辑细节,例如禁止条件:status==2)
- 必须包含(页面、逻辑)title
- 逻辑:必须保留具体逻辑,例如禁止,权限等
- 先整体后细节:先列模块(例如:查询/筛选、列表、详情、弹窗、抽屉等),再进入每个模块内部。
- 如果同一页面存在多种“展示场景/模式”(比如不同 tab、不同业务类型、不同入口),要按“场景”分别列字段顺序(不能合并写“字段A/字段B”)
### 页面
应该先整体到细节列出页面展示情况,如果某个按钮有简单逻辑逻辑,在这个部分必须列出,如果太复杂则在逻辑列出
#### 列表
如果有列表应该列出所有的字段、如果有表单应该保留表单字段(字段名字一个字不能错,必须按照顺序),列表就是从左到右,表单有可能是从上到下或者从左到右
##### 操作按钮必须拆两层写(强制)
页面-操作栏:只写“按钮是否展示”的条件
条件写法:中文可读的状态/原因 +(括号里写代码条件)
对于无法推断含义的“权限位/标记位数字”,只写代码条件本身,不要硬翻译
#### 弹窗
必须写 标题 + 核心文案/关键字段(不能只写“有弹窗”)
有动态文案时,必须写清楚 变量取值规则(例如 planName 怎么算)
### 逻辑
#### 列表-操作
逻辑-操作行为:写“点了按钮发生什么”
必须落到具体动作:跳转到哪(路径 + query/params)、请求哪个接口(method + url)、是否二次确认、成功后如何刷新/回跳/提示
如果按钮只是触发上层回调,必须继续向上追踪到页面/模型/服务层,直到能写出“跳转/接口/弹窗”的真实行为
## 输出示例
### 案例1
流程:1. 读取文件,或者通过中文识别用户输入的业务是哪个文件下
输入:短信工具
读取:message_tool下
### 案例2
流程:3. 整理成简要逻辑
#### 短信工具或者message_tool
#### 输出
参考.docs/代码逻辑梳理/短信工具
案例3
流程:3.整理成简要逻辑
输入:src/pages/message_tool/components/message整理成前端逻辑
错误输入:./案例/案例3-错误.md
正确输入:./案例/案例3-正确.md
## 限制
- 允许写代码,但只能“最小代码”
- 文档里不贴大段代码;只允许在括号里放关键判断(例如 status == 1),或列举映射(value→name)。
重点是中文解释“为什么”,不是复述实现细节(例如不要展开 props 列表、不要写分页参数这种细节)。
- 不允许写props、向父组件派发的事件这种技术方面的梳理
## 检查
- 字段自检:列表字段是否与 title 文案逐字一致?顺序是否从左到右?
- 场景自检:是否把不同场景的字段/规则混写在一起?
- 映射自检:所有 value→name 是否逐条列出?是否遗漏某个值?
- 展示条件是否都在“页面-操作栏”?
- 点击后的跳转/接口/确认/刷新是否都在“逻辑-操作行为”?
- 动态文案自检:弹窗/页面上出现的关键文案是否遗漏?动态变量取值规则是否写清?
这个技能超级牛逼,这个是我让ai参考原有逻辑的一环,也是让我更好更快速的理解历史逻辑,比如说某个表格,我想找到某个字段存不存在,这样我能更好的去跟后端沟通是否加字段,这个skill会帮我直接把接口在项目上下文涉及出入参的中文和字段直接列出,我一眼就能看出历史逻辑,又或者某段代码自己看逻辑要看半天,直接看中文梳理马上理解
rule分享
- 禁止在用户未提供或未引用具体需求材料的情况下,凭空增加 PRD 之外的功能
- 当某个功能块改了,之后又让撤回去不改了,必须保证跟原来一模一样(换行、逗号等一个符号都不能变)
- 表单的里面 radio 的顺序和布局,必须跟图片保持一致
- 本文件所有规则均为强制执行;如出现“建议/倾向/尽量/优先”等措辞,统一按必须理解。
- 只写 JS/JSX:不要引入 TypeScript,不要新增/改成
.ts/.tsx,也不要为了修复问题“迁移到 TS”。(如果遇到现有 TS 类型/报错,仅做不改变业务逻辑的修复,但本项目新增代码保持 JS。) - 必须符合 eslint:改动后代码需通过项目 eslint 规则(Airbnb 体系 + 项目现有配置)。避免引入会触发规则的大范围写法变化。