diff --git a/skills/le-app-design/SKILL.md b/skills/le-app-design/SKILL.md index b2f631b..a55a7f2 100644 --- a/skills/le-app-design/SKILL.md +++ b/skills/le-app-design/SKILL.md @@ -6,7 +6,7 @@ description: | 不要触发:点名单个上游 Skill 的直接请求(直连该上游即可);写作与排版类任务;单张配图生成;纯功能开发与排障(无设计诉求)。 metadata: author: Leroy - version: 1.1.0 + version: 1.2.0 runtimes: zcode, claude-code, codex, opencode requires: - "ui-ux-pro-max (MIT, nextlevelbuilder/ui-ux-pro-max-skill)" @@ -23,7 +23,7 @@ metadata: 1. **真调用,不冒充。** 三个上游必须以其原生形态被实际调用:ui-ux-pro-max 跑它的 `search.py` CLI;impeccable 跑它的 `impeccable` CLI 并按其 SKILL.md 路由装载 reference/*.md playbook 照做;frontend-design 经宿主 Skill 工具装载(或 Read 原文全文)。禁止只引用名字、模仿理念、用自写流程替代。 2. **依赖门不过,不许动工。** S0 检测到任何一个上游缺失/失活,立即向用户报告缺什么、怎么装,终止本次运行。不许跳过、不许假装集成完成。 3. **调用必记账。** 每次对上游的调用(含 playbook/文档装载)都经 `log_call.py` 落入本次运行目录的 `calls.jsonl`。没进账本的调用视为没发生。 -4. **交付必过验收门。** S7 跑 `evidence_report.py`,三方各有 ≥1 条成功调用记录才可宣称完成;否则如实报告 FAIL 与原因。 +4. **交付必过验收门。** S7 跑 `evidence_report.py`,门按任务类型的 `--require` 集合判:完整流程要求三方各 ≥1 条**履职阶段**成功调用(pro-max 计 S3- 前缀,防 S2 调研混门);轻量路由只要求参与该路由的上游。不过门不许宣称完成。 5. **不改上游。** 三个上游目录只读(调用、装载),任何修改都不属于本 Skill 的职责。 6. **用户 brief 原话 > 一切。** 三个上游都自认 brief 优先,本 Skill 同样:brief 钉死的方向照办,冲突记入决策日志。 @@ -50,7 +50,7 @@ python3 /scripts/check_deps.py --out /deps.json ### S1 产品理解 -产出 `/BRIEF.md`:产品是什么、给谁、核心任务、平台与形态(移动 Web / 桌面 / 响应式)、impeccable 四模式归属(Persuade / Operate / Read / Experience)。brief 信息不足且影响方向 → 问用户;足够 → 写明假设直接做。 +产出 `/BRIEF.md`:**项目代号**(供 S3 的 `-p` 与目录命名)、产品是什么、给谁、核心任务、平台与形态、impeccable 四模式归属(Persuade / Operate / Read / Experience)。brief 信息不足且影响方向 → 问用户;足够 → 写明假设直接做。 ### S2 视觉探索 — frontend-design(方向先行) @@ -78,11 +78,12 @@ python3 /scripts/log_call.py ui-ux-pro-max --run-dir --note S3-desi 向用户展示 BRIEF + design-plan(设计方向)+ MASTER 要点或降级说明,等确认或调整后再进构建。用户已明确说「一口气跑完」→ 豁免本停点,继续。**本停点必须终止回合等待用户,不得自答自继续。** -### S4 高保真构建 +### S4 高保真构建(a 首屏 → 停点 1.5 → b 全量) -1. Read `/reference/craft-floor.md`(impeccable 施工底线,装载即调用)并记账 `log_call.py impeccable --load <该文件>`。 -2. 照规范 tokens(MASTER.md,或 S3 降级时的 design-plan token 表)+ design-plan 写可运行、可交互的 Web 原型(默认单文件或多文件 HTML/CSS/JS,无构建链)。 -3. headless Chrome 截图核对(375/390 移动档 + 桌面档),按 craft-floor「一次看一批」原则修完再截。 +1. Read `/reference/craft-floor.md`(装载即调用)并记账。 +2. **S4a 首屏**:先只构建主界面一屏(真实内容 + 规范 token + design-plan 个性),390×844 截图。 +3. **停点 1.5(首屏确认,回合终止点)**:把首屏截图发到对话,请用户确认「方向落地长这样」再继续——这一站消除盲盒:成品第一次见面不再是 S5 之后。豁免时跳过停顿,**但截图仍必须发出**。 +4. **S4b 全量**:其余屏 + 完整交互(390 主档 + 375 兼容档截图;移动 Web 任务免桌面档)。显隐/布局断言用渲染事实(computed display / boundingRect),不信 hidden 属性。 ### S5 设计审查 — impeccable @@ -93,7 +94,7 @@ python3 /scripts/log_call.py ui-ux-pro-max --run-dir --note S3-desi ### 停点 2(回合终止点) -展示审查报告,与用户确认修复范围(全部 / Top 3 / 仅 P0-P1)再进 S6。「一口气跑完」豁免同上;**豁免时默认修复范围为 P0+P1,且审查报告末尾必须补字面行 `Questions skipped: 停点2经用户豁免(默认修复 P0+P1)`——这是 impeccable critique 契约的收尾要求,漏了即该次 critique 不完整。** +展示审查报告**并附修复前后关键截图**(不是纯文字报告——用户确认修复范围时应已见过成品),四选一:全部 / Top 3 / 仅 P0-P1 / 保持现状(现状=跳过 S6 直接 S7,报告照出)。「一口气跑完」豁免同上;豁免时默认修 P0+P1,且审查报告末尾必须补字面行 `Questions skipped: 停点2经用户豁免(默认修复 P0+P1)`——这是 impeccable critique 契约的收尾要求,漏了即该次 critique 不完整。 ### S6 优化迭代 @@ -102,17 +103,20 @@ python3 /scripts/log_call.py ui-ux-pro-max --run-dir --note S3-desi ### S7 交付 + 验收门 ```bash +# 完整流程(默认三方门,pro-max 计履职前缀) python3 /scripts/evidence_report.py --run-dir --out /INTEGRATION-REPORT.md \ - --artifact <原型主文件> --artifact <截图...> + --require "ui-ux-pro-max:S3-,frontend-design:S2-,impeccable" \ + --artifact <原型主文件> --artifact /shot-*.png --artifact /design-plan.md +# 系统路径(非降级)另加 --artifact design-system//MASTER.md(slug 跑完 S3 后 ls design-system/ 确认) ``` -交付物 = 原型(可打开可交互)+ BRIEF/design-plan/MASTER + 审查报告与快照 + INTEGRATION-REPORT(三方调用统计、命令清单、产物存在性核验)。报告 FAIL(任何一方 0 成功调用)→ 不许宣称完成,如实说明缺什么。 +交付物 = 原型(可打开可交互)+ BRIEF/design-plan/MASTER(或降级说明)+ 审查报告与快照 + INTEGRATION-REPORT。报告 FAIL(门或产物缺失)→ 不许宣称完成,如实说明缺什么。 -## 轻量任务路由 +## 轻量任务路由(含各自的验收门口径) -- **仅审查/体检**(「帮我审一下这个原型的设计」):S0 → S5(→停点2)→ S6 → S7。 -- **局部修改**(「把这个页面间距调好」):S0 → 若涉及视觉决策走 S2 快速版 → S4′(craft-floor 装载后施工)→ S5′(detect+复截)→ S7。 -- 三上游经 check_deps 解析后始终可调用;轻量路由是省阶段,不是换实现。 +- **仅审查/体检**(「帮我审一下这个原型的设计」):S0 → S5(完整 critique:装载 critique.md + 双 sub-agent + detect + 快照)→ 停点 2 →(S6 按所选范围)→ S7。验收门 `--require "impeccable"`。 +- **局部修改**(「把这个页面间距调好」):S0 → S2 快速版(涉及视觉决策时:装载 frontend-design + 记账,方向口头确认即可,无 design-plan 全文档)→ S4′(craft-floor 装载 + 就地修改 + 渲染事实断言 + 复截图)→ S5′(detect --json + 复截对比,不走完整 critique)→ S7。验收门 `--require "impeccable"`(走了 S2 快速版则加 `,frontend-design`)。 +- 三上游经 check_deps 解析后始终可调用;轻量路由是省阶段,不是换实现——省掉的阶段不要求调用,但**不许伪造调用记录凑门**。 ## 失败模式与停手点 diff --git a/skills/le-app-design/references/pipeline.md b/skills/le-app-design/references/pipeline.md index ea855ef..cdb4afc 100644 --- a/skills/le-app-design/references/pipeline.md +++ b/skills/le-app-design/references/pipeline.md @@ -60,7 +60,7 @@ python3 /scripts/log_call.py ui-ux-pro-max --run-dir --note S3-ux-c **两条规则**: - **硬约束否决权**:frontend-design 定的 hex/字号若不达标(WCAG/HIG/MD 数据为准),**改值不改方向**;每处修改记入 design-plan 决策记录。 -- **目录回弹降级**:pro-max 风格目录(51 个活跃风格)若对已定方向匹配失败——生成结果明显回弹到品类默认(拿 tell 清单对:cream 底、默认靛蓝、SaaS 卡组等)——则**不采用该 MASTER**,降级为「design-plan 的 token 表即规范 + pro-max 逐项校验补硬约束」,决策记录写明降级理由。方向的独特性优先于系统的便利性。 +- **目录回弹降级(操作化判据)**:生成结果命中以下任意两条即判回弹、不采用该 MASTER——①Style 名与方向关键词无词面或语义关联(如「练习本手写」→ Swiss/Helvetica);②色板命中 AI-tell 家族(暖奶油底、默认靛蓝/紫系、近黑+酸绿)且与 design-plan 色板无共享主色;③关键 Effects/Anti-patterns 与方向的手感相反(如手绘方向得到 corporate/rational)。降级后:design-plan 的 token 表即规范 + pro-max 逐项校验补硬约束,决策记录写明命中哪两条。方向的独特性优先于系统的便利性。 **验收**:MASTER.md 存在且与方向一致,或降级路径已记录;校验检索在账本;design-plan 决策记录含 S3 的改值/降级条目。 @@ -68,25 +68,24 @@ python3 /scripts/log_call.py ui-ux-pro-max --run-dir --note S3-ux-c 把 BRIEF(要点)、design-plan(方向 + ASCII + 色板 + 原则)、MASTER 要点或 S3 降级说明展示给用户,明确请求确认或调整意见,**终止回合**。用户豁免(已说「一口气跑完」)→ 跳过继续。 -## S4 高保真构建 +## S4 高保真构建(a 首屏 → 停点 1.5 → b 全量) -**动作** +**S4a 首屏** 1. Read `/reference/craft-floor.md` 并记账: `python3 /scripts/log_call.py impeccable --run-dir --note S4-craft-floor --load /reference/craft-floor.md` -2. 构建:默认无构建链的 HTML/CSS/JS(单文件优先,可拆 CSS/JS 文件)。硬性要求: +2. 只构建**主界面一屏**(真实内容 + 规范 tokens + design-plan 个性),390×844 截一张。 + +**停点 1.5(首屏确认)**:截图发到对话请用户确认方向落地;豁免时跳过停顿但截图必须发出。**终止回合**;这一站是「盲盒阀门」——成品首见从 S5 之后提前到构建开头。 + +**S4b 全量** +1. 构建:默认无构建链的 HTML/CSS/JS(单文件优先,可拆 CSS/JS 文件)。硬性要求: - token 来自 MASTER.md(或降级时的 design-plan token 表),不发明规范之外的美学量 - 布局与个性按 design-plan;SVG 图标(真图标库或手绘一致笔画),禁 emoji 图标 - - craft-floor 全条目施工时遵守(尤其:eyebrow 是 ban;嵌套卡片必错;elevation 声明一次;浏览器表面——selection/caret/scrollbar/focus ring/表格数字——要从色板定制) + - craft-floor 全条目施工时遵守(尤其:eyebrow 是 ban;嵌套卡片必错;elevation 声明一次;浏览器表面——selection/caret/scrollbar/focus ring/表格数字——从色板定制) - 交互真实可用(点击/切换/滚动行为写 JS),不是静态画片 - pro-max Pre-Delivery 逐条过:44px 触控、4.5:1 对比、focus ring、reduced-motion、375px 无横滚 -3. 截图核对(headless Chrome,找不准路径先 `ls /Applications | grep -i chrome`): - ```bash - "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \ - --headless=new --disable-gpu --screenshot=/shot-mobile.png \ - --window-size=390,844 file://<绝对路径> - ``` - 移动 390×844 + 桌面 1440×900 至少各一张;按 craft-floor「一次看一批」:Read 截图找问题 → 修完一批 → 再截。 - **显隐与布局断言用渲染事实(computed display / getBoundingClientRect),不信 hidden 属性——id/类选择器的 display 会压过 [hidden](2026-11-07 v1.1 重跑实测翻车:两页堆叠渲染而属性检查全绿)。编排器无法亲验截图图像时,把截图交 S5 Assessment A 首个看图,不得只凭 DOM 断言放行。** +2. 截图口径(统一):**390×844 主档 + 375 兼容档各至少一张**;移动 Web 任务免桌面档(body 居中列已保证桌面不破)。按 craft-floor「一次看一批」:Read 截图找问题 → 修完一批 → 再截。编排器无法亲验截图图像时,交 S5 Assessment A 首个看图。 +3. **显隐与布局断言用渲染事实(computed display / getBoundingClientRect),不信 hidden 属性**——id/类选择器的 display 会压过 [hidden](实测翻车:两页堆叠渲染而属性检查全绿)。 **验收**:原型可打开(`file://` 直开无 console error 级问题)、双档截图在 `/`、craft-floor 关键项肉眼过。 @@ -101,6 +100,9 @@ python3 /scripts/log_call.py ui-ux-pro-max --run-dir --note S3-ux-c 按 context 输出的指令行事(它可能要求 init/PRODUCT.md——轻量原型按其 SCOPED_EXISTING_ALLOWED 通道走,不阻塞)。 2. Read `/reference/critique.md` 并记账(`--load`)。**按 critique.md 原文执行**,特别注意其 Hard Invariants: - 双独立 sub-agent:Assessment A(设计评审)/ Assessment B(detect + 浏览器证据)。ZCode/Claude Code 用 Agent 工具并行派发,两者互不可见对方输出;Codex 有 spawn_agent 先问一次;都没有才单上下文顺序跑并打 `⚠️ DEGRADED` 横幅 + - **派发模板要点**(子代理看不到主上下文,prompt 必须自带全部材料): + - A 传:目标文件路径、BRIEF/design-plan 路径、全部截图路径(要求「真正看图」)、四模式与受众摘要、输出契约(specificity/十启发式表/认知负荷/情绪/P0-P3/persona) + - B 传:经 log_call 包裹的 detect 命令全文(注明 exit 0=clean / 2=findings 属成功)、截图清点、误报核对要求(对源码实算)、fallback signal 原文案 - B 的 CLI 扫描: ```bash python3 /scripts/log_call.py impeccable --run-dir --note S5-detect -- \ @@ -115,7 +117,7 @@ python3 /scripts/log_call.py ui-ux-pro-max --run-dir --note S3-ux-c ## 停点 2 -展示审查报告,给结构化选项请用户定修复范围:全部 / Top 3 / 仅 P0–P1 / 保持现状。**终止回合**;豁免规则同停点 1(豁免时默认修 P0+P1,并在审查报告末尾补字面行 `Questions skipped: 停点2经用户豁免(默认修复 P0+P1)`,满足 impeccable critique 的收尾契约)。 +展示审查报告**并附修复前后关键截图**,四选一:全部 / Top 3 / 仅 P0–P1 / 保持现状(跳过 S6 直接 S7,报告照出)。**终止回合**;豁免规则同停点 1(豁免时默认修 P0+P1,并在审查报告末尾补字面行 `Questions skipped: 停点2经用户豁免(默认修复 P0+P1)`,满足 impeccable critique 的收尾契约)。 ## S6 优化迭代 @@ -127,17 +129,22 @@ python3 /scripts/log_call.py ui-ux-pro-max --run-dir --note S3-ux-c **动作** ```bash +# 完整流程:默认三方门,pro-max 计履职前缀(S2-research 不混门) python3 /scripts/evidence_report.py --run-dir \ - --out /INTEGRATION-REPORT.md --title "<任务名> 集成证据" \ - --artifact <原型主文件> --artifact /shot-mobile.png \ - --artifact <项目根>/design-system//MASTER.md --artifact /design-plan.md + --out /INTEGRATION-REPORT.md --title "<项目代号> 集成证据" \ + --require "ui-ux-pro-max:S3-,frontend-design:S2-,impeccable" \ + --artifact <原型主文件> --artifact /shot-<主档>.png --artifact /design-plan.md +# 仅审查路由:--require "impeccable";局部修改:--require "impeccable[,frontend-design]" +# 系统路径(非降级)另加 --artifact design-system//MASTER.md; +# slug 由上游按 -p 项目代号生成(小写连字符),跑完 S3 用 ls design-system/ 确认实际目录名 ``` -向用户交付:原型入口(`file://` 路径,可交互)、INTEGRATION-REPORT 判定与三方统计、审查分数与修复摘要、运行目录索引。**FAIL 时不宣称完成**,把缺口(哪个上游 0 成功调用/哪个产物缺失)说清楚。 +向用户交付:原型入口(`file://` 路径,可交互)、关键截图、INTEGRATION-REPORT 判定与调用统计、审查分数与修复摘要、运行目录索引。**FAIL 时不宣称完成**,把缺口(哪个门没过/哪个产物缺失)说清楚。 ## 全程通用约束 -- 每次对上游的调用都过 `log_call.py`,`--note` 标阶段(S2-design-system / S5-detect…),失败调用也要留痕。 +- **note 命名规范**(验收门的履职前缀依赖它):`S2-load`(frontend-design 装载)、`S2-research`(可选调研,不计入门)、`S3-design-system` / `S3-ux-check` / `S3-typography-check`(pro-max 履职)、`S4-craft-floor`、`S5-context` / `S5-critique-playbook` / `S5-detect`、`S6-redetect`。 +- 每次对上游的调用都过 `log_call.py`,`--run-dir` 显式传(缺省会另建 `<时间戳>-run` 目录,账本裂成两份、验收门读空账本 FAIL);失败调用也要留痕。 - 不修改三个上游目录的任何文件;PYTHONDONTWRITEBYTECODE 已由脚本注入。 -- 运行目录是本次任务的唯一工作痕迹区:BRIEF / design-plan / 截图 / 报告全进 ``;MASTER.md 在项目根(上游约定位置)。 -- 用户豁免只作用于停点,不作用于铁律与验收门。 +- 运行目录是本次任务的唯一工作痕迹区:BRIEF / design-plan / 截图 / 报告全进 ``;MASTER.md 在项目根(上游约定位置,slug 跑完 S3 后 `ls design-system/` 确认实际目录名)。 +- 用户豁免只作用于停点,不作用于铁律与验收门;豁免停点 1.5 时首屏截图仍须发出。 diff --git a/skills/le-app-design/scripts/evidence_report.py b/skills/le-app-design/scripts/evidence_report.py index f69e251..f5959b7 100644 --- a/skills/le-app-design/scripts/evidence_report.py +++ b/skills/le-app-design/scripts/evidence_report.py @@ -3,15 +3,21 @@ 用法: python3 evidence_report.py --run-dir [--out /INTEGRATION-REPORT.md] \ - [--artifact <路径>]... [--title "任务名"] + [--artifact <路径>]... [--title "任务名"] \ + [--require "dep[:note前缀],..."] 验收规则(硬门): - 三个上游 ui-ux-pro-max / frontend-design / impeccable 各需 ≥1 条成功调用 + 默认要求三个上游 ui-ux-pro-max / frontend-design / impeccable 各 ≥1 条成功调用 (exec 且 exit_code==0,或 load 且 exit_code==0)。 + 轻量路由用 --require 指定参与该路由的上游子集,如仅审查任务: + --require "impeccable" + 每项可带 note 前缀限定履职阶段,防止非履职调用(如 S2-research 调研检索) + 混过门,如完整流程的严格口径: + --require "ui-ux-pro-max:S3-,frontend-design:S2-,impeccable" --artifact 指定的每个文件必须存在。 任一不满足 → 报告标 FAIL,exit 1;全满足 → PASS,exit 0。 -报告内容: 判定横幅、三方调用统计表、逐条调用清单(时间/依赖/命令/退出码)、 +报告内容: 判定横幅、调用统计表、逐条调用清单(时间/依赖/命令/退出码)、 产物核验清单、失败与缺口说明。这份报告就是「真实集成」的可检查证据。 仅 python3 标准库。 """ @@ -64,19 +70,42 @@ def main() -> int: ap.add_argument("--out", default=None, help="报告写入路径,缺省 /INTEGRATION-REPORT.md") ap.add_argument("--artifact", action="append", default=[], help="须存在的交付物路径(可多次)") ap.add_argument("--title", default="le-app-design 集成证据报告") + ap.add_argument("--require", default=None, + help='门规格 "dep[:note前缀],...";缺省=三个上游全部、不限前缀。轻量路由传子集') args = ap.parse_args() + # 解析门规格:dep[:note-prefix] + gate: dict[str, str | None] = {} + if args.require: + for item in args.require.split(","): + item = item.strip() + if not item: + continue + dep, _, prefix = item.partition(":") + gate[dep] = prefix or None + else: + gate = {dep: None for dep in GATE_DEPS} + run_dir = Path(args.run_dir).expanduser() records = load_records(run_dir / "calls.jsonl") out_path = Path(args.out).expanduser() if args.out else run_dir / "INTEGRATION-REPORT.md" - stats = {dep: {"ok": 0, "fail": 0} for dep in GATE_DEPS} + stats = {dep: {"ok": 0, "fail": 0} for dep in gate} for rec in records: dep = rec.get("dep") if dep in stats: stats[dep]["ok" if is_success(rec) else "fail"] += 1 - gate_pass = all(stats[d]["ok"] >= 1 for d in GATE_DEPS) + def gate_ok(dep: str) -> bool: + prefix = gate[dep] + if prefix is None: + return stats[dep]["ok"] >= 1 + return any( + is_success(rec) and str(rec.get("note", "")).startswith(prefix) + for rec in records if rec.get("dep") == dep + ) + + gate_pass = all(gate_ok(dep) for dep in gate) artifacts_missing = [a for a in args.artifact if not Path(a).expanduser().exists()] overall = gate_pass and not artifacts_missing @@ -91,9 +120,10 @@ def main() -> int: lines.append("") lines.append("| 上游 | 成功调用 | 失败调用 | 门(≥1 成功) |") lines.append("|---|---|---|---|") - for dep in GATE_DEPS: + for dep in gate: s = stats[dep] - lines.append(f"| {dep} | {s['ok']} | {s['fail']} | {'✅' if s['ok'] >= 1 else '❌ 未被真实调用'} |") + req = f"(限 note={gate[dep]}*)" if gate[dep] else "" + lines.append(f"| {dep}{req} | {s['ok']} | {s['fail']} | {'✅' if gate_ok(dep) else '❌ 未被真实调用'} |") lines.append("") if artifacts_missing: @@ -121,9 +151,10 @@ def main() -> int: if not overall: lines.append("## 缺口说明") lines.append("") - for dep in GATE_DEPS: - if stats[dep]["ok"] < 1: - lines.append(f"- `{dep}` 无成功调用记录——该上游未被真实使用,本次流程**不得标记为成功**。") + for dep in gate: + if not gate_ok(dep): + prefix = f"(履职阶段 note={gate[dep]}*)" if gate[dep] else "" + lines.append(f"- `{dep}` 无成功调用记录{prefix}——该上游未被真实使用,本次流程**不得标记为成功**。") for a in artifacts_missing: lines.append(f"- 产物缺失: `{a}`") lines.append("")