fe-harness 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -0
- package/agents/fe-codebase-mapper.md +945 -0
- package/agents/fe-design-scanner.md +47 -0
- package/agents/fe-executor.md +221 -0
- package/agents/fe-fix-loop.md +310 -0
- package/agents/fe-fixer.md +153 -0
- package/agents/fe-project-scanner.md +95 -0
- package/agents/fe-reviewer.md +141 -0
- package/agents/fe-verifier.md +231 -0
- package/agents/fe-wave-runner.md +477 -0
- package/bin/install.js +292 -0
- package/commands/fe/complete.md +35 -0
- package/commands/fe/execute.md +46 -0
- package/commands/fe/help.md +17 -0
- package/commands/fe/map-codebase.md +60 -0
- package/commands/fe/plan.md +36 -0
- package/commands/fe/status.md +39 -0
- package/fe-harness/bin/browser.cjs +271 -0
- package/fe-harness/bin/fe-tools.cjs +317 -0
- package/fe-harness/bin/lib/__tests__/browser.test.cjs +422 -0
- package/fe-harness/bin/lib/__tests__/config.test.cjs +93 -0
- package/fe-harness/bin/lib/__tests__/core.test.cjs +127 -0
- package/fe-harness/bin/lib/__tests__/scoring.test.cjs +130 -0
- package/fe-harness/bin/lib/__tests__/tasks.test.cjs +698 -0
- package/fe-harness/bin/lib/browser-core.cjs +365 -0
- package/fe-harness/bin/lib/config.cjs +34 -0
- package/fe-harness/bin/lib/core.cjs +135 -0
- package/fe-harness/bin/lib/logger.cjs +93 -0
- package/fe-harness/bin/lib/scoring.cjs +219 -0
- package/fe-harness/bin/lib/tasks.cjs +632 -0
- package/fe-harness/references/model-profiles.md +44 -0
- package/fe-harness/templates/config.jsonc +31 -0
- package/fe-harness/vendor/.gitkeep +0 -0
- package/fe-harness/vendor/puppeteer-core.cjs +445 -0
- package/fe-harness/workflows/complete.md +143 -0
- package/fe-harness/workflows/execute.md +227 -0
- package/fe-harness/workflows/help.md +89 -0
- package/fe-harness/workflows/map-codebase.md +331 -0
- package/fe-harness/workflows/plan.md +244 -0
- package/package.json +35 -0
- package/scripts/bundle-puppeteer.js +38 -0
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
<purpose>
|
|
2
|
+
编排并行前端代码库映射代理,分析代码库并在 .fe/codebase/ 中生成结构化文档。
|
|
3
|
+
|
|
4
|
+
每个代理拥有独立上下文,探索特定聚焦领域,并**直接写入文档**。编排器仅接收确认 + 行数,然后输出总结。
|
|
5
|
+
|
|
6
|
+
输出: .fe/codebase/ 目录,包含 7 个前端专属结构化文档。
|
|
7
|
+
</purpose>
|
|
8
|
+
|
|
9
|
+
<philosophy>
|
|
10
|
+
**为什么使用专属映射代理:**
|
|
11
|
+
- 每个领域独立上下文 (无 token 污染)
|
|
12
|
+
- 代理直接写入文档 (不回传上下文给编排器)
|
|
13
|
+
- 编排器仅总结创建了什么 (最小上下文占用)
|
|
14
|
+
- 更快执行 (代理同时运行)
|
|
15
|
+
|
|
16
|
+
**前端垂直化:**
|
|
17
|
+
不同于通用代码库映射,前端映射聚焦于:
|
|
18
|
+
- 组件架构与设计系统
|
|
19
|
+
- 样式方案与设计 token
|
|
20
|
+
- 状态管理与数据获取模式
|
|
21
|
+
- 路由与页面组织
|
|
22
|
+
- 前端性能指标 (LCP, CLS, INP, 包体积)
|
|
23
|
+
|
|
24
|
+
**文档质量优于简洁:**
|
|
25
|
+
包含足够的细节作为参考。优先提供实际的代码模式示例。
|
|
26
|
+
|
|
27
|
+
**始终包含文件路径:**
|
|
28
|
+
文档是 Claude 规划/执行时的参考材料。始终使用反引号格式化实际文件路径: `src/components/Button.tsx`。
|
|
29
|
+
</philosophy>
|
|
30
|
+
|
|
31
|
+
<process>
|
|
32
|
+
|
|
33
|
+
<step name="check_existing">
|
|
34
|
+
检查 .fe/codebase/ 是否已存在:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
ls -la .fe/codebase/ 2>/dev/null
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**如果目录存在且有文件:**
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
.fe/codebase/ 已存在,包含以下文档:
|
|
44
|
+
[列出找到的文件]
|
|
45
|
+
|
|
46
|
+
下一步?
|
|
47
|
+
1. 刷新 - 删除现有映射,重新分析
|
|
48
|
+
2. 更新 - 保留现有,仅更新特定文档
|
|
49
|
+
3. 跳过 - 使用现有代码库映射
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
等待用户响应。
|
|
53
|
+
|
|
54
|
+
如果 "刷新": 删除 .fe/codebase/,继续到 create_structure
|
|
55
|
+
如果 "更新": 询问更新哪些文档,继续到 spawn_agents (过滤)
|
|
56
|
+
如果 "跳过": 退出流程
|
|
57
|
+
|
|
58
|
+
**如果不存在:**
|
|
59
|
+
继续到 create_structure。
|
|
60
|
+
</step>
|
|
61
|
+
|
|
62
|
+
<step name="create_structure">
|
|
63
|
+
创建 .fe/codebase/ 目录:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
mkdir -p .fe/codebase
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**预期输出文件:**
|
|
70
|
+
- STACK.md (来自 tech 映射器) — 前端技术栈
|
|
71
|
+
- COMPONENTS.md (来自 ui 映射器) — 组件架构与设计系统
|
|
72
|
+
- STYLING.md (来自 ui 映射器) — 样式方案与设计 token
|
|
73
|
+
- STATE.md (来自 tech 映射器) — 状态管理与数据获取
|
|
74
|
+
- STRUCTURE.md (来自 structure 映射器) — 目录结构与路由
|
|
75
|
+
- CONVENTIONS.md (来自 structure 映射器) — 前端编码惯例
|
|
76
|
+
- CONCERNS.md (来自 concerns 映射器) — 前端问题与技术债
|
|
77
|
+
|
|
78
|
+
继续到 spawn_agents。
|
|
79
|
+
</step>
|
|
80
|
+
|
|
81
|
+
<step name="spawn_agents">
|
|
82
|
+
生成 4 个并行 fe-codebase-mapper 代理。
|
|
83
|
+
|
|
84
|
+
使用 Agent 工具,`subagent_type="general-purpose"`,`run_in_background=true` 并行执行。
|
|
85
|
+
|
|
86
|
+
**代理 1: 技术聚焦 (Tech Focus)**
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
Agent(
|
|
90
|
+
run_in_background=true,
|
|
91
|
+
subagent_type="general-purpose",
|
|
92
|
+
model="haiku",
|
|
93
|
+
description="映射前端技术栈",
|
|
94
|
+
prompt="你是前端代码库映射代理。
|
|
95
|
+
|
|
96
|
+
聚焦: tech
|
|
97
|
+
|
|
98
|
+
分析此前端代码库的技术栈和状态管理模式。
|
|
99
|
+
|
|
100
|
+
写入以下文档到 .fe/codebase/:
|
|
101
|
+
- STACK.md — 前端框架、构建工具、TypeScript 配置、包管理器、关键依赖
|
|
102
|
+
- STATE.md — 状态管理方案、数据获取模式、表单管理、URL 状态
|
|
103
|
+
|
|
104
|
+
**探索方法:**
|
|
105
|
+
1. 读取 package.json 分析依赖
|
|
106
|
+
2. 查找框架配置文件 (next.config.*, vite.config.*, nuxt.config.*, angular.json 等)
|
|
107
|
+
3. 查找 TypeScript 配置 (tsconfig.json)
|
|
108
|
+
4. 搜索状态管理库的使用 (redux, zustand, jotai, pinia, vuex, @tanstack/react-query, swr 等)
|
|
109
|
+
5. 分析数据获取模式 (fetch, axios, graphql 等)
|
|
110
|
+
|
|
111
|
+
使用 @~/.claude/agents/fe-codebase-mapper.md 中的模板。
|
|
112
|
+
深入探索。直接使用 Write 工具写入文档。仅返回确认信息。"
|
|
113
|
+
)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**代理 2: UI 聚焦 (UI Focus)**
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
Agent(
|
|
120
|
+
run_in_background=true,
|
|
121
|
+
subagent_type="general-purpose",
|
|
122
|
+
model="haiku",
|
|
123
|
+
description="映射前端组件与样式",
|
|
124
|
+
prompt="你是前端代码库映射代理。
|
|
125
|
+
|
|
126
|
+
聚焦: ui
|
|
127
|
+
|
|
128
|
+
分析此前端代码库的组件架构和样式方案。
|
|
129
|
+
|
|
130
|
+
写入以下文档到 .fe/codebase/:
|
|
131
|
+
- COMPONENTS.md — 组件库/设计系统、组件模式、Props 惯例、复合组件、图标系统
|
|
132
|
+
- STYLING.md — CSS 方案、设计 token、主题系统、响应式策略、暗色模式、动画
|
|
133
|
+
|
|
134
|
+
**探索方法:**
|
|
135
|
+
1. 查找组件目录 (src/components/, src/ui/, components/, app/components/ 等)
|
|
136
|
+
2. 分析组件模式 (函数组件、HOC、render props、compound components)
|
|
137
|
+
3. 查找 UI 库依赖 (antd, @mui, shadcn, @radix-ui, element-plus, arco-design 等)
|
|
138
|
+
4. 分析 CSS 方案 (Tailwind, CSS Modules, styled-components, Sass, Less, UnoCSS 等)
|
|
139
|
+
5. 查找设计 token 或主题配置
|
|
140
|
+
|
|
141
|
+
使用 @~/.claude/agents/fe-codebase-mapper.md 中的模板。
|
|
142
|
+
深入探索。直接使用 Write 工具写入文档。仅返回确认信息。"
|
|
143
|
+
)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**代理 3: 结构聚焦 (Structure Focus)**
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
Agent(
|
|
150
|
+
run_in_background=true,
|
|
151
|
+
subagent_type="general-purpose",
|
|
152
|
+
model="haiku",
|
|
153
|
+
description="映射前端结构与惯例",
|
|
154
|
+
prompt="你是前端代码库映射代理。
|
|
155
|
+
|
|
156
|
+
聚焦: structure
|
|
157
|
+
|
|
158
|
+
分析此前端代码库的目录结构和编码惯例。
|
|
159
|
+
|
|
160
|
+
写入以下文档到 .fe/codebase/:
|
|
161
|
+
- STRUCTURE.md — 目录布局、路由方案、页面组织、功能模块结构、新代码放置指南
|
|
162
|
+
- CONVENTIONS.md — 命名模式、组件命名、Hooks 模式、TypeScript 模式、导入组织、代码风格
|
|
163
|
+
|
|
164
|
+
**探索方法:**
|
|
165
|
+
1. 分析目录结构 (find . -type d 排除 node_modules)
|
|
166
|
+
2. 查找路由配置 (pages/, app/, router/, routes/ 等)
|
|
167
|
+
3. 分析文件命名模式
|
|
168
|
+
4. 查找 lint/format 配置 (.eslintrc*, .prettierrc*, biome.json 等)
|
|
169
|
+
5. 读取示例文件分析编码惯例
|
|
170
|
+
6. 查找自定义 hooks 的模式
|
|
171
|
+
|
|
172
|
+
使用 @~/.claude/agents/fe-codebase-mapper.md 中的模板。
|
|
173
|
+
深入探索。直接使用 Write 工具写入文档。仅返回确认信息。"
|
|
174
|
+
)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**代理 4: 问题聚焦 (Concerns Focus)**
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
Agent(
|
|
181
|
+
run_in_background=true,
|
|
182
|
+
subagent_type="general-purpose",
|
|
183
|
+
model="haiku",
|
|
184
|
+
description="映射前端问题与技术债",
|
|
185
|
+
prompt="你是前端代码库映射代理。
|
|
186
|
+
|
|
187
|
+
聚焦: concerns
|
|
188
|
+
|
|
189
|
+
分析此前端代码库的技术债、性能问题和潜在风险。
|
|
190
|
+
|
|
191
|
+
写入以下文档到 .fe/codebase/:
|
|
192
|
+
- CONCERNS.md — 性能问题(包体积/渲染/Core Web Vitals)、可访问性差距、技术债、浏览器兼容、测试覆盖缺口
|
|
193
|
+
|
|
194
|
+
**探索方法:**
|
|
195
|
+
1. 搜索 TODO/FIXME/HACK 注释
|
|
196
|
+
2. 查找大型文件 (>500行的组件可能需要拆分)
|
|
197
|
+
3. 分析包体积 (检查大型依赖如 moment.js, lodash 全量导入)
|
|
198
|
+
4. 检查可访问性 (搜索 aria-*, role, alt 属性的使用情况)
|
|
199
|
+
5. 查找性能反模式 (内联函数创建、缺少 memo/useMemo、大型列表无虚拟化)
|
|
200
|
+
6. 检查测试覆盖 (查找测试文件分布)
|
|
201
|
+
7. 检查 any 类型使用、ts-ignore 等 TypeScript 问题
|
|
202
|
+
|
|
203
|
+
使用 @~/.claude/agents/fe-codebase-mapper.md 中的模板。
|
|
204
|
+
深入探索。直接使用 Write 工具写入文档。仅返回确认信息。"
|
|
205
|
+
)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
继续到 collect_confirmations。
|
|
209
|
+
</step>
|
|
210
|
+
|
|
211
|
+
<step name="collect_confirmations">
|
|
212
|
+
等待所有 4 个代理完成。
|
|
213
|
+
|
|
214
|
+
Agent 工具会在后台代理完成时自动通知。收集所有 4 个代理的确认。
|
|
215
|
+
|
|
216
|
+
**预期确认格式:**
|
|
217
|
+
```
|
|
218
|
+
## 映射完成
|
|
219
|
+
|
|
220
|
+
**聚焦:** {focus}
|
|
221
|
+
**已写入文档:**
|
|
222
|
+
- `.fe/codebase/{DOC1}.md` ({N} 行)
|
|
223
|
+
- `.fe/codebase/{DOC2}.md` ({N} 行)
|
|
224
|
+
|
|
225
|
+
已就绪。
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
**你收到的:** 仅文件路径和行数,不是文档内容。
|
|
229
|
+
|
|
230
|
+
如果任何代理失败,记录失败并继续处理成功的文档。
|
|
231
|
+
|
|
232
|
+
继续到 verify_output。
|
|
233
|
+
</step>
|
|
234
|
+
|
|
235
|
+
<step name="verify_output">
|
|
236
|
+
验证所有文档是否成功创建:
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
ls -la .fe/codebase/
|
|
240
|
+
wc -l .fe/codebase/*.md
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
**验证清单:**
|
|
244
|
+
- 所有 7 个文档存在
|
|
245
|
+
- 没有空文档 (每个应有 >20 行)
|
|
246
|
+
|
|
247
|
+
如果有文档缺失或为空,记录哪些代理可能失败了。
|
|
248
|
+
|
|
249
|
+
继续到 scan_for_secrets。
|
|
250
|
+
</step>
|
|
251
|
+
|
|
252
|
+
<step name="scan_for_secrets">
|
|
253
|
+
**关键安全检查:** 扫描输出文件中是否意外泄露了密钥。
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
grep -E '(sk-[a-zA-Z0-9]{20,}|sk_live_[a-zA-Z0-9]+|sk_test_[a-zA-Z0-9]+|ghp_[a-zA-Z0-9]{36}|gho_[a-zA-Z0-9]{36}|glpat-[a-zA-Z0-9_-]+|AKIA[A-Z0-9]{16}|xox[baprs]-[a-zA-Z0-9-]+|-----BEGIN.*PRIVATE KEY|eyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+\.)' .fe/codebase/*.md 2>/dev/null && SECRETS_FOUND=true || SECRETS_FOUND=false
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
**如果 SECRETS_FOUND=true:**
|
|
260
|
+
警告用户并等待确认后再继续。
|
|
261
|
+
|
|
262
|
+
**如果 SECRETS_FOUND=false:**
|
|
263
|
+
继续到 commit_codebase_map。
|
|
264
|
+
</step>
|
|
265
|
+
|
|
266
|
+
<step name="commit_codebase_map">
|
|
267
|
+
提交代码库映射文档:
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
git add .fe/codebase/*.md
|
|
271
|
+
git commit -m "docs: 映射前端代码库结构"
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
如果提交失败 (如没有 git 仓库或 pre-commit hook 失败),记录错误但不阻塞流程,继续到 offer_next。
|
|
275
|
+
|
|
276
|
+
继续到 offer_next。
|
|
277
|
+
</step>
|
|
278
|
+
|
|
279
|
+
<step name="offer_next">
|
|
280
|
+
展示完成总结和下一步操作。
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
wc -l .fe/codebase/*.md
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
**输出格式:**
|
|
287
|
+
|
|
288
|
+
```
|
|
289
|
+
前端代码库映射完成。
|
|
290
|
+
|
|
291
|
+
已创建 .fe/codebase/:
|
|
292
|
+
- STACK.md ([N] 行) - 前端技术栈与依赖
|
|
293
|
+
- COMPONENTS.md ([N] 行) - 组件架构与设计系统
|
|
294
|
+
- STYLING.md ([N] 行) - 样式方案与设计 token
|
|
295
|
+
- STATE.md ([N] 行) - 状态管理与数据获取
|
|
296
|
+
- STRUCTURE.md ([N] 行) - 目录结构与路由
|
|
297
|
+
- CONVENTIONS.md ([N] 行) - 前端编码惯例
|
|
298
|
+
- CONCERNS.md ([N] 行) - 问题与技术债
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## 下一步
|
|
304
|
+
|
|
305
|
+
**开始规划** — 基于代码库理解创建任务计划
|
|
306
|
+
|
|
307
|
+
`/fe:plan`
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
**其他操作:**
|
|
312
|
+
- 重新映射: `/fe:map-codebase`
|
|
313
|
+
- 查看特定文档: `cat .fe/codebase/STACK.md`
|
|
314
|
+
- 在继续前编辑任何文档
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
结束流程。
|
|
320
|
+
</step>
|
|
321
|
+
|
|
322
|
+
</process>
|
|
323
|
+
|
|
324
|
+
<success_criteria>
|
|
325
|
+
- .fe/codebase/ 目录已创建
|
|
326
|
+
- 4 个并行 fe-codebase-mapper 代理使用 run_in_background=true 生成
|
|
327
|
+
- 所有 7 个代码库文档存在
|
|
328
|
+
- 没有空文档 (每个应有 >20 行)
|
|
329
|
+
- 清晰的完成总结包含行数
|
|
330
|
+
- 用户获得明确的下一步操作指引
|
|
331
|
+
</success_criteria>
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
# 任务规划工作流
|
|
2
|
+
|
|
3
|
+
## 概述
|
|
4
|
+
解析用户输入的功能列表和 Figma URL,通过设计分析、多轮讨论和智能优化创建精准的任务列表。
|
|
5
|
+
|
|
6
|
+
## 流程
|
|
7
|
+
|
|
8
|
+
### Step 1: 检查状态
|
|
9
|
+
|
|
10
|
+
检查 `.fe-runtime/tasks.json` 是否存在:
|
|
11
|
+
- 不存在 → 进入初始化阶段
|
|
12
|
+
- 已存在:
|
|
13
|
+
- 用户提供了新功能列表 → 询问:重新初始化(覆盖)还是合并追加
|
|
14
|
+
- 用户没有提供新功能列表 → 显示当前状态概览(调用 `/fe:status`)
|
|
15
|
+
|
|
16
|
+
### Step 2: 解析用户输入
|
|
17
|
+
|
|
18
|
+
**期望的输入格式:**
|
|
19
|
+
```
|
|
20
|
+
功能1: 用户头像组件, figma设计稿: https://figma.com/design/xxx?node-id=1-2
|
|
21
|
+
功能2: 登录页面, figma设计稿: https://figma.com/design/xxx?node-id=3-4
|
|
22
|
+
功能3: 用户登录 API 对接
|
|
23
|
+
功能4: 全局状态管理
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
解析每条功能,提取:
|
|
27
|
+
- `name`: 功能名称
|
|
28
|
+
- `figmaUrl`: Figma URL(可能没有)
|
|
29
|
+
- `figmaFileKey`: 从 URL 提取
|
|
30
|
+
- `figmaNodeId`: 从 URL 提取(将 `-` 转为 `:`)
|
|
31
|
+
|
|
32
|
+
有 Figma URL 的 → 设计任务(视觉验证)
|
|
33
|
+
无 Figma URL 的 → 逻辑任务(代码审查)
|
|
34
|
+
|
|
35
|
+
### Step 3: 智能分析和优化
|
|
36
|
+
|
|
37
|
+
#### 3a+3b. 并行分析(设计截图 + 项目扫描)
|
|
38
|
+
|
|
39
|
+
3a(获取设计截图)和 3b(扫描现有项目)之间没有数据依赖,**必须使用 Agent 工具并行执行**。
|
|
40
|
+
|
|
41
|
+
在一条消息中同时发起两个 Agent 调用,等待两者都完成后再继续:
|
|
42
|
+
|
|
43
|
+
**Agent 1: 设计截图分析**
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
Agent(
|
|
47
|
+
subagent_type="general-purpose",
|
|
48
|
+
model="haiku",
|
|
49
|
+
description="获取 Figma 设计截图",
|
|
50
|
+
prompt="使用 @fe-harness/agents/fe-design-scanner.md 中的流程。
|
|
51
|
+
|
|
52
|
+
设计任务列表:
|
|
53
|
+
${DESIGN_TASKS_JSON}"
|
|
54
|
+
)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Agent 2: 项目扫描**
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
Agent(
|
|
61
|
+
subagent_type="general-purpose",
|
|
62
|
+
model="haiku",
|
|
63
|
+
description="扫描现有项目结构",
|
|
64
|
+
prompt="使用 @fe-harness/agents/fe-project-scanner.md 中的流程。"
|
|
65
|
+
)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
两个 Agent 都完成后,读取 `.fe-runtime/context/design-analysis.json` 和 `.fe-runtime/context/project-scan.json`,作为后续步骤的输入。
|
|
69
|
+
|
|
70
|
+
#### 3c. 灰色地带讨论
|
|
71
|
+
|
|
72
|
+
基于设计截图分析(design-analysis.json)和项目上下文(project-scan.json),识别设计稿中未明确表达的实现决策点。
|
|
73
|
+
|
|
74
|
+
**识别维度:**
|
|
75
|
+
- **交互行为**: 点击、悬停、动画、过渡效果等设计稿无法表达的行为
|
|
76
|
+
- **响应式策略**: 不同屏幕尺寸下的布局变化、折叠/隐藏规则
|
|
77
|
+
- **边界情况**: 空状态、加载状态、错误状态、超长文本、极端数据
|
|
78
|
+
- **业务逻辑**: 表单验证规则、权限控制、数据流向
|
|
79
|
+
- **组件复用**: 是否拆为公共组件、组件 API 设计倾向
|
|
80
|
+
|
|
81
|
+
**执行方式:**
|
|
82
|
+
1. 逐个任务审视设计截图,列出不确定的灰色地带
|
|
83
|
+
2. 将所有灰色地带合并去重,按优先级排序
|
|
84
|
+
3. 用 `AskUserQuestion` 逐个或分组提问(每个问题提供 2-4 个选项 + 推荐项)
|
|
85
|
+
4. 如果用户回复"跳过"或"都行",使用推荐默认值
|
|
86
|
+
5. 将所有决策记录到内存中,传递给下一步优化(最终写入各任务的 `techNotes` 字段)
|
|
87
|
+
|
|
88
|
+
**控制节奏:**
|
|
89
|
+
- 聚焦于真正影响实现方向的决策,避免问琐碎细节(如颜色、字号等设计稿已明确的内容)
|
|
90
|
+
- 每轮可利用 `AskUserQuestion` 的多问题能力(最多 4 个问题/轮)批量提问
|
|
91
|
+
- 讨论持续到所有重要灰色地带都有明确决策为止,不设硬性轮次上限
|
|
92
|
+
- 如果用户回复"够了"或"剩下的你决定",立即结束讨论,未决项使用推荐默认值
|
|
93
|
+
|
|
94
|
+
#### 3c+. 反问确认
|
|
95
|
+
|
|
96
|
+
灰色地带讨论结束后,主动反问用户是否还有补充:
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
AskUserQuestion(
|
|
100
|
+
question: "在我开始生成最终任务列表之前,你还有什么需要和我讨论的吗?",
|
|
101
|
+
header: "补充讨论",
|
|
102
|
+
options: [
|
|
103
|
+
{ label: "没有,继续", description: "所有需要讨论的内容已经覆盖,直接进入任务优化阶段" }
|
|
104
|
+
]
|
|
105
|
+
)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
- 用户选择「没有,继续」→ 直接进入 3d
|
|
109
|
+
- 用户选择「Other」并输入补充内容 → 针对补充内容继续讨论,讨论完毕后再次反问,直到用户选择「没有,继续」
|
|
110
|
+
|
|
111
|
+
#### 3d. AI 驱动优化(6 个维度)
|
|
112
|
+
|
|
113
|
+
基于用户输入、设计截图、项目上下文,以及**灰色地带讨论中的决策结果**,进行智能优化:
|
|
114
|
+
|
|
115
|
+
1. **名称优化**: 使名称更精确、可操作
|
|
116
|
+
2. **描述充实**: 为每个任务生成三个维度的描述:
|
|
117
|
+
- `description`: 功能描述(做什么)
|
|
118
|
+
- `acceptanceCriteria`: 验收条件数组(怎么算做好了,verifier/reviewer 的判定标准)
|
|
119
|
+
- `techNotes`: 实现提示(怎么做:复用哪些现有组件、灰色地带讨论决策、技术方案等)
|
|
120
|
+
3. **粒度拆分**: 过大的任务拆分为更小的子任务
|
|
121
|
+
4. **粒度合并**: 过于琐碎的相关任务合并
|
|
122
|
+
5. **缺口识别**: 发现遗漏的任务(例如需要但未列出的公共组件、API 对接等)
|
|
123
|
+
6. **路由推断**: 根据项目路由方案(project-scan.json)和功能描述,为每个任务推断 `route`(dev server 中的可访问路径)
|
|
124
|
+
7. **文件所有权声明**: 为每个任务声明 `filesModified`(预计修改的文件路径列表)
|
|
125
|
+
|
|
126
|
+
**文件所有权规则(用于并行执行冲突检测):**
|
|
127
|
+
- 每个任务必须声明 `filesModified` 字段,列出预计创建或修改的文件
|
|
128
|
+
- 同一 Wave 内的任务,`filesModified` 不允许有交集(否则并行 worktree 合并会冲突)
|
|
129
|
+
- 如果检测到同 wave 内文件冲突,有两种处理方式:
|
|
130
|
+
1. 将冲突任务加入 `dependsOn`,使其分到不同 wave(串行执行)
|
|
131
|
+
2. 将冲突任务合并为一个任务
|
|
132
|
+
- 文件路径粒度:使用文件级,不使用目录级(如 `src/components/Avatar.tsx` 而非 `src/components/`)
|
|
133
|
+
- 公共文件(如 `src/App.tsx`, `src/router.ts`, `package.json`):多个任务可能都需要修改的公共文件,应通过 `dependsOn` 确保这些任务分到不同 wave
|
|
134
|
+
|
|
135
|
+
#### 3e. 展示优化后的任务列表
|
|
136
|
+
以表格形式展示优化后的任务列表,自动继续(不需要用户确认)。
|
|
137
|
+
|
|
138
|
+
### Step 4: 确认配置完整
|
|
139
|
+
|
|
140
|
+
读取 `.fe/config.jsonc`,**仅当存在设计任务时**检查 `devServerCommand` 是否已填写。
|
|
141
|
+
- 有设计任务(含 figmaUrl 的任务)且未配置 → 提示用户先编辑 `.fe/config.jsonc` 配置开发服务器启动命令
|
|
142
|
+
- 全部都是逻辑任务 → 跳过此检查,不需要开发服务器
|
|
143
|
+
|
|
144
|
+
### Step 5: 创建任务文件
|
|
145
|
+
|
|
146
|
+
写入 `.fe-runtime/tasks.json`,每个任务的 schema:
|
|
147
|
+
```json
|
|
148
|
+
{
|
|
149
|
+
"id": 1,
|
|
150
|
+
"name": "功能名称",
|
|
151
|
+
"description": "功能描述(做什么)",
|
|
152
|
+
"acceptanceCriteria": ["验收条件1", "验收条件2"],
|
|
153
|
+
"techNotes": "实现提示(复用哪些组件、灰色地带决策、技术方案等)",
|
|
154
|
+
"route": "/page-path",
|
|
155
|
+
"figmaUrl": "https://...",
|
|
156
|
+
"figmaFileKey": "xxx",
|
|
157
|
+
"figmaNodeId": "1:2",
|
|
158
|
+
"dependsOn": [],
|
|
159
|
+
"filesModified": ["src/components/Avatar.tsx", "src/components/Avatar.css"],
|
|
160
|
+
"status": "pending",
|
|
161
|
+
"verifyPassed": false,
|
|
162
|
+
"retryCount": 0,
|
|
163
|
+
"bestScore": 0,
|
|
164
|
+
"bestScoresJSON": null,
|
|
165
|
+
"lastError": "",
|
|
166
|
+
"completedAt": ""
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**`route` 字段说明:**
|
|
171
|
+
- 填写该功能实现后在 dev server 中可访问的页面路径(如 `"/login"`, `"/settings/profile"`)
|
|
172
|
+
- 如果是全局组件/工具函数(不对应特定页面),填 `"/"`
|
|
173
|
+
- executor 自检、verifier 验证、fixer 自检都依赖此字段导航到正确页面
|
|
174
|
+
|
|
175
|
+
依赖关系和文件所有权规则:
|
|
176
|
+
- `dependsOn` 通过分析任务间的逻辑关系自动生成
|
|
177
|
+
- `filesModified` 通过分析设计稿和项目结构推断
|
|
178
|
+
- 同一 wave 内任务的 `filesModified` 不允许交集
|
|
179
|
+
|
|
180
|
+
### Step 5b: Wave 分组与冲突检测
|
|
181
|
+
|
|
182
|
+
任务写入后,调用 fe-tools 验证 wave 分组:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
WAVES=$(node ~/.claude/fe-harness/bin/fe-tools.cjs tasks waves)
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**Wave 分组基于 `dependsOn` 自动计算(拓扑排序):**
|
|
189
|
+
- Wave 1: 无依赖的任务(可并行执行)
|
|
190
|
+
- Wave 2: 仅依赖 Wave 1 的任务(可并行执行)
|
|
191
|
+
- Wave N: 依赖 Wave N-1 的任务
|
|
192
|
+
|
|
193
|
+
**文件冲突检测:**
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
CONFLICTS=$(node ~/.claude/fe-harness/bin/fe-tools.cjs tasks check-conflicts)
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
如果检测到同 wave 内文件冲突:
|
|
200
|
+
1. 输出冲突详情:哪些任务、哪些文件有冲突
|
|
201
|
+
2. 自动将冲突任务添加 `dependsOn` 关系,使其分到不同 wave
|
|
202
|
+
3. 重新计算 wave 分组
|
|
203
|
+
|
|
204
|
+
**展示格式:**
|
|
205
|
+
```
|
|
206
|
+
## Wave 执行计划
|
|
207
|
+
|
|
208
|
+
| Wave | 任务 | 类型 | 并行 |
|
|
209
|
+
|------|------|------|------|
|
|
210
|
+
| 1 | #1 用户头像组件, #2 登录表单 | design, design | ✓ |
|
|
211
|
+
| 2 | #3 API 对接 | logic | - |
|
|
212
|
+
|
|
213
|
+
文件所有权:
|
|
214
|
+
- #1: src/components/Avatar.tsx, src/components/Avatar.css
|
|
215
|
+
- #2: src/components/LoginForm.tsx, src/components/LoginForm.css
|
|
216
|
+
- #3: src/api/auth.ts, src/components/LoginForm.tsx (→ 依赖 #2)
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
如果所有任务都在同一个 wave(无依赖关系且无文件冲突),提示用户:"所有任务无依赖关系,将在 Wave 1 中并行执行。"
|
|
220
|
+
|
|
221
|
+
### Step 6: 创建进度文件
|
|
222
|
+
|
|
223
|
+
写入 `.fe-runtime/progress.md`:
|
|
224
|
+
```markdown
|
|
225
|
+
# Figma Implementation Progress
|
|
226
|
+
|
|
227
|
+
## 项目信息
|
|
228
|
+
- 创建时间: {timestamp}
|
|
229
|
+
- 任务总数: {count}
|
|
230
|
+
- 设计任务: {design_count}
|
|
231
|
+
- 逻辑任务: {logic_count}
|
|
232
|
+
|
|
233
|
+
## 执行日志
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Step 7: 完成
|
|
237
|
+
|
|
238
|
+
输出规划完成信息和 wave 执行计划,提示用户先清除上下文再开始执行。
|
|
239
|
+
|
|
240
|
+
提示信息应包含:
|
|
241
|
+
- 任务总数和 wave 数
|
|
242
|
+
- 每个 wave 的任务数和并行执行能力
|
|
243
|
+
- 预期的执行流程:"Wave 1 (3个任务并行) → Wave 2 (2个任务并行) → ..."
|
|
244
|
+
- 提示用户:「规划已完成并写入 `.fe/` 目录。建议先执行 `/clear` 清除上下文,再使用 `/fe:execute` 开始执行,以获得更充裕的上下文空间。」
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fe-harness",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Figma design-to-code harness for Claude Code. Subagent-driven implementation, visual verification, and iterative fixing.",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "node scripts/bundle-puppeteer.js",
|
|
7
|
+
"test": "node --test fe-harness/bin/lib/__tests__/*.test.cjs"
|
|
8
|
+
},
|
|
9
|
+
"bin": {
|
|
10
|
+
"fe-harness": "bin/install.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"bin",
|
|
14
|
+
"commands",
|
|
15
|
+
"agents",
|
|
16
|
+
"fe-harness",
|
|
17
|
+
"scripts"
|
|
18
|
+
],
|
|
19
|
+
"keywords": [
|
|
20
|
+
"claude",
|
|
21
|
+
"claude-code",
|
|
22
|
+
"figma",
|
|
23
|
+
"design-to-code",
|
|
24
|
+
"visual-verification",
|
|
25
|
+
"subagent"
|
|
26
|
+
],
|
|
27
|
+
"author": "qidian",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"puppeteer-core": "^24.0.0"
|
|
31
|
+
},
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=18.0.0"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 将 puppeteer-core 打包为单文件 vendor/puppeteer-core.cjs
|
|
6
|
+
* 发布前运行: npm run build
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const { execSync } = require('child_process');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
|
|
13
|
+
const ROOT = path.resolve(__dirname, '..');
|
|
14
|
+
const ENTRY = path.join(ROOT, 'scripts', '_puppeteer-entry.cjs');
|
|
15
|
+
const OUT = path.join(ROOT, 'fe-harness', 'vendor', 'puppeteer-core.cjs');
|
|
16
|
+
|
|
17
|
+
// 创建临时入口:re-export puppeteer-core
|
|
18
|
+
fs.writeFileSync(ENTRY, `module.exports = require('puppeteer-core');\n`);
|
|
19
|
+
|
|
20
|
+
const externals = [
|
|
21
|
+
'fs', 'path', 'child_process', 'os', 'net', 'http', 'https',
|
|
22
|
+
'tls', 'crypto', 'stream', 'url', 'zlib', 'events', 'util',
|
|
23
|
+
'buffer', 'querystring', 'string_decoder', 'assert', 'dns',
|
|
24
|
+
'readline', 'worker_threads', 'perf_hooks', 'async_hooks',
|
|
25
|
+
].map(m => `--external:${m}`).join(' ');
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
execSync(
|
|
29
|
+
`npx esbuild "${ENTRY}" --bundle --platform=node --target=node18 --format=cjs --outfile="${OUT}" --minify ${externals}`,
|
|
30
|
+
{ cwd: ROOT, stdio: 'inherit' }
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const size = (fs.statSync(OUT).size / 1024 / 1024).toFixed(1);
|
|
34
|
+
console.log(`\n✓ puppeteer-core bundled → fe-harness/vendor/puppeteer-core.cjs (${size} MB)\n`);
|
|
35
|
+
} finally {
|
|
36
|
+
// 清理临时入口
|
|
37
|
+
try { fs.unlinkSync(ENTRY); } catch (_) {}
|
|
38
|
+
}
|