figma-cache-toolchain 1.4.2 → 1.4.4
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/LICENSE +21 -21
- package/README.md +142 -98
- package/README.owner.md +37 -0
- package/cursor-bootstrap/AGENT-SETUP-PROMPT.md +53 -62
- package/cursor-bootstrap/examples/README.md +5 -3
- package/cursor-bootstrap/figma-cache.config.example.js +238 -138
- package/cursor-bootstrap/rules/01-figma-cache-core.mdc +42 -5
- package/cursor-bootstrap/skills/figma-mcp-local-cache/SKILL.md +10 -5
- package/figma-cache/{README.md → docs/README.md} +42 -19
- package/figma-cache/{colleague-guide-zh.md → docs/colleague-guide-zh.md} +8 -7
- package/figma-cache/docs/figma-cache-adapter-hint.md +14 -0
- package/figma-cache/figma-cache.js +250 -881
- package/figma-cache/js/backfill-cli.js +50 -0
- package/figma-cache/js/budget-cli.js +108 -0
- package/figma-cache/js/cursor-bootstrap-cli.js +178 -0
- package/figma-cache/js/entry-files.js +149 -0
- package/figma-cache/js/flow-cli.js +227 -0
- package/figma-cache/js/index-store.js +86 -0
- package/figma-cache/js/project-config.js +97 -0
- package/figma-cache/js/upsert-core.js +156 -0
- package/figma-cache/js/validate-cli.js +233 -0
- package/package.json +72 -54
- /package/figma-cache/{flow-edge-taxonomy.md → docs/flow-edge-taxonomy.md} +0 -0
- /package/figma-cache/{link-normalization-spec.md → docs/link-normalization-spec.md} +0 -0
|
@@ -1,139 +1,239 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 项目级 Figma 缓存扩展(示例模板,**不绑定任何 UI 框架**)。
|
|
3
|
-
*
|
|
4
|
-
* 安装本 npm 包并执行 `npx figma-cache cursor init` 后,项目根会出现 **AGENT-SETUP-PROMPT.md**:
|
|
5
|
-
* 请用 Cursor Agent **按该文件全文**执行,以自动生成 `figma-cache.config.js`、栈专属 Adapter、并删除占位规则等(尽量少手动步骤)。
|
|
6
|
-
*
|
|
7
|
-
* 若你已有 `figma-cache.config.js`,可由 Agent 合并而非覆盖。
|
|
8
|
-
*
|
|
9
|
-
* 加载顺序见 `figma-cache/figma-cache.js`:FIGMA_CACHE_PROJECT_CONFIG → figma-cache.config.js → .figmacacherc.js
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
const fs = require("fs");
|
|
13
|
-
const path = require("path");
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
* @
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
1
|
+
/**
|
|
2
|
+
* 项目级 Figma 缓存扩展(示例模板,**不绑定任何 UI 框架**)。
|
|
3
|
+
*
|
|
4
|
+
* 安装本 npm 包并执行 `npx figma-cache cursor init` 后,项目根会出现 **AGENT-SETUP-PROMPT.md**:
|
|
5
|
+
* 请用 Cursor Agent **按该文件全文**执行,以自动生成 `figma-cache.config.js`、栈专属 Adapter、并删除占位规则等(尽量少手动步骤)。
|
|
6
|
+
*
|
|
7
|
+
* 若你已有 `figma-cache.config.js`,可由 Agent 合并而非覆盖。
|
|
8
|
+
*
|
|
9
|
+
* 加载顺序见 `figma-cache/figma-cache.js`:FIGMA_CACHE_PROJECT_CONFIG → figma-cache.config.js → .figmacacherc.js
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const fs = require("fs");
|
|
13
|
+
const path = require("path");
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Adapter 提示文档基础名:
|
|
17
|
+
* - node 模式时用于节点目录文件名
|
|
18
|
+
* - cache-root 模式时用于 figma-cache 根目录文件名
|
|
19
|
+
*/
|
|
20
|
+
const ADAPTER_DOC_BASENAME =
|
|
21
|
+
process.env.FIGMA_CACHE_ADAPTER_DOC || "figma-cache-adapter-hint.md";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Adapter 提示写入模式:
|
|
25
|
+
* - cache-root(默认):仅在 figma-cache 目录维护单文件,避免每节点重复
|
|
26
|
+
* - node:按节点目录写入提示
|
|
27
|
+
* - off:关闭提示文件写入
|
|
28
|
+
*/
|
|
29
|
+
const ADAPTER_DOC_MODE = normalizeAdapterDocMode(
|
|
30
|
+
process.env.FIGMA_CACHE_ADAPTER_DOC_MODE || "cache-root"
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* cache-root 模式下的提示文档路径(相对项目根)
|
|
35
|
+
*/
|
|
36
|
+
const ADAPTER_DOC_CACHE_REL =
|
|
37
|
+
process.env.FIGMA_CACHE_ADAPTER_DOC_CACHE ||
|
|
38
|
+
`figma-cache/docs/${ADAPTER_DOC_BASENAME}`;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* 提示文档写入策略:
|
|
42
|
+
* - if-missing(默认):仅目标不存在时写入
|
|
43
|
+
* - always:每次 ensure 都覆盖更新
|
|
44
|
+
*/
|
|
45
|
+
const ADAPTER_DOC_WRITE_POLICY =
|
|
46
|
+
process.env.FIGMA_CACHE_ADAPTER_DOC_WRITE_POLICY || "if-missing";
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* 人类可读的「流程 / 需求总览」骨架路径(相对项目根)。仅本示例写入;可在业务项目中改路径或删除相关逻辑。
|
|
50
|
+
* @type {string}
|
|
51
|
+
*/
|
|
52
|
+
const FLOW_README_REL =
|
|
53
|
+
process.env.FIGMA_CACHE_FLOW_README || "docs/figma-flow-readme.md";
|
|
54
|
+
|
|
55
|
+
const FLOW_README_REGISTRY_BEGIN = "<!-- figma-cache-flow-readme: registry -->";
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @param {string} raw
|
|
59
|
+
* @returns {"cache-root" | "node" | "off"}
|
|
60
|
+
*/
|
|
61
|
+
function normalizeAdapterDocMode(raw) {
|
|
62
|
+
const value = String(raw || "")
|
|
63
|
+
.trim()
|
|
64
|
+
.toLowerCase();
|
|
65
|
+
if (value === "node" || value === "node-each") {
|
|
66
|
+
return "node";
|
|
67
|
+
}
|
|
68
|
+
if (value === "off" || value === "none" || value === "disable") {
|
|
69
|
+
return "off";
|
|
70
|
+
}
|
|
71
|
+
return "cache-root";
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @returns {boolean}
|
|
76
|
+
*/
|
|
77
|
+
function shouldOverwriteAdapterDoc() {
|
|
78
|
+
return String(ADAPTER_DOC_WRITE_POLICY || "")
|
|
79
|
+
.trim()
|
|
80
|
+
.toLowerCase() === "always";
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* @param {string} absPath
|
|
85
|
+
* @param {string} content
|
|
86
|
+
* @returns {boolean}
|
|
87
|
+
*/
|
|
88
|
+
function writeTextByPolicy(absPath, content) {
|
|
89
|
+
fs.mkdirSync(path.dirname(absPath), { recursive: true });
|
|
90
|
+
if (!shouldOverwriteAdapterDoc() && fs.existsSync(absPath)) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
fs.writeFileSync(absPath, content, "utf8");
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @param {object} ctx
|
|
99
|
+
* @returns {string}
|
|
100
|
+
*/
|
|
101
|
+
function buildCacheRootHint(ctx) {
|
|
102
|
+
return `# Figma 缓存 → UI 实现(目录级提示)
|
|
103
|
+
|
|
104
|
+
本文件由示例 \`postEnsure\` 生成,默认放在 **figma-cache 目录级**,用于避免“每个节点重复生成同一提示”。
|
|
105
|
+
|
|
106
|
+
- **默认来源优先级**:先用 \`raw.json\` / \`spec.md\` / \`meta.json\` / \`state-map.md\`,仅在缺口或冲突时再读 \`mcp-raw/*\`
|
|
107
|
+
- **证据约束**:同一设计事实只保留一个主证据来源,避免重复引用
|
|
108
|
+
- **命中检查**:先查本地缓存命中与字段覆盖,再决定是否需要 MCP 补齐
|
|
109
|
+
|
|
110
|
+
可选模式(环境变量):
|
|
111
|
+
- \`FIGMA_CACHE_ADAPTER_DOC_MODE=cache-root\`(默认)
|
|
112
|
+
- \`FIGMA_CACHE_ADAPTER_DOC_MODE=node\`(按节点写入)
|
|
113
|
+
- \`FIGMA_CACHE_ADAPTER_DOC_MODE=off\`(关闭)
|
|
114
|
+
|
|
115
|
+
最近触发:\`${ctx.cacheKey}\`(\`${ctx.syncedAt || ""}\`)
|
|
116
|
+
`;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* @param {object} ctx
|
|
121
|
+
* @returns {string}
|
|
122
|
+
*/
|
|
123
|
+
function buildNodeHint(ctx) {
|
|
124
|
+
const nodeLabel = ctx.nodeId == null ? "" : String(ctx.nodeId);
|
|
125
|
+
return `# Figma 缓存 → UI 实现(节点提示)
|
|
126
|
+
|
|
127
|
+
本文件由示例 \`postEnsure\` 生成。若你希望减少重复,可改用目录级模式:\`FIGMA_CACHE_ADAPTER_DOC_MODE=cache-root\`。
|
|
128
|
+
|
|
129
|
+
- **设计事实来源**(勿改写成框架代码):同目录 \`raw.json\`、\`spec.md\`、\`state-map.md\`、\`meta.json\`
|
|
130
|
+
- cacheKey: \`${ctx.cacheKey}\`
|
|
131
|
+
- fileKey: \`${ctx.fileKey}\`
|
|
132
|
+
- nodeId: \`${nodeLabel}\`
|
|
133
|
+
|
|
134
|
+
**流程 / 交互总览(可选)**:若使用本示例默认钩子,项目根下另有 **\`${FLOW_README_REL}\`**,随每次 \`ensure\` 追加节点小节,便于与 \`index.json\` 里的 \`flows\` 互补(人读 md,机读索引)。
|
|
135
|
+
`;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* @param {object} ctx
|
|
140
|
+
*/
|
|
141
|
+
function writeAdapterHint(ctx) {
|
|
142
|
+
if (ADAPTER_DOC_MODE === "off") {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (ADAPTER_DOC_MODE === "node") {
|
|
147
|
+
const metaAbs = path.resolve(ctx.root, ctx.paths.meta);
|
|
148
|
+
const nodeDir = path.dirname(metaAbs);
|
|
149
|
+
const target = path.join(nodeDir, ADAPTER_DOC_BASENAME);
|
|
150
|
+
writeTextByPolicy(target, buildNodeHint(ctx));
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const cacheRootTarget = path.resolve(ctx.root, ADAPTER_DOC_CACHE_REL);
|
|
155
|
+
writeTextByPolicy(cacheRootTarget, buildCacheRootHint(ctx));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* 在单文件里维护「已缓存节点」登记(按 cacheKey 幂等追加),与 index.json / flows 互补:适合评审与新人阅读。
|
|
160
|
+
* @param {object} ctx
|
|
161
|
+
*/
|
|
162
|
+
function appendFlowReadmeRegistry(ctx) {
|
|
163
|
+
const abs = path.resolve(ctx.root, FLOW_README_REL);
|
|
164
|
+
const marker = `<!-- cache-node:${ctx.cacheKey} -->`;
|
|
165
|
+
const specRel = normalizePosixPath(path.relative(ctx.root, path.resolve(ctx.root, ctx.paths.spec)));
|
|
166
|
+
const metaRel = normalizePosixPath(path.relative(ctx.root, path.resolve(ctx.root, ctx.paths.meta)));
|
|
167
|
+
const completeness = Array.isArray(ctx.completeness) && ctx.completeness.length ? ctx.completeness.join(", ") : "—";
|
|
168
|
+
const block =
|
|
169
|
+
`\n${marker}\n` +
|
|
170
|
+
`### \`${ctx.cacheKey}\`\n\n` +
|
|
171
|
+
`- **Figma**: ${ctx.url || "—"}\n` +
|
|
172
|
+
`- **syncedAt**: ${ctx.syncedAt || "—"}\n` +
|
|
173
|
+
`- **source**: ${ctx.source || "—"}\n` +
|
|
174
|
+
`- **completeness**: ${completeness}\n` +
|
|
175
|
+
`- **spec**: \`${specRel}\` · **meta**: \`${metaRel}\`\n` +
|
|
176
|
+
`- **提示**: 像素级还原以 \`spec.md\` / \`raw.json\` 为准;用户路径请维护 \`flows\` 后把 \`npm run figma:cache:flow mermaid\` 输出贴到下方「流程总览」。\n`;
|
|
177
|
+
|
|
178
|
+
if (!fs.existsSync(abs)) {
|
|
179
|
+
fs.mkdirSync(path.dirname(abs), { recursive: true });
|
|
180
|
+
const head =
|
|
181
|
+
`# 设计与流程说明(示例骨架)\n\n` +
|
|
182
|
+
`> 本文件由 **figma-cache.config.example.js** 的 \`postEnsure\` 自动创建并增量更新;**可整文件改写**或复制逻辑到自有 \`figma-cache.config.js\`。\n\n` +
|
|
183
|
+
`## 流程总览(手填 / 或粘贴 mermaid)\n\n` +
|
|
184
|
+
`用自然语言写用户路径,或粘贴 \`npm run figma:cache:flow mermaid -- --flow=<flowId>\` 的输出:\n\n` +
|
|
185
|
+
`\`\`\`mermaid\n%% flow mermaid 输出贴此处\n\`\`\`\n\n` +
|
|
186
|
+
`## 交互与边界(手填)\n\n` +
|
|
187
|
+
`- 分支条件:\n` +
|
|
188
|
+
`- 异常与空状态:\n\n` +
|
|
189
|
+
`## 已从 Figma 写入缓存的节点(钩子按节点幂等追加)\n\n` +
|
|
190
|
+
`${FLOW_README_REGISTRY_BEGIN}\n`;
|
|
191
|
+
fs.writeFileSync(abs, head + block + "\n", "utf8");
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
let body = fs.readFileSync(abs, "utf8");
|
|
196
|
+
if (body.includes(marker)) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
if (!body.includes(FLOW_README_REGISTRY_BEGIN)) {
|
|
200
|
+
body =
|
|
201
|
+
body.trimEnd() +
|
|
202
|
+
`\n\n## 已从 Figma 写入缓存的节点(钩子按节点幂等追加)\n\n${FLOW_README_REGISTRY_BEGIN}\n`;
|
|
203
|
+
}
|
|
204
|
+
fs.writeFileSync(abs, body.trimEnd() + block + "\n", "utf8");
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* @param {string} p
|
|
209
|
+
* @returns {string}
|
|
210
|
+
*/
|
|
211
|
+
function normalizePosixPath(p) {
|
|
212
|
+
return p.split(path.sep).join("/");
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
module.exports = {
|
|
216
|
+
buildCacheRootHint,
|
|
217
|
+
buildNodeHint,
|
|
218
|
+
ADAPTER_DOC_BASENAME,
|
|
219
|
+
ADAPTER_DOC_MODE,
|
|
220
|
+
ADAPTER_DOC_CACHE_REL,
|
|
221
|
+
ADAPTER_DOC_WRITE_POLICY,
|
|
222
|
+
FLOW_README_REL,
|
|
223
|
+
appendFlowReadmeRegistry,
|
|
224
|
+
|
|
225
|
+
hooks: {
|
|
226
|
+
/**
|
|
227
|
+
* 默认实现:目录级 adapter 提示(避免节点重复)+ 项目根下「流程/需求」总览骨架(单文件、幂等追加节点块)。
|
|
228
|
+
* 用 Agent 生成业务方案后,可整体替换本模块逻辑。
|
|
229
|
+
*/
|
|
230
|
+
postEnsure(ctx) {
|
|
231
|
+
try {
|
|
232
|
+
writeAdapterHint(ctx);
|
|
233
|
+
appendFlowReadmeRegistry(ctx);
|
|
234
|
+
} catch (err) {
|
|
235
|
+
console.error(`[figma-cache.config] postEnsure: ${err.message}`);
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
},
|
|
139
239
|
};
|
|
@@ -28,7 +28,7 @@ alwaysApply: true
|
|
|
28
28
|
</Trigger Conditions>
|
|
29
29
|
|
|
30
30
|
## 执行顺序
|
|
31
|
-
1. 按 `figma-cache/link-normalization-spec.md` 标准化链接。
|
|
31
|
+
1. 按 `figma-cache/docs/link-normalization-spec.md` 标准化链接。
|
|
32
32
|
2. 读本地 `index.json` 判断是否命中。
|
|
33
33
|
3. 命中且字段满足任务 → 只读本地,不调 MCP。
|
|
34
34
|
4. 未命中或不足 → MCP 拉取并回写通用缓存文件。
|
|
@@ -42,12 +42,24 @@ alwaysApply: true
|
|
|
42
42
|
- `interactions` / `flow` / `states` → `get_design_context` + `state-map.md`/`flows` 回写
|
|
43
43
|
- `accessibility`(若任务声明)→ 优先 `get_design_context` 的语义线索,不足时标注缺口
|
|
44
44
|
- `assets`(若任务声明)→ `get_design_context` 中资产 URL;仅当用户要求截图留档再调 `get_screenshot`
|
|
45
|
+
- **flow 自动追加白名单(强制)**:默认 completeness 基线为 `layout,text,tokens,interactions,states,accessibility`(不含 `flow`);仅在命中白名单时自动追加 `flow`:
|
|
46
|
+
- 用户明确表达关系/流程意图,且语义命中关键词:`关联`、`流程`、`跳转`、`前后页`、`上一步`、`下一步`、`分支`、`链路`、`路径`、`from/to`、`next`、`branch`
|
|
47
|
+
- 同轮或断续出现多个 Figma 链接,且存在明确先后或串联意图(如 A->B)
|
|
48
|
+
- 单链接且无关系意图、仅视觉微调、仅资产导出时,禁止自动追加 `flow`
|
|
45
49
|
9. **两阶段拉取**:先按最小必要工具取数并检查字段缺口;仅在缺口存在时进入第二阶段补调工具。
|
|
46
50
|
10. **写入一致性门禁(强制)**:当 `source=figma-mcp` 或输出来源标注 MCP 时,节点目录必须存在 `mcp-raw/` 与对应原始文件;若缺失则视为未完成,必须停止并报告,不得宣称“更新成功”。
|
|
47
|
-
11.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
11. **严格证据门禁(强制)**:当 `source=figma-mcp` 且未显式传入 `--allow-skeleton-with-figma-mcp` 时,`upsert/ensure` 必须在写入前校验 `mcp-raw` 证据:
|
|
52
|
+
- `layout` 至少命中 `get_metadata` 或 `get_design_context`
|
|
53
|
+
- `text/interactions/states/accessibility/flow/assets` 必须命中 `get_design_context`
|
|
54
|
+
- `tokens` 必须命中 `get_variable_defs`
|
|
55
|
+
任一维度缺证据即失败退出,不得写入成功状态。
|
|
56
|
+
12. **严格 validate(强制)**:`validate` 不仅校验索引字段,还校验证据完整性:
|
|
57
|
+
- `completeness` 声明的维度必须在 `raw.json.coverageSummary.evidence` 中提供非空证据
|
|
58
|
+
- 对 `source=figma-mcp` 且声明 `interactions/states/accessibility` 的节点,禁止保留 TODO 占位内容
|
|
59
|
+
13. **大文件读取策略(强制)**:仅在 UI 还原/像素对齐/组件实现任务中读取 `mcp-raw-get-design-context.txt` 全文;非 UI 任务(命中检查、预算统计、校验、流程维护)默认仅读取 `raw.json` / `spec.md` / `mcp-raw-manifest.json`。
|
|
60
|
+
14. **闭环校验(强制)**:每次 **`npm run figma:cache:upsert`** 或 **`npm run figma:cache:ensure`** 成功结束后,**自动静默**执行 `npm run figma:cache:validate`。
|
|
61
|
+
15. validate 失败 → **自行修复并重复 validate 直至通过**,不得宣称缓存已就绪。
|
|
62
|
+
16. **不写前端**:本阶段禁止输出业务组件实现;若用户要求写 UI,在缓存就绪后转由 **栈专属 Adapter 规则**(如 `02-figma-stack-adapter.mdc` 占位,或项目内 `02-figma-<栈>-adapter.mdc`)接管。
|
|
51
63
|
|
|
52
64
|
## Agent 最终输出格式(强制)
|
|
53
65
|
凡触发 `<Trigger Conditions>` 且本轮涉及缓存读写的回复,**正文第一段**必须为单行 Blockquote:
|
|
@@ -56,6 +68,8 @@ alwaysApply: true
|
|
|
56
68
|
|
|
57
69
|
(语义与 `index.json` 中 `nodeId` / `__FILE__` 约定同前;Blockquote 后再写结论。)
|
|
58
70
|
|
|
71
|
+
- 若本轮自动追加了 `flow`,必须在回复中显式写明触发原因:`关键词命中` 或 `多链接串联意图`(二选一或同时命中)。
|
|
72
|
+
|
|
59
73
|
## 配置与钩子
|
|
60
74
|
- `npm run figma:cache:config` 可查看是否加载 `hooks.postEnsure`。
|
|
61
75
|
- `ensure` 在写入通用骨架后会调用 `hooks.postEnsure`;钩子异常**不得**阻断 ensure 成功退出(由 Core 捕获)。
|
|
@@ -69,3 +83,26 @@ alwaysApply: true
|
|
|
69
83
|
- 单节点 MCP 调用预算默认不超过 3 次;超过时必须在输出中说明缺口字段与补调原因。
|
|
70
84
|
- 仅对超时/5xx做指数退避重试;对参数错误/权限错误不重试,直接报告并等待用户指令。
|
|
71
85
|
- 不在未校验时假定 Figma 为最新;用户显式要求实时读取时须遵守。
|
|
86
|
+
## Encoding, Shell 兼容与安全写入(强制)
|
|
87
|
+
- 仓库内 README / mdc / SKILL / json / js 等文本文件默认使用 **UTF-8 无 BOM**。
|
|
88
|
+
- Node 写文件必须显式指定 utf8(如 writeFileSync(path, text, "utf8"))。
|
|
89
|
+
- 在 Windows PowerShell 下,**禁止**把 Set-Content / Out-File -Encoding utf8 作为 js/mdc/md/json 的默认写入方式(可能写出 BOM)。
|
|
90
|
+
- 若必须用 PowerShell 写文本文件,使用无 BOM 写法:
|
|
91
|
+
- `$enc = New-Object System.Text.UTF8Encoding($false)`
|
|
92
|
+
- `[System.IO.File]::WriteAllText($path, $text, $enc)`
|
|
93
|
+
|
|
94
|
+
## Shell 语法兼容(PowerShell 强制)
|
|
95
|
+
- 当前终端为 PowerShell 时,**禁止**使用 bash heredoc(如 `<<'EOF'`、`<<'PY'`)。
|
|
96
|
+
- 当前终端为 PowerShell 时,命令串联默认使用 `;`(或拆成多次调用),**禁止**使用 `&&`。
|
|
97
|
+
- 多行文本注入优先使用 PowerShell here-string(`@' ... '@` 或 `@" ... "@`)。
|
|
98
|
+
- 文本替换时,禁止把字面量 `\n` / `` `n `` 当作真实换行依赖;必须写入真实换行并回读确认。
|
|
99
|
+
|
|
100
|
+
## 写后必检(强制)
|
|
101
|
+
- 每次脚本化写入后,必须立刻回读目标文件,确认无字面量 `\n`、`` `n ``、乱码、截断。
|
|
102
|
+
- 对 shebang 文件(如 `#!/usr/bin/env node`),必须确认文件首字节无 BOM。
|
|
103
|
+
- 修改 README / rules / skills 后,必须执行 `npm run docs:encoding:check`(或等价编码检查)并确认通过。
|
|
104
|
+
|
|
105
|
+
## 故障恢复(强制)
|
|
106
|
+
- 一旦出现 BOM、乱码、PowerShell 语法不兼容、转义换行误写,立即停止增量替换。
|
|
107
|
+
- 先回读定位受影响文件,再用 UTF-8 无 BOM 方式整段重写,最后重新执行验证命令。
|
|
108
|
+
|
|
@@ -47,10 +47,13 @@ description: 将 Figma 链接信息沉淀到项目本地缓存并执行缓存优
|
|
|
47
47
|
|
|
48
48
|
## 流程关系(Flow)
|
|
49
49
|
- `figma-cache/index.json` 中的 `flows` 用于维护业务/交互流程的节点集合与边关系。
|
|
50
|
-
- 当用户描述「下一步/分支/同一流程」时,应同步更新对应 `flow` 的 `nodes/edges`。
|
|
50
|
+
- 当用户描述「下一步/分支/同一流程」时,应同步更新对应 `flow` 的 `nodes/edges`。
|
|
51
|
+
- 默认 completeness 不含 `flow`;仅命中 flow 白名单时自动追加。
|
|
52
|
+
- flow 白名单:关系关键词(关联/流程/跳转/前后页/上一步/下一步/分支/链路/路径/from/to/next/branch),或同轮/断续多链接且明确串联意图。
|
|
53
|
+
- 不触发:单链接且无关系意图、仅视觉微调、仅资产导出。
|
|
51
54
|
|
|
52
55
|
## 标准流程
|
|
53
|
-
1. 按 `figma-cache/link-normalization-spec.md` 标准化链接并生成键:
|
|
56
|
+
1. 按 `figma-cache/docs/link-normalization-spec.md` 标准化链接并生成键:
|
|
54
57
|
- 节点级:`cacheKey = <fileKey>#<nodeId>`
|
|
55
58
|
- 文件级(无 `node-id`):`cacheKey = <fileKey>#__FILE__`
|
|
56
59
|
2. 读取 `index.json`:
|
|
@@ -139,7 +142,7 @@ description: 将 Figma 链接信息沉淀到项目本地缓存并执行缓存优
|
|
|
139
142
|
"raw": "figma-cache/files/xxxx/nodes/12-34/raw.json"
|
|
140
143
|
},
|
|
141
144
|
"syncedAt": "2026-04-14T12:00:00Z",
|
|
142
|
-
"completeness": ["layout", "text", "tokens", "interactions"]
|
|
145
|
+
"completeness": ["layout", "text", "tokens", "interactions", "states", "accessibility"]
|
|
143
146
|
}
|
|
144
147
|
}
|
|
145
148
|
}
|
|
@@ -167,8 +170,10 @@ description: 将 Figma 链接信息沉淀到项目本地缓存并执行缓存优
|
|
|
167
170
|
- `npm run figma:cache:init`:初始化空索引(用于纯净移植)
|
|
168
171
|
- `npm run figma:cache:config`:查看当前生效配置
|
|
169
172
|
- `npm run figma:cache:get -- "<figma-url>"`:检查命中情况
|
|
170
|
-
- 先执行 MCP 最小调用集并写入 `mcp-raw/`,再执行:`npm run figma:cache:upsert -- "<figma-url>" --source=figma-mcp --completeness=layout,text,tokens,interactions,
|
|
171
|
-
- `npm run figma:cache:ensure -- "<figma-url>" --source=manual --completeness=layout,text,tokens,interactions,
|
|
173
|
+
- 先执行 MCP 最小调用集并写入 `mcp-raw/`,再执行:`npm run figma:cache:upsert -- "<figma-url>" --source=figma-mcp --completeness=layout,text,tokens,interactions,states,accessibility`
|
|
174
|
+
- `npm run figma:cache:ensure -- "<figma-url>" --source=manual --completeness=layout,text,tokens,interactions,states,accessibility`:自动补齐缓存骨架文件(非 MCP 拉取)
|
|
175
|
+
- 若命中 flow 白名单场景,自动或显式追加:`--completeness=layout,text,tokens,interactions,states,accessibility,flow`
|
|
176
|
+
- 一旦自动追加了 `flow`,对用户回复必须附带触发原因:`关键词命中` 或 `多链接串联意图`。
|
|
172
177
|
- MCP 默认最小调用集:`get_design_context(excludeScreenshot=true)` + `get_metadata` + `get_variable_defs`
|
|
173
178
|
- `npm run figma:cache:validate`:**每次 upsert/ensure 成功后必须自动执行**;失败则修至通过
|
|
174
179
|
- `npm run figma:cache:budget`:查看 MCP 节点预算汇总(默认 `--mcp-only`,按文件大小估算 token 代理)
|
|
@@ -26,10 +26,10 @@
|
|
|
26
26
|
- `figma-cache/figma-cache.js`:缓存流程脚本主入口
|
|
27
27
|
- `figma-cache/index.json`:全量索引
|
|
28
28
|
- `figma-cache/files/...`:节点缓存内容
|
|
29
|
-
- **`figma-cache/README.md`**:接入、scripts、环境变量、人工校验与回填(本文件,随包分发的主文档)
|
|
30
|
-
- **`figma-cache/colleague-guide-zh.md`**:团队向说明与提示词模板;**`npx figma-cache cursor init` 会写入/刷新**(与 `FIGMA_CACHE_DIR` 下路径一致),便于纳入版本库、不必从 `node_modules` 手抄
|
|
31
|
-
- `figma-cache/link-normalization-spec.md`:链接标准化规则(Core / Skill 会引用)
|
|
32
|
-
- `figma-cache/flow-edge-taxonomy.md`:流程边类型约定
|
|
29
|
+
- **`figma-cache/docs/README.md`**:接入、scripts、环境变量、人工校验与回填(本文件,随包分发的主文档)
|
|
30
|
+
- **`figma-cache/docs/colleague-guide-zh.md`**:团队向说明与提示词模板;**`npx figma-cache cursor init` 会写入/刷新**(与 `FIGMA_CACHE_DIR` 下路径一致),便于纳入版本库、不必从 `node_modules` 手抄
|
|
31
|
+
- `figma-cache/docs/link-normalization-spec.md`:链接标准化规则(Core / Skill 会引用)
|
|
32
|
+
- `figma-cache/docs/flow-edge-taxonomy.md`:流程边类型约定
|
|
33
33
|
|
|
34
34
|
## 默认配置
|
|
35
35
|
|
|
@@ -52,19 +52,31 @@ $env:FIGMA_DEFAULT_FLOW="sip-calling-phase1"
|
|
|
52
52
|
npm run figma:cache:config
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
-
## 常用命令(通常由 agent 自动执行)
|
|
55
|
+
## 常用命令(通常由 agent 自动执行)
|
|
56
|
+
|
|
57
|
+
- `npm run figma:cache:init`
|
|
58
|
+
- `npm run figma:cache:get -- "<figma-url>"`
|
|
59
|
+
- `npm run figma:cache:ensure -- "<figma-url>" --source=manual --completeness=layout,text,tokens,interactions,states,accessibility`
|
|
60
|
+
- `npm run figma:cache:upsert -- "<figma-url>" --source=figma-mcp --completeness=layout,text,tokens,interactions,states,accessibility`
|
|
61
|
+
- `npm run figma:cache:upsert -- "<figma-url>" --source=figma-mcp --completeness=layout,text,tokens --allow-skeleton-with-figma-mcp`(仅写骨架,后续仍需 `validate` 通过)
|
|
62
|
+
- `npm run figma:cache:ensure -- "<figma-url>" --source=figma-mcp --completeness=layout,text,tokens --allow-skeleton-with-figma-mcp`(仅写骨架,后续仍需 `validate` 通过)
|
|
63
|
+
- 若不传 `--completeness`,CLI 默认即使用:`layout,text,tokens,interactions,states,accessibility`
|
|
64
|
+
- 自动追加 `flow` 仅限白名单:关系关键词(关联/流程/跳转/前后页/上一步/下一步/分支/链路/路径/from/to/next/branch),或同轮/断续多链接且明确先后/串联意图
|
|
65
|
+
- 单链接且无关系意图、仅视觉微调、仅资产导出时,不自动追加 `flow`
|
|
66
|
+
- 若自动追加了 `flow`,Agent 输出中必须记录触发原因:`关键词命中` 或 `多链接串联意图`
|
|
67
|
+
- `npm run figma:cache:validate`
|
|
68
|
+
- `npm run figma:cache:budget`(默认 `--mcp-only`)
|
|
69
|
+
- `npm run figma:cache:stale`
|
|
70
|
+
- `npm run figma:cache:backfill`
|
|
71
|
+
> 注意:`ensure` 默认职责是“写索引 + 生成骨架文件”,不是 MCP 拉取器。
|
|
72
|
+
> 当 `upsert/ensure` 传 `--source=figma-mcp` 且未显式允许骨架模式时,CLI 会先执行 MCP 原始证据门禁(缺失即失败,退出码 2)。
|
|
73
|
+
> 正确流程是先由 Agent/Figma MCP 获取最小调用集并写入 `mcp-raw/`,再执行 `upsert/ensure` 与 `validate`。
|
|
56
74
|
|
|
57
|
-
|
|
58
|
-
- `npm run figma:cache:get -- "<figma-url>"`
|
|
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`
|
|
61
|
-
- `npm run figma:cache:validate`
|
|
62
|
-
- `npm run figma:cache:budget`(默认 `--mcp-only`)
|
|
63
|
-
- `npm run figma:cache:stale`
|
|
64
|
-
- `npm run figma:cache:backfill`
|
|
75
|
+
### 严格 validate 规则(默认)
|
|
65
76
|
|
|
66
|
-
|
|
67
|
-
|
|
77
|
+
- `validate` 会检查 `raw.json.coverageSummary.evidence` 与 `completeness` 是否一致。
|
|
78
|
+
- 当 `source=figma-mcp` 且声明 `interactions/states/accessibility` 时,不允许保留 TODO 占位说明。
|
|
79
|
+
- 若你仅想先落骨架,可使用 `--allow-skeleton-with-figma-mcp`(仅放行 upsert/ensure 写入,不放行 validate);后续必须补齐证据并通过 `validate`。
|
|
68
80
|
|
|
69
81
|
### 预算统计(token/调用)
|
|
70
82
|
|
|
@@ -97,7 +109,7 @@ npm run figma:cache:config
|
|
|
97
109
|
3. 当你描述跳转/下一步/分支:用 `flow link`;批量默认串联可用 `flow chain`
|
|
98
110
|
4. 定期 `validate`;需要看图用 `flow mermaid`
|
|
99
111
|
|
|
100
|
-
边类型约定见:`figma-cache/flow-edge-taxonomy.md`
|
|
112
|
+
边类型约定见:`figma-cache/docs/flow-edge-taxonomy.md`
|
|
101
113
|
|
|
102
114
|
## 纯净版初始化
|
|
103
115
|
|
|
@@ -165,7 +177,10 @@ npm run figma:cache:init
|
|
|
165
177
|
| `FIGMA_ITERATIONS_DIR` | **仅** `backfill` 扫描的历史 Markdown 目录;不存在时扫描为空,`validate` 不受影响 |
|
|
166
178
|
| `FIGMA_CACHE_STALE_DAYS` | 陈旧阈值(天) |
|
|
167
179
|
| `FIGMA_DEFAULT_FLOW` | 默认 `flowId`(大迭代推荐设置) |
|
|
168
|
-
| `FIGMA_CACHE_ADAPTER_DOC` | 覆盖
|
|
180
|
+
| `FIGMA_CACHE_ADAPTER_DOC` | 覆盖 adapter 提示文档基础名(默认 `figma-cache-adapter-hint.md`) |
|
|
181
|
+
| `FIGMA_CACHE_ADAPTER_DOC_MODE` | adapter 提示写入模式:`cache-root`(默认,目录级单文件)/ `node`(按节点)/ `off`(关闭) |
|
|
182
|
+
| `FIGMA_CACHE_ADAPTER_DOC_CACHE` | `cache-root` 模式下 adapter 提示文档路径(相对项目根,默认 `figma-cache/docs/figma-cache-adapter-hint.md`) |
|
|
183
|
+
| `FIGMA_CACHE_ADAPTER_DOC_WRITE_POLICY` | adapter 提示写入策略:`if-missing`(默认)/ `always` |
|
|
169
184
|
| `FIGMA_CACHE_FLOW_README` | **仅包内示例钩子**:人类可读的「流程 / 需求总览」Markdown 相对路径,默认 **`docs/figma-flow-readme.md`**;每次 `ensure` 对**新 cacheKey** 幂等追加一节 |
|
|
170
185
|
|
|
171
186
|
## 人工校验清单(对照 `validate`)
|
|
@@ -174,8 +189,9 @@ npm run figma:cache:init
|
|
|
174
189
|
- 记录包含 `fileKey` / `scope` / `url` / `syncedAt`
|
|
175
190
|
- `normalizationVersion` 与当前规范一致
|
|
176
191
|
- `paths.meta` 与 `paths.spec` 已定义
|
|
177
|
-
- `completeness`
|
|
192
|
+
- `completeness` 覆盖当前任务字段,且在 `raw.json.coverageSummary.evidence` 有非空对应证据
|
|
178
193
|
- `scope=node` 时存在 `nodeId`
|
|
194
|
+
- 对 `source=figma-mcp` 节点,`interactions/states/accessibility` 不得仅为 TODO 占位
|
|
179
195
|
- 若维护了 `flows`,边的 `from` / `to` 必须存在于 `items`
|
|
180
196
|
|
|
181
197
|
## 历史链接回填(backfill)
|
|
@@ -202,7 +218,7 @@ npm run figma:cache:stale
|
|
|
202
218
|
|
|
203
219
|
`hooks.postEnsure` 会做两件事(均在 **Core 写完通用骨架之后**):
|
|
204
220
|
|
|
205
|
-
1.
|
|
221
|
+
1. **adapter 提示文档(默认目录级)**:默认在 **`figma-cache/docs/figma-cache-adapter-hint.md`** 写入单文件(可由 `FIGMA_CACHE_ADAPTER_DOC_CACHE` 覆盖),避免每节点重复;如需按节点写入,可设 `FIGMA_CACHE_ADAPTER_DOC_MODE=node`。
|
|
206
222
|
2. **项目根**:维护或创建 **`docs/figma-flow-readme.md`**(路径可由 **`FIGMA_CACHE_FLOW_README`** 覆盖)— 含「流程总览 / 交互边界」**手填区**,以及按 **`cacheKey` 幂等追加**的「已从 Figma 写入缓存的节点」登记(含 Figma 链接、`syncedAt`、`completeness`、相对 `spec`/`meta` 路径)。**像素级还原**仍以各节点 **`spec.md`** 为准;**用户路径图**请继续用 CLI **`flow`** 维护 `index.json`,再把 **`flow mermaid`** 贴进该 md 的 mermaid 代码块,便于评审与新人阅读。
|
|
207
223
|
|
|
208
224
|
`postEnsure` 的 **`ctx`** 还包含 **`url` / `source` / `syncedAt` / `completeness`**(与 `index.json` 中 item 一致),便于自定义钩子写文档或触发 CI。
|
|
@@ -210,3 +226,10 @@ npm run figma:cache:stale
|
|
|
210
226
|
## 包维护者
|
|
211
227
|
|
|
212
228
|
维护 **`figma-cache-toolchain` 源码**时:见**仓库根** `README.md`(发布)与 `CHANGELOG.md`;修改 `cursor-bootstrap/`(含 `AGENT-SETUP-PROMPT.md`)或 CLI 后 bump 版本并 `npm publish`,消费方 `cursor init` 才会刷新到最新任务书。将 Core 抽成独立包、semver 与 `ctx` 约定等,可在发包前对照 `CHANGELOG` 与 `npm publish --dry-run`。
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
|