figma-cache-toolchain 1.4.0 → 1.4.2
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 +63 -24
- package/cursor-bootstrap/AGENT-SETUP-PROMPT.md +16 -2
- package/cursor-bootstrap/rules/01-figma-cache-core.mdc +23 -3
- package/cursor-bootstrap/rules/02-figma-stack-adapter.mdc +9 -0
- package/cursor-bootstrap/skills/figma-mcp-local-cache/SKILL.md +40 -7
- package/figma-cache/README.md +13 -1
- package/figma-cache/colleague-guide-zh.md +26 -240
- package/figma-cache/figma-cache.js +139 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,59 +1,98 @@
|
|
|
1
|
-
# figma-cache-toolchain
|
|
1
|
+
# figma-cache-toolchain
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
闈㈠悜**涓氬姟椤圭洰**鐨?Figma 鏈湴缂撳瓨锛氶摼鎺ユ爣鍑嗗寲銆侀」鐩唴 **`figma-cache/`** 绱㈠紩涓庢牎楠屻€侀浂渚濊禆 Node CLI銆?*涓嶇粦瀹?*鍏蜂綋 UI 妗嗘灦锛涙爤鐩稿叧鐢?Cursor Agent 鎸?**`@AGENT-SETUP-PROMPT.md`** 鐢熸垚 **`figma-cache.config.js`** 涓?**`.cursor/rules/02-figma-<鏍?-adapter.mdc`**銆?
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## 鍥㈤槦璇存槑涓庢彁绀鸿瘝锛堢粰鍚屼簨锛?
|
|
6
6
|
|
|
7
|
-
**`figma-cache/colleague-guide-zh.md
|
|
7
|
+
**`figma-cache/colleague-guide-zh.md`**锛氫娇鐢ㄥ満鏅€佸崟鏉?澶氭潯閾炬帴銆佹笎杩涘紡鍏宠仈鐨?**Cursor 鎻愮ず璇嶆ā鏉?*銆佸崌绾ц鏄庣瓑銆?
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
姣忔墽琛屼竴娆?**`npx figma-cache cursor init`**锛屼細鎶婂寘鍐呮渶鏂扮増**鍚屾鍐欏叆**椤圭洰涓嬬殑 **`figma-cache/colleague-guide-zh.md`**锛堢洰褰曠敱 **`FIGMA_CACHE_DIR`** 鍐冲畾锛岄粯璁?`figma-cache/`锛夛紝**鏃犻渶**浠?`node_modules` 鎵嬫妱锛涗笌鍚屼簨鐩存帴鐪嬩粨搴撻噷璇ユ枃浠跺嵆鍙€?
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## 鍥涙鎺ュ叆锛堝潎鍦ㄤ笟鍔¢」鐩牴鐩綍锛?
|
|
14
14
|
|
|
15
|
-
### 1.
|
|
15
|
+
### 1. 瀹夎
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
18
|
npm i -D figma-cache-toolchain
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
### 2.
|
|
21
|
+
### 2. 鍒濆鍖?Cursor 涓庝换鍔′功锛堝苟鍚屾鍥㈤槦璇存槑锛?
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
24
|
npx figma-cache cursor init
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
27
|
+
- 鍐欏叆鎴栬烦杩囷紙宸插瓨鍦ㄤ笖鏈?`--force`锛夛細`.cursor/rules/`銆乣.cursor/skills/`銆乣figma-cache.config.example.js`銆?
|
|
28
|
+
- **姣忔**鍒锋柊锛?*`AGENT-SETUP-PROMPT.md`**锛堥」鐩牴锛夈€?*`figma-cache/colleague-guide-zh.md`**锛堢紦瀛樼洰褰曚笅锛夈€?
|
|
29
|
+
- 缁堢浼氭彁绀猴細鍏?**`@AGENT-SETUP-PROMPT.md`** 浜ょ粰 Agent锛?*Agent 瀹屾垚鍚庡啀**鍋氱 4 姝ャ€?
|
|
30
30
|
|
|
31
|
-
### 3.
|
|
31
|
+
### 3. 浜ょ粰 Cursor Agent
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
鍦ㄥ璇濅腑 **`@AGENT-SETUP-PROMPT.md`**锛岃鏄庛€屾寜璇ユ枃妗f墽琛屻€嶃€侫gent 浼氭帹鏂爤銆佺敓鎴?鍚堝苟閰嶇疆涓?Adapter銆佽ˉ鍏?**`figma:cache:*`** scripts 绛夈€?
|
|
34
34
|
|
|
35
|
-
### 4.
|
|
35
|
+
### 4. 鍒濆鍖栨湰鍦扮储寮曪紙涓?`cursor init` 涓嶅悓锛?
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
鍒涘缓 **`figma-cache/index.json`**锛堢┖绱㈠紩锛夌瓑锛屼緵鍚庣画 `ensure` / `get` 鍐欏叆鑺傜偣锛?
|
|
38
38
|
|
|
39
39
|
```bash
|
|
40
40
|
npm run figma:cache:init
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
鑻ユ棤瀵瑰簲 script锛歚npx figma-cache init`銆傜劧鍚庡彲鎸夐渶 **`npm run figma:cache:validate`**銆?
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
**璇存槑**锛氬彂甯冪殑 npm 鍖?*涓嶅惈**浣犱笟鍔′粨搴撻噷鐨?**`figma-cache/files/`** 涓?**`index.json`**锛涙暟鎹敱涓婅堪 init 涓庡悗缁懡浠ゅ湪鏈湴鐢熸垚銆?
|
|
46
46
|
|
|
47
47
|
---
|
|
48
48
|
|
|
49
|
-
##
|
|
49
|
+
## 鍗囩骇 npm 鍖呭悗鎺ㄨ崘娴佺▼锛堜笟鍔¢」鐩級
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
宸插湪鐢ㄦ湰鍖呮椂锛?*姣忓崌涓€娆$増鏈?*寤鸿鍦ㄤ笟鍔′粨搴撴牴鎸変笅闈㈠仛涓€閬嶏紝閬垮厤妯℃澘涓庨厤缃暱鏈熻惤鍚庛€?
|
|
52
|
+
|
|
53
|
+
### 1. 鍗囩骇渚濊禆
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npm i -D figma-cache-toolchain@latest
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
锛堟垨閿佸畾鍏蜂綋鐗堟湰鍙枫€傦級
|
|
60
|
+
|
|
61
|
+
### 2. 鍒锋柊 Cursor 妯℃澘涓庤鏄庢枃浠?
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
npx figma-cache cursor init
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
- 浼氬埛鏂伴」鐩牴 **`AGENT-SETUP-PROMPT.md`**銆?*`FIGMA_CACHE_DIR/colleague-guide-zh.md`**锛屽苟鏇存柊锛堟垨璺宠繃锛?*`.cursor/`** 涓庢牴鐩綍 **`figma-cache.config.example.js`**銆?
|
|
68
|
+
- 鑻ラ渶**寮哄埗瑕嗙洊**宸插瓨鍦ㄧ殑 `.cursor` 妯℃澘锛屼娇鐢?**`npx figma-cache cursor init --force`**锛堜細瑕嗙洊宸叉湁瑙勫垯鏂囦欢锛屾厧鐢級銆?
|
|
69
|
+
|
|
70
|
+
### 3. 瀵归綈 `figma-cache.config.js`锛堝悆杩涙柊鑳藉姏锛?
|
|
71
|
+
|
|
72
|
+
- **鑻ユ寮忛厤缃槸 `require` 鍖呭唴绀轰緥**锛氫竴鑸?*涓嶅繀鏀规枃浠?*锛屽崌绾у悗閲嶆柊 `require` 鍗冲姞杞芥柊閫昏緫銆?
|
|
73
|
+
- **鑻ユ寮忛厤缃槸褰撳垵澶嶅埗/鑷啓鐨?*锛氭牴鐩綍鐨?**`figma-cache.config.example.js`** 宸叉槸**鏈€鏂板鐓?*锛岃**鍚堝苟**杩?**`figma-cache.config.js`**锛堜緥濡?1.4+ 鐨?**`docs/figma-flow-readme.md`**銆乣postEnsure` 鐨?**`ctx`** 鎵╁睍绛夛級锛?*鍕挎暣鏂囦欢瑕嗙洊**瀵艰嚧涓㈠け鑷畾涔夐挬瀛愩€?
|
|
74
|
+
- 鍙湪 Cursor 閲?**`@figma-cache.config.example.js`** + **`@figma-cache.config.js`** + **`@AGENT-SETUP-PROMPT.md`**锛岃 Agent銆屾寜浠诲姟涔︽鏌ヨˉ缂?+ 鍚堝苟绀轰緥鏂板閮ㄥ垎銆嶏紱澶ф壒閲忛摼鎺ヤ笌涓氬姟娴佺▼鏂囨。鍐欐硶瑙?**`figma-cache/colleague-guide-zh.md` 搂5.9锝灺?.10**銆?
|
|
75
|
+
|
|
76
|
+
### 4. 绱㈠紩涓庢牎楠?
|
|
77
|
+
|
|
78
|
+
- **宸叉湁** **`figma-cache/index.json`**锛氶€氬父**涓嶅繀**鍐嶈窇 **`figma:cache:init`**銆?
|
|
79
|
+
- 鎵ц **`npm run figma:cache:validate`**锛堟垨 **`npx figma-cache validate`**锛夈€?
|
|
80
|
+
- 闃呰 **`CHANGELOG.md`**锛坣pm 鍖呭唴鎴?GitHub锛変簡瑙g牬鍧忔€у彉鏇达紙鑻ユ湁锛夈€?
|
|
81
|
+
|
|
82
|
+
### 5. 鎻愪氦涓庡崗浣?
|
|
83
|
+
|
|
84
|
+
灏嗘湰娆″崌绾ф秹鍙婄殑 **`package.json` / lock**銆佽嫢鍚堝苟杩囧垯 **`figma-cache.config.js`**銆佷互鍙婂埛鏂板悗鐨?**`AGENT-SETUP-PROMPT.md` / `.cursor/` / `figma-cache/colleague-guide-zh.md`** 绛夋寜鍥㈤槦瑙勮寖鎻愪氦锛?*`figma-cache/files/`** 鏄惁鍏ュ簱浠嶆寜鍘熷洟闃熺害瀹氥€?
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## 鏇村畬鏁寸殑璇存槑鍦ㄥ摢
|
|
89
|
+
|
|
90
|
+
| 闇€姹?| 鏂囨。锛堥殢鍖呭湪 `node_modules/figma-cache-toolchain/figma-cache/`锛?|
|
|
52
91
|
|------|------------------------------------------------------------------|
|
|
53
|
-
| scripts
|
|
54
|
-
|
|
|
55
|
-
| Flow
|
|
92
|
+
| scripts 鍏ㄩ噺 JSON銆佺幆澧冨彉閲忋€佹棤 npm 澶嶅埗鎺ュ叆銆佸洖濉€佺淮鎶ゅ彂鐗?| 鍖呭唴 **`figma-cache/README.md`** |
|
|
93
|
+
| 閾炬帴閿鍒?| **`link-normalization-spec.md`** |
|
|
94
|
+
| Flow 杈圭被鍨?| **`flow-edge-taxonomy.md`** |
|
|
56
95
|
|
|
57
|
-
npm
|
|
96
|
+
npm 鍖呴椤靛嵆鏈枃浠讹紱**缁存姢鑰呭彂鐗堟祦绋?*鍐欏湪 **`figma-cache/README.md`** 鏂囨湯銆屽寘缁存姢鑰呫€嶄笌浠撳簱 **`CHANGELOG.md`**銆?
|
|
58
97
|
|
|
59
|
-
|
|
98
|
+
甯哥敤鐜鍙橀噺鑺傞€夛細`FIGMA_CACHE_DIR`銆乣FIGMA_CACHE_INDEX_FILE`銆乣FIGMA_ITERATIONS_DIR`銆乣FIGMA_CACHE_STALE_DAYS`銆乣FIGMA_DEFAULT_FLOW`銆乣FIGMA_CACHE_PROJECT_CONFIG`銆乣FIGMA_CACHE_FLOW_README`锛堢ず渚嬮挬瀛愬啓銆屾祦绋嬫€昏銆峬d 鐨勮矾寰勶級鈥?閲婁箟涓庡畬鏁磋〃瑙?**`figma-cache/README.md`**銆?
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Figma Cache:请 Agent 一次性完成项目适配
|
|
1
|
+
# Figma Cache:请 Agent 一次性完成项目适配
|
|
2
2
|
|
|
3
3
|
> **给 Cursor Agent 的指令**:你正在操作的是**用户业务项目**的根目录。以下文件应已存在(由 `npx figma-cache cursor init` 从 npm 包 **`{{NPM_PACKAGE_NAME}}`** 复制到当前仓库根):
|
|
4
4
|
> - `.cursor/rules/01-figma-cache-core.mdc`
|
|
@@ -30,7 +30,20 @@
|
|
|
30
30
|
- 若项目根**尚无** `figma-cache/index.json`,提示用户执行:`npm run figma:cache:init`(若已加 script)或 `npx figma-cache init`(与 `cursor init` 不同,用于创建空索引与缓存目录)。
|
|
31
31
|
- 提示用户在本项目根执行:`npm run figma:cache:validate`(若已加 script)或 `npx figma-cache validate`。
|
|
32
32
|
- 说明:后续 Figma 相关对话将主要由 **01 Core + 新 Adapter + Skill** 驱动。
|
|
33
|
-
|
|
33
|
+
- **可选**:若项目已通过 `cursor init` 同步 `figma-cache/colleague-guide-zh.md`,提示团队默认只使用 **§5.1「最推荐主提示词」**,只有特殊诉求再追加 **§5.2** 的一句附加要求。
|
|
34
|
+
- 若用户希望你直接给可复制文本,可贴这段(与 `colleague-guide-zh.md` §5.1 保持一致):
|
|
35
|
+
|
|
36
|
+
```text
|
|
37
|
+
请按项目 figma 缓存规则处理下面这条 Figma 链接,并遵循“缓存优先 + 按需 MCP + 最小调用集”:
|
|
38
|
+
1) 先查本地 figma-cache,命中则直接复用,不做刷新;
|
|
39
|
+
2) 仅在未命中或我明确要求刷新时,才调用 figma-mcp 拉取并写入 mcp-raw(随后再 ensure/upsert);
|
|
40
|
+
3) completeness 默认使用 layout,text,tokens(若我补充再扩展 interactions/flow/states/assets/accessibility);
|
|
41
|
+
4) 原始 MCP 数据统一保存到节点目录 mcp-raw/ 子目录;
|
|
42
|
+
5) 默认不保存 whoami 原始文件(仅鉴权排障或我明确要求时保存);
|
|
43
|
+
6) 完成后执行 figma:cache:validate,并汇报:缓存状态、实际 MCP 调用次数、输出文件清单。
|
|
44
|
+
|
|
45
|
+
[Figma 链接]
|
|
46
|
+
```
|
|
34
47
|
|
|
35
48
|
## 硬约束(违反则视为未完成)
|
|
36
49
|
|
|
@@ -47,3 +60,4 @@
|
|
|
47
60
|
---
|
|
48
61
|
|
|
49
62
|
**开始执行:**读完本文件后立刻按上述顺序操作仓库文件,直至全部完成。
|
|
63
|
+
|
|
@@ -10,6 +10,7 @@ alwaysApply: true
|
|
|
10
10
|
## 目标
|
|
11
11
|
- 对用户提供的 Figma 链接,优先复用项目内已落地的结构化文档(`meta.json`、`spec.md`、`raw.json`、`state-map.md` 等)。
|
|
12
12
|
- 仅在本地信息不足以完成任务时调用 Figma MCP。
|
|
13
|
+
- 默认采用 MCP 最小调用集,并按 `completeness` 精确裁剪调用:优先在满足字段目标前提下最少调用工具。
|
|
13
14
|
- 项目级扩展通过仓库根目录的 `figma-cache.config.js` / `.figmacacherc.js` 的 `hooks.postEnsure` 完成;Core 脚本不包含任何具体 UI 框架名。
|
|
14
15
|
|
|
15
16
|
<Trigger Conditions>
|
|
@@ -31,9 +32,22 @@ alwaysApply: true
|
|
|
31
32
|
2. 读本地 `index.json` 判断是否命中。
|
|
32
33
|
3. 命中且字段满足任务 → 只读本地,不调 MCP。
|
|
33
34
|
4. 未命中或不足 → MCP 拉取并回写通用缓存文件。
|
|
34
|
-
5.
|
|
35
|
-
6.
|
|
36
|
-
7.
|
|
35
|
+
5. **`ensure` 语义边界(强制)**:`figma:cache:ensure` 仅负责索引与骨架文件,不视为 MCP 拉取动作;不得把“执行 ensure”当作“已完成 MCP 调用”。
|
|
36
|
+
6. **MCP 最小调用集(默认)**:以单个 `fileKey + nodeId` 为粒度,默认只调用 `get_design_context`(建议 `excludeScreenshot=true`)、`get_metadata`、`get_variable_defs`;禁止同参数重复调用同一工具。
|
|
37
|
+
7. **按需调用策略**:`get_screenshot` 仅在用户显式要求可视留档/截图回包,或上述三项仍不足以消除结构歧义时调用;`whoami` 仅在鉴权/权限报错时调用,不作为常规流程步骤。
|
|
38
|
+
8. **按 completeness 的调用矩阵(强制)**:
|
|
39
|
+
- `layout` → `get_metadata`(若结构层级不足,再补 `get_design_context`)
|
|
40
|
+
- `text` → `get_design_context`
|
|
41
|
+
- `tokens` → `get_variable_defs`
|
|
42
|
+
- `interactions` / `flow` / `states` → `get_design_context` + `state-map.md`/`flows` 回写
|
|
43
|
+
- `accessibility`(若任务声明)→ 优先 `get_design_context` 的语义线索,不足时标注缺口
|
|
44
|
+
- `assets`(若任务声明)→ `get_design_context` 中资产 URL;仅当用户要求截图留档再调 `get_screenshot`
|
|
45
|
+
9. **两阶段拉取**:先按最小必要工具取数并检查字段缺口;仅在缺口存在时进入第二阶段补调工具。
|
|
46
|
+
10. **写入一致性门禁(强制)**:当 `source=figma-mcp` 或输出来源标注 MCP 时,节点目录必须存在 `mcp-raw/` 与对应原始文件;若缺失则视为未完成,必须停止并报告,不得宣称“更新成功”。
|
|
47
|
+
11. **大文件读取策略(强制)**:仅在 UI 还原/像素对齐/组件实现任务中读取 `mcp-raw-get-design-context.txt` 全文;非 UI 任务(命中检查、预算统计、校验、流程维护)默认仅读取 `raw.json` / `spec.md` / `mcp-raw-manifest.json`。
|
|
48
|
+
12. **闭环校验(强制)**:每次 **`npm run figma:cache:upsert`** 或 **`npm run figma:cache:ensure`** 成功结束后,**自动静默**执行 `npm run figma:cache:validate`。
|
|
49
|
+
13. validate 失败 → **自行修复并重复 validate 直至通过**,不得宣称缓存已就绪。
|
|
50
|
+
14. **不写前端**:本阶段禁止输出业务组件实现;若用户要求写 UI,在缓存就绪后转由 **栈专属 Adapter 规则**(如 `02-figma-stack-adapter.mdc` 占位,或项目内 `02-figma-<栈>-adapter.mdc`)接管。
|
|
37
51
|
|
|
38
52
|
## Agent 最终输出格式(强制)
|
|
39
53
|
凡触发 `<Trigger Conditions>` 且本轮涉及缓存读写的回复,**正文第一段**必须为单行 Blockquote:
|
|
@@ -45,7 +59,13 @@ alwaysApply: true
|
|
|
45
59
|
## 配置与钩子
|
|
46
60
|
- `npm run figma:cache:config` 可查看是否加载 `hooks.postEnsure`。
|
|
47
61
|
- `ensure` 在写入通用骨架后会调用 `hooks.postEnsure`;钩子异常**不得**阻断 ensure 成功退出(由 Core 捕获)。
|
|
62
|
+
- `ensure` 不是 MCP 拉取入口;若命令声明 `source=figma-mcp`,应先完成 MCP 工具调用并落盘 `mcp-raw/`,再进行 upsert/ensure。
|
|
48
63
|
|
|
49
64
|
## 其余约定
|
|
50
65
|
- 缓存目录、环境变量、`flows`、陈旧策略、提交前校验等与原「Local Cache First」一致,参见 `figma-cache/` 内文档及 `npm run figma:cache:*`。
|
|
66
|
+
- 对同一节点写缓存时,优先复用本轮已拿到的 MCP 响应做落盘,避免“仅为生成原始文件而重复调同一工具”。
|
|
67
|
+
- 若保存原始数据,统一写入节点目录下 `mcp-raw/` 子目录(如 `mcp-raw/mcp-raw-get-design-context.txt`),与加工缓存文件分层。
|
|
68
|
+
- 默认不写 `whoami` 原始文件;仅在鉴权排障或用户显式要求账号态审计时才写入。
|
|
69
|
+
- 单节点 MCP 调用预算默认不超过 3 次;超过时必须在输出中说明缺口字段与补调原因。
|
|
70
|
+
- 仅对超时/5xx做指数退避重试;对参数错误/权限错误不重试,直接报告并等待用户指令。
|
|
51
71
|
- 不在未校验时假定 Figma 为最新;用户显式要求实时读取时须遵守。
|
|
@@ -18,6 +18,15 @@ alwaysApply: false
|
|
|
18
18
|
- **单一事实来源**:实现 UI 时只从 `raw.json`、`spec.md`、`state-map.md`、`meta.json` 取数;不在这些通用文件里写入框架专有代码或路由名。
|
|
19
19
|
- **仅当任务包含「写/改业务 UI」且缓存可读**时,才应用具体栈的 Adapter;纯缓存维护、只跑 CLI,不触发表现层规则。
|
|
20
20
|
|
|
21
|
+
## React 直复用(选用规则)
|
|
22
|
+
|
|
23
|
+
仅当 Agent 识别目标项目为 **React 栈**(如 React + Tailwind / React + CSS Modules / React + styled-system)时启用:
|
|
24
|
+
|
|
25
|
+
- 优先复用节点目录下 `mcp-raw-get-design-context.txt` 的 React 参考代码作为起稿。
|
|
26
|
+
- 在此基础上仅做必要微调:项目 token 映射、组件替换、状态/交互逻辑、数据绑定、可访问性与响应式。
|
|
27
|
+
- 若项目非 React 栈,禁止直接复用该 React 代码,应按目标栈 Adapter 规则转换实现。
|
|
28
|
+
- 复用时优先保持结构与视觉一致性;改动应聚焦“接入项目规范”而非重写布局。
|
|
29
|
+
|
|
21
30
|
## 参考实现(非默认)
|
|
22
31
|
|
|
23
32
|
安装本包后,示例路径为 **`node_modules/figma-cache-toolchain/cursor-bootstrap/examples/vue2-vuetify2-adapter.reference.mdc`**(Vue 2 + Vuetify 2 全文参考),需时由 Agent 读入并改写为你的 `.cursor/rules/02-figma-...`。
|
|
@@ -56,10 +56,34 @@ description: 将 Figma 链接信息沉淀到项目本地缓存并执行缓存优
|
|
|
56
56
|
2. 读取 `index.json`:
|
|
57
57
|
- 若命中且字段满足当前任务,直接读取本地缓存并继续实现。
|
|
58
58
|
- 若未命中或信息不足,再调用 Figma MCP 拉取缺失数据。
|
|
59
|
-
3.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
3. 若需调用 MCP,默认按 **最小调用集**执行(同一 `fileKey + nodeId`):
|
|
60
|
+
- `get_design_context`(建议 `excludeScreenshot=true`)
|
|
61
|
+
- `get_metadata`
|
|
62
|
+
- `get_variable_defs`
|
|
63
|
+
4. **按需扩展调用**:
|
|
64
|
+
- `get_screenshot` 仅在用户明确要求截图原始留档,或前三项不足以消除结构歧义时调用。
|
|
65
|
+
- `whoami` 仅在鉴权/权限报错时调用;无报错时不调用。
|
|
66
|
+
5. **`get_design_context` 单轮硬约束**:同一 `fileKey + nodeId` 下,若已成功调用一次 `get_design_context`,除非参数发生变化(如 `forceCode`、`disableCodeConnect`、`excludeScreenshot`)或出现明确报错,否则禁止再次调用。
|
|
67
|
+
6. **按 completeness 的调用矩阵(强制)**:
|
|
68
|
+
- `layout` → `get_metadata`(若结构层级不足,再补 `get_design_context`)
|
|
69
|
+
- `text` → `get_design_context`
|
|
70
|
+
- `tokens` → `get_variable_defs`
|
|
71
|
+
- `interactions` / `flow` / `states` → `get_design_context`,并同步完善 `state-map.md` / `flows`
|
|
72
|
+
- `accessibility`(若任务声明)→ 优先 `get_design_context` 语义线索,不足需显式标注缺口
|
|
73
|
+
- `assets`(若任务声明)→ 使用 `get_design_context` 资产 URL;截图按需
|
|
74
|
+
7. **两阶段拉取**:先最小必要调用并检查字段缺口;仅在缺口存在时补调。
|
|
75
|
+
8. 同一参数的 MCP 工具在单轮内不得重复调用;若需落盘原始数据,必须优先复用首次响应。
|
|
76
|
+
9. **原始大文本直存策略**:当需保存 `mcp-raw-get-design-context.txt` 时,优先直接写入 `mcp-raw/` 子目录(不改写、不摘要、不二次解释),避免把整段文本再次喂给模型。
|
|
77
|
+
10. **本地分析优先**:若本地已存在可用 `mcp-raw-*` 与缓存加工文件,且用户未要求刷新/强制最新,后续分析默认只读本地文件,不再调用 Figma MCP。
|
|
78
|
+
11. 发生 MCP 拉取或本地补齐时,写入/更新 `meta.json`、`spec.md`、必要补充文件,并更新索引。
|
|
79
|
+
12. **`ensure` 语义边界(强制)**:`figma:cache:ensure` 仅补齐索引与骨架文件,不能替代 MCP 拉取;不得把“执行了 ensure”当成“完成了 figma-mcp 调用”。
|
|
80
|
+
13. **MCP 证据门禁(强制)**:当输出来源声明为 `figma-mcp` 时,节点目录必须存在 `mcp-raw/` 及最小调用集原始回包(按 completeness 裁剪);若缺失,立即停止并报告“未完成”,不得宣称更新成功。
|
|
81
|
+
14. **调用预算**:单节点默认 MCP 调用不超过 3 次;超过时必须在回复中说明缺口字段与补调理由。
|
|
82
|
+
15. **重试策略**:仅对超时/5xx进行指数退避重试;参数错误/权限错误不重试并直接报告。
|
|
83
|
+
16. **大文件读取策略(强制)**:仅在“UI 还原/像素对齐/组件实现”任务时读取 `mcp-raw-get-design-context.txt` 全文;非 UI 实现任务(如命中检查、预算统计、校验、流程维护)默认只读 `raw.json`/`spec.md`/`mcp-raw-manifest.json`,避免无意义 token 消耗。
|
|
84
|
+
17. **闭环校验(强制)**:凡本轮执行了 **`npm run figma:cache:upsert`** 或 **`npm run figma:cache:ensure`**(任意参数组合),在命令成功结束后,Agent **必须**在同一仓库根目录**自动、静默**执行 `npm run figma:cache:validate`。
|
|
85
|
+
18. **校验失败**:根据脚本输出修复索引、`paths`、缺失文件、JSON 结构等,**循环执行 validate 直至退出码为 0**;不得在 validate 未通过时结束本轮「写缓存」任务。
|
|
86
|
+
19. 对用户反馈时除 Blockquote 外可补充:`source: local-cache` / `source: figma-mcp` 与简要文件列表(不必粘贴完整终端日志)。
|
|
63
87
|
|
|
64
88
|
## Agent 最终输出格式(强制)
|
|
65
89
|
- 触发 `<Trigger Conditions>` 且本轮触碰缓存读写的回复,**第一段**必须为单行 Blockquote:
|
|
@@ -126,19 +150,28 @@ description: 将 Figma 链接信息沉淀到项目本地缓存并执行缓存优
|
|
|
126
150
|
- 仅缺某些字段:执行部分刷新,保留已有内容,更新 `completeness`。
|
|
127
151
|
- 若链接无 `node-id`,先缓存到文件级(`__FILE__`),再按后续 node 增量补充。
|
|
128
152
|
- 当 `syncedAt` 超过 14 天时,默认先提示用户是否刷新。
|
|
153
|
+
- 若需“保存 MCP 原始数据”,默认保存最小调用集三项原始回包;截图原始回包按需保存。
|
|
154
|
+
- 原始数据统一写到节点目录 `mcp-raw/` 子目录;加工缓存继续放在节点根目录(`meta.json` / `raw.json` / `spec.md` / `state-map.md`)。
|
|
155
|
+
- 默认不保存 `whoami` 原始文件;仅在鉴权排障或用户显式要求时保存。
|
|
156
|
+
- 对 `mcp-raw-get-design-context.txt` 优先采用“直存”方式(不二次改写正文),降低 token 消耗并保持可追溯性。
|
|
157
|
+
- `completeness` 建议至少按以下维度声明:`layout`、`text`、`tokens`、`interactions`、`flow`、`states`、`assets`、`accessibility`(按任务取子集)。
|
|
158
|
+
- `mcp-raw-manifest.json` 应包含审计字段:`callPolicy`(如 `minimum-set-v1`)、`dedupeApplied`(布尔)、`toolCalls`(每个工具的 `count` / `effectiveSaved`),便于后续统计与复盘。
|
|
159
|
+
- 折中推荐:在 `raw.json` 增加 `coverageSummary`(`covered` / `missing` / `evidence`)用于最小覆盖审计,不强制完整模板。
|
|
129
160
|
|
|
130
161
|
## 输出约束
|
|
131
162
|
- **必须先**输出规定的缓存状态 Blockquote,再给出设计结论或实现说明。
|
|
132
163
|
- 若跳过 MCP,Blockquote 中来源为 Local,状态多为「命中」。
|
|
133
164
|
- 若调用 MCP,Blockquote 中来源为 MCP,状态多为「缺失→更新」或「更新」,并在后文简述触发原因(未命中/信息不足/用户强刷)。
|
|
134
165
|
|
|
135
|
-
##
|
|
166
|
+
## 推荐命令(v2 流程)
|
|
136
167
|
- `npm run figma:cache:init`:初始化空索引(用于纯净移植)
|
|
137
168
|
- `npm run figma:cache:config`:查看当前生效配置
|
|
138
169
|
- `npm run figma:cache:get -- "<figma-url>"`:检查命中情况
|
|
139
|
-
- `npm run figma:cache:upsert -- "<figma-url>" --source=figma-mcp --completeness=layout,text,tokens`
|
|
140
|
-
- `npm run figma:cache:ensure -- "<figma-url>" --source=
|
|
170
|
+
- 先执行 MCP 最小调用集并写入 `mcp-raw/`,再执行:`npm run figma:cache:upsert -- "<figma-url>" --source=figma-mcp --completeness=layout,text,tokens,interactions,flow,states`
|
|
171
|
+
- `npm run figma:cache:ensure -- "<figma-url>" --source=manual --completeness=layout,text,tokens,interactions,flow,states`:自动补齐缓存骨架文件(非 MCP 拉取)
|
|
172
|
+
- MCP 默认最小调用集:`get_design_context(excludeScreenshot=true)` + `get_metadata` + `get_variable_defs`
|
|
141
173
|
- `npm run figma:cache:validate`:**每次 upsert/ensure 成功后必须自动执行**;失败则修至通过
|
|
174
|
+
- `npm run figma:cache:budget`:查看 MCP 节点预算汇总(默认 `--mcp-only`,按文件大小估算 token 代理)
|
|
142
175
|
- `npm run figma:cache:stale`:检查超 14 天的陈旧缓存
|
|
143
176
|
- `npm run figma:cache:backfill`:从历史迭代文档回填索引
|
|
144
177
|
- `npm run figma:cache:flow:init|add-node|link|chain|show|mermaid`:维护流程关系
|
package/figma-cache/README.md
CHANGED
|
@@ -56,11 +56,22 @@ npm run figma:cache:config
|
|
|
56
56
|
|
|
57
57
|
- `npm run figma:cache:init`
|
|
58
58
|
- `npm run figma:cache:get -- "<figma-url>"`
|
|
59
|
-
- `npm run figma:cache:ensure -- "<figma-url>" --source=
|
|
59
|
+
- `npm run figma:cache:ensure -- "<figma-url>" --source=manual --completeness=layout,text,tokens,interactions`
|
|
60
|
+
- `npm run figma:cache:upsert -- "<figma-url>" --source=figma-mcp --completeness=layout,text,tokens,interactions`
|
|
60
61
|
- `npm run figma:cache:validate`
|
|
62
|
+
- `npm run figma:cache:budget`(默认 `--mcp-only`)
|
|
61
63
|
- `npm run figma:cache:stale`
|
|
62
64
|
- `npm run figma:cache:backfill`
|
|
63
65
|
|
|
66
|
+
> 注意:`ensure` 默认职责是“写索引 + 生成骨架文件”,不是 MCP 拉取器。
|
|
67
|
+
> 当传 `--source=figma-mcp` 时,当前 CLI 会阻止“假成功”(若未显式允许骨架模式);正确流程是先由 Agent/Figma MCP 获取最小调用集数据并写入 `mcp-raw/`,再执行 `upsert/ensure` 与 `validate`。
|
|
68
|
+
|
|
69
|
+
### 预算统计(token/调用)
|
|
70
|
+
|
|
71
|
+
- `npm run figma:cache:budget`:输出 MCP 节点预算汇总(调用次数、原始文件体积、token 代理值)。
|
|
72
|
+
- 预算字段统一使用 `tokenProxyBytes`(基于 `mcp-raw-get-design-context.txt` 文件大小估算)。
|
|
73
|
+
- 兼容字段 `tokenProxyChars` 仍保留,便于旧脚本平滑迁移。
|
|
74
|
+
|
|
64
75
|
## 流程关系(Flow)
|
|
65
76
|
|
|
66
77
|
`index.json` 现在包含 `flows`,用于维护“业务/交互流程”的节点集合与边关系。
|
|
@@ -122,6 +133,7 @@ npm run figma:cache:init
|
|
|
122
133
|
"figma:cache:upsert": "node figma-cache/figma-cache.js upsert",
|
|
123
134
|
"figma:cache:ensure": "node figma-cache/figma-cache.js ensure",
|
|
124
135
|
"figma:cache:validate": "node figma-cache/figma-cache.js validate",
|
|
136
|
+
"figma:cache:budget": "node figma-cache/figma-cache.js budget --mcp-only",
|
|
125
137
|
"figma:cache:stale": "node figma-cache/figma-cache.js stale",
|
|
126
138
|
"figma:cache:backfill": "node figma-cache/figma-cache.js backfill",
|
|
127
139
|
"figma:cache:init": "node figma-cache/figma-cache.js init",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# figma-cache-toolchain:团队使用说明(可转发)
|
|
1
|
+
# figma-cache-toolchain:团队使用说明(可转发)
|
|
2
2
|
|
|
3
3
|
本文面向**业务仓库**里要用 Figma 本地缓存的同事:说明**是什么、何时用、怎么接、日常怎么用、怎么升级**。技术细节仍以包内**根 `README.md`**、**`figma-cache/README.md`** 为准;链接与键、Flow 边类型分别见 **`link-normalization-spec.md`**、**`flow-edge-taxonomy.md`**。**专用名词**见**文首「术语与专用名词(速查)」**表格。
|
|
4
4
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
| 名词 | 一句话解释 |
|
|
12
12
|
|------|------------|
|
|
13
|
-
| **`ensure`** | 针对一条 Figma 链接:在 **`figma-cache/index.json`** 里登记/更新一条 **`items`** 记录,并在磁盘上生成/补齐该节点的 **`meta.json` / `spec.md` / `raw.json` / `state-map.md`** 等骨架;常由 Agent 调用 CLI `figma-cache ensure`
|
|
13
|
+
| **`ensure`** | 针对一条 Figma 链接:在 **`figma-cache/index.json`** 里登记/更新一条 **`items`** 记录,并在磁盘上生成/补齐该节点的 **`meta.json` / `spec.md` / `raw.json` / `state-map.md`** 等骨架;常由 Agent 调用 CLI `figma-cache ensure` 完成。**它不是自动 MCP 拉取器**,MCP 原始回包应先由 Agent 调 figma-mcp 写入 `mcp-raw/`,再 `upsert/ensure`。 |
|
|
14
14
|
| **`get`** | 按链接查看缓存是否命中、或拉取条目信息;不一定写盘。 |
|
|
15
15
|
| **`validate`** | 检查 **`index.json`** 结构是否合法(必填字段、`flows` 里的边是否指向存在的 `items` 等)。合并前可跑。 |
|
|
16
16
|
| **`completeness`** | `ensure` 时可传的**标签列表**(如 `layout`、`text`、`tokens`、`interactions`),表示「希望这次把哪些方面的设计信息写进缓存/交给 MCP」。**不是 Figma 官方枚举**,而是你们流程里约定「要记多细」;具体写入内容仍落在 **`spec.md` / `raw.json`** 等文件里。 |
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
| **`postEnsure`** | **`figma-cache.config.js`** 里的钩子:**每次 `ensure` 写完通用骨架文件之后**调用一次,可写适配说明、维护 **`docs/figma-flow-readme.md`** 等;**抛错不会让整个 ensure 失败**(由 Core 捕获日志)。 |
|
|
37
37
|
| **`cursor init` vs `figma-cache init`** | **`cursor init`**:拷 `.cursor` 模板、刷新 **`AGENT-SETUP-PROMPT.md`**、同步 **`colleague-guide-zh.md`**。**`figma-cache init`**:只建 **`figma-cache/index.json`** 空索引,**不管 Cursor**。 |
|
|
38
38
|
| **`npm run figma:cache:*`** | 项目在 **`package.json` 的 `scripts`** 里封装的 CLI;未配置时可用 **`npx figma-cache <子命令>`** 代替。 |
|
|
39
|
+
| **`tokenProxyBytes`** | 预算统计字段:用 `mcp-raw-get-design-context.txt` 的文件大小做 token 代理估算(用于成本趋势,不等于模型精确 token)。兼容字段 `tokenProxyChars` 仅用于平滑迁移。 |
|
|
39
40
|
| **业务流程文档(推荐)** | 通常指项目里的 **`docs/figma-flow-readme.md`**(路径可改):用**中文叙事**写清主路径/分支/边界,并粘贴 **`flow mermaid`**;与 **`index.json` 的 `flows`** 双轨对齐,**人和 Agent 都优先读它建立上下文**。详见 **§5.8~§5.10**。 |
|
|
40
41
|
|
|
41
42
|
---
|
|
@@ -125,258 +126,40 @@ npx figma-cache init
|
|
|
125
126
|
```
|
|
126
127
|
|
|
127
128
|
3. **规范文档在哪**:包内自带说明(安装后在 **`node_modules/figma-cache-toolchain/figma-cache/`** 下的多个 `.md`)。一般**不必**再复制一份到业务仓库;需要时让 Agent **`@` 该路径**即可。
|
|
129
|
+
4. **看预算**(可选):`npm run figma:cache:budget`,快速看 MCP 调用与 `tokenProxyBytes`。
|
|
128
130
|
|
|
129
131
|
---
|
|
130
132
|
|
|
131
|
-
## 5.
|
|
133
|
+
## 5. 团队统一提示词(只保留一个主模板)
|
|
132
134
|
|
|
133
|
-
|
|
135
|
+
为了避免“模板太多不好选”,这里统一成 **1 个最推荐提示词**。
|
|
136
|
+
默认先复制这一段,再按需要补 1~2 句附加要求。
|
|
134
137
|
|
|
135
|
-
### 5.1
|
|
136
|
-
|
|
137
|
-
**意图**:把该节点写入本地 `figma-cache`(含 `ensure`、必要时 MCP、最后 `validate`),先不实现页面。
|
|
138
|
-
|
|
139
|
-
**可复制提示词示例**:
|
|
138
|
+
### 5.1 最推荐主提示词(默认用这个)
|
|
140
139
|
|
|
141
140
|
```text
|
|
142
|
-
请按项目 figma
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
141
|
+
请按项目 figma 缓存规则处理下面这条 Figma 链接,并遵循“缓存优先 + 按需 MCP + 最小调用集”:
|
|
142
|
+
1) 先查本地 figma-cache,命中则直接复用,不做刷新;
|
|
143
|
+
2) 仅在未命中或我明确要求刷新时,才调用 figma-mcp 拉取并写入 mcp-raw(随后再 ensure/upsert);
|
|
144
|
+
3) completeness 默认使用 layout,text,tokens(若我补充再扩展 interactions/flow/states/assets/accessibility);
|
|
145
|
+
4) 原始 MCP 数据统一保存到节点目录 mcp-raw/ 子目录;
|
|
146
|
+
5) 默认不保存 whoami 原始文件(仅鉴权排障或我明确要求时保存);
|
|
147
|
+
6) 完成后执行 figma:cache:validate,并汇报:缓存状态、实际 MCP 调用次数、输出文件清单。
|
|
149
148
|
|
|
150
|
-
```text
|
|
151
149
|
[Figma 链接]
|
|
152
|
-
先按缓存规范写入 figma-cache;若本地没有或过期再调 MCP。完成后 validate。
|
|
153
150
|
```
|
|
154
151
|
|
|
155
|
-
|
|
152
|
+
### 5.2 仅在需要时追加的附加句(可选)
|
|
156
153
|
|
|
157
|
-
|
|
154
|
+
- 要强制最新:`忽略本地缓存,强制刷新,以 Figma 最新为准。`
|
|
155
|
+
- 要 React 直复用:`若目标项目是 React 栈,优先复用 mcp-raw-get-design-context.txt 的 React 代码,只做必要微调。`
|
|
156
|
+
- 要补流程关系:`请在 flow [flowId] 下补齐节点关系(link/chain),并输出 mermaid。`
|
|
158
157
|
|
|
159
|
-
|
|
158
|
+
### 5.3 使用建议(团队口径)
|
|
160
159
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
把 [某路由/某组件名] 对齐到该设计(间距、字体、颜色与状态)。
|
|
165
|
-
完成后运行 figma:cache:validate。
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
**变体(只问规格、不写代码)**:
|
|
169
|
-
|
|
170
|
-
```text
|
|
171
|
-
[Figma 链接]
|
|
172
|
-
缓存若缺失请先 ensure。请根据 spec/meta 用中文列出与当前代码 [文件路径] 的差异清单,先不改代码。
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
---
|
|
176
|
-
|
|
177
|
-
### 5.3 多条 Figma 链接:希望「有关联」(流程 / 跳转)
|
|
178
|
-
|
|
179
|
-
**背景**:索引里除单条 `items` 外,还可以维护 **`flows`**:多个节点用**边**连接,类型见包内 **`flow-edge-taxonomy.md`**(如 `next_step`、`related`、`child` 等)。适合「多屏同一条用户路径」。
|
|
180
|
-
|
|
181
|
-
**第一次拉多条、且你已知道顺序(推荐先说清 flow 名字)**:
|
|
182
|
-
|
|
183
|
-
```text
|
|
184
|
-
我们要维护一条用户流程,flowId 叫 [my-onboarding-flow],中文标题 [新用户引导]。
|
|
185
|
-
请若尚无则 flow init;然后按顺序 ensure 下面这些链接并把它们加入该 flow,
|
|
186
|
-
相邻两屏之间用 flow link,类型 next_step(若你不确定先后关系则先用 related 并加 note 说明):
|
|
187
|
-
|
|
188
|
-
1) [Figma 链接 A]
|
|
189
|
-
2) [Figma 链接 B]
|
|
190
|
-
3) [Figma 链接 C]
|
|
191
|
-
|
|
192
|
-
最后 flow show 或 flow mermaid 输出让我确认,并 validate。
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
**已经 ensure 过、只想补关系**:
|
|
196
|
-
|
|
197
|
-
```text
|
|
198
|
-
在 flow [my-onboarding-flow] 里:
|
|
199
|
-
从 [Figma 链接 A] 到 [Figma 链接 B] 是主流程下一步,请 flow link,类型 next_step,note:[例如:点击首页「设置」进入]。
|
|
200
|
-
完成后 validate。
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
**一次性串联(链式,适合一条直线)**:
|
|
204
|
-
|
|
205
|
-
```text
|
|
206
|
-
对 flow [my-onboarding-flow],把下面链接按顺序 flow chain,类型 next_step:
|
|
207
|
-
[URL1] [URL2] [URL3]
|
|
208
|
-
若某条尚未在 items 里,可带 --ensure 再 add-node。最后 mermaid 给我看一眼。
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
---
|
|
212
|
-
|
|
213
|
-
### 5.4 渐进式:每次只给一条新链接,但要挂到「之前的」上面
|
|
214
|
-
|
|
215
|
-
典型情况:**上周缓存了登录页**,这周发**首页**链接,并说「首页是登录成功后的下一屏」。
|
|
216
|
-
|
|
217
|
-
**写法 A(依赖同线程上文:最省事)**
|
|
218
|
-
|
|
219
|
-
在同一条 Cursor 对话里,先有过登录页的讨论或你明确粘贴过登录链接,然后发:
|
|
220
|
-
|
|
221
|
-
```text
|
|
222
|
-
新链接(下一屏):[Figma 链接-首页]
|
|
223
|
-
|
|
224
|
-
请 ensure 这条;然后把它与**本对话里前面那条登录页 Figma 链接**在流程上连起来:
|
|
225
|
-
flowId 仍用 [my-onboarding-flow],边类型 next_step,note:[登录成功进入首页]。
|
|
226
|
-
若 flow 不存在请先 flow init。最后 validate。
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
**写法 B(不依赖上下文:两条都写全)**
|
|
230
|
-
|
|
231
|
-
新开对话或怕 Agent 对不上时,**两条 URL 都贴上**,并说明谁接谁:
|
|
232
|
-
|
|
233
|
-
```text
|
|
234
|
-
已有节点(上一屏):[Figma 链接-登录]
|
|
235
|
-
新节点(下一屏):[Figma 链接-首页]
|
|
236
|
-
|
|
237
|
-
请 ensure 两条(若已缓存可跳过重复拉取);在 flow [my-onboarding-flow] 里 add-node(若缺)并用 flow link 从登录到首页,类型 next_step。
|
|
238
|
-
validate。
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
**写法 C(弹层 / 子结构挂在某一屏上)**
|
|
242
|
-
|
|
243
|
-
边类型常用 **`child`**(结构父子)或 **`related`**,不确定时先用 `related`,见 `flow-edge-taxonomy.md`。
|
|
244
|
-
|
|
245
|
-
```text
|
|
246
|
-
主屏:[Figma 链接-通话中页面]
|
|
247
|
-
弹层(依附该主屏):[Figma 链接-更多菜单抽屉]
|
|
248
|
-
|
|
249
|
-
请 ensure 两条;在同一 flow [sip-calling-flow] 里建立从主屏到弹层的边,类型 child,note:[点击「更多」打开抽屉]。
|
|
250
|
-
validate。
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
**写法 D(分支:成功 / 失败两种下一屏)**
|
|
254
|
-
|
|
255
|
-
```text
|
|
256
|
-
决策点屏:[Figma 链接-表单页]
|
|
257
|
-
成功分支下一屏:[Figma 链接-成功页]
|
|
258
|
-
失败分支下一屏:[Figma 链接-错误提示]
|
|
259
|
-
|
|
260
|
-
请 ensure 三屏;在 flow [form-submit-flow] 中:
|
|
261
|
-
从表单到成功页 flow link,类型 branch_true,note:[校验通过];
|
|
262
|
-
从表单到错误页 flow link,类型 branch_false,note:[校验失败]。
|
|
263
|
-
validate。
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
---
|
|
267
|
-
|
|
268
|
-
### 5.5 只有 node-id、或只有「文件里之前那个 key」时怎么说
|
|
269
|
-
|
|
270
|
-
- **两条都是完整 Figma URL**:最稳,直接粘贴即可(Agent 会按 **`link-normalization-spec.md`** 生成同一 `cacheKey` 体系)。
|
|
271
|
-
- **你只有 node-id、和 fileKey**:可以写「与登录页**同一 Figma 文件**,node-id 为 `123:456`」,并贴上**该文件任意带 node-id 的链接**作为锚点,让 Agent 拼出规范 URL 再 ensure。
|
|
272
|
-
- **想指「index 里已有的一项」**:可以说「`cacheKey` 为 `xxxx#yyyy` 的那条」(若你打开过 `figma-cache/index.json`);一般同事**不必**手写 cacheKey,**两条 URL 都贴上**即可。
|
|
273
|
-
|
|
274
|
-
---
|
|
275
|
-
|
|
276
|
-
### 5.6 多条链接但**暂时不想**建 flow 关系
|
|
277
|
-
|
|
278
|
-
可以只要求**批量进缓存**,不建边:
|
|
279
|
-
|
|
280
|
-
```text
|
|
281
|
-
请分别 ensure 下面这些链接(同一文件不同节点也可以),completeness [layout,text,tokens];
|
|
282
|
-
**不要**修改现有 flows,除非我明确说要建立关系。
|
|
283
|
-
|
|
284
|
-
- [URL1]
|
|
285
|
-
- [URL2]
|
|
286
|
-
- [URL3]
|
|
287
|
-
|
|
288
|
-
完成后 validate。
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
以后若要补关系,再用 **5.3 / 5.4** 的 `flow link` 话术即可。
|
|
292
|
-
|
|
293
|
-
---
|
|
294
|
-
|
|
295
|
-
### 5.7 易错提醒(给使用者看的)
|
|
296
|
-
|
|
297
|
-
| 情况 | 建议 |
|
|
298
|
-
|------|------|
|
|
299
|
-
| **新开对话** | Agent 可能看不到「上一条链接」,请用 **5.4 写法 B** 两条 URL 写全,或 **`@` 含链接/含 cacheKey 的本地文件**。 |
|
|
300
|
-
| **flow 子命令要 `--flow=`** | 若项目设置了环境变量 **`FIGMA_DEFAULT_FLOW`**,可省略;否则在提示词里写清 `flowId`。 |
|
|
301
|
-
| **add-node 报缺 item** | 提示词里写明「若缺则对某 URL **带 --ensure** 先写入 items 再 add-node」。 |
|
|
302
|
-
| **不确定边类型** | 写「边类型不确定,先用 **related**,并在 note 里用一句话描述设计关系」。 |
|
|
303
|
-
|
|
304
|
-
### 5.8 自动维护的「流程 / 需求总览」单文件(可选)
|
|
305
|
-
|
|
306
|
-
若项目使用包内默认 **`figma-cache.config.example.js`**(或由 Agent 合并后的等价 **`postEnsure`**),每次对某节点 **`ensure`** 成功后,钩子会在项目根下维护 **`docs/figma-flow-readme.md`**(可用环境变量 **`FIGMA_CACHE_FLOW_README`** 改路径):
|
|
307
|
-
|
|
308
|
-
- 文件里预留 **「流程总览」**(可粘贴 **`npm run figma:cache:flow mermaid`** 输出)和 **「交互与边界」** 手填区,方便产品/评审阅读。
|
|
309
|
-
- **「已从 Figma 写入缓存的节点」** 区会按 **`cacheKey` 幂等追加**小节(含 Figma 链接、`completeness`、指向 **`spec.md`** 的相对路径),与 **`figma-cache/index.json`** 里的 **`flows`** 互补:**索引 + mermaid 给机器与校验,本 md 给人读**。
|
|
310
|
-
- **像素级细节**仍以各节点目录下的 **`spec.md` / `raw.json`** 为准;本文件不做第二份设计稿,只做**导航与流程叙事**。
|
|
311
|
-
|
|
312
|
-
在提示词里可 **`@docs/figma-flow-readme.md`**,要求 Agent 根据刚 ensure 的节点更新手填区或补充用户故事。
|
|
313
|
-
**大批量链接**与**少量但已建 flow** 时如何把「业务逻辑」写成人话,见 **§5.9、§5.10**。
|
|
314
|
-
|
|
315
|
-
---
|
|
316
|
-
|
|
317
|
-
### 5.9 大批量链接(几十条):推荐两阶段
|
|
318
|
-
|
|
319
|
-
**说明**:缓存 **不会**自动从几十个 URL 推断页面跳转;**业务关系**靠 **`flows` + `flow link`** 与/或 **Agent 归纳** 写进文档。
|
|
320
|
-
|
|
321
|
-
**阶段 1 — 先全部进缓存(事实层)**
|
|
322
|
-
|
|
323
|
-
```text
|
|
324
|
-
本迭代有一批 Figma 节点需要先写入 figma-cache(只做 ensure,暂不新建 flow、不改现有 flows):
|
|
325
|
-
completeness 统一为 layout,text,tokens,interactions(可按项目约定改)。
|
|
326
|
-
|
|
327
|
-
请逐条 ensure 下列链接(若已存在可跳过重复 MCP),最后 validate:
|
|
328
|
-
|
|
329
|
-
- [URL1]
|
|
330
|
-
- [URL2]
|
|
331
|
-
…(可继续列,或分多条消息粘贴,但请在同一任务内做完再汇报)
|
|
332
|
-
|
|
333
|
-
完成后简要列出:新增了几个 cacheKey、有无失败项。
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
**阶段 2 — 再整理业务逻辑 + 写进 index 的 flows + 给人看的文档**
|
|
337
|
-
|
|
338
|
-
```text
|
|
339
|
-
上一步已 ensure 的链接如下(或请直接读 figma-cache/index.json 里本迭代相关 items):
|
|
340
|
-
[可再贴一遍 URL 列表,或 @figma-cache/index.json]
|
|
341
|
-
|
|
342
|
-
请结合设计稿/MCP(如需)与产品常识,完成:
|
|
343
|
-
1) 归纳**用户主路径、分支、异常与空状态**(用中文写清假设);
|
|
344
|
-
2) 在 flowId [my-iteration-flow] 下维护 flows:若无则 flow init;用 flow add-node / flow link(类型见 flow-edge-taxonomy.md,不确定用 related + note)把屏与屏关系写进 index.json;
|
|
345
|
-
3) 运行 flow mermaid,把输出贴进 docs/figma-flow-readme.md 的「流程总览」代码块,并更新「交互与边界」手填区;
|
|
346
|
-
4) validate。
|
|
347
|
-
|
|
348
|
-
若与产品文档冲突,在 docs/figma-flow-readme.md 里用「待产品确认」标出差异点。
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
链接特别多时,可让 Agent **分批 ensure**(每批 10~15 条)以免单次上下文过长,**阶段 2 尽量用 `@index.json` + 抽样 `@spec.md`** 归纳。
|
|
352
|
-
|
|
353
|
-
---
|
|
354
|
-
|
|
355
|
-
### 5.10 少量链接,但只要建了 flow 或有人专门补了提示:也要有一份「人 + Agent 都读得懂」的业务流程文档吗?
|
|
356
|
-
|
|
357
|
-
**建议:要。** 链接少不代表关系简单;**只要存在 `flows` 或有人用自然语言补过「谁接谁」**,就值得在 **`docs/figma-flow-readme.md`**(或你们约定的路径)里维护**同一份**「业务流程说明」,和 **`index.json` 里的机器结构**对齐:
|
|
358
|
-
|
|
359
|
-
| 做法 | 说明 |
|
|
360
|
-
|------|------|
|
|
361
|
-
| **谁写** | **专人**可只写手填区(主路径、分支、边界);**Agent** 可根据 `flow show` / `flow mermaid` + 各屏 `spec.md` 起草再让人改。 |
|
|
362
|
-
| **何时更新** | 每次 **`flow link` / `flow chain` 有变**、或产品改口径、或某屏 **re-ensure** 后行为变了,就同步改 md(可与 PR 一起审)。 |
|
|
363
|
-
| **和 Agent 的关系** | Agent 读 **`@docs/figma-flow-readme.md`** 比纯读 `index.json` 更快建立业务上下文;新人 onboarding 同理。 |
|
|
364
|
-
|
|
365
|
-
**可复制提示词(flow 已建好,补「人话」文档)**:
|
|
366
|
-
|
|
367
|
-
```text
|
|
368
|
-
flowId:[my-iteration-flow]
|
|
369
|
-
请读取 figma-cache/index.json 里该 flow 的 nodes 与 edges,并运行 flow mermaid。
|
|
370
|
-
|
|
371
|
-
请更新 @docs/figma-flow-readme.md:
|
|
372
|
-
1) 「流程总览」贴上当前 mermaid;
|
|
373
|
-
2) 「交互与边界」用中文写:主路径、分支条件、异常与空状态(没有信息就写「待补充」并列出需问产品的问题);
|
|
374
|
-
3) 在文末加一小节「与开发对齐的检查清单」(可勾选)便于实现与测试。
|
|
375
|
-
|
|
376
|
-
不要改各节点 spec.md 里的设计事实,只整理叙事层。
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
**结论**:**链接多少不是门槛**;**只要开始有 flow 关系或有人愿意用提示补业务语义**,就应用**同一份业务流程 md** 把「给人看的逻辑」固定下来,与 **`flows` + `validate`** 形成双轨(机读 + 人读),更利于开发与评审。
|
|
160
|
+
- 日常协作默认只用 **5.1 主提示词**。
|
|
161
|
+
- 只有确实需要时,再从 5.2 里加一句附加要求。
|
|
162
|
+
- 新同事只记住一条:**先缓存、后实现;能复用本地就不重复调 MCP**。
|
|
380
163
|
|
|
381
164
|
---
|
|
382
165
|
|
|
@@ -418,3 +201,6 @@ npx figma-cache cursor init
|
|
|
418
201
|
- **维护工具链源码的仓库**:同路径 **`figma-cache/colleague-guide-zh.md`**。
|
|
419
202
|
|
|
420
203
|
将本文件全文复制到 IM / 邮件 / 内部文档即可给同事使用。
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
|
|
@@ -669,6 +669,118 @@ function printStale(days) {
|
|
|
669
669
|
});
|
|
670
670
|
}
|
|
671
671
|
|
|
672
|
+
function safeReadJson(absPath) {
|
|
673
|
+
try {
|
|
674
|
+
return JSON.parse(fs.readFileSync(absPath, "utf8"));
|
|
675
|
+
} catch {
|
|
676
|
+
return null;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
function safeFileSize(absPath) {
|
|
681
|
+
try {
|
|
682
|
+
return fs.statSync(absPath).size;
|
|
683
|
+
} catch {
|
|
684
|
+
return 0;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
function parsePositiveIntOr(input, fallback) {
|
|
689
|
+
const n = Number(input);
|
|
690
|
+
return Number.isFinite(n) && n > 0 ? Math.floor(n) : fallback;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
function buildBudgetReport(options) {
|
|
694
|
+
const index = normalizeIndexShape(readIndex());
|
|
695
|
+
const items = index.items || {};
|
|
696
|
+
const keys = Object.keys(items);
|
|
697
|
+
const filteredKeys = keys.filter((cacheKey) => {
|
|
698
|
+
if (options.cacheKey && cacheKey !== options.cacheKey) {
|
|
699
|
+
return false;
|
|
700
|
+
}
|
|
701
|
+
if (options.mcpOnly) {
|
|
702
|
+
const item = items[cacheKey];
|
|
703
|
+
return item && item.source === "figma-mcp";
|
|
704
|
+
}
|
|
705
|
+
return true;
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
const entries = filteredKeys.map((cacheKey) => {
|
|
709
|
+
const item = items[cacheKey];
|
|
710
|
+
const metaAbs = resolveMaybeAbsolutePath(item.paths.meta);
|
|
711
|
+
const nodeDir = path.dirname(metaAbs);
|
|
712
|
+
const mcpRawDir = path.join(nodeDir, "mcp-raw");
|
|
713
|
+
const manifestAbs = path.join(mcpRawDir, "mcp-raw-manifest.json");
|
|
714
|
+
const manifest = safeReadJson(manifestAbs);
|
|
715
|
+
const filesMap = manifest && manifest.files && typeof manifest.files === "object" ? manifest.files : {};
|
|
716
|
+
const fileEntries = Object.entries(filesMap);
|
|
717
|
+
const mcpRawBytes = fileEntries.reduce((acc, [, fileName]) => {
|
|
718
|
+
const abs = path.join(mcpRawDir, String(fileName));
|
|
719
|
+
return acc + safeFileSize(abs);
|
|
720
|
+
}, 0);
|
|
721
|
+
const mcpRawFilesCount = fileEntries.length;
|
|
722
|
+
const toolCalls = manifest && manifest.toolCalls && typeof manifest.toolCalls === "object" ? manifest.toolCalls : {};
|
|
723
|
+
const toolCallCount = Object.values(toolCalls).reduce((acc, v) => {
|
|
724
|
+
const count = v && typeof v === "object" ? Number(v.count) : 0;
|
|
725
|
+
return acc + (Number.isFinite(count) ? count : 0);
|
|
726
|
+
}, 0);
|
|
727
|
+
const designContextFile =
|
|
728
|
+
filesMap && Object.prototype.hasOwnProperty.call(filesMap, "get_design_context")
|
|
729
|
+
? String(filesMap.get_design_context)
|
|
730
|
+
: "";
|
|
731
|
+
const designContextChars = designContextFile
|
|
732
|
+
? safeFileSize(path.join(mcpRawDir, designContextFile))
|
|
733
|
+
: 0;
|
|
734
|
+
|
|
735
|
+
return {
|
|
736
|
+
cacheKey,
|
|
737
|
+
source: item.source || "manual",
|
|
738
|
+
completeness: Array.isArray(item.completeness) ? item.completeness : [],
|
|
739
|
+
hasMcpRawManifest: !!manifest,
|
|
740
|
+
mcpRawFilesCount,
|
|
741
|
+
mcpRawBytes,
|
|
742
|
+
tokenProxyBytes: designContextChars,
|
|
743
|
+
tokenProxyChars: designContextChars,
|
|
744
|
+
toolCallCount,
|
|
745
|
+
toolCalls,
|
|
746
|
+
};
|
|
747
|
+
});
|
|
748
|
+
|
|
749
|
+
entries.sort((a, b) => b.mcpRawBytes - a.mcpRawBytes);
|
|
750
|
+
const limit = parsePositiveIntOr(options.limit, entries.length);
|
|
751
|
+
const limitedEntries = entries.slice(0, limit);
|
|
752
|
+
const totals = limitedEntries.reduce(
|
|
753
|
+
(acc, e) => {
|
|
754
|
+
acc.nodes += 1;
|
|
755
|
+
acc.nodesWithMcpRaw += e.hasMcpRawManifest ? 1 : 0;
|
|
756
|
+
acc.mcpRawBytes += e.mcpRawBytes;
|
|
757
|
+
acc.tokenProxyBytes += e.tokenProxyBytes;
|
|
758
|
+
acc.toolCallCount += e.toolCallCount;
|
|
759
|
+
return acc;
|
|
760
|
+
},
|
|
761
|
+
{
|
|
762
|
+
nodes: 0,
|
|
763
|
+
nodesWithMcpRaw: 0,
|
|
764
|
+
mcpRawBytes: 0,
|
|
765
|
+
tokenProxyBytes: 0,
|
|
766
|
+
toolCallCount: 0,
|
|
767
|
+
}
|
|
768
|
+
);
|
|
769
|
+
|
|
770
|
+
totals.tokenProxyChars = totals.tokenProxyBytes;
|
|
771
|
+
|
|
772
|
+
return {
|
|
773
|
+
generatedAt: new Date().toISOString(),
|
|
774
|
+
filters: {
|
|
775
|
+
cacheKey: options.cacheKey || null,
|
|
776
|
+
mcpOnly: !!options.mcpOnly,
|
|
777
|
+
limit,
|
|
778
|
+
},
|
|
779
|
+
totals,
|
|
780
|
+
entries: limitedEntries,
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
|
|
672
784
|
function run() {
|
|
673
785
|
const [, , cmd, ...args] = process.argv;
|
|
674
786
|
if (!cmd) {
|
|
@@ -681,7 +793,10 @@ function run() {
|
|
|
681
793
|
console.log(` ${ex} validate`);
|
|
682
794
|
console.log(` ${ex} stale [--days=14]`);
|
|
683
795
|
console.log(` ${ex} backfill`);
|
|
684
|
-
console.log(` ${ex}
|
|
796
|
+
console.log(` ${ex} budget [--mcp-only] [--cacheKey=<fileKey#nodeId>] [--limit=50]`);
|
|
797
|
+
console.log(
|
|
798
|
+
` ${ex} ensure <figmaUrl> [--source=manual] [--completeness=a,b] [--allow-skeleton-with-figma-mcp]`
|
|
799
|
+
);
|
|
685
800
|
console.log(` ${ex} init`);
|
|
686
801
|
console.log(` ${ex} config`);
|
|
687
802
|
console.log(
|
|
@@ -769,6 +884,7 @@ function run() {
|
|
|
769
884
|
const url = args[0];
|
|
770
885
|
const sourceArg = args.find((x) => x.startsWith("--source="));
|
|
771
886
|
const completenessArg = args.find((x) => x.startsWith("--completeness="));
|
|
887
|
+
const allowSkeletonWithFigmaMcp = args.includes("--allow-skeleton-with-figma-mcp");
|
|
772
888
|
const source = sourceArg ? sourceArg.split("=")[1] : "manual";
|
|
773
889
|
const completeness = completenessArg
|
|
774
890
|
? completenessArg
|
|
@@ -777,6 +893,17 @@ function run() {
|
|
|
777
893
|
.map((x) => x.trim())
|
|
778
894
|
.filter(Boolean)
|
|
779
895
|
: [];
|
|
896
|
+
if (source === "figma-mcp" && !allowSkeletonWithFigmaMcp) {
|
|
897
|
+
console.error(
|
|
898
|
+
[
|
|
899
|
+
"ensure 检测到 --source=figma-mcp,但当前 CLI 不会主动发起 MCP 请求。",
|
|
900
|
+
"为避免“假成功”,已阻止本次写入。",
|
|
901
|
+
"请先由 Agent/Figma MCP 拉取并写入 mcp-raw,再执行 upsert/ensure;",
|
|
902
|
+
"若你只想生成本地骨架,请显式追加 --allow-skeleton-with-figma-mcp。",
|
|
903
|
+
].join("\n")
|
|
904
|
+
);
|
|
905
|
+
process.exit(2);
|
|
906
|
+
}
|
|
780
907
|
const result = upsertByUrl(url, { source, completeness });
|
|
781
908
|
ensureEntryFilesAndHook(result.normalized.cacheKey, result.item);
|
|
782
909
|
console.log(
|
|
@@ -817,6 +944,17 @@ function run() {
|
|
|
817
944
|
return;
|
|
818
945
|
}
|
|
819
946
|
|
|
947
|
+
if (cmd === "budget") {
|
|
948
|
+
const mcpOnly = args.includes("--mcp-only");
|
|
949
|
+
const cacheKeyArg = args.find((x) => x.startsWith("--cacheKey="));
|
|
950
|
+
const limitArg = args.find((x) => x.startsWith("--limit="));
|
|
951
|
+
const cacheKey = cacheKeyArg ? cacheKeyArg.split("=").slice(1).join("=") : "";
|
|
952
|
+
const limit = limitArg ? limitArg.split("=")[1] : "";
|
|
953
|
+
const report = buildBudgetReport({ mcpOnly, cacheKey, limit });
|
|
954
|
+
console.log(JSON.stringify(report, null, 2));
|
|
955
|
+
return;
|
|
956
|
+
}
|
|
957
|
+
|
|
820
958
|
if (cmd === "config") {
|
|
821
959
|
const cfg = loadProjectConfig();
|
|
822
960
|
const hooks = cfg && cfg.hooks;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "figma-cache-toolchain",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.2",
|
|
4
4
|
"description": "Figma link normalization, local cache index, validation, and Node CLI (framework-agnostic core).",
|
|
5
5
|
"homepage": "https://www.npmjs.com/package/figma-cache-toolchain",
|
|
6
6
|
"keywords": [
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"figma:cache:ensure": "node bin/figma-cache.js ensure",
|
|
37
37
|
"figma:cache:validate": "node bin/figma-cache.js validate",
|
|
38
38
|
"figma:cache:stale": "node bin/figma-cache.js stale",
|
|
39
|
+
"figma:cache:budget": "node bin/figma-cache.js budget --mcp-only",
|
|
39
40
|
"figma:cache:backfill": "node bin/figma-cache.js backfill",
|
|
40
41
|
"figma:cache:init": "node bin/figma-cache.js init",
|
|
41
42
|
"figma:cache:config": "node bin/figma-cache.js config",
|