figma-cache-toolchain 2.0.2 → 2.0.3
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 +2 -2
- package/cursor-bootstrap/AGENT-SETUP-PROMPT.md +43 -70
- package/cursor-bootstrap/examples/README.md +10 -6
- package/cursor-bootstrap/examples/generated-ui-reset.css.template +32 -0
- package/cursor-bootstrap/managed-files.json +41 -0
- package/cursor-bootstrap/rules/02-figma-stack-adapter.mdc +15 -25
- package/cursor-bootstrap/rules/03-figma-ui-implementation-hard-constraints.mdc +58 -91
- package/cursor-bootstrap/rules/04-ui-baseline-governance.mdc +35 -86
- package/cursor-bootstrap/skills/figma-ui-dual-mode-execution/SKILL.md +37 -50
- package/figma-cache/docs/README.md +1 -1
- package/figma-cache/figma-cache.js +10 -4
- package/figma-cache/js/cursor-bootstrap-cli.js +218 -202
- package/package.json +75 -74
- package/cursor-bootstrap/skills/ui-baseline-governance/SKILL.md +0 -51
|
@@ -1,50 +1,37 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: figma-ui-dual-mode-execution
|
|
3
|
-
description: 仅用 nodeId
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Figma UI Dual Mode Execution
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
- 禁止使用 Figma 临时远程资产 URL 作为运行时图标。
|
|
40
|
-
- 图标优先项目图标系统;无则 `inline svg`。
|
|
41
|
-
- 默认按 `border-box` 思维实现;弹层必须锚定触发器。
|
|
42
|
-
|
|
43
|
-
## 固定输出
|
|
44
|
-
|
|
45
|
-
1. 缓存定位结果(命中节点目录)
|
|
46
|
-
2. 事实对齐清单(结构/文案/token/状态/交互)
|
|
47
|
-
3. 变更文件列表
|
|
48
|
-
4. 关键设计值 -> 代码映射
|
|
49
|
-
5. lint/验证结果
|
|
50
|
-
6. 未决问题(如有)
|
|
1
|
+
---
|
|
2
|
+
name: figma-ui-dual-mode-execution
|
|
3
|
+
description: 仅用 nodeId 或 Figma 链接触发 UI 实现,支持 L0/L1/L2 压缩级别,并内置基线判型与 B0/B1/B2 选择。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Figma UI Dual Mode Execution(分级)
|
|
7
|
+
|
|
8
|
+
## 执行步骤(固定)
|
|
9
|
+
1. 规范化 nodeId 并命中缓存目录。
|
|
10
|
+
2. 读取 `spec/raw/state-map/design-context`。
|
|
11
|
+
3. 选择压缩级别:L0/L1/L2(默认 L1)。
|
|
12
|
+
4. 输出事实对齐清单并实现挂载。
|
|
13
|
+
5. lint 验证并输出映射结论。
|
|
14
|
+
|
|
15
|
+
## 压缩级别
|
|
16
|
+
- L0:高保真严格流程(预检文档 + 完整状态)。
|
|
17
|
+
- L1:标准流程(精简清单 + 核心状态)。
|
|
18
|
+
- L2:快速看效果(先静态后补交互)。
|
|
19
|
+
|
|
20
|
+
## 基线治理(并入)
|
|
21
|
+
- 项目判型:新项目 / 老项目 / 不确定(不确定按老项目)。
|
|
22
|
+
- 基线级别:B0/B1/B2(老项目默认 B0)。
|
|
23
|
+
- B0(默认):
|
|
24
|
+
- 复制模板到 `src/styles/generated-ui-reset.css`
|
|
25
|
+
- 入口单次引入
|
|
26
|
+
- 生成组件根节点加 `generate-ui-reset`
|
|
27
|
+
- B1:仅新页面/模块范围启用作用域基线。
|
|
28
|
+
- B2:全局基线,仅新项目或明确授权。
|
|
29
|
+
- 若与规则冲突,以 `.cursor/rules/04-ui-baseline-governance.mdc` 为准。
|
|
30
|
+
|
|
31
|
+
## 标签口径
|
|
32
|
+
- 默认 `div/span/img`
|
|
33
|
+
- 默认禁 `p/ul/li/ol/h1-h6`
|
|
34
|
+
- `input/select/textarea/a` 允许
|
|
35
|
+
- 原生 `button` 默认禁用(封装/UI 库按钮除外)
|
|
36
|
+
- `role/aria-*` 默认不强制
|
|
37
|
+
- `data-node-id/data-name` 默认不输出
|
|
@@ -134,7 +134,7 @@ npm run figma:cache:init
|
|
|
134
134
|
- **项目根**仍需:`figma-cache.config.js`、`.cursor/` 规则与 Skill、`AGENT-SETUP-PROMPT.md`(或由等价流程生成)。
|
|
135
135
|
- Vue2+Vuetify2 参考 Adapter:`cursor-bootstrap/examples/vue2-vuetify2-adapter.reference.mdc`(npm 安装时在 `node_modules/.../cursor-bootstrap/examples/`)。
|
|
136
136
|
|
|
137
|
-
说明:Cursor **不会**在 `npm install` 时写入 `.cursor/`;`npx figma-cache cursor init` 负责从包内复制模板。`cursor init`
|
|
137
|
+
说明:Cursor **不会**在 `npm install` 时写入 `.cursor/`;`npx figma-cache cursor init` 负责从包内复制模板。`cursor init` 默认**保留**同名模板(安全模式);使用 `--overwrite` 可覆盖为最新版本;并会下发通用低 token 规则 `00-output-token-budget.mdc`;**`AGENT-SETUP-PROMPT.md` 每次 `cursor init` 均刷新**。
|
|
138
138
|
|
|
139
139
|
## package.json scripts 示例
|
|
140
140
|
|
|
@@ -353,7 +353,7 @@ function run() {
|
|
|
353
353
|
console.log(` ${ex} flow show --flow=<flowId>`);
|
|
354
354
|
console.log(` ${ex} flow mermaid --flow=<flowId>`);
|
|
355
355
|
console.log(
|
|
356
|
-
`${ex} cursor init [--force] # default
|
|
356
|
+
`${ex} cursor init [--overwrite] [--force] # default safe mode; --overwrite forces replacement; --force keeps legacy behavior (no overwrite)`,
|
|
357
357
|
);
|
|
358
358
|
process.exit(1);
|
|
359
359
|
}
|
|
@@ -362,12 +362,18 @@ function run() {
|
|
|
362
362
|
const sub = args[0];
|
|
363
363
|
if (sub !== "init") {
|
|
364
364
|
console.error(
|
|
365
|
-
"Usage: figma-cache cursor init [--force] #
|
|
365
|
+
"Usage: figma-cache cursor init [--overwrite] [--force] # --overwrite replaces existing templates; --force keeps legacy no-overwrite behavior",
|
|
366
366
|
);
|
|
367
367
|
process.exit(1);
|
|
368
368
|
}
|
|
369
|
-
const
|
|
370
|
-
|
|
369
|
+
const hasOverwrite = args.includes("--overwrite");
|
|
370
|
+
const hasForce = args.includes("--force");
|
|
371
|
+
if (hasOverwrite && hasForce) {
|
|
372
|
+
console.error("Do not use --overwrite and --force together. Choose one mode.");
|
|
373
|
+
process.exit(1);
|
|
374
|
+
}
|
|
375
|
+
const overwrite = hasOverwrite;
|
|
376
|
+
copyCursorBootstrap({ overwrite, legacyForce: hasForce }, {
|
|
371
377
|
fs,
|
|
372
378
|
path,
|
|
373
379
|
ROOT,
|
|
@@ -1,202 +1,218 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
|
-
|
|
3
|
-
function readUtf8IfExists(fs, absPath) {
|
|
4
|
-
if (!fs.existsSync(absPath)) {
|
|
5
|
-
return "";
|
|
6
|
-
}
|
|
7
|
-
return fs.readFileSync(absPath, "utf8");
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
function
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
if (fs.existsSync(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
fs.
|
|
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
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
|
|
3
|
+
function readUtf8IfExists(fs, absPath) {
|
|
4
|
+
if (!fs.existsSync(absPath)) {
|
|
5
|
+
return "";
|
|
6
|
+
}
|
|
7
|
+
return fs.readFileSync(absPath, "utf8");
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function loadManagedManifest({ fs, path, CURSOR_BOOTSTRAP_DIR, normalizeSlash }) {
|
|
11
|
+
const manifestPath = path.join(CURSOR_BOOTSTRAP_DIR, "managed-files.json");
|
|
12
|
+
if (!fs.existsSync(manifestPath)) {
|
|
13
|
+
console.error(`[figma-cache] missing managed files manifest: ${normalizeSlash(manifestPath)}`);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let parsed;
|
|
18
|
+
try {
|
|
19
|
+
parsed = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
|
|
20
|
+
} catch (error) {
|
|
21
|
+
console.error(`[figma-cache] invalid managed files manifest: ${error.message}`);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const { managedFiles, retiredFiles } = parsed || {};
|
|
26
|
+
if (!Array.isArray(managedFiles) || managedFiles.length === 0) {
|
|
27
|
+
console.error("[figma-cache] managed-files.json must contain non-empty managedFiles");
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const pairs = managedFiles.map((item, index) => {
|
|
32
|
+
if (!item || typeof item.from !== "string" || typeof item.to !== "string") {
|
|
33
|
+
console.error(`[figma-cache] invalid managedFiles[${index}] item`);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
from: item.from,
|
|
38
|
+
to: item.to,
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const retired = Array.isArray(retiredFiles)
|
|
43
|
+
? retiredFiles.filter((item) => typeof item === "string" && item.trim())
|
|
44
|
+
: [];
|
|
45
|
+
|
|
46
|
+
return { pairs, retired };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function copyCursorBootstrap(options, deps) {
|
|
50
|
+
const {
|
|
51
|
+
fs,
|
|
52
|
+
path,
|
|
53
|
+
ROOT,
|
|
54
|
+
CACHE_DIR,
|
|
55
|
+
CURSOR_BOOTSTRAP_DIR,
|
|
56
|
+
normalizeSlash,
|
|
57
|
+
readSelfNpmPackageName,
|
|
58
|
+
packageDir,
|
|
59
|
+
} = deps;
|
|
60
|
+
const {
|
|
61
|
+
overwrite = false,
|
|
62
|
+
legacyForce = false,
|
|
63
|
+
} = options || {};
|
|
64
|
+
|
|
65
|
+
const { pairs, retired } = loadManagedManifest({ fs, path, CURSOR_BOOTSTRAP_DIR, normalizeSlash });
|
|
66
|
+
|
|
67
|
+
if (!fs.existsSync(CURSOR_BOOTSTRAP_DIR)) {
|
|
68
|
+
console.error(
|
|
69
|
+
`[figma-cache] cursor-bootstrap not found at ${normalizeSlash(CURSOR_BOOTSTRAP_DIR)} (broken package install?)`
|
|
70
|
+
);
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
let copied = 0;
|
|
75
|
+
let skipped = 0;
|
|
76
|
+
pairs.forEach(({ from: relFrom, to: relTo }) => {
|
|
77
|
+
const absFrom = path.join(CURSOR_BOOTSTRAP_DIR, relFrom);
|
|
78
|
+
const absTo = path.join(ROOT, relTo);
|
|
79
|
+
if (!fs.existsSync(absFrom)) {
|
|
80
|
+
console.error(`[figma-cache] missing template file: ${normalizeSlash(absFrom)}`);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
fs.mkdirSync(path.dirname(absTo), { recursive: true });
|
|
84
|
+
if (fs.existsSync(absTo) && !overwrite) {
|
|
85
|
+
skipped += 1;
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
fs.copyFileSync(absFrom, absTo);
|
|
89
|
+
copied += 1;
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const retiredDeleted = retired
|
|
93
|
+
.map((relPath) => {
|
|
94
|
+
const abs = path.join(ROOT, relPath);
|
|
95
|
+
if (!fs.existsSync(abs)) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
fs.unlinkSync(abs);
|
|
99
|
+
return normalizeSlash(relPath);
|
|
100
|
+
})
|
|
101
|
+
.filter(Boolean);
|
|
102
|
+
|
|
103
|
+
const configTemplatePath = path.join(CURSOR_BOOTSTRAP_DIR, "figma-cache.config.example.js");
|
|
104
|
+
const projectConfigPath = path.join(ROOT, "figma-cache.config.js");
|
|
105
|
+
const legacyExamplePath = path.join(ROOT, "figma-cache.config.example.js");
|
|
106
|
+
|
|
107
|
+
if (!fs.existsSync(configTemplatePath)) {
|
|
108
|
+
console.error(`[figma-cache] missing template file: ${normalizeSlash(configTemplatePath)}`);
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const hadProjectConfig = fs.existsSync(projectConfigPath);
|
|
113
|
+
const hadLegacyExample = fs.existsSync(legacyExamplePath);
|
|
114
|
+
const configTemplateBody = fs.readFileSync(configTemplatePath, "utf8");
|
|
115
|
+
|
|
116
|
+
let configAction = "skipped";
|
|
117
|
+
let configSource = "existing";
|
|
118
|
+
if (hadProjectConfig && !overwrite) {
|
|
119
|
+
configAction = "skipped";
|
|
120
|
+
configSource = "existing";
|
|
121
|
+
} else if (!hadProjectConfig && hadLegacyExample && !overwrite) {
|
|
122
|
+
fs.copyFileSync(legacyExamplePath, projectConfigPath);
|
|
123
|
+
configAction = "created";
|
|
124
|
+
configSource = "legacy-example";
|
|
125
|
+
} else {
|
|
126
|
+
fs.writeFileSync(projectConfigPath, configTemplateBody, "utf8");
|
|
127
|
+
configAction = hadProjectConfig ? "overwritten" : "created";
|
|
128
|
+
configSource = "template";
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
let legacyExampleStatus = "not-found";
|
|
132
|
+
if (fs.existsSync(legacyExamplePath)) {
|
|
133
|
+
const legacyBody = readUtf8IfExists(fs, legacyExamplePath);
|
|
134
|
+
const projectBody = readUtf8IfExists(fs, projectConfigPath);
|
|
135
|
+
const sameAsTemplate = legacyBody === configTemplateBody;
|
|
136
|
+
const sameAsProject = projectBody && legacyBody === projectBody;
|
|
137
|
+
if (sameAsTemplate || sameAsProject) {
|
|
138
|
+
fs.unlinkSync(legacyExamplePath);
|
|
139
|
+
legacyExampleStatus = "deleted";
|
|
140
|
+
} else {
|
|
141
|
+
legacyExampleStatus = "kept-customized";
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const agentSrc = path.join(CURSOR_BOOTSTRAP_DIR, "AGENT-SETUP-PROMPT.md");
|
|
146
|
+
const agentDest = path.join(ROOT, "AGENT-SETUP-PROMPT.md");
|
|
147
|
+
if (!fs.existsSync(agentSrc)) {
|
|
148
|
+
console.error(`[figma-cache] missing ${normalizeSlash(agentSrc)}`);
|
|
149
|
+
process.exit(1);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
let agentBody = fs.readFileSync(agentSrc, "utf8");
|
|
153
|
+
const npmPkg = readSelfNpmPackageName();
|
|
154
|
+
agentBody = agentBody.replace(/\{\{NPM_PACKAGE_NAME\}\}/g, npmPkg);
|
|
155
|
+
fs.writeFileSync(agentDest, agentBody, "utf8");
|
|
156
|
+
|
|
157
|
+
const colleagueSrc = path.join(packageDir, "docs", "colleague-guide-zh.md");
|
|
158
|
+
const colleagueDest = path.join(CACHE_DIR, "docs", "colleague-guide-zh.md");
|
|
159
|
+
if (!fs.existsSync(colleagueSrc)) {
|
|
160
|
+
console.error(`[figma-cache] missing ${normalizeSlash(colleagueSrc)} (broken package install?)`);
|
|
161
|
+
process.exit(1);
|
|
162
|
+
}
|
|
163
|
+
const colleagueSameFile = path.resolve(colleagueSrc) === path.resolve(colleagueDest);
|
|
164
|
+
if (!colleagueSameFile) {
|
|
165
|
+
fs.mkdirSync(path.dirname(colleagueDest), { recursive: true });
|
|
166
|
+
fs.copyFileSync(colleagueSrc, colleagueDest);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
console.log(
|
|
170
|
+
JSON.stringify(
|
|
171
|
+
{
|
|
172
|
+
ok: true,
|
|
173
|
+
root: normalizeSlash(ROOT),
|
|
174
|
+
copied,
|
|
175
|
+
skipped,
|
|
176
|
+
overwrite,
|
|
177
|
+
legacyForce,
|
|
178
|
+
retiredDeleted,
|
|
179
|
+
hint: skipped
|
|
180
|
+
? "Some template files were skipped (default safe mode keeps existing files)."
|
|
181
|
+
: overwrite
|
|
182
|
+
? "Done. Existing .cursor templates were overwritten by latest bootstrap."
|
|
183
|
+
: "Done.",
|
|
184
|
+
configFile: normalizeSlash(projectConfigPath),
|
|
185
|
+
configAction,
|
|
186
|
+
configSource,
|
|
187
|
+
legacyExampleFile: normalizeSlash(legacyExamplePath),
|
|
188
|
+
legacyExampleStatus,
|
|
189
|
+
agentPromptFile: normalizeSlash(agentDest),
|
|
190
|
+
colleagueGuideFile: normalizeSlash(colleagueDest),
|
|
191
|
+
colleagueGuideSynced: !colleagueSameFile,
|
|
192
|
+
colleagueGuideNote: colleagueSameFile
|
|
193
|
+
? "colleague-guide-zh.md already at package path (toolchain dev tree); no copy."
|
|
194
|
+
: "colleague-guide-zh.md refreshed under FIGMA_CACHE_DIR/docs (default figma-cache/docs/).",
|
|
195
|
+
agentPromptNote:
|
|
196
|
+
"AGENT-SETUP-PROMPT.md is refreshed every run. Next: @ it in Cursor; after Agent finishes, run npm run figma:cache:init (or npx figma-cache init if scripts are missing).",
|
|
197
|
+
npmPackageName: npmPkg,
|
|
198
|
+
},
|
|
199
|
+
null,
|
|
200
|
+
2
|
|
201
|
+
)
|
|
202
|
+
);
|
|
203
|
+
console.log(
|
|
204
|
+
"\n" +
|
|
205
|
+
"================================================================\n" +
|
|
206
|
+
"下一步(请按顺序):\n" +
|
|
207
|
+
"1) 在 Cursor 对话中输入 @AGENT-SETUP-PROMPT.md,并说明「按该文档执行」\n" +
|
|
208
|
+
" (每次 cursor init 都会刷新该文件;无需再整篇粘贴。)\n" +
|
|
209
|
+
"2) 待 Agent 完成后,在项目根初始化本地缓存索引:\n" +
|
|
210
|
+
" npm run figma:cache:init\n" +
|
|
211
|
+
" 若尚未补全 npm scripts,请改用:npx figma-cache init\n" +
|
|
212
|
+
"================================================================\n"
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
module.exports = {
|
|
217
|
+
copyCursorBootstrap,
|
|
218
|
+
};
|