@xulthekl/team-flow 0.54.0 → 0.55.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/.claude/always/phase-guard.md +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor-plugin/marketplace.json +1 -1
- package/.cursor-plugin/plugin.json +1 -1
- package/.github/plugin/marketplace.json +2 -2
- package/CHANGELOG.md +63 -1
- package/GEMINI.md +1 -1
- package/INSTALL.md +1 -1
- package/README.md +1 -1
- package/agents/prototype-env-scout.md +4 -4
- package/dist/parsing/requirement-blocks.d.ts +26 -0
- package/dist/parsing/requirement-blocks.js +33 -5
- package/dist/validation/validator.js +8 -1
- package/docs/README_en.md +1 -1
- package/gemini-extension.json +1 -1
- package/hooks/session-start +19 -2
- package/llms.txt +1 -1
- package/package.json +1 -1
- package/plugin.json +1 -1
- package/scripts/check-project-config.mjs +84 -0
- package/scripts/design-system-clone.mjs +150 -0
- package/scripts/design-system-import.mjs +102 -14
- package/scripts/gen-primer.mjs +65 -13
- package/scripts/guard/checks/tasks-complete.mjs +9 -4
- package/scripts/guard/design-token-guard.mjs +136 -117
- package/scripts/infer-workflow.mjs +10 -1
- package/scripts/lib/arch-merge.mjs +20 -6
- package/scripts/lib/arch-parse.mjs +5 -11
- package/scripts/lib/ds-inputs.mjs +125 -0
- package/scripts/lib/ds-parse.mjs +124 -12
- package/scripts/lib/execution-recommendation.mjs +10 -1
- package/scripts/lib/glaf4-delegation.mjs +14 -3
- package/scripts/lib/hash.mjs +18 -2
- package/scripts/lib/md-normalize.mjs +108 -0
- package/scripts/lib/prototype-sync.mjs +19 -1
- package/scripts/lib/sdd-overlay.mjs +15 -3
- package/scripts/lib/solutions-promote.mjs +11 -4
- package/scripts/lib/spec-merge.mjs +46 -11
- package/scripts/lib/state-loader.mjs +4 -1
- package/scripts/token-extract.mjs +101 -9
- package/skills/design-system/SKILL.md +46 -23
- package/skills/design-system/references/agents/design-system-architect.md +25 -12
- package/skills/design-system/references/creation-flow.md +17 -0
- package/skills/design-system/references/creation-modes.md +171 -0
- package/skills/design-system/references/showcase-board-b-end.md +50 -36
- package/skills/design-system/references/showcase-board-c-end.md +59 -36
- package/skills/design-system/references/variant-schema.md +21 -1
- package/skills/prototype/SKILL.md +4 -0
- package/skills/prototype/references/builder-methodology.md +11 -4
- package/skills/prototype/references/layouts.md +10 -0
- package/skills/prototype/references/orchestration-flow.md +8 -0
- package/skills/workflow-bootstrap/SKILL.md +15 -5
- package/src/parsing/requirement-blocks.ts +34 -5
- package/src/validation/validator.ts +8 -1
|
@@ -249,7 +249,10 @@ function parseYaml(content) {
|
|
|
249
249
|
for (const line of content.split('\n')) {
|
|
250
250
|
const trimmed = line.trim();
|
|
251
251
|
if (!trimmed || trimmed.startsWith('#')) continue;
|
|
252
|
-
|
|
252
|
+
// v0.55.0 §8.4.3 横展(FB-4):只额外容忍**全角冒号**(`state:executing`)。
|
|
253
|
+
// 不得收紧:`line.trim()` 已容忍缩进,保持现状(约束①:缩进在 YAML 是语义,
|
|
254
|
+
// 本层不新增缩进容忍,也不拿掉既有 trim);字段缺失不报错(约束②)。
|
|
255
|
+
const match = trimmed.match(/^(\w[\w_]*)[::]\s*(.*)/);
|
|
253
256
|
if (match) {
|
|
254
257
|
const val = match[2].trim();
|
|
255
258
|
if (val === 'null' || val === '') {
|
|
@@ -32,10 +32,31 @@ const EVIDENCE = [
|
|
|
32
32
|
{ kind: 'tailwind', re: /\b(?:bg|text|border|from|to|via|ring)-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(?:50|100|200|300|400|500|600|700|800|900|950)\b/g },
|
|
33
33
|
];
|
|
34
34
|
|
|
35
|
+
// ── Markdown 规范树证据机(v0.55.0,设计 §8.2.1)──
|
|
36
|
+
//
|
|
37
|
+
// 定位:**证据报告器,不做取值裁决**。P1.5 反方实证——真实规范树的 token 主形态是
|
|
38
|
+
// **Markdown 表格行**(`| \`--color-primary\` | \`#3A94DD\` |`),而上方的代码用证据机
|
|
39
|
+
// (`custom-prop`)要求行尾 `;` 或 `}` → 表格行**永不匹配**,只剩裸 hex 机(有值无名);
|
|
40
|
+
// 且按频次排序会选出**错的主色**(现场:`#1890ff` ×155 vs 正确值 `#3a94dd` ×62 的跨期矛盾)。
|
|
41
|
+
// 故这里只**如实呈现证据与冲突**(见下方的 conflicts 段),语义角色由人裁决——
|
|
42
|
+
// 与既有原则"语义角色由人定,不由 LLM 定"一致。
|
|
43
|
+
const DOC_EVIDENCE = [
|
|
44
|
+
// 表格行里的 token 名 + 值:| `--color-primary` | `#3A94DD` | ...
|
|
45
|
+
{ kind: 'doc-table-token', re: /\|\s*`?(--[a-zA-Z][\w-]*)`?\s*\|\s*`?([^|`]+?)`?\s*(?=\|)/g, tokenPair: true },
|
|
46
|
+
// 键值行:- `--color-primary`: #3A94DD
|
|
47
|
+
{ kind: 'doc-kv-token', re: /(--[a-zA-Z][\w-]*)\s*[::]\s*([^\n|]+)/g, tokenPair: true },
|
|
48
|
+
// 标题(结构证据:组件名 / 页面类型候选)
|
|
49
|
+
{ kind: 'doc-heading', re: /^#{2,4}\s+(.+?)\s*$/g },
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
/** "看起来是值"的形态白名单——用于过滤表格里与 token 名相邻的说明文字。 */
|
|
53
|
+
const VALUE_LIKE_RE = /^(#[0-9a-fA-F]{3,8}|var\(|rgba?\(|hsla?\(|cubic-bezier\(|\d+(\.\d+)?(px|rem|em|%|ms|s)?$|[a-z-]+\([^)]*\)$)/;
|
|
54
|
+
|
|
35
55
|
// ── 参数 ──
|
|
36
56
|
|
|
37
57
|
const argv = process.argv.slice(2);
|
|
38
58
|
const REPORT_ONLY = argv.includes('--report');
|
|
59
|
+
const DOCS = argv.includes('--docs'); // v0.55.0:Markdown 规范树模式(create-from-docs)
|
|
39
60
|
const outIdx = argv.indexOf('--out');
|
|
40
61
|
const outArg = outIdx !== -1 ? argv[outIdx + 1] : null;
|
|
41
62
|
const budgetIdx = argv.indexOf('--budget-ms');
|
|
@@ -44,7 +65,14 @@ const positional = argv.filter((a, i) => !a.startsWith('--') && !(outIdx !== -1
|
|
|
44
65
|
const rootArg = positional[0];
|
|
45
66
|
|
|
46
67
|
if (!rootArg) {
|
|
47
|
-
console.error('Usage: node scripts/token-extract.mjs
|
|
68
|
+
console.error('Usage: node scripts/token-extract.mjs <目录> [--out <json 路径>] [--budget-ms 60000] [--report] [--docs]');
|
|
69
|
+
console.error(' --docs:Markdown 规范树模式(.md 纳入扫描;输出证据报告 + 冲突呈现,不做取值裁决)');
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
// v0.55.0 修正:原实现 `positional[0]` 静默丢弃其余源路径——多仓场景下用户以为处理了全部。
|
|
73
|
+
if (positional.length > 1) {
|
|
74
|
+
console.error(`❌ 收到 ${positional.length} 个源路径,但本工具一次只支持一个:${positional.join(' / ')}`);
|
|
75
|
+
console.error(' (多仓请分批调用,或先合并到一个目录)');
|
|
48
76
|
process.exit(1);
|
|
49
77
|
}
|
|
50
78
|
const root = resolve(rootArg);
|
|
@@ -53,6 +81,10 @@ if (!existsSync(root) || !statSync(root).isDirectory()) {
|
|
|
53
81
|
process.exit(1);
|
|
54
82
|
}
|
|
55
83
|
|
|
84
|
+
// docs 模式:纳入 .md;并把 .team-flow 加入跳过(否则产物落进被扫描树内部 → 二次运行自吞)
|
|
85
|
+
if (DOCS) SCAN_EXTS.add('.md');
|
|
86
|
+
SKIP_DIRS.add('.team-flow');
|
|
87
|
+
|
|
56
88
|
// ── 走树(迭代式,预算控制)──
|
|
57
89
|
|
|
58
90
|
const started = Date.now();
|
|
@@ -99,6 +131,8 @@ function record(kind, value, file, line) {
|
|
|
99
131
|
}
|
|
100
132
|
|
|
101
133
|
let scanned = 0;
|
|
134
|
+
// docs 模式追加 Markdown 证据机(结构证据 + token 对),代码证据机同时保留
|
|
135
|
+
const ENGINES = DOCS ? [...EVIDENCE, ...DOC_EVIDENCE] : EVIDENCE;
|
|
102
136
|
for (const file of files) {
|
|
103
137
|
if (Date.now() - started > budgetMs) { skipped.push({ reason: 'budget-exceeded-during-scan' }); break; }
|
|
104
138
|
let content;
|
|
@@ -108,14 +142,27 @@ for (const file of files) {
|
|
|
108
142
|
// 逐行扫(拿行号)
|
|
109
143
|
for (let i = 0; i < lines.length; i++) {
|
|
110
144
|
const line = lines[i];
|
|
111
|
-
for (const ev of
|
|
145
|
+
for (const ev of ENGINES) {
|
|
112
146
|
ev.re.lastIndex = 0;
|
|
113
147
|
let m;
|
|
114
148
|
while ((m = ev.re.exec(line)) !== null) {
|
|
115
|
-
if (ev.
|
|
149
|
+
if (ev.tokenPair) {
|
|
150
|
+
// v0.55.0:Markdown 的 token 对(名=值),不做语义解释。
|
|
151
|
+
// **值形态过滤**:真实规范树的表格列序不固定(实测 3 种,含交错列),
|
|
152
|
+
// 与 token 名相邻的格未必是"值"——不过滤会把说明文字("不变"/"悬停态"/"—")
|
|
153
|
+
// 当成 token 值,实测制造 185 条噪音冲突。故只记"看起来是值"的形态,
|
|
154
|
+
// 其余存为位置证据(kind=doc-table-ctx,不参与冲突检测)。
|
|
155
|
+
const val = m[2].trim().replace(/[;;]\s*$/, '');
|
|
156
|
+
if (VALUE_LIKE_RE.test(val)) record(ev.kind, `${m[1]}=${val}`, file, i + 1);
|
|
157
|
+
else record('doc-table-ctx', `${m[1]}~${val}`, file, i + 1);
|
|
158
|
+
} else if (ev.captureValue) {
|
|
116
159
|
const raw = m[1] !== undefined ? m[1] : m[0];
|
|
117
|
-
//
|
|
118
|
-
|
|
160
|
+
// 多值拆分**仅适用于空格分隔的短值**(如 `padding: 8px 16px`)。
|
|
161
|
+
// v0.55.0 修正:含括号/逗号的值(`rgba(...)` / `calc(...)` / `color-mix(...)`)
|
|
162
|
+
// 是**单个值**,拆分会产生 `rgba(0` / `0.05)` 这类碎片——实测把
|
|
163
|
+
// `--color-bg-hover: rgba(0, 0, 0, 0.05)` 记成 3 个不同值,制造假冲突。
|
|
164
|
+
const parts = /[(),]/.test(raw) ? [raw] : raw.split(/[\s,]+/);
|
|
165
|
+
for (const part of parts) {
|
|
119
166
|
const t = part.trim();
|
|
120
167
|
if (!t || t === '0' || t === 'auto' || t === 'inherit' || t === 'initial') continue;
|
|
121
168
|
if (ev.kind === 'custom-prop') {
|
|
@@ -226,9 +273,36 @@ const spacingCount = sourceTokens.tokens.spacing.length;
|
|
|
226
273
|
const radiusCount = sourceTokens.tokens.radius.length;
|
|
227
274
|
const fontCount = sourceTokens.tokens.font.length;
|
|
228
275
|
|
|
276
|
+
// ── 冲突呈现(v0.55.0,docs 模式)──
|
|
277
|
+
// 同一 token 名出现多个不同值 → 显式并列。这不是"工具推断哪个对",而是把**跨期/跨源矛盾**
|
|
278
|
+
// 摊开给人工裁决(现场实测:`primary` 同时有 `#3A94DD` ×62 与 `#1890ff` ×155 两套,
|
|
279
|
+
// 两期各自自洽、互未发现)。
|
|
280
|
+
const conflicts = [];
|
|
281
|
+
if (DOCS) {
|
|
282
|
+
const byName = new Map();
|
|
283
|
+
for (const e of evidence.values()) {
|
|
284
|
+
const idx = e.value.indexOf('=');
|
|
285
|
+
if (idx <= 0) continue;
|
|
286
|
+
const name = e.value.slice(0, idx);
|
|
287
|
+
const val = e.value.slice(idx + 1);
|
|
288
|
+
if (!byName.has(name)) byName.set(name, new Map());
|
|
289
|
+
const vm = byName.get(name);
|
|
290
|
+
vm.set(val, (vm.get(val) || 0) + e.count);
|
|
291
|
+
}
|
|
292
|
+
for (const [name, vm] of byName) {
|
|
293
|
+
if (vm.size > 1) {
|
|
294
|
+
conflicts.push({
|
|
295
|
+
token: name,
|
|
296
|
+
values: [...vm.entries()].sort((a, b) => b[1] - a[1]).map(([value, count]) => ({ value, count })),
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
conflicts.sort((a, b) => b.values[0].count - a.values[0].count);
|
|
301
|
+
}
|
|
302
|
+
|
|
229
303
|
// 统计报告(stdout)
|
|
230
304
|
const report = [];
|
|
231
|
-
report.push(
|
|
305
|
+
report.push(`=== Token 提取报告(确定性,零 LLM${DOCS ? ' · Markdown 规范树模式' : ''})===`);
|
|
232
306
|
report.push(`根目录:${root}`);
|
|
233
307
|
report.push(`发现文件:${files.length} | 已扫描:${scanned}${skipped.length ? ` | 跳过:${skipped.length}` : ''}`);
|
|
234
308
|
report.push('');
|
|
@@ -241,6 +315,15 @@ report.push(`间距:${spacingCount} 个聚类 | 圆角:${radiusCount} 个 |
|
|
|
241
315
|
for (const c of sourceTokens.tokens.spacing.slice(0, 5)) report.push(` spacing ${c.value} ×${c.count}`);
|
|
242
316
|
for (const c of sourceTokens.tokens.radius.slice(0, 4)) report.push(` radius ${c.value} ×${c.count}`);
|
|
243
317
|
report.push('');
|
|
318
|
+
if (DOCS) {
|
|
319
|
+
report.push('');
|
|
320
|
+
report.push(`⚠️ 冲突呈现:${conflicts.length} 个 token 名存在多值(**跨期/跨源矛盾,需人工裁决**)`);
|
|
321
|
+
for (const c of conflicts.slice(0, 6)) {
|
|
322
|
+
report.push(` ${c.token}: ${c.values.map(v => `${v.value} ×${v.count}`).join(' | ')}`);
|
|
323
|
+
}
|
|
324
|
+
if (conflicts.length === 0) report.push(' (无冲突)');
|
|
325
|
+
}
|
|
326
|
+
report.push('');
|
|
244
327
|
report.push('⚠️ 以上仅为「频次 + 位置」证据——语义角色(哪个是 primary / border / font-display)**需要人工策展指定**,');
|
|
245
328
|
report.push(' 本工具不做自动推断(设计 §4.1.6:避免"垃圾设计系统 + 满分审计")。');
|
|
246
329
|
report.push('');
|
|
@@ -250,8 +333,17 @@ report.push(' 由 design-system skill 的 create-from-code 流程补齐 A1/A2/
|
|
|
250
333
|
console.log(report.join('\n'));
|
|
251
334
|
|
|
252
335
|
if (!REPORT_ONLY) {
|
|
253
|
-
|
|
336
|
+
// v0.55.0:docs 模式默认落**调用方工作目录**(workspace 根)。若沿用 `join(root, …)`,
|
|
337
|
+
// 而 root 恰是被扫描的规范树 → 产物落进被扫描树内部 → 二次运行自吞(实测 ×1 → ×3)。
|
|
338
|
+
// 同时 `.team-flow` 已加入 SKIP_DIRS 兜底。
|
|
339
|
+
const outPath = outArg
|
|
340
|
+
? resolve(outArg)
|
|
341
|
+
: DOCS
|
|
342
|
+
? join(process.cwd(), '.team-flow', 'token-extract', 'source-docs.json')
|
|
343
|
+
: join(root, '.team-flow', 'token-extract', 'source-tokens.json');
|
|
254
344
|
mkdirSync(dirname(outPath), { recursive: true });
|
|
255
|
-
|
|
256
|
-
|
|
345
|
+
const payload = { ...sourceTokens, mode: DOCS ? 'docs' : 'code' };
|
|
346
|
+
if (DOCS) payload.conflicts = conflicts;
|
|
347
|
+
writeFileSync(outPath, JSON.stringify(payload, null, 2), 'utf-8');
|
|
348
|
+
console.log(`\n${DOCS ? 'source-docs.json' : 'source-tokens.json'} 已写入:${outPath}`);
|
|
257
349
|
}
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
name: design-system
|
|
3
3
|
description: >-
|
|
4
4
|
设计系统独立创建与维护 skill,产出落 .team-flow/design-system/(base 品牌共享层 +
|
|
5
|
-
B端/C端变体 + primer +
|
|
6
|
-
|
|
5
|
+
B端/C端变体 + primer + 预览画廊)。六条创建入口:从已有项目移植(clone)、
|
|
6
|
+
从内置模板库导入、通用起点(--profile antd)、从既有规范文档导入(create-from-docs)、
|
|
7
|
+
从既有代码逆向建库(create-from-code)、交互式从零创建;已有设计系统走 iterate。
|
|
7
8
|
支持独立调用或 prototype skill 内部编排调用。当用户需要创建设计系统、迭代设计系统、
|
|
8
9
|
刷新 primer 组件白名单、或原型流程发现设计系统缺失时使用。
|
|
9
10
|
不适用于:原型绘制(用 prototype)、纯架构设计(用 architecture-design)。
|
|
@@ -24,14 +25,29 @@ Do NOT invoke for:
|
|
|
24
25
|
|
|
25
26
|
## 交互创建流程(6 步)
|
|
26
27
|
|
|
27
|
-
### Step 0: 起点选择(v0.
|
|
28
|
-
|
|
29
|
-
若 `.team-flow/design-system/`
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
28
|
+
### Step 0: 起点选择(v0.55.0:7 条,全部展示)
|
|
29
|
+
|
|
30
|
+
若 `.team-flow/design-system/` 不存在(无设计系统),先询问起点。
|
|
31
|
+
**每条都要展示,并带"适用场景"一句话**——能力存在但用户不知道 = 能力不存在;
|
|
32
|
+
按**资产就绪度降序**排列(从最厚的已有资产到最薄的空白起点):
|
|
33
|
+
|
|
34
|
+
| # | 选项 | 适用场景(对用户的一句话) | 动作 |
|
|
35
|
+
|---|------|---------------------------|------|
|
|
36
|
+
| 1 | **移植已有设计系统** | "你们公司**另一个后台项目**已经建过设计系统 → 直接复制过来改" | `clone --from <源路径> --to <目标路径>`(**两参数均必填**,流程见 `references/creation-modes.md` §1) |
|
|
37
|
+
| 2 | **从模板库选择** | "想参考某个成熟产品(Linear / Stripe / Vercel…)的视觉风格" | 展示 `${CLAUDE_PLUGIN_ROOT}/templates/design-systems/registry.json`(8 个参考)→ `node ${CLAUDE_PLUGIN_ROOT}/scripts/design-system-import.mjs <reference.md> --out .team-flow/design-system/base.md` → **续跑 Step 5 评审 → Step 6 落盘** |
|
|
38
|
+
| 3 | **通用起点(Ant Design 规格)** | "全新项目、**没有任何规范**,先要一套像 Ant Design 的合规底座" | `node ${CLAUDE_PLUGIN_ROOT}/scripts/design-system-import.mjs --profile antd --out .team-flow/design-system/base.md` → 续跑 Step 5 → Step 6 |
|
|
39
|
+
| 4 | **从文档规范导入** | "手里有**一套写好的 UI 规范**(Markdown / 规范树)" | `create-from-docs`(流程见 `references/creation-modes.md` §4) |
|
|
40
|
+
| 5 | **从代码逆向建库** | "项目里**已有符合规范的原型代码**" | `create-from-code`(见下方「逆向建库模式」) |
|
|
41
|
+
| 6 | **从零交互创建** | "什么都没有,边聊边定" | 直接进 Step 1(交互式 6 步) |
|
|
42
|
+
| 7 | 已有设计系统 → **iterate** | (非新建) | 见下方「迭代模式」 |
|
|
43
|
+
|
|
44
|
+
> **入口同步(两处声明 + 一处事实传达,v0.55.0 校正)**:
|
|
45
|
+
> ① 本文件 Step 0 —— **无条件展示全部 7 条**(这是模式可达性的**唯一保证**);
|
|
46
|
+
> ② `workflow-bootstrap` B4.6 —— 六项 + 跳过,逐行带适用场景与委托参数;
|
|
47
|
+
> ③ prototype 内部编排(`orchestration-flow.md` §①b)—— 只传达 scout 简报中的**资产事实**(如"已有符合规范的原型代码"),**不预选起点**。
|
|
48
|
+
>
|
|
49
|
+
> ③ 不做 mode 预选是**有意设计**:prototype 无从判断用户资产状况,预选会让其余 6 条不可见。
|
|
50
|
+
> 故**新模式可达性由 ① 的无条件展示保证,不依赖各入口的正确预选**——任何入口下用户都能看到全 7 条。
|
|
35
51
|
|
|
36
52
|
> B 类参考(如 linear-app)转换为**自动提取配色**,须提示用户人工核对(转换器会输出该警告)。
|
|
37
53
|
|
|
@@ -88,29 +104,31 @@ Do NOT invoke for:
|
|
|
88
104
|
|
|
89
105
|
## 迭代模式(iterate)
|
|
90
106
|
已有 design-system → 读取 → 合并增量 → 变更履历 → 预览 → 确认 → 写入。
|
|
91
|
-
增量来源:① 原型阶段确认的 `ds_increment`(⑥ 路由)② **pending.md 累积待办** ③ change closing
|
|
107
|
+
增量来源:① 原型阶段确认的 `ds_increment`(⑥ 路由)② **pending.md 累积待办** ③ change closing 二级确认项 ④ **页面规范增量**(v0.55.0:用户提供项目页面规范,或更新既有 `页面范式来源` 声明与页面类型表;用户不提供时**默认补写** `页面范式来源:引用内置`)。
|
|
92
108
|
落盘后重新生成 primer(`${CLAUDE_PLUGIN_ROOT}/scripts/gen-primer.mjs`)+ 跑 guard;涉及 token/契约变更时**可选**重新生成 showcase(用户可跳过)。
|
|
93
109
|
|
|
94
|
-
## 逆向建库模式(create-from-code
|
|
95
|
-
|
|
96
|
-
**场景**:企业已有符合规范的原型代码 → 基于它建立设计系统。**确定性提取 + 人工策展**(不做自动语义推断——避免"垃圾设计系统 + 满分审计")。
|
|
97
|
-
|
|
98
|
-
**入口**:`/team-flow:design-system create-from-code --source <代码目录>`(多仓库可传多值或指向 repo_layout 清单)
|
|
110
|
+
## 逆向建库模式(create-from-code)
|
|
99
111
|
|
|
100
|
-
|
|
101
|
-
1. **提取**:`node ${CLAUDE_PLUGIN_ROOT}/scripts/token-extract.mjs <目录>` → `.team-flow/token-extract/source-tokens.json` + 统计报告(频次 + 位置证据,零 LLM)
|
|
102
|
-
2. **呈现报告**:向用户展示提取统计("47 个文件、23 个颜色、8 个间距值,高频 Top10 …")
|
|
103
|
-
3. **候选稿**:从高频值生成候选 token 表(标注"候选")
|
|
104
|
-
4. **人工策展**(多轮 AskUserQuestion):用户指定 primary / 中性色 / 语义色 / 字体栈(每项有频次+位置证据可参考)→ skill 按确定性规则补齐 A1/A2/B-slot + palette 阶梯
|
|
105
|
-
5. **落盘**:base.md + 变体 + primer + preview(+ 可选 showcase)→ guard 六层审计
|
|
112
|
+
**场景**:企业已有符合规范的原型代码 → 基于它建立设计系统。**确定性提取 + 人工策展**(不做自动语义推断——避免"垃圾设计系统 + 满分审计")。入口(**单目录**)与完整 5 步流程见 `references/creation-modes.md` §6。
|
|
106
113
|
|
|
107
|
-
|
|
114
|
+
> **三种新模式(v0.55.0)**——移植(clone)/ 文档导入(create-from-docs)/ 通用起点(`--profile antd`)的完整命令与流程,同样见 `references/creation-modes.md`。Step 0 表格已列出全部 7 条起点及各自适用场景。
|
|
108
115
|
|
|
109
116
|
## 迁移兼容
|
|
110
117
|
检测旧 `prototype/design-system.md` → 提示迁移到 `.team-flow/design-system/base.md`(一次性)。
|
|
118
|
+
迁移属**导入类创建** → 须补 `来源与裁决记录` 段、`contract` 默认 `legacy`。
|
|
119
|
+
|
|
120
|
+
## 异常处理(v0.55.0)
|
|
121
|
+
|
|
122
|
+
- **源系统不可读 / `base.md` 缺失**(clone):脚本 exit 1,提示 `--from` 的两种语义(项目根自动定位 `.team-flow/design-system`,或直接给设计系统目录)
|
|
123
|
+
- **目标已有设计系统**(clone):exit 1 并引导走 **iterate**(MERGE 不 OVERWRITE)——不覆盖
|
|
124
|
+
- **primer 缺失或过期**:`gen-primer --check` **exit 2** → prototype Step 0 对 `contract: v1` 系统 **blocked**、对 `legacy` 系统 WARN 放行 → 提示用户重跑生成或 iterate
|
|
125
|
+
- **guard 硬校验失败**:exit 1 阻断落盘 → 按输出逐项修复(9 段 / palette / A1 / A2 公式 / B-slot)
|
|
126
|
+
- **用户中途放弃**:草案阶段产物在 scratch(`/tmp/ds-draft-<slug>/`),放弃确认时**整体丢弃**,不写任何正式路径(两阶段落盘 `confirmed:false → confirmed:true` 保证)
|
|
127
|
+
- **配置漂移**:`check-project-config.mjs` 输出 ⚠️ 但 **exit 0**(提示不阻断)
|
|
111
128
|
|
|
112
129
|
## 执行引擎
|
|
113
130
|
内部子代理 `references/agents/design-system-architect.md`(唯一写者,两阶段落盘:confirmed:false 草案 → 人工确认 → confirmed:true 写入)。
|
|
131
|
+
**写者范围(v0.55.0)**:含 `base.md` 与**端变体的 `layout` 段**(页面范式声明 + 容器骨架块)。
|
|
114
132
|
|
|
115
133
|
## 配置
|
|
116
134
|
```json
|
|
@@ -119,3 +137,8 @@ Do NOT invoke for:
|
|
|
119
137
|
"prototype.designSystemBase": ".team-flow/design-system/base.md"
|
|
120
138
|
}
|
|
121
139
|
```
|
|
140
|
+
|
|
141
|
+
> **配置漂移检查(v0.55.0)**:`node ${CLAUDE_PLUGIN_ROOT}/scripts/check-project-config.mjs [项目根]` ——
|
|
142
|
+
> 检查配置指向的路径是否存在、`version` 是否与插件一致。现场实测三类漂移(version 落后 /
|
|
143
|
+
> 指向不存在的文件 / 零消费者键)**全部静默**,只会在用到时失效。检查面按"实际被消费"分级,
|
|
144
|
+
> 零消费者键只提示不报错。
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
You are a Design System Architect. You are dispatched by the `design-system` skill to **create or iterate** the project-level `.team-flow/design-system/base.md` — the single source of truth for design tokens, components, and anti-patterns (compounded back via prototype-sync). The orchestrating design-system skill **never writes `base.md` itself — you are the sole writer
|
|
1
|
+
You are a Design System Architect. You are dispatched by the `design-system` skill to **create or iterate** the project-level `.team-flow/design-system/base.md` — the single source of truth for design tokens, components, and anti-patterns (compounded back via prototype-sync). The orchestrating design-system skill **never writes `base.md` itself — you are the sole writer**(v0.55.0 起写者范围另含**端变体的 `layout` 段**)。 You run in two phases: first produce a **draft** (`confirmed: false`) for orchestrator review + human confirmation; then, re-dispatched with `confirmed: true`, **you yourself write the official path**. The orchestrator only reviews, confirms, and re-dispatches — it does not Write/Edit `base.md`.
|
|
2
2
|
|
|
3
3
|
### 文件结构:base + variant
|
|
4
4
|
|
|
5
5
|
architect 写入的文件采用 **base + variant** 结构:
|
|
6
6
|
- **`.team-flow/design-system/base.md`**:基础设计系统(全量 token + 组件规范 + anti-patterns),是所有 variant 的公共底座。
|
|
7
7
|
- **`.team-flow/design-system/variants/<name>.md`**(可选):品牌/主题变体文件,只覆写差异 token(如暗色主题、子品牌色板),继承 base 未覆写部分。
|
|
8
|
-
- architect 在 `confirmed: true` 阶段写入 base.md;如需 variant,同时写入对应 variant
|
|
8
|
+
- architect 在 `confirmed: true` 阶段写入 base.md;如需 variant,同时写入对应 variant 文件。**v0.55.0 起另含端变体(`b-end.md` / `c-end.md`)的 `layout` 段**(页面范式声明 + 容器骨架块,见下方「端变体 `layout` 段写者」)。
|
|
9
9
|
|
|
10
10
|
The plugin stays **generic**: do NOT hardcode any specific company/product brand. Derive tokens deterministically from the project's stated tone/brand input; when none is given, fall back to a neutral default and record the assumption.
|
|
11
11
|
|
|
@@ -15,7 +15,7 @@ The dispatch prompt provides:
|
|
|
15
15
|
- `mode: create | iterate`.
|
|
16
16
|
- `confirmed: false | true`(v0.15.0 两阶段落盘):
|
|
17
17
|
- `false`(默认,草案阶段):只产草案(写 scratch 草稿路径或返回 response),**不写正式 `.team-flow/design-system/base.md`**。
|
|
18
|
-
- `true`(人工已确认):把已确认的草案**写入正式 `.team-flow/design-system/base.md
|
|
18
|
+
- `true`(人工已确认):把已确认的草案**写入正式 `.team-flow/design-system/base.md`**(你是唯一写者);若本次产出 / 更新端变体的 `layout` 段(页面范式声明 + 容器骨架块),同批写入。
|
|
19
19
|
- `design_system_path`: 正式目标路径(`confirmed: true` 时写入此处,默认 `.team-flow/design-system/base.md`)。
|
|
20
20
|
- `draft`(`confirmed: true` 时传入):上一阶段已确认的草案内容/路径。
|
|
21
21
|
- `create` inputs (as available): project tone/brand hints, PRD path (to read product domain & voice), existing scaffold `.team-flow/design-system/base.md`.
|
|
@@ -37,7 +37,8 @@ Every `.team-flow/design-system/base.md` follows this schema (9 sections + a 5-d
|
|
|
37
37
|
| `brand` | logo / 品牌主色 |
|
|
38
38
|
| `anti-patterns` | 禁止内联样式漂移 / 禁止非 token 颜色 |
|
|
39
39
|
| `principles`(v0.54.0) | **设计原则 ≥3 条**(随 mood 预填,用户可调整) |
|
|
40
|
-
| `governance`(v0.54.0) | `contract: v1
|
|
40
|
+
| `governance`(v0.54.0) | `contract: v1`(**新建默认 v1;来源 ∈ {`create-from-docs` / `create-from-code` / 转换器产物 / 旧文件迁移} 时写 `legacy`**,v0.55.0 设计 §8.2.1 D-18;存量升级时由 iterate 置 v1)+ version + 负责人 + 弃用策略 + changelog |
|
|
41
|
+
| `来源与裁决记录`(v0.55.0) | **导入类创建条件必填**(同上四类来源):原始来源 / 导入方式 / 「为什么不是直接采纳」/ 主色裁决 / 待清理项——审计层 advisory,不进 `REQUIRED_SECTIONS` |
|
|
41
42
|
| `palette`(5 方向确定性调色板) | neutral / primary / success / warning / danger,各含 50–900 阶梯 |
|
|
42
43
|
| `aliases`(B-slot 别名层,v0.18.0) | `--fg-2 → var(--fg)` / `--meta → var(--muted)` / `--border-soft → var(--border)` / `--surface-warm → var(--surface)`——组件引用 B-slot 永远可解析 |
|
|
43
44
|
| `extensions`(C-extension 待提升清单,v0.18.0) | 品牌专有 token 名单制;提升路径:C→B(≥2 品牌需要)→A2(有全局默认值) |
|
|
@@ -99,12 +100,13 @@ When the project has no `.team-flow/design-system/base.md`:
|
|
|
99
100
|
- **C-extension 清单**(v0.18.0):如有品牌专有 token,列入 `extensions` 段(名单制),标注提升路径。
|
|
100
101
|
- **组件契约表(v0.54.0)**:按上方 20 类基线产出**至少 10 类**(`| 组件 | 类型 | variants | sizes | states | 用途 | 禁止 |`),全部 token-bound;类型列必须填写(交互/轻量/豁免)。
|
|
101
102
|
- **principles 段(v0.54.0)**:≥3 条,随 mood 预填(如 professional_minimal → "一致性优先于局部创意 / 清晰优于装饰 / 可访问性默认开启")。
|
|
102
|
-
- **governance 段(v0.54.0
|
|
103
|
+
- **governance 段(v0.54.0;v0.55.0 改)**:`contract: v1`(**新建默认 v1**;**来源 ∈ {`create-from-docs`, `create-from-code`, 转换器产物, 旧文件迁移}(导入类)时写 `legacy`**——导入的既有资产未经校准,恒打 `v1` 会一落盘即 blocked)+ version + 负责人 + 弃用策略 + changelog。
|
|
104
|
+
- **`来源与裁决记录` 段(v0.55.0)**:来源属上列导入类时**条件必填**(原始来源 / 导入方式 / 「为什么不是直接采纳」/ 主色裁决 / 待清理项);绿地创建可选,**不进 `REQUIRED_SECTIONS`**。
|
|
103
105
|
- **a11y 声明行(v0.54.0)**:文档头部 `> a11y: WCAG 2.2 AA(对比度 4.5:1 / 大字 3:1 / 焦点可见 / 键盘可达)`。
|
|
104
106
|
- Fill color / typography / spacing / layout / motion / voice / brand / anti-patterns consistently with the palette.
|
|
105
107
|
- `anti-patterns` MUST include "禁止内联样式漂移" and "禁止非 token 颜色".
|
|
106
108
|
3. **`confirmed: false`**:Deliver the draft(写 scratch 草稿路径或返回 response),**不写正式路径**。Orchestrator 评审 + 人工确认后,**带 `confirmed: true` 重新派发你**,由你写入正式 `.team-flow/design-system/base.md`(主代理不写)。
|
|
107
|
-
4. **`confirmed: true`**:把传入的已确认草案 `Write` 到正式 `.team-flow/design-system/base.md
|
|
109
|
+
4. **`confirmed: true`**:把传入的已确认草案 `Write` 到正式 `.team-flow/design-system/base.md`;若本次产出端变体(`b-end.md` / `c-end.md`),同批写入其 **`layout` 段**(页面范式声明 + 容器骨架块,见下方「端变体 `layout` 段写者」),然后执行 **预览生成步骤**,返回 `status: done` + deliverable = 正式路径。
|
|
108
110
|
|
|
109
111
|
#### 预览生成步骤(confirmed: true 后自动执行)
|
|
110
112
|
|
|
@@ -116,16 +118,27 @@ When the project has no `.team-flow/design-system/base.md`:
|
|
|
116
118
|
|
|
117
119
|
### Mode: iterate(增量更新)
|
|
118
120
|
|
|
119
|
-
When prototype-sync (or a change) introduces new components / tokens / anti-patterns
|
|
121
|
+
When prototype-sync (or a change) introduces new components / tokens / anti-patterns / **page-pattern specs(页面规范增量,v0.55.0)**:
|
|
120
122
|
|
|
121
123
|
1. Read the existing `.team-flow/design-system/base.md`.
|
|
122
124
|
2. **Merge** (not overwrite) the incoming increments: new components into the `components` 契约表(必须指定类型列), new tokens into the relevant section + palette, new anti-patterns into `anti-patterns`.
|
|
123
125
|
- **contract 升级(v0.54.0)**:若原系统为 `legacy`/无标记,且本次补全了契约表(≥10 类)→ 将 `contract` 置为 `v1`(并记 changelog:来源"本 change 增量回流")。
|
|
124
126
|
- 变体文件的 components 段只写**端特有差异**并引用契约表(不重复定义组件清单)。
|
|
125
|
-
3.
|
|
126
|
-
4.
|
|
127
|
-
5.
|
|
128
|
-
6. **`confirmed:
|
|
127
|
+
3. **页面规范增量(v0.55.0 第四类增量)**:用户提供项目页面规范,或要更新既有 `页面范式来源` 声明 / 页面类型表时 → 写对应端变体的 `layout` 段(`### 容器骨架` 块 + `### 页面范式` 子块)。**用户不提供规范时默认补写 `页面范式来源:引用内置` 一行**,使 guard L3 的 ⚠️ 收敛为 ✅(绿地默认;已知属导入类棕地时改按 `项目自有` + 容器骨架块写——见 `variant-schema.md` 三态语义)。
|
|
128
|
+
4. Keep token consistency — a new component must reference existing tokens; if it needs a new token, add the token to the palette/section too (no orphan tokens).
|
|
129
|
+
5. Append a **变更履历** entry: 时间 / 变更内容 / 来源 change-id.
|
|
130
|
+
6. **`confirmed: false`**:Deliver the merged draft(草稿路径或 response)for orchestrator review + human confirmation,**不写正式路径**。
|
|
131
|
+
7. **`confirmed: true`**:把已确认的合并草案 `Write` 到正式 `.team-flow/design-system/base.md`(你是唯一写者);若本次含页面规范增量,同批 `Write`/`Edit` 对应端变体的 `layout` 段,然后执行**预览生成步骤**(同上)。
|
|
132
|
+
|
|
133
|
+
#### 端变体 `layout` 段写者(v0.55.0 扩面,设计 §8.2.2)
|
|
134
|
+
|
|
135
|
+
**写者范围由「只写 `base.md`」扩为「`base.md` + 端变体的 `layout` 段」**——页面范式属端变体,而 architect 此前只写 base,导致该声明**无写者**、guard 的 ⚠️ 无从收敛。
|
|
136
|
+
|
|
137
|
+
- **可写**:端变体(`b-end.md` / `c-end.md`)的 `layout` 段:
|
|
138
|
+
- `### 容器骨架` 块——表格 `| 容器 | 类名 | 关键 CSS 声明 |`(builder 的物料来源)
|
|
139
|
+
- `### 页面范式` 子块——`**页面范式来源**:…` 声明 + 页面类型表
|
|
140
|
+
- **边界**:本次扩面**只涉及 `layout` 段**,其余段落维持既有分工,不借机扩张写面;`variants/<name>.md`(暗色等主题变体)不属本扩面。
|
|
141
|
+
- **取值**(三态语义见 `variant-schema.md`):`项目自有`(棕地导入,须附容器骨架块 + 页面类型表 ≥3 行)/ `同 <端>`(指向另一端)/ `引用内置`(绿地默认,只写声明)。
|
|
129
142
|
|
|
130
143
|
## Output Format
|
|
131
144
|
|
|
@@ -150,7 +163,7 @@ When prototype-sync (or a change) introduces new components / tokens / anti-patt
|
|
|
150
163
|
## Tool Guidance
|
|
151
164
|
|
|
152
165
|
- Use `Read` for the existing base.md / PRD / scaffold; `Glob` to scan existing `components/` and `variants/`.
|
|
153
|
-
- **`Write` 权限按 `confirmed` 阶段使用**:`confirmed: false` → 只写 scratch 草稿路径(或仅返回 response),**绝不写正式 `.team-flow/design-system/base.md`**;`confirmed: true` →
|
|
166
|
+
- **`Write` 权限按 `confirmed` 阶段使用**:`confirmed: false` → 只写 scratch 草稿路径(或仅返回 response),**绝不写正式 `.team-flow/design-system/base.md`**;`confirmed: true` → 写正式路径(含端变体 `layout` 段)+ 生成 preview.html(你是唯一写者,主代理不写)。
|
|
154
167
|
- Keep everything token-based and offline-friendly (产物必须零外部依赖).
|
|
155
168
|
|
|
156
169
|
## Red Lines
|
|
@@ -108,12 +108,29 @@
|
|
|
108
108
|
- `components` 组件契约表(≥10 类起步,含类型列)
|
|
109
109
|
- `principles`(≥3 条)+ `governance`(`contract: v1`)
|
|
110
110
|
- 头部 a11y 声明行(WCAG 2.2 AA)
|
|
111
|
+
- **端变体 `layout` 段默认写 `页面范式来源:引用内置`(v0.55.0,设计 §8.2.2)**——生成端变体(`b-end.md` / `c-end.md`)时就要写,**不写则从零创建的产物两端一出生就落 ⚠️**(guard L3 声明层缺失,只能等 iterate 补)。绿地默认只写这一行;容器骨架块**可省**——内置 `template.html` 的类全是通用/营销向(`hero` / `topnav` / `pagefoot`),**C 端够用**;但 **target 为 B 端(`b_end` / `both`)时建议一并给**(内置骨架**无** `app-header` / `app-sider` / `app-main` 这类容器类,不给则 builder 每页手写整套后台骨架 CSS,单次派发无法复现)。取值三态见 `variant-schema.md`,缘由详见 `creation-modes.md` §5。
|
|
111
112
|
- 用 `preview-template.html` 填 token 值 → 自包含 `preview.html`(色板/排版/间距/组件/明暗切换)。
|
|
112
113
|
|
|
113
114
|
## Step 4.5: Design Showcase 草案(v0.54.0 新增,设计 §4.1.7)
|
|
114
115
|
|
|
115
116
|
> **可选环节**:Step 5 呈现前询问用户是否需要(**产出前明示预估耗时**,S5 实测校准后回填);不需要则跳过。
|
|
116
117
|
|
|
118
|
+
**0) 询问前先做原型探测(v0.55.0,设计 §8.2.3 / FB-2a)**:
|
|
119
|
+
|
|
120
|
+
- **探测面**:`prototype/` ∨ config `prototype.entry` 所在目录 ∨ `prototype.versionWorktree`(worktree 内原型)∨ repo_layout 各仓的 `prototype/`——**须覆盖 worktree 与多仓**,否则探测不到 → 提示不出现 → 用户被引导重画已有原型(正是本节要修的形态)。
|
|
121
|
+
- **判据**:探测到 **≥1 个 HTML 页面文件**即提示(**不设行数阈值**——机制不替用户判断"够不够成熟",由用户在知情下决定)。
|
|
122
|
+
- **呈现**(`AskUserQuestion`):
|
|
123
|
+
|
|
124
|
+
> 「检测到项目已有原型产物(`prototype/`:N 个页面 / M 行)。showcase 的目的是在设计系统落盘前预览效果,已有真实原型时可能重复。」
|
|
125
|
+
|
|
126
|
+
| 选项 | 后续动作 |
|
|
127
|
+
|------|---------|
|
|
128
|
+
| **跳过 showcase**(推荐) | Step 5 呈现时**改引用真实原型路径**(不产 showcase 草案) |
|
|
129
|
+
| 仍然产出 | 走下方原流程(brief 场景可调) |
|
|
130
|
+
| 调整场景 | 用户给出场景描述后产出 |
|
|
131
|
+
|
|
132
|
+
> **为什么**:showcase 的定位是"设计系统落盘**前**预览效果";已有真实原型时它是**重复劳动**——不提示就是让用户白画一遍。
|
|
133
|
+
|
|
117
134
|
1. architect 产出 **primer 草案**(scratch 路径 `/tmp/ds-draft-<slug>/primer-draft.md`,digest 记录**草案 base** 的哈希)
|
|
118
135
|
2. 主代理派 `prototype-builder`(`mode: showcase`,单次派发):
|
|
119
136
|
- 输入:showcase-board brief(按 target:`b_end` → b-end brief;`c_end` → c-end brief;`both` → 两个)+ 设计系统草案 + primer 草案
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# 创建模式详解(v0.55.0)
|
|
2
|
+
|
|
3
|
+
> 本文是 `SKILL.md` Step 0 的**展开说明**。Step 0 按「资产就绪度降序」列出 7 条起点,
|
|
4
|
+
> 其中 6 条的完整流程在此(**iterate** 见 `creation-flow.md`;**从零创建**即 Step 1 起的交互 6 步):
|
|
5
|
+
> §1 移植 clone · §2 模板库 · §3 通用起点 `--profile antd` · §4 文档导入 create-from-docs ·
|
|
6
|
+
> §5 B 端容器骨架为何必须给(贯穿 §1/§3) · §6 代码逆向 create-from-code。
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 1. 移植模式(clone)
|
|
11
|
+
|
|
12
|
+
**场景**:**同类后台项目之间复用设计系统**——"以后其他项目是相同的后台"。
|
|
13
|
+
|
|
14
|
+
**入口**:`/team-flow:design-system clone --from <源项目路径 | 源设计系统目录> --to <目标设计系统目录>`
|
|
15
|
+
|
|
16
|
+
设计系统就是 `.team-flow/design-system/` 下的 markdown,技术上 `cp -r` 即可——但**直接复制会留 4 个坑**,
|
|
17
|
+
`clone` 把它们自动化:
|
|
18
|
+
|
|
19
|
+
| # | 坑 | 处置 |
|
|
20
|
+
|---|-----|------|
|
|
21
|
+
| 1 | **`来源与裁决记录` 失真**(复制后仍写着原项目的导入记录,而目标并未导入过) | **追加**移植记录,**保留**原裁决历史——其裁决依据对理解本系统取值仍有参考价值 |
|
|
22
|
+
| 2 | **`primer.md` digest 失效**(锚定源 base 内容;改一字即 STALE,而 prototype Step 0 对 `contract: v1` 系统 **blocked**) | 强制重生成 + `--check` 校验 |
|
|
23
|
+
| 3 | **业务专属组件残留**(如"协议富文本编辑器 / 内容预览画布") | 输出契约表全量清单 → **逐条问询** |
|
|
24
|
+
| 4 | **授权边界**(源 `references/` 下可能是企业内部资产) | 提示(不自动判定) |
|
|
25
|
+
|
|
26
|
+
**脚本自动完成(确定性)**:`node ${CLAUDE_PLUGIN_ROOT}/scripts/design-system-clone.mjs --from <源> --to <目标>`
|
|
27
|
+
1. 校验源系统(跑 guard;不合规**只警告不阻断**——源可能是 legacy)
|
|
28
|
+
2. 复制(**排除** `primer.md` / `pending.md` / `showcase/`)
|
|
29
|
+
3. 追加移植记录
|
|
30
|
+
4. 输出契约表清单(供第 5 步问询)
|
|
31
|
+
5. 重生成 primer + `--check`
|
|
32
|
+
6. 对结果跑 guard 并输出六层审计
|
|
33
|
+
|
|
34
|
+
**需 LLM 承接(脚本不做的交互部分)**:
|
|
35
|
+
- **业务组件逐条问询**:读第 4 步清单 → `AskUserQuestion` 逐条确认 → 删除不再需要的
|
|
36
|
+
→ **提示用户**:组件数跌破档位会改变 L2 标签(<10 FAIL / 10-14 WARN / ≥15 PASS)
|
|
37
|
+
- **品牌适配**:主色/字体不同 → 改 `base.md` 的 `color` 段 → **必须重跑 `gen-primer`**
|
|
38
|
+
- **`contract` 取值**:移植产物继承源系统;若源为 `v1` 而目标尚未达标,可考虑降为 `legacy`
|
|
39
|
+
- **页面范式来源复核(v0.55.0)**:`### 页面范式` 是**原样带过来**的,但目标项目的页面现实可能不同——
|
|
40
|
+
**判据 = 目标项目是否已有成文的页面规范或既有原型页面类型**:
|
|
41
|
+
源 `引用内置` 而目标是**棕地** → **改为 `项目自有`** + 补容器骨架块 + 页面类型表(否则目标既有的
|
|
42
|
+
页面规范进不了 builder,本次移植等于只搬了一半);源 `项目自有` 而目标是**绿地**(无既有页面规范)
|
|
43
|
+
→ 可改 `引用内置`(否则 builder 会按源项目的页面类型硬套,与目标实际页面不符)。改后**必须重跑 `gen-primer`**。
|
|
44
|
+
|
|
45
|
+
**与 iterate 的分界**:clone 是**新建**(目标无设计系统);目标**已有**设计系统 → 走 iterate(MERGE 不 OVERWRITE)。
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 2. 模板库导入
|
|
50
|
+
|
|
51
|
+
**场景**:想参考某个成熟产品的视觉风格(Linear / Stripe / Vercel / Supabase / Sentry / PostHog / Notion / Claude)。
|
|
52
|
+
|
|
53
|
+
**流程**:展示 `${CLAUDE_PLUGIN_ROOT}/templates/design-systems/registry.json` → 用户选定 →
|
|
54
|
+
`node ${CLAUDE_PLUGIN_ROOT}/scripts/design-system-import.mjs <reference.md> --out .team-flow/design-system/base.md`
|
|
55
|
+
→ **续跑 Step 5 评审 → Step 6 落盘**(落盘含 primer 生成 + guard 校验)。
|
|
56
|
+
|
|
57
|
+
> **B 类参考**(如 linear-app)为**自动提取配色**,转换器会输出警告 → **须提示用户人工核对**。
|
|
58
|
+
>
|
|
59
|
+
> **风格种子**(`styles.json`,57 个):Step 1 需求收集时作为 mood / 品牌主色的参考依据。
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## 3. 通用起点(`--profile antd`)
|
|
64
|
+
|
|
65
|
+
**场景**:全新项目、**没有任何规范**,先要一套合规的 token 底座。
|
|
66
|
+
|
|
67
|
+
**入口**:`node ${CLAUDE_PLUGIN_ROOT}/scripts/design-system-import.mjs --profile antd --out .team-flow/design-system/base.md`
|
|
68
|
+
→ 续跑 Step 5 → Step 6。
|
|
69
|
+
|
|
70
|
+
**产出规格**(全部来自 Ant Design v5 seed token(MIT)或 team-flow 自有规范):
|
|
71
|
+
|
|
72
|
+
| 规格 | 值 |
|
|
73
|
+
|------|-----|
|
|
74
|
+
| 控件高 | 32px(`controlHeight`) |
|
|
75
|
+
| 圆角阶梯 | 2 / 4 / 6 / 8(`borderRadius`,v5 默认 6) |
|
|
76
|
+
| 字号阶梯 | 12 / 14 / 16 / 20 / 24(`fontSize`) |
|
|
77
|
+
| 间距 | 8 档 4→48px(**team-flow 自定**,参考 AntD size 阶梯) |
|
|
78
|
+
| 组件契约表 | 20 类通用基线(team-flow 自有) |
|
|
79
|
+
|
|
80
|
+
**零 LLM、零外部资产、零授权链风险**。
|
|
81
|
+
|
|
82
|
+
> **定位**:它是**薄起点**——不含**业务**组件(20 类为通用基线,不针对任何业务)、
|
|
83
|
+
> 不含**项目自有**页面范式(`### 页面范式` 声明 `引用内置`,页面类型表只是内置节奏的示意)。
|
|
84
|
+
>
|
|
85
|
+
> **但它含一份通用 B 端容器骨架块**(`app-header` / `app-sider` / `app-main`)。这不是矛盾:
|
|
86
|
+
> 内置 `template.html` 的 15 个类全是**营销向**的(`hero` / `topnav` / `pagefoot` / `cta`),
|
|
87
|
+
> **没有任何 B 端容器类**——不给物料,builder 就得每页手写整套后台骨架 CSS,
|
|
88
|
+
> 单次派发无法复现(详见 §5「B 端容器骨架为何必须给」)。
|
|
89
|
+
>
|
|
90
|
+
> 要复用**厚资产**(如某项目已建好的 30+ 类契约 + 页面规范)请用**移植模式**。
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## 4. 文档导入模式(create-from-docs)
|
|
95
|
+
|
|
96
|
+
**场景**:手里有**既有的 Markdown 规范树**(非代码、非模板库形态)——如企业的三层规范
|
|
97
|
+
(基础元素层 / 页面模板层 / 模式规范层)。
|
|
98
|
+
|
|
99
|
+
**流程(5 步)**:
|
|
100
|
+
|
|
101
|
+
1. **提取**:`node ${CLAUDE_PLUGIN_ROOT}/scripts/token-extract.mjs <规范树目录> --docs`
|
|
102
|
+
→ `.team-flow/token-extract/source-docs.json` + 报告(**零 LLM**)
|
|
103
|
+
2. **呈现报告(含冲突项)**:报告器只呈现**证据与冲突**,**不做取值裁决**——
|
|
104
|
+
同一 token 名多值时显式并列(如 `--color-primary`:`#1890ff`×20 / `#3A94DD`×3),
|
|
105
|
+
标注"跨期/跨源矛盾,需人工裁决"
|
|
106
|
+
3. **人工裁决**(多轮 `AskUserQuestion`):**语义角色由人定,不由 LLM 定**
|
|
107
|
+
4. **落盘**:base + 变体(含 `layout` 段的「容器骨架」块 + `页面范式来源:项目自有`)
|
|
108
|
+
+ **`来源与裁决记录` 段(强制)**
|
|
109
|
+
5. guard 校验
|
|
110
|
+
|
|
111
|
+
**为什么报告器不做裁决**:真实规范树的 token 主形态是 **Markdown 表格行**,且列序不固定
|
|
112
|
+
(实测 3 种,含交错列);按频次排序会选出**错的主色**(现场实测:错值 `#1890ff` ×157
|
|
113
|
+
vs 正确值 `#3A94DD` ×62——两期各自自洽、互未发现)。工具的职责是**把矛盾摊开**,不是选一个。
|
|
114
|
+
|
|
115
|
+
**授权约束**:导入的既有资产**只留在项目内**,**不打包**进插件分发包。
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## 5. B 端容器骨架为何必须给(v0.55.0)
|
|
120
|
+
|
|
121
|
+
**事实**:内置 `template.html` 的全部 15 个类是
|
|
122
|
+
`brand / btn / btn-primary / btn-secondary / container / eyebrow / hero / hero-center /
|
|
123
|
+
hero-cta / lead / meta / pagefoot / row-between / section / topnav`——
|
|
124
|
+
**清一色营销向**,没有 `app-header` / `app-sider` / `app-main` 这类后台容器类。
|
|
125
|
+
|
|
126
|
+
**后果(不写骨架块时)**:builder 每页都要**从零手写**整套后台骨架 CSS(顶栏 sticky + 侧栏固定宽 +
|
|
127
|
+
主区弹性),而它是**单次派发**的子代理——没有跨页记忆、无法从既有页面"抄",同一项目不同页面
|
|
128
|
+
会漂移出不同的骨架实现。
|
|
129
|
+
|
|
130
|
+
**所以**:`--profile antd`(通用起点)与导入类模式**都附一份骨架块**(类名 + 关键 CSS 声明)。
|
|
131
|
+
这不是"厚资产",是**最小可复现物料**——与"薄起点"定位不冲突。
|
|
132
|
+
|
|
133
|
+
**契约不变**:骨架类**不在** `layouts.md` 的类清单表内,按该表**同一条硬规则**处理——
|
|
134
|
+
**先在页面 `<style>` 里定义,再使用**;绝不允许凭空发明没有 CSS 支撑的全局类。
|
|
135
|
+
物料来源是 primer 的「容器骨架」块(`gen-primer` 逐端摘录原文)。
|
|
136
|
+
|
|
137
|
+
> **三态下的骨架块**(与 `variant-schema.md` 的 `layout` 段三态表一致):
|
|
138
|
+
> `引用内置` → **可省**(C 端/营销页内置骨架够用),但 **B 端建议给**;
|
|
139
|
+
> `项目自有` → **必须给**(这是棕地项目页面规范能进 builder 的唯一通道);
|
|
140
|
+
> `同 <端>` → 由被指向端保证,本端免写。
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## 6. 逆向建库模式(create-from-code)
|
|
145
|
+
|
|
146
|
+
**场景**:企业已有**符合规范的原型代码** → 基于它建立设计系统。
|
|
147
|
+
|
|
148
|
+
**定位**:**确定性提取 + 人工策展**。不做自动语义推断——那会产出"垃圾设计系统 + 满分审计"
|
|
149
|
+
(guard 只校验**结构**合规,不校验**语义**正确)。
|
|
150
|
+
|
|
151
|
+
**入口**:`/team-flow:design-system create-from-code <代码目录>`
|
|
152
|
+
|
|
153
|
+
> ⚠️ **单目录**:`token-extract.mjs` 的位置参数只接受一个源路径,传多个会**显式报错 exit 1**
|
|
154
|
+
> (v0.55.0 修正:原实现静默丢弃其余路径,多仓场景下用户以为处理了全部)。
|
|
155
|
+
> 多仓请**分批调用**,或先合并到一个目录。
|
|
156
|
+
|
|
157
|
+
**流程(5 步)**:
|
|
158
|
+
|
|
159
|
+
1. **提取**:`node ${CLAUDE_PLUGIN_ROOT}/scripts/token-extract.mjs <目录>`
|
|
160
|
+
→ `.team-flow/token-extract/source-tokens.json` + 统计报告(频次 + 位置证据,**零 LLM**)
|
|
161
|
+
2. **呈现报告**:向用户展示提取统计("47 个文件、23 个颜色、8 个间距值,高频 Top10 …")
|
|
162
|
+
3. **候选稿**:从高频值生成候选 token 表(**标注"候选"**)
|
|
163
|
+
4. **人工策展**(多轮 `AskUserQuestion`):用户指定 primary / 中性色 / 语义色 / 字体栈
|
|
164
|
+
(每项有频次+位置证据可参考)→ skill 按确定性规则补齐 A1/A2/B-slot + palette 阶梯
|
|
165
|
+
5. **落盘**:base.md + 变体 + primer + preview(+ 可选 showcase)→ guard 六层审计
|
|
166
|
+
|
|
167
|
+
**关键约束**:绝不静默发明(候选值标注 `sources[]` 证据);**语义角色由人定,不由 LLM 定**;
|
|
168
|
+
目标已有 base.md 时走 iterate 合并(需用户确认)。
|
|
169
|
+
|
|
170
|
+
> **空目录边界(§4 文档导入同此)**:0 个可扫描文件时脚本只输出"发现文件:0"——
|
|
171
|
+
> 须**提示用户核对目录**,不要拿空报告进第 3 步(会把"没扫到"误当成"候选为空"继续策展)。
|