diff --git a/.claude/skills/d8d-iterate/phase-00-scan.md b/.claude/skills/d8d-iterate/phase-00-scan.md index 6314848..14ca206 100644 --- a/.claude/skills/d8d-iterate/phase-00-scan.md +++ b/.claude/skills/d8d-iterate/phase-00-scan.md @@ -62,6 +62,43 @@ - 关键字段 - 模型间关系 +### 3.5 设计文件变更检测(⭐ 设计文件) + +扫描项目根目录的设计文件变更。 + +**先加载适配层文档**: + +``` +Read _d8d/design-tool-adapter/interface.md — 了解 detect 操作 +Read _d8d/design-tool-adapter/adapters/pencil.md — 了解具体命令 +``` + +**检测流程**: + +``` +1. 调用 detect(项目根目录) +2. IF found: + a. 对每个设计文件,执行 git log --oneline -3 {file} 获取最近提交 + b. 执行 git diff HEAD~1 -- {file} 检测是否有变更 + c. 如果发现设计文件有未提交或最近的变更: + → 标记 design_file_changed: true + → 记录变更的文件名和变更摘要 + d. 调用 extract_structure(设计文件) 获取页面名称列表 +3. IF 未找到设计文件: design_file_changed: false +``` + +**输出写入 iterate-context.md**: + +```markdown +### 设计文件状态 +| 文件 | 大小 | 最近修改 | 变更状态 | +|------|------|---------|---------| +| VividSpark1.2.pen | 988KB | 2026-04-09 | 🆕 新增 | + +design_file_changed: true +design_pages: ["Dashboard", "Auth & Pricing", "Pricing Modal", "Publishing Dashboard"] +``` + ### 4. 技术栈识别 从 `package.json` 提取: @@ -98,6 +135,13 @@ - Next.js 16 + App Router - PostgreSQL 17 + Prisma - shadcn/ui + Tailwind CSS + +### 设计文件状态 +| 文件 | 大小 | 最近修改 | 变更状态 | +|------|------|---------|---------| +| VividSpark1.2.pen | 988KB | 2026-04-09 | 🆕 新增 | + +design_file_changed: true/false ``` ## 判断规则 @@ -116,4 +160,13 @@ IF 有规划文档但无 pipeline-state: → 项目类型: planned (已规划未开发) ``` +### 设计文件变更提示 + +``` +IF design_file_changed == true: + → 在 iterate-context.md 中添加提示: + "⚠️ 检测到设计文件有变更。如果用户描述涉及 UI 更新, + 建议变更类型分类为 design,并通过适配层重新提取设计变量。" +``` + 将项目类型写入 `iterate-checkpoint.md`。 diff --git a/.claude/skills/d8d-iterate/phase-01-analyze.md b/.claude/skills/d8d-iterate/phase-01-analyze.md index df6652f..214ca36 100644 --- a/.claude/skills/d8d-iterate/phase-01-analyze.md +++ b/.claude/skills/d8d-iterate/phase-01-analyze.md @@ -126,7 +126,8 @@ regression: → Phase 5 only: d8d-dev --regression design: - → Phase 3: d8d-prototype --incremental + → Phase 2.5: 设计工具适配层重新提取设计变量(⭐ 如 design_file_changed=true 则必须) + → Phase 3: d8d-prototype --incremental(使用最新设计截图作为基准) → Phase 4: d8d-dev --story {affected-stories} → Phase 5: d8d-dev --regression (可选) ``` diff --git a/.claude/skills/d8d-iterate/phase-03-prototype.md b/.claude/skills/d8d-iterate/phase-03-prototype.md index f6b3b6e..5714417 100644 --- a/.claude/skills/d8d-iterate/phase-03-prototype.md +++ b/.claude/skills/d8d-iterate/phase-03-prototype.md @@ -27,6 +27,41 @@ IF NOT has_new_pages AND NOT has_doc_changes → 跳过 Phase 3 ## 执行方式 +### Step 3.0: 设计文件重新提取(⭐ 如 design_file_changed=true 则必须) + +**当 Phase 0 检测到设计文件变更(design_file_changed=true)时,必须先更新设计上下文。** + +**先加载适配层文档**: + +``` +Read _d8d/design-tool-adapter/interface.md +Read _d8d/design-tool-adapter/adapters/pencil.md +``` + +``` +IF design_file_changed == true: + 1. 调用适配层操作重新提取设计文件: + a. extract_structure(设计文件) → 获取最新页面结构 + b. extract_tokens(设计文件) → 获取最新设计 Token + + 2. 更新 UX 设计文档: + - 读取 _bmad-output/planning-artifacts/ux-design-specification.md + - 用新提取的 Token 更新色彩、字体、间距等定义 + - 保留文档中的非设计系统内容(交互规范、页面流程等) + - 如果页面结构有变化,更新页面列表 + + 3. 导出设计页面截图: + - 调用 export_screenshots(设计文件, prototype/.pen-references/) + + 4. 在 iterate-progress.md 记录: + design_re_extracted: true + design_file: "{变更的设计文件}" + updated_tokens: [列出更新的 Token 类别] + +ELSE: + 跳过此步骤 +``` + ### Step 3.1: 检测原型状态 读取 `prototype/.prototype-state.md` 判断状态: @@ -116,5 +151,7 @@ phase-03-prototype: mode: full | [D] | [P] | [A] | first-time pages_updated: [...] # 更新/新增的页面列表 docs_updated: true | false # 文档中心是否更新 + pen_re_extracted: true | false # 设计变量是否通过适配层重新提取 + pen_fidelity_score: "85%" # 设计保真度评分(如适用) reason: "..." # 如果跳过了 ``` diff --git a/.claude/skills/d8d-prototype/steps/step-01-analyze.md b/.claude/skills/d8d-prototype/steps/step-01-analyze.md index a545f19..e053977 100644 --- a/.claude/skills/d8d-prototype/steps/step-01-analyze.md +++ b/.claude/skills/d8d-prototype/steps/step-01-analyze.md @@ -8,7 +8,7 @@ ## 执行序列 -### 1.1 检查可复用的现有素材 +### 1.1 检查可复用的现有素材 + .pen 设计文件提取 在开始生成之前,**先检查项目中是否有客户/设计师提供的现有页面或设计素材**: @@ -21,25 +21,78 @@ - 提取现有页面的设计 token(颜色、字体、间距)作为新页面的基础 - 确保复用页面与新页面的设计风格一致 +#### 1.1.1 设计文件检测与提取(⭐ 高保真关键步骤) + +如果项目根目录存在设计文件(如 `*.pen`),**必须**通过设计工具适配层提取精确设计信息,作为原型生成的视觉基准。 + +**先加载适配层文档**: + +``` +Read _d8d/design-tool-adapter/interface.md — 了解可用操作 +Read _d8d/design-tool-adapter/adapters/pencil.md — 了解具体命令(如使用 Pencil) +``` + +**执行流程**: + +``` +1. 调用 detect(项目根目录) +2. IF found: + a. 调用 extract_structure(设计文件) → 获取页面名称和组件层级 + b. 调用 extract_tokens(设计文件) → 获取精确的颜色、字体、间距 Token + c. 调用 export_screenshots(设计文件, prototype/.pen-references/) → 导出页面截图 +3. IF 未找到设计文件: 跳过此步骤 +``` + +**提取内容写入状态文件**: + +```yaml +design_file: + tool: "pencil" + file: "VividSpark1.2.pen" + pages: + - name: "Dashboard" + id: "2dEtF" + screenshot: ".pen-references/dashboard.png" + - name: "Auth & Pricing" + id: "Er7uX" + screenshot: ".pen-references/auth-pricing.png" + variables: + colors: { background: "#0a0a0f", foreground: "#ffffff", ... } + fonts: { family: "Inter", sizes: [...] } + spacing: { unit: "4px", scale: [...] } +``` + +**为什么这一步至关重要**: +- 设计文件包含精确的像素级设计信息(间距、圆角、阴影) +- 仅靠 UX 文档的文字描述无法还原这些细节 +- 导出的截图作为 step-02 生成 HTML 时的视觉参考 +- step-07 验证时用于对比原型与原始设计的保真度 + ### 1.2 读取项目设计系统(⚠️ 最高优先级) **必须先读取项目的设计系统文档,项目设计系统优先级高于一切默认值。** #### 设计系统发现顺序(按优先级) -1. **项目 UX 设计文档**(最高优先级) +1. **设计文件**(最高优先级,精确值) + - 通过 1.1.1 步骤 detect() 检测到的设计文件 + - 提取的精确 Token 和截图 + - **如果存在,设计 Token 必须以设计文件提取值为准** + - UX 文档和设计文件 Token 冲突时,以设计文件为准 + +2. **项目 UX 设计文档** - 路径: `_bmad-output/planning-artifacts/*ux*.md` 或 `docs/*ux*.md` - 提取: CSS 变量、色彩系统、字体系统、组件样式、页面布局规范 - - 如果存在,**必须使用其中定义的所有设计 Token** + - 如果存在,**必须使用其中定义的所有设计 Token**(.pen 不存在的部分) -2. **项目 CLAUDE.md 中的设计规范** +3. **项目 CLAUDE.md 中的设计规范** - 查找 CLAUDE.md 中的"设计风格"、"色彩规范"等章节 -3. **DESIGN.md 或类似设计系统文件** +4. **DESIGN.md 或类似设计系统文件** - 路径: `DESIGN.md`、`docs/DESIGN.md`、`design-system.md` -4. **references/design-patterns.md**(兜底默认值) - - 仅在前三者均不存在时使用 +5. **references/design-patterns.md**(兜底默认值) + - 仅在前四者均不存在时使用 - 使用时需告知用户:"未找到项目设计系统文档,使用默认配色方案" #### Token 提取清单 @@ -120,8 +173,10 @@ prototype-v2/screenshots/ - [ ] 方案文档已读取和分析 - [ ] 设计系统已提取(或确认使用默认值) +- [ ] 设计文件已检测和提取(如存在,通过适配层) +- [ ] 设计文件页面截图已导出到 prototype/.pen-references/(如存在) - [ ] 页面清单已生成(前台+后台) -- [ ] 状态文件已写入页面清单 +- [ ] 状态文件已写入页面清单(含 pen_design 部分,如适用) - [ ] 状态文件 current_step 已更新为 step-02 **完成后,加载 `steps/step-02-generate-pages.md` 继续执行。** diff --git a/.claude/skills/d8d-prototype/steps/step-07-validate.md b/.claude/skills/d8d-prototype/steps/step-07-validate.md index 2068941..2b1e25c 100644 --- a/.claude/skills/d8d-prototype/steps/step-07-validate.md +++ b/.claude/skills/d8d-prototype/steps/step-07-validate.md @@ -150,6 +150,46 @@ actual_image_source: prototype/screenshots/actual.png prompt: 对比参考设计与实际实现,指出差异和问题 ``` +### 7.5.1 设计保真度验证(⭐ 如有设计文件则强制执行) + +**当 step-01 在状态文件中生成了 `design_file` 部分时,本步骤不可跳过。** + +**先加载适配层文档**: + +``` +Read _d8d/design-tool-adapter/interface.md — 了解 compare_visuals 操作 +Read _d8d/design-tool-adapter/adapters/pencil.md — 了解具体命令 +``` + +**目标**:将生成的原型页面截图与设计文件导出的原始截图进行对比,检测保真度差距。 + +**执行流程**: + +``` +1. 读取 .prototype-state.md 中的 design_file 部分 +2. IF design_file 存在: + a. 对 design_file.pages 中的每个页面: + - 找到对应的原型截图(prototype/screenshots/) + - 读取设计文件参考截图(prototype/.pen-references/ 或等效目录) + - 调用 compare_visuals(设计截图, 原型截图) + + b. 汇总所有页面的对比结果 + +3. IF 发现 🔴 关键差异: + → 输出修复建议(精确到 CSS 属性级别) + → 建议重新生成该页面的 HTML + +4. 记录到验证报告的「设计保真度」部分 +``` + +**差异分类标准**: + +| 级别 | 描述 | 示例 | 处理 | +|------|------|------|------| +| 🔴 关键 | 布局结构不一致 | 导航栏位置错误、缺少侧边栏 | 必须修复 | +| 🟡 中等 | 视觉明显不同但不影响功能 | 配色偏差、间距不一致 | 建议修复 | +| 🟢 次要 | 细微差别 | 字号差 1px、阴影深度微差 | 可接受 | + ### 7.6 验证检查清单 #### 链接验证 @@ -192,6 +232,13 @@ prompt: 对比参考设计与实际实现,指出差异和问题 - [ ] 交互流程正确 - [ ] 与需求文档描述一致 +#### 设计保真度验证 ⭐(如有设计文件则强制) +- [ ] 设计文件参考截图已加载 +- [ ] 每个原型页面已与对应设计页面对比 +- [ ] 关键差异(🔴)已记录并修复 +- [ ] 中等差异(🟡)已记录并有处理决定 +- [ ] 保真度评分已记录(0-100%) + ### 7.7 生成验证报告 ```markdown @@ -233,6 +280,16 @@ prompt: 对比参考设计与实际实现,指出差异和问题 ## 问题列表 1. [问题描述] → [改进建议] + +## 设计保真度 ⭐(如有设计文件) +### 保真度总评: X% +| 页面 | 设计文件截图 | 原型截图 | 保真度 | 🔴 关键 | 🟡 中等 | 🟢 次要 | +|------|------------|---------|--------|--------|--------|--------| +| Dashboard | .pen-references/dashboard.png | screenshots/dashboard.png | 85% | 0 | 2 | 3 | +| Login | .pen-references/auth.png | screenshots/login.png | 92% | 0 | 1 | 2 | + +### 关键差异修复建议 +1. [差异描述] → [具体 CSS/HTML 修复建议] ``` ### 7.8 最终状态更新 @@ -245,6 +302,7 @@ prompt: 对比参考设计与实际实现,指出差异和问题 - [ ] 所有页面已截图 - [ ] **所有文档内容已验证加载成功** +- [ ] 设计保真度验证完成(如适用,含截图对比) - [ ] 链接验证通过 - [ ] 平铺布局验证通过 - [ ] 样式分析完成 diff --git a/.claude/skills/d8d-requirements/steps/phase-00-setup.md b/.claude/skills/d8d-requirements/steps/phase-00-setup.md index a02490f..1074b1e 100644 --- a/.claude/skills/d8d-requirements/steps/phase-00-setup.md +++ b/.claude/skills/d8d-requirements/steps/phase-00-setup.md @@ -25,11 +25,12 @@ ## 3. 设计文件检测 -1. Glob 项目根目录 `*.pen` +**先加载适配层**:`Read _d8d/design-tool-adapter/interface.md` 和 `adapters/pencil.md` + +1. 调用 `detect(项目根目录)` 检测设计文件 2. 如果找到: - - 使用 `mcp__pencil__snapshot_layout` 读取顶层结构(maxDepth=0) - - 使用 `mcp__pencil__batch_get` 提取页面名称(readDepth=0) - - 使用 `mcp__pencil__get_variables` 提取设计系统变量 + - 调用 `extract_structure(设计文件)` 提取页面名称和组件层级 + - 调用 `extract_tokens(设计文件)` 提取设计系统变量 - 构建设计上下文摘要 3. 如果未找到:记录 `design_file: null` diff --git a/.claude/skills/d8d-requirements/steps/phase-02-planning.md b/.claude/skills/d8d-requirements/steps/phase-02-planning.md index 8ad53d8..6f6c60c 100644 --- a/.claude/skills/d8d-requirements/steps/phase-02-planning.md +++ b/.claude/skills/d8d-requirements/steps/phase-02-planning.md @@ -147,9 +147,9 @@ Glob {planning_artifacts}/*ux*.md 2. 产品简报(完整内容) 3. 设计文件详细上下文(从 pipeline-context.md 获取设计系统变量、页面布局) -如果 .pen 文件存在,额外提取: -- 使用 `mcp__pencil__get_variables` 获取设计 token -- 使用 `mcp__pencil__batch_get` 获取关键页面的布局结构 +如果设计文件存在(从 pipeline-context.md 检测),通过适配层额外提取(参见 `_d8d/design-tool-adapter/`): +- 调用 `extract_tokens(设计文件)` 获取设计 token +- 调用 `extract_structure(设计文件)` 获取关键页面的布局结构 ### 2.3.3 调用子技能 diff --git a/.claude/skills/d8d-requirements/workflow.md b/.claude/skills/d8d-requirements/workflow.md index 52ef853..40fdbe6 100644 --- a/.claude/skills/d8d-requirements/workflow.md +++ b/.claude/skills/d8d-requirements/workflow.md @@ -231,11 +231,10 @@ phases: ### Scanning (phase-00) ``` -1. Glob 项目根目录 *.pen -2. 如找到:使用 mcp__pencil__snapshot_layout 读取顶层结构 -3. 使用 mcp__pencil__batch_get 提取页面名称和组件层级 -4. 使用 mcp__pencil__get_variables 提取设计系统变量 -5. 存储摘要到 pipeline-context.md +1. 调用 detect(项目根目录) 检测设计文件(参见 _d8d/design-tool-adapter/) +2. 如找到:调用 extract_structure() 提取页面结构和组件层级 +3. 调用 extract_tokens() 提取设计系统变量 +4. 存储摘要到 pipeline-context.md ``` ### Context Per Sub-Skill diff --git a/.claude/skills/d8d-skills-sync/SKILL.md b/.claude/skills/d8d-skills-sync/SKILL.md index e09717e..14a7a28 100644 --- a/.claude/skills/d8d-skills-sync/SKILL.md +++ b/.claude/skills/d8d-skills-sync/SKILL.md @@ -7,7 +7,9 @@ description: '将项目中 .claude/skills/ 下所有 d8d-* 技能目录(d8d-de 将项目 `.claude/skills/` 下所有 `d8d-*` 目录与 `https://gitea.d8d.fun/d8dfun/bmad-method-template` 双向同步。 -同步范围:所有匹配 `d8d-*/` 的技能目录(包括 d8d-dev、d8d-requirements、d8d-prototype、d8d-skills-sync 自身等) +同步范围: +1. 所有匹配 `d8d-*/` 的技能目录(包括 d8d-dev、d8d-requirements、d8d-prototype、d8d-skills-sync 自身等) +2. `_d8d/` 共享资源目录(设计工具适配层等) ## 配置 @@ -15,7 +17,7 @@ description: '将项目中 .claude/skills/ 下所有 d8d-* 技能目录(d8d-de TEMPLATE_REPO_URL: https://gitea.d8d.fun/d8dfun/bmad-method-template.git TEMPLATE_REPO_API: https://gitea.d8d.fun/api/v1/repos/d8dfun/bmad-method-template LOCAL_CLONE_PATH: /tmp/bmad-method-template -SYNC_PATTERNS: .claude/skills/d8d-*/ +SYNC_PATTERNS: .claude/skills/d8d-*/ _d8d/ ``` Gitea 认证信息从项目 git remote URL 提取(oauth2 token 在 remote URL 中)。 @@ -49,6 +51,13 @@ for skill_dir in $PROJECT_ROOT/.claude/skills/d8d-*/; do fi done +# _d8d 共享资源目录差异 +if [ -d $PROJECT_ROOT/_d8d ] && [ -d /tmp/bmad-method-template/_d8d ]; then + diff -rq $PROJECT_ROOT/_d8d/ /tmp/bmad-method-template/_d8d/ 2>/dev/null || true +elif [ -d $PROJECT_ROOT/_d8d ]; then + echo " NEW in project: _d8d/" +fi + echo "=== B) 模板有而项目无(需先拉到项目)===" for skill_dir in /tmp/bmad-method-template/.claude/skills/d8d-*/; do skill=$(basename $skill_dir) @@ -58,6 +67,11 @@ for skill_dir in /tmp/bmad-method-template/.claude/skills/d8d-*/; do echo " NEW in template: $skill/" fi done + +# _d8d 模板独有 +if [ -d /tmp/bmad-method-template/_d8d ] && [ ! -d $PROJECT_ROOT/_d8d ]; then + echo " NEW in template: _d8d/" +fi ``` 如果 A 和 B 都为空 → 告知用户"已是最新,无需同步"。 @@ -81,7 +95,7 @@ done 3. 拉取完成后提交: ```bash - git add .claude/skills/d8d-*/ && git commit -m "chore(skill): 从模板拉取更新 — {摘要}" + git add .claude/skills/d8d-*/ _d8d/ _d8d/ && git commit -m "chore(skill): 从模板拉取更新 — {摘要}" git push ``` @@ -99,12 +113,18 @@ for skill_dir in $PROJECT_ROOT/.claude/skills/d8d-*/; do mkdir -p .claude/skills/$skill/ cp -r $skill_dir* .claude/skills/$skill/ done + +# 同步 _d8d 共享资源目录 +if [ -d $PROJECT_ROOT/_d8d ]; then + mkdir -p _d8d/ + cp -r $PROJECT_ROOT/_d8d/* _d8d/ +fi ``` ### Step 4: 提交 ```bash -git add .claude/skills/d8d-*/ +git add .claude/skills/d8d-*/ _d8d/ git diff --cached --stat # 确认只有项目独有的变更 git commit -m "sync: {简要描述变更内容}" ``` diff --git a/_d8d/design-tool-adapter/adapters/pencil.md b/_d8d/design-tool-adapter/adapters/pencil.md new file mode 100644 index 0000000..dc1667b --- /dev/null +++ b/_d8d/design-tool-adapter/adapters/pencil.md @@ -0,0 +1,167 @@ +# Pencil CLI 适配器 + +> 实现 `_d8d/design-tool-adapter/interface.md` 定义的 5 个操作。 +> **环境要求**:`pencil` CLI 已安装(`npm install -g @pencil.dev/cli`),无桌面环境依赖。 + +## 前置检查 + +```bash +pencil --version # 确认 >= 0.2.4 +pencil status # 确认已认证 +``` + +## 操作实现 + +### 1. detect(root_dir) + +```bash +find {root_dir} -maxdepth 1 -name "*.pen" -type f +``` + +对找到的每个 .pen 文件,获取文件信息: + +```bash +stat --format="%s %y" {file}.pen +``` + +返回: + +```yaml +found: true +files: + - path: "{root_dir}/VividSpark1.2.pen" + size: "988KB" + modified: "2026-04-09" +tool_type: "pencil" +``` + +### 2. extract_structure(file) + +使用 `pencil interactive` 模式提取结构: + +```bash +pencil interactive --in {file}.pen <<'EOF' +snapshot_layout({"maxDepth": 1}) +EOF +``` + +再提取页面详情: + +```bash +pencil interactive --in {file}.pen <<'EOF' +batch_get({"readDepth": 0}) +EOF +``` + +**解析输出**:从 JSON 输出中提取: +- 顶层 frame 节点作为页面(`type: "frame"`, 无父节点) +- 可复用组件列表(`reusable_components` 数组) + +返回: + +```yaml +pages: + - id: "{node_id}" + name: "{node_name}" + type: "frame" +components: + - name: "{component_name}" + instances: {count} +``` + +**注意**:interactive 模式的输出可能很大(几百 KB),建议保存到文件后分段读取: + +```bash +pencil interactive --in {file}.pen <<'EOF' > /tmp/pencil-structure.json +snapshot_layout({"maxDepth": 1}) +EOF +``` + +### 3. extract_tokens(file) + +```bash +pencil interactive --in {file}.pen <<'EOF' > /tmp/pencil-tokens.json +get_variables({}) +EOF +``` + +**解析输出**:从 `get_variables` 返回的 JSON 中提取: +- `$--background`, `$--foreground`, `$--primary` 等颜色变量 +- 字体 family 和 size +- 其他 CSS 变量 + +**注意变量引用格式**:.pen 文件中变量用 `$--name` 格式,但有些文件可能有转义问题(`\\$--name`)。解析时需要处理两种格式。 + +返回格式见 `interface.md` extract_tokens 部分。 + +### 4. export_screenshots(file, output_dir, pages) + +**导出全部页面**: + +```bash +pencil --in {file}.pen --out {output_dir}/full-export.png +``` + +**导出特定页面**(使用 interactive 模式的 export_nodes): + +```bash +pencil interactive --in {file}.pen <<'EOF' +export_nodes({"nodeIds": ["page_id_1", "page_id_2"], "format": "png", "outputDir": "{output_dir}"}) +EOF +``` + +或逐页面导出: + +```bash +pencil --in {file}.pen --out {output_dir}/dashboard.png --node-id 2dEtF +``` + +**确保输出目录存在**: + +```bash +mkdir -p {output_dir} +``` + +返回: + +```yaml +screenshots: + - page_id: "{id}" + page_name: "{name}" + path: "{output_dir}/{name}.png" +``` + +### 5. compare_visuals(img_a, img_b) + +使用 ZAI MCP 的 ui_diff_check 工具(非 Pencil MCP,在服务器上可用): + +``` +mcp__zai-mcp-server__ui_diff_check + expected_image_source: {img_a} + actual_image_source: {img_b} + prompt: "严格对比原始设计与实现。重点检查: + 1. 布局结构(导航栏、侧边栏、内容区域位置) + 2. 配色方案(背景色、文字色、强调色) + 3. 组件间距和比例 + 4. 字体大小和粗细 + 5. 圆角、阴影等细节 + 按严重程度分类:🔴 critical / 🟡 moderate / 🟢 minor" +``` + +解析 MCP 返回结果,映射到接口格式: + +```yaml +score: "85%" +differences: + - level: "critical" | "moderate" | "minor" + category: "layout" | "color" | "spacing" | "typography" | "component" + description: "{从 MCP 结果中提取}" + suggestion: "{从 MCP 结果中提取}" +``` + +## 已知问题 + +1. **大文件处理**:`get_editor_state` 输出可达 638KB+,必须保存到文件后分段读取 +2. **变量转义**:部分 .pen 文件变量引用使用 `\\$--name` 而非 `$--name`,解析时需兼容 +3. **interactive 模式输入**:需要通过 heredoc 或管道传入 JSON 命令 +4. **导出限制**:CLI 导出可能不支持所有节点类型,fallback 到全页面导出 diff --git a/_d8d/design-tool-adapter/interface.md b/_d8d/design-tool-adapter/interface.md new file mode 100644 index 0000000..0425eb0 --- /dev/null +++ b/_d8d/design-tool-adapter/interface.md @@ -0,0 +1,163 @@ +# 设计工具适配层 — 接口定义 + +> 本文件定义设计工具的抽象接口。具体实现见 `adapters/{tool}.md`。 +> 当前可用适配器:`pencil.md`(Pencil CLI) + +## 前置条件 + +使用前需确认目标工具已安装且可用: + +``` +pencil --version # 或其他工具的版本命令 +``` + +## 操作接口 + +### 1. detect(root_dir) + +**用途**:检测项目根目录中是否存在设计文件。 + +| 参数 | 类型 | 说明 | +|------|------|------| +| root_dir | string | 项目根目录绝对路径 | + +**返回**: + +```yaml +found: true | false +files: + - path: "VividSpark1.2.pen" + size: "988KB" + modified: "2026-04-09" +tool_type: "pencil" | "figma" | null +``` + +### 2. extract_structure(file) + +**用途**:提取设计文件的页面结构和组件层级。 + +| 参数 | 类型 | 说明 | +|------|------|------| +| file | string | 设计文件绝对路径 | + +**返回**: + +```yaml +pages: + - id: "2dEtF" + name: "Dashboard" + type: "frame" + - id: "Er7uX" + name: "Auth & Pricing" + type: "frame" +components: + - name: "Button" + instances: 12 + - name: "Card" + instances: 8 +``` + +### 3. extract_tokens(file) + +**用途**:提取设计文件的样式变量(Token)。 + +| 参数 | 类型 | 说明 | +|------|------|------| +| file | string | 设计文件绝对路径 | + +**返回**: + +```yaml +colors: + background: "#0a0a0f" + foreground: "#ffffff" + primary: "#ff6b2b" + card: "#141420" + border: "#2a2a3a" + muted_foreground: "#8888a0" +fonts: + family: "Inter" + sizes: [12, 14, 16, 18, 20, 24, 32, 48] + weights: [400, 500, 600, 700] +spacing: + unit: "4" + scale: [4, 8, 12, 16, 20, 24, 32, 48, 64] +radii: + sm: "4" + md: "8" + lg: "12" + xl: "16" + full: "9999" +shadows: + sm: "0 1px 2px rgba(0,0,0,0.3)" + md: "0 4px 8px rgba(0,0,0,0.4)" + lg: "0 8px 16px rgba(0,0,0,0.5)" +``` + +### 4. export_screenshots(file, output_dir, pages) + +**用途**:导出设计文件中指定页面的截图。 + +| 参数 | 类型 | 说明 | +|------|------|------| +| file | string | 设计文件绝对路径 | +| output_dir | string | 截图输出目录 | +| pages | string[] | 可选,指定导出的页面 ID。为空则导出所有顶层页面 | + +**返回**: + +```yaml +screenshots: + - page_id: "2dEtF" + page_name: "Dashboard" + path: "{output_dir}/dashboard.png" + width: 1440 + height: 900 + - page_id: "Er7uX" + page_name: "Auth & Pricing" + path: "{output_dir}/auth-pricing.png" +``` + +### 5. compare_visuals(img_a, img_b) + +**用途**:对比两张截图的视觉差异。 + +| 参数 | 类型 | 说明 | +|------|------|------| +| img_a | string | 参考截图路径(设计文件导出) | +| img_b | string | 实际截图路径(原型或实现) | + +**返回**: + +```yaml +score: "85%" +differences: + - level: "critical" | "moderate" | "minor" + category: "layout" | "color" | "spacing" | "typography" | "component" + description: "导航栏位置不一致" + suggestion: "调整导航栏为固定顶部" +``` + +## 使用模式 + +在 d8d 技能步骤文件中引用本接口: + +```markdown +#### 设计文件操作 + +加载 `_d8d/design-tool-adapter/interface.md` 了解可用操作。 +加载 `_d8d/design-tool-adapter/adapters/pencil.md` 了解具体命令。 + +1. 调用 detect(项目根目录) 检测设计文件 +2. IF found: 调用 extract_structure() + extract_tokens() 提取设计信息 +3. 调用 export_screenshots() 导出页面截图 +4. 调用 compare_visuals() 对比设计 vs 实现 +``` + +## 适配器实现指南 + +新增适配器(如 Figma)只需在 `adapters/` 下创建 `{tool}.md`,实现上述 5 个操作。每个操作需包含: +- 具体的命令或 API 调用 +- 输入参数映射 +- 输出格式转换(需匹配本接口定义的返回格式) +- 环境要求和前置条件