Ver código fonte

optimize huashu-design: round3 dim7重构——652行→500行,路由前移,App守则下沉

- App/iOS守则140行下沉到新建references/app-prototype.md,主文件留7条硬规则速查版(judge C/D共识处方)
- 「任务路由:一张表定入口」从工作流程中部前移到使用前提之后——agent开工前先见导航
- deck概览墙4处复述收敛:Phase 4长bullet和Starter表行压缩,canonical留技术红线
- 水印JSX模板下沉video-export.md末节,主文件留4行规则
- §1.a资产自检与检查点2撞车处改为指向,Pocket 4反例6行压1行
- description补SKIP边界(生产级WebApp不适用),路由表补app-prototype行
- logo子门补硬规则:单文件交付必须base64内嵌(盲测裂图实锤)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
alchain 19 horas atrás
pai
commit
2e50b73bef
3 arquivos alterados com 196 adições e 187 exclusões
  1. 35 187
      SKILL.md
  2. 146 0
      references/app-prototype.md
  3. 15 0
      references/video-export.md

+ 35 - 187
SKILL.md

@@ -1,6 +1,6 @@
 ---
 name: huashu-design
-description: 花叔Design——用HTML做高保真原型、幻灯片、动画、可视化与专家评审,需求模糊时给设计方向。触发词:做原型、PPT、幻灯片、动画、设计风格、评审、做个HTML页面、UI mockup、导出MP4/GIF、做个好看的。
+description: 花叔Design——用HTML做高保真原型、幻灯片、动画、可视化与专家评审,需求模糊时给设计方向。触发词:做原型、PPT、幻灯片、动画、设计风格、评审、做个HTML页面、UI mockup、导出MP4/GIF、做个好看的。生产级Web App/需后端的系统不适用。
 ---
 
 # 花叔Design · Huashu-Design
@@ -21,6 +21,24 @@ description: 花叔Design——用HTML做高保真原型、幻灯片、动画、
 
 不适用场景:生产级Web App、SEO网站、需要后端的动态系统——这些用frontend-design skill。
 
+## 任务路由:一张表定入口
+
+收到任务先扫一遍这张表,确定走哪条线再开工(多信号同时命中按行序叠加):
+
+| 任务信号 | 入口 |
+|---------|------|
+| 提到具体品牌/产品名 | 核心原则#0 事实验证 → §1.a 资产协议 → 标准流程 |
+| 没给风格参考(最常见) | Fallback 顾问模式 Phase 1-5 → 回标准流程 Step 2 |
+| 幻灯片/PPT | 标准流程 + Step 1 deck 交付链 + 「技术红线」架构选型 |
+| 动画/导出 MP4/GIF | 标准流程 + Step 9;动手前必读 `references/animation-pitfalls.md` |
+| 带解说长视频(≥1分钟) | Step 9.5 → `references/voiceover-pipeline.md` |
+| launch film/品牌宣传片(「Apple级」「超级碗品质」) | 先写万字 director's notes → `references/launch-film-director-notes.md` |
+| App/iOS 原型 | 「App / iOS 原型专属守则」(覆盖通用规则) |
+| 评审/打分 | Step 10 → `references/critique-guide.md` |
+| 弱 runtime(无 subagent/非 Claude) | 上述任一条 + 「弱 runtime 降级模式」 |
+
+例:「做个咖啡主题的 PPT」= 第 2 行 + 第 3 行——Fallback 出三版(咖啡是主题不是品牌,不找 logo),deck 骨架统一用概览墙模板。
+
 ## 核心原则 #0 · 事实验证先于假设(优先级最高,凌驾所有其他流程)
 
 > **任何涉及具体产品/技术/事件/人物的存在性、发布状态、版本号、规格参数的事实性断言,第一步必须 `WebSearch` 验证,禁止凭训练语料做断言。**
@@ -37,12 +55,7 @@ description: 花叔Design——用HTML做高保真原型、幻灯片、动画、
 3. 把事实写进项目的 `product-facts.md`(见工作流 Step 2),不靠记忆
 4. 搜不到或结果模糊 → 问用户,而不是自行假设
 
-**反例**(2026-04-20 真实踩过的坑):
-- 用户:"给大疆 Pocket 4 做发布动画"
-- 我:凭记忆说"Pocket 4 还没发布,我们做概念 demo"
-- 真相:Pocket 4 已在 4 天前(2026-04-16)发布,官方 Launch Film + 产品渲染图俱在
-- 后果:基于错误假设做了"概念剪影"动画,违背用户期待,返工 1-2 小时
-- **成本对比:WebSearch 10 秒 << 返工 2 小时**
+**反例**(2026-04-20 实测):用户要「大疆 Pocket 4 发布动画」,我凭记忆断言「还没发布」做了概念剪影——真相是 4 天前已发布、官方物料俱在。**成本对比:WebSearch 10 秒 << 返工 2 小时**。
 
 **这条原则优先级高于"问 clarifying questions"**——问问题的前提是你对事实已有正确理解。事实错了,问什么都是歪的。
 
@@ -81,7 +94,7 @@ description: 花叔Design——用HTML做高保真原型、幻灯片、动画、
 4. **验证 + 提取**:不只 grep 色值,要核对 logo / 产品图真实性
 5. **固化为 `brand-spec.md`**:模板覆盖所有资产路径(logo / 产品图 / UI / 色板 / 字型 / 禁区 / 气质)
 
-🛑 **检查点 · 资产自检**:实体产品要有产品图(不是 CSS 剪影)、数字产品要有 logo+UI 截图、色值从真实 HTML/SVG 抽取。缺了就停下补,不硬做
+🛑 自检门统一在工作流「检查点2·资产自检」执行,不在此重复
 
 > **完整协议**(5 步详细操作 + 下载命令 + brand-spec 模板 + 全流程失败兜底 + 反例 + 代价对比)→ `references/brand-asset-protocol.md`
 
@@ -218,7 +231,7 @@ description: 花叔Design——用HTML做高保真原型、幻灯片、动画、
 | 用户自己的产品 / 品牌 | 走 §1.a 核心资产协议取官方图 |
 | **设计中要点名 / 并列展示的具体产品·品牌(含第三方对比对象)** | **走 §1.a 取每个产品的官方 logo**(svgl API → simpleicons → Google favicon,见 `references/brand-asset-protocol.md` Step 3.1)。对比 / 榜单 / 评测 deck 必走这行 |
 
-🔴 **具名产品 logo 子门(spawn 三套逻辑前必过,硬要求)**:把设计里会出现的产品 / 品牌名**逐个列成清单**,确认每个都已取到官方 logo 并内嵌(base64 / 本地路径),再 spawn。**清单里有一个没取到 logo = 🛑 STOP 补齐**(实在取不到才退诚实 placeholder 并明说「X 的 logo 待补」)。三个 subagent 共用这批 logo。⚠️ 这是对比 / 榜单 / 评测 deck 最常见的翻车点——「只抽了品牌色就开做」就是漏了这道门(2026-06-06 五大 Coding Agent PPT 实测翻车,见 brand-asset-protocol 反例)。
+🔴 **具名产品 logo 子门(spawn 三套逻辑前必过,硬要求)**:把设计里会出现的产品 / 品牌名**逐个列成清单**,确认每个都已取到官方 logo 并内嵌,再 spawn。**交付形态是「双击就能开」的单文件 HTML 时,logo/图片必须 base64 内嵌**——相对路径的交付物挪个目录就全员裂图(盲测实锤:`../assets/google.svg` 六个按钮全裂直接输掉评审);仅多文件+启动说明的项目允许本地路径。**清单里有一个没取到 logo = 🛑 STOP 补齐**(实在取不到才退诚实 placeholder 并明说「X 的 logo 待补」)。三个 subagent 共用这批 logo。⚠️ 这是对比 / 榜单 / 评测 deck 最常见的翻车点——「只抽了品牌色就开做」就是漏了这道门(2026-06-06 五大 Coding Agent PPT 实测翻车,见 brand-asset-protocol 反例)。
 
 🛠️ **取图用现成脚本(别每次现写)**:`python3 scripts/fetch_images.py --query "英文关键词1" "英文关键词2" --out 项目/assets/img --count 2 --width 1600`——已内置清代理 + 合规 UA + 许可输出 + 失败兜底,下次只改关键词。
 
@@ -253,7 +266,7 @@ description: 花叔Design——用HTML做高保真原型、幻灯片、动画、
 - **三版的布局骨架必须互异**:导航/构图/内容区结构至少一项结构性不同,不许两版共用同一骨架只换色换字体(盲测实锤:共用骨架会被评审一眼识破「换皮」)
 - 🔴 **可读性硬底线(任何风格温度都不豁免,包括「奢侈留白」的安静派)**:正文 ≥14px、标签/注释 ≥12px、正文对比度 ≥4.5:1;留白必须是**构图**(首屏有明确视觉锚点,视线有落点),不是内容缺席。盲测实锤:安静派做过头 = 「大片死白+微缩字号,第一眼像页面渲染坏了」,直接输给普通 baseline
 - 纯 HTML/CSS 单文件;**内容必需的图用 Phase 3.5 取的真图**(三版共用),仅装饰/抽象图才用 CSS 几何/SVG/纯色块,绝不留空占位
-- 🎞️ **PPT / deck 场景必走 deck 模板(绝不写竖向平铺长页!)**:每页做成独立 `<section>`(1920×1080),套 `assets/deck_index.html` 的翻页缩放外壳——**左右键 / 点击翻页 + 自适应 `fit()` 缩放**(整页缩进浏览器窗口,绝不按真实像素放大到只看见一角)。三版只换视觉风格,deck 骨架统一用这个模板,演示体验一致。详见 `references/slide-decks.md`。截图按**单页** 1920×1080 截,不是截整条长页。**单页内容绝不自带页码 / 页数 / 进度标记**——页码由 deck 外壳(`deck_index.html` 计数器)统一承载,单页自己画会和 deck 重复打架(实测出现「02/03」和「6/16」双页码)。`deck_index.html` 现**默认进 3D 概览墙**(所有页斜铺延展悬浮,点「▶ 开始演示」或点任意卡片进全屏单页,ESC 回概览)——交付 deck 时跟用户提一句这个功能
+- 🎞️ **PPT / deck 场景必走 deck 模板(绝不写竖向平铺长页!)**:每页独立 `<section>`(1920×1080)套 `assets/deck_index.html` 外壳,三版只换视觉风格、deck 骨架统一(架构规则与概览墙细节见「技术红线」+ `references/slide-decks.md`)。截图按**单页** 1920×1080 截;**单页内容绝不自带页码/进度标记**——页码由 deck 外壳统一承载(实测出过「02/03」+「6/16」双页码打架)
 - 存当前**项目目录**(`项目名/design-demos/[逻辑名].html`)——❌ 禁 `_temp/`(花叔铁律)
 - 截图:`npx playwright screenshot file:///path.html out.png --viewport-size=1440,900`(PPT 用 1920,1080)
 - ✅ **产出自检(防偷懒,进 Phase 5 前必查)**:确认 `design-demos/` 下真有 **3 个 .html**——少于 3 个 = 没走完三套逻辑,补齐再往下,不许只做一版交差
@@ -273,170 +286,21 @@ description: 花叔Design——用HTML做高保真原型、幻灯片、动画、
 2. 首次使用:复制 `assets/personal-asset-index.example.json` 到上述私有路径,填入真实数据
 3. 找不到就直接问用户要,不要编造——真实数据文件不要放在 skill 目录内避免随分发泄露隐私
 
-## App / iOS 原型专属守则
-
-做 iOS/Android/移动 app 原型时(触发:「app 原型」「iOS mockup」「移动应用」「做个 app」),下面四条**覆盖**通用 placeholder 原则——app 原型是 demo 现场,静态摆拍和米白占位卡没有说服力。
-
-### 0. 架构选型(必先决定)
-
-**默认单文件 inline React**——所有 JSX/data/styles 直接写进主 HTML 的 `<script type="text/babel">...</script>` 标签,**不要**用 `<script src="components.jsx">` 外部加载。原因:`file://` 协议下浏览器把外部 JS 当跨 origin 拦截,强制用户起 HTTP server 违反「双击就能开」的原型直觉。引用本地图片必须 base64 内嵌 data URL,别假设有 server。
-
-**拆外部文件只在两种情况**:
-- (a) 单文件 >1000 行难维护 → 拆成 `components.jsx` + `data.js`,同时明确交付说明(`python3 -m http.server` 命令 + 访问 URL)
-- (b) 需要多 subagent 并行写不同屏 → `index.html` + 每屏独立 HTML(`today.html`/`graph.html`...),iframe 聚合,每屏也都是自包含单文件
+## App / iOS 原型专属守则(速查版)
 
-**选型速查**
+做移动 app 原型时(触发:「app 原型」「iOS mockup」「移动应用」「做个 app」),以下硬规则**覆盖**通用 placeholder 原则——app 原型是 demo 现场,静态摆拍没有说服力。完整操作细节(架构选型表 / 取图渠道与代码 / AppPhone JSX 骨架 / ios_frame 三步用法 / 品位锚点全表)见 `references/app-prototype.md`:
 
-| 场景 | 架构 | 交付方式 |
-|------|------|----------|
-| 单人做 4-6 屏原型(主流) | 单文件 inline | 一个 `.html` 双击开 |
-| 单人做大型 App(>10 屏) | 多 jsx + server | 附启动命令 |
-| 多 agent 并行 | 多 HTML + iframe | `index.html` 聚合,每屏独立可开 |
+1. **架构默认单文件 inline React**:`file://` 双击就能开,本地图片 base64 内嵌;仅 >1000 行难维护或多 agent 并行写不同屏才拆多文件(拆了必须附 `python3 -m http.server` 启动说明)
+2. **先找真图再设计**:渠道同 Phase 3.5 取图表;取图前过**真图诚实性测试**——「去掉这张图信息是否有损?」无损 = 装饰 = slop,不加
+3. **交付形态默认「平铺 4-6 主屏 + 每台可交互」**,不要问用户二选一;每台是独立迷你状态机(tab 可切 / 按钮可点 / 能弹 modal),仅用户明确说「只要静态」或「单流程 demo」才偏离
+4. 🔴 **iOS 设备框必须用 `assets/ios_frame.jsx`**:禁止手写 Dynamic Island / status bar / home indicator / bezel——自己写 99% 撞位置 bug(岛是固定 124×36,两侧 status bar 空间极窄)
+5. **信息密度分型**:默认克制型(少一层容器 / 少一个 border / 少一个装饰 icon);产品卖点是 AI / 数据 / 上下文感知时走**高密度型**——每屏 ≥3 处**有内容的**差异化信息,装饰 icon 照样忌讳
+6. **交付前 Playwright 跑 3 项点击测试**(进详情 / 关键标注点 / tab 切换),`pageerror` 为 0 再交付
+7. **品位锚点**:衬线 display(Newsreader/Source Serif/EB Garamond)+ `-apple-system` body;一个有温度的底色 + 单 accent 贯穿;留一处「值得截图」的 120% 细节签名
 
-### 1. 先找真图,不是 placeholder 摆着
-
-默认主动去取真实图片填充,不要画 SVG、不要拿米白卡摆着、不要等用户要求。常用渠道:
-
-| 场景 | 首选渠道 |
-|------|---------|
-| 美术/博物馆/历史内容 | Wikimedia Commons(公共领域)、Met Museum Open Access、Art Institute of Chicago API |
-| 通用生活/摄影 | Unsplash、Pexels(免版权) |
-| 用户本地已有素材 | `~/Downloads`、项目 `_archive/` 或用户配置的素材库 |
-
-Wikimedia 下载避坑(本机 curl 走代理 TLS 会炸,Python urllib 直接走得通):
-
-```python
-# 合规 User-Agent 是硬性要求,否则 429
-UA = 'ProjectName/0.1 (https://github.com/you; you@example.com)'
-# 用 MediaWiki API 查真实 URL
-api = 'https://commons.wikimedia.org/w/api.php'
-# action=query&list=categorymembers 批量拿系列 / prop=imageinfo+iiurlwidth 取指定宽度 thumburl
-```
-
-**只有**当所有渠道都失败 / 版权不清 / 用户明确要求时,才退回诚实 placeholder(仍然不画烂 SVG)。
-
-**真图诚实性测试**(关键):取图之前先问自己——「如果去掉这张图,信息是否有损?」
-
-| 场景 | 判断 | 动作 |
-|------|------|------|
-| 文章/Essay 列表的封面、Profile 页的风景头图、设置页的装饰 banner | 装饰,与内容无内在关联 | **不要加**。加了就是 AI slop,等同紫色渐变 |
-| 博物馆/人物内容的肖像、产品详情的实物、地图卡片的地点 | 内容本身,有内在关联 | **必须加** |
-| 图谱/可视化背景的极淡纹理 | 氛围,服从内容不抢戏 | 加,但 opacity ≤ 0.08 |
-
-**反例**:给文字 Essay 配 Unsplash「灵感图」、给笔记 App 配 stock photo 模特——都是 AI slop。取真图的许可不等于滥用真图的通行证。
-
-### 2. 交付形态:默认「平铺 + 可操作」,不要问用户
-
-iOS App 原型的**默认交付形态就一种,不要再问用户「要平铺还是可操作」**:**平铺 4-6 个主界面,且每一台都能交互**。一眼看全貌(多台 iPhone 并排),又每台都能点 tab 切换、在界面上做基本操作(展开、切换、选中、打开弹层)。两个好处一次给齐,别让用户二选一。
-
-| 维度 | 默认做法 |
-|------|---------|
-| **屏数** | 平铺 **4-6 个主界面**(覆盖 app 的核心功能面,不是随便摆几个)。多于 6 个抓最主要的 4-6 个,其余可在单台内通过 tab/导航到达 |
-| **布局** | 多台独立 iPhone 横向 `flexWrap` 并排,每台上方一行 italic 小字标签说明这是哪个界面 |
-| **每台交互** | 每台都是独立的迷你状态机:tab bar 可切、界面内按钮/卡片/开关可点、能弹 modal——不是静态摆拍 |
-
-**只有两种特例才偏离默认**(用户明确说了才走,否则一律默认):
-- 用户明确「只要静态截图 / 不用能点 / 就看 layout」→ 退回纯静态 overview(每台只渲染 `ScreenComponent`,不挂状态机)
-- 用户明确「只演示一条流程 / 走一遍 onboarding / 单机 demo」→ 单台 `AppPhone` 走完整 flow
-
-**默认骨架**(平铺多台,每台各自一个带 state 的 AppPhone):
-
-```jsx
-// 每台 = 一个独立状态机,初始落在自己负责的主界面
-function AppPhone({ initial }) {
-  const [screen, setScreen] = React.useState(initial);
-  const [modal, setModal] = React.useState(null);
-  // 按 screen 渲染对应 ScreenComponent,传入 onTabChange/onOpen/onClose/onToggle 等 callback
-  return (
-    <IosFrame>
-      <ScreenComponent
-        screen={screen}
-        onTabChange={setScreen}
-        onOpen={setModal}
-        onClose={() => setModal(null)}
-      />
-    </IosFrame>
-  );
-}
-
-// 平铺:4-6 台并排,每台 initial 落在不同主界面
-<div style={{display: 'flex', gap: 32, flexWrap: 'wrap', padding: 48, alignItems: 'flex-start'}}>
-  {mainScreens.map(s => (
-    <div key={s.id}>
-      <div style={{fontSize: 13, color: '#666', marginBottom: 8, fontStyle: 'italic'}}>{s.label}</div>
-      <AppPhone initial={s.id} />
-    </div>
-  ))}
-</div>
-```
-
-Screen 组件接 callback props(`onTabChange`、`onOpen`、`onClose`、`onToggle`、`onAnnotation`),不硬编码状态。TabBar、按钮、作品卡、开关加 `cursor: pointer` + hover 反馈。每台落在不同主界面,但 tab 切换后能到达彼此——平铺给全貌,点击给纵深。
-
-### 3. 交付前跑真实点击测试
-
-静态截图只能看 layout,交互 bug 要点过才发现。用 Playwright 跑 3 项最小点击测试:进入详情 / 关键标注点 / tab 切换。检查 `pageerror` 为 0 再交付。Playwright 可用 `npx playwright` 调用,或按本机全局安装路径(`npm root -g` + `/playwright`)。
-
-### 4. 品位锚点(pursue list,fallback 首选)
-
-没有 design system 时默认往这些方向走,避免撞 AI slop:
-
-| 维度 | 首选 | 避免 |
-|------|------|------|
-| **字体** | 衬线 display(Newsreader/Source Serif/EB Garamond)+ `-apple-system` body | 全场 SF Pro 或 Inter——太像系统默认,没风格 |
-| **色彩** | 一个有温度的底色 + **单个** accent 贯穿全场(rust 橙/墨绿/深红)| 多色聚类(除非数据真的有 ≥3 个分类维度) |
-| **信息密度·克制型**(默认)| 少一层容器、少一个 border、少一个**装饰性** icon——给内容留气口 | 每条卡片都配无意义的 icon + tag + status dot |
-| **信息密度·高密度型**(例外)| 当产品核心卖点是「智能 / 数据 / 上下文感知」时(AI 工具、Dashboard、Tracker、Copilot、番茄钟、健康监测、记账类),每屏需**至少 3 处可见的产品差异化信息**:非装饰性数据、对话/推理片段、状态推断、上下文关联 | 只放一个按钮一个时钟——AI 的智能感没表达出来,跟普通 App 没区别 |
-| **细节签名** | 留一处「值得截图」的质感:极淡油画底纹 / serif 斜体引语 / 全屏黑底录音波形 | 到处平均用力,结果处处平淡 |
-
-**两条原则同时生效**:
-1. 品位 = 一个细节做到 120%,其它做到 80%——不是所有地方都精致,而是在合适的地方足够精致
-2. 减法是 fallback,不是普适律——产品核心卖点需要信息密度支撑时(AI / 数据 / 上下文感知类),加法优先于克制。详见下文「信息密度分型」
-
-### 5. iOS 设备框必须用 `assets/ios_frame.jsx`——禁止手写 Dynamic Island / status bar
-
-做 iPhone mockup 时**硬性绑定** `assets/ios_frame.jsx`。这是已经对齐过 iPhone 15 Pro 精确规格的标准外壳:bezel、Dynamic Island(124×36、top:12、居中)、status bar(时间/信号/电池、两侧避让岛、vertical center 对齐岛中线)、Home Indicator、content 区 top padding 都处理好了。
-
-**禁止在你的 HTML 里自己写**以下任何一项:
-- `.dynamic-island` / `.island` / `position: absolute; top: 11/12px; width: ~120; 居中的黑圆角矩形`
-- `.status-bar` with 手写的时间/信号/电池图标
-- `.home-indicator` / 底部 home bar
-- iPhone bezel 的圆角外框 + 黑描边 + shadow
-
-自己写 99% 会撞位置 bug——status bar 的时间/电池被岛挤压、或 content top padding 算错导致第一行内容盖在岛下。iPhone 15 Pro 的刘海是**固定 124×36 像素**,留给 status bar 两侧的可用宽度很窄,不是你凭空估的。
-
-**用法(严格三步)**:
-
-```jsx
-// 步骤 1: Read 本 skill 的 assets/ios_frame.jsx(相对本 SKILL.md 的路径)
-// 步骤 2: 把整个 iosFrameStyles 常量 + IosFrame 组件贴进你的 <script type="text/babel">
-// 步骤 3: 你自己的屏组件包在 <IosFrame>...</IosFrame> 里,不碰 island/status bar/home indicator
-<IosFrame time="9:41" battery={85}>
-  <YourScreen />  {/* 内容从 top 54 开始渲染,下边留给 home indicator,你不用管 */}
-</IosFrame>
-```
-
-**例外**:只有用户明确要求「假装是 iPhone 14 非 Pro 的刘海」「做 Android 不是 iOS」「自定义设备形态」时才绕过——此时读对应 `android_frame.jsx` 或修改 `ios_frame.jsx` 的常量,**不要**在项目 HTML 里另起一套 island/status bar。
 
 ## 工作流程
 
-### 先路由:一张表定入口
-
-收到任务先扫一遍这张表,确定走哪条线再开工(多信号同时命中按行序叠加):
-
-| 任务信号 | 入口 |
-|---------|------|
-| 提到具体品牌/产品名 | 核心原则#0 事实验证 → §1.a 资产协议 → 标准流程 |
-| 没给风格参考(最常见) | Fallback 顾问模式 Phase 1-5 → 回标准流程 Step 2 |
-| 幻灯片/PPT | 标准流程 + Step 1 deck 交付链 + 「技术红线」架构选型 |
-| 动画/导出 MP4/GIF | 标准流程 + Step 9;动手前必读 `references/animation-pitfalls.md` |
-| 带解说长视频(≥1分钟) | Step 9.5 → `references/voiceover-pipeline.md` |
-| launch film/品牌宣传片(「Apple级」「超级碗品质」) | 先写万字 director's notes → `references/launch-film-director-notes.md` |
-| App/iOS 原型 | 「App / iOS 原型专属守则」(覆盖通用规则) |
-| 评审/打分 | Step 10 → `references/critique-guide.md` |
-| 弱 runtime(无 subagent/非 Claude) | 上述任一条 + 「弱 runtime 降级模式」 |
-
-例:「做个咖啡主题的 PPT」= 第 2 行 + 第 3 行——Fallback 出三版(咖啡是主题不是品牌,不找 logo),deck 骨架统一用概览墙模板。
-
 ### 标准流程(用TaskCreate追踪)
 
 1. **理解需求**:
@@ -550,7 +414,7 @@ Screen 组件接 callback props(`onTabChange`、`onOpen`、`onClose`、`onTogg
 
 | 文件 | 何时用 | 提供 |
 |------|--------|------|
-| `deck_index.html` | **幻灯片的默认基础产物**(不管最终出 PDF 还是 PPTX,HTML 聚合版永远先做) | **直接复制、不要重写其概览逻辑**。自带**两种自适应概览**(打开按秒数随机:网格 iframe 60% / 无限画廊图片 40%)+ 键盘翻页 + scale + 计数器 + 打印合并,每页独立 HTML 免 CSS 串扰,点任意卡片进演示。用法:复制为 `index.html`、编辑 MANIFEST(每项 `{file,label}`;**要用画廊模式则加 `thumb` 字段并先跑 `scripts/gen_deck_thumbs.mjs` 生成缩略图**,否则画廊回退 iframe 会卡)。⚠️ 概览墙已内建解决「任意页数自适应 / 卡片点击命中 / 倾斜不裁切」三个坑——**别自己重写倾斜或网格逻辑**,要改先读 `references/slide-decks.md` 的三条硬约束 |
+| `deck_index.html` | **幻灯片的默认基础产物** | **直接复制为 `index.html`、编辑 MANIFEST 即用,不要重写概览逻辑**(三个坑已内建解决)。自带两种自适应概览(网格 iframe 60% / 画廊 40%,画廊需 `thumb` 字段 + 先跑 `scripts/gen_deck_thumbs.mjs`)+ 键盘翻页 + scale + 计数器 + 打印合并。要改先读 `references/slide-decks.md` 三条硬约束 |
 | `scripts/gen_deck_thumbs.mjs` | **给无限画廊概览生成缩略图**(网格 iframe 模式不需要)| playwright 截每页 + sharp 降采样 1600px JPEG:`npm i playwright sharp && node gen_deck_thumbs.mjs --slides slides --out thumbs`,再给 MANIFEST 每项加 `thumb`。分辨率别 <1000px 否则 hover 发虚 |
 | `deck_stage.js` | 做幻灯片(单文件架构,≤10页) | web component:auto-scale + 键盘导航 + slide counter + localStorage + speaker notes ⚠️ **script 必须放在 `</deck-stage>` 之后,section 的 `display: flex` 必须写到 `.active` 上**,详见 `references/slide-decks.md` 的两个硬约束 |
 | `scripts/export_deck_pdf.mjs` | **HTML→PDF 导出(多文件架构)** · 每页独立 HTML 文件,playwright 逐个 `page.pdf()` → pdf-lib 合并。文字保留矢量可搜。依赖 `playwright pdf-lib` |
@@ -573,6 +437,7 @@ Screen 组件接 callback props(`onTabChange`、`onOpen`、`onClose`、`onTogg
 | 任务 | 读 |
 |------|-----|
 | 开工前问问题、定方向 | `references/workflow.md` |
+| **App/iOS 原型完整守则**(架构表/取图代码/AppPhone骨架/ios_frame用法) | `references/app-prototype.md` |
 | 反AI slop、内容规范、scale | `references/content-guidelines.md` |
 | 字体排印/字体配对/中文排印 | `references/typography.md` |
 | React+Babel项目setup | `references/react-setup.md` |
@@ -631,22 +496,5 @@ Skill 路径引用均采用**相对本 skill 根目录**的形式(`references/
 
 ## Skill 推广水印(仅动画产出)
 
-**只在动画产出**(HTML 动画 → MP4 / GIF)默认带「**Created by Huashu-Design**」水印,辅助 skill 传播。**幻灯片 / 信息图 / 原型 / 网页等其他场景不加**——加了反而干扰用户实际使用。
-
-- **必带场景**:HTML 动画 → 导出 MP4 / GIF(用户会拿去公众号、X、B站传播,水印能跟着流通)
-- **不带场景**:幻灯片(用户自己讲)、信息图(嵌文章)、App / 网页原型(设计 review)、配图
-- **第三方品牌的非官方致敬动画**:水印前加「非官方出品 · 」前缀,避免被误认为官方物料引发 IP 争议
-- **用户明确说"不要水印"**:尊重,移除
-- **水印模板**:
-  ```jsx
-  <div style={{
-    position: 'absolute', bottom: 24, right: 32,
-    fontSize: 11, color: 'rgba(0,0,0,0.4)' /* 深底用 rgba(255,255,255,0.35) */,
-    letterSpacing: '0.15em', fontFamily: 'monospace',
-    pointerEvents: 'none', zIndex: 100,
-  }}>
-    Created by Huashu-Design
-    {/* 第三方品牌动画前缀「非官方出品 · 」*/}
-  </div>
-  ```
+**只在动画产出**(HTML 动画 → MP4 / GIF)默认带「**Created by Huashu-Design**」水印;**幻灯片 / 信息图 / 原型 / 网页一律不加**——加了干扰使用。第三方品牌的非官方致敬动画前缀「非官方出品 · 」防 IP 争议;用户说不要就移除。JSX 水印模板见 `references/video-export.md` 末节。
 

+ 146 - 0
references/app-prototype.md

@@ -0,0 +1,146 @@
+# App / iOS 原型专属守则 · 完整操作手册
+
+> 从 SKILL.md 下沉的完整版。SKILL.md 保留 7 条硬规则速查,本文件是每条规则的展开:架构选型、取图渠道与代码、AppPhone JSX 骨架、ios_frame 三步用法、品位锚点全表。
+
+
+做 iOS/Android/移动 app 原型时(触发:「app 原型」「iOS mockup」「移动应用」「做个 app」),下面四条**覆盖**通用 placeholder 原则——app 原型是 demo 现场,静态摆拍和米白占位卡没有说服力。
+
+### 0. 架构选型(必先决定)
+
+**默认单文件 inline React**——所有 JSX/data/styles 直接写进主 HTML 的 `<script type="text/babel">...</script>` 标签,**不要**用 `<script src="components.jsx">` 外部加载。原因:`file://` 协议下浏览器把外部 JS 当跨 origin 拦截,强制用户起 HTTP server 违反「双击就能开」的原型直觉。引用本地图片必须 base64 内嵌 data URL,别假设有 server。
+
+**拆外部文件只在两种情况**:
+- (a) 单文件 >1000 行难维护 → 拆成 `components.jsx` + `data.js`,同时明确交付说明(`python3 -m http.server` 命令 + 访问 URL)
+- (b) 需要多 subagent 并行写不同屏 → `index.html` + 每屏独立 HTML(`today.html`/`graph.html`...),iframe 聚合,每屏也都是自包含单文件
+
+**选型速查**:
+
+| 场景 | 架构 | 交付方式 |
+|------|------|----------|
+| 单人做 4-6 屏原型(主流) | 单文件 inline | 一个 `.html` 双击开 |
+| 单人做大型 App(>10 屏) | 多 jsx + server | 附启动命令 |
+| 多 agent 并行 | 多 HTML + iframe | `index.html` 聚合,每屏独立可开 |
+
+### 1. 先找真图,不是 placeholder 摆着
+
+默认主动去取真实图片填充,不要画 SVG、不要拿米白卡摆着、不要等用户要求。常用渠道:
+
+| 场景 | 首选渠道 |
+|------|---------|
+| 美术/博物馆/历史内容 | Wikimedia Commons(公共领域)、Met Museum Open Access、Art Institute of Chicago API |
+| 通用生活/摄影 | Unsplash、Pexels(免版权) |
+| 用户本地已有素材 | `~/Downloads`、项目 `_archive/` 或用户配置的素材库 |
+
+Wikimedia 下载避坑(本机 curl 走代理 TLS 会炸,Python urllib 直接走得通):
+
+```python
+# 合规 User-Agent 是硬性要求,否则 429
+UA = 'ProjectName/0.1 (https://github.com/you; you@example.com)'
+# 用 MediaWiki API 查真实 URL
+api = 'https://commons.wikimedia.org/w/api.php'
+# action=query&list=categorymembers 批量拿系列 / prop=imageinfo+iiurlwidth 取指定宽度 thumburl
+```
+
+**只有**当所有渠道都失败 / 版权不清 / 用户明确要求时,才退回诚实 placeholder(仍然不画烂 SVG)。
+
+**真图诚实性测试**(关键):取图之前先问自己——「如果去掉这张图,信息是否有损?」
+
+| 场景 | 判断 | 动作 |
+|------|------|------|
+| 文章/Essay 列表的封面、Profile 页的风景头图、设置页的装饰 banner | 装饰,与内容无内在关联 | **不要加**。加了就是 AI slop,等同紫色渐变 |
+| 博物馆/人物内容的肖像、产品详情的实物、地图卡片的地点 | 内容本身,有内在关联 | **必须加** |
+| 图谱/可视化背景的极淡纹理 | 氛围,服从内容不抢戏 | 加,但 opacity ≤ 0.08 |
+
+**反例**:给文字 Essay 配 Unsplash「灵感图」、给笔记 App 配 stock photo 模特——都是 AI slop。取真图的许可不等于滥用真图的通行证。
+
+### 2. 交付形态:默认「平铺 + 可操作」,不要问用户
+
+iOS App 原型的**默认交付形态就一种,不要再问用户「要平铺还是可操作」**:**平铺 4-6 个主界面,且每一台都能交互**。一眼看全貌(多台 iPhone 并排),又每台都能点 tab 切换、在界面上做基本操作(展开、切换、选中、打开弹层)。两个好处一次给齐,别让用户二选一。
+
+| 维度 | 默认做法 |
+|------|---------|
+| **屏数** | 平铺 **4-6 个主界面**(覆盖 app 的核心功能面,不是随便摆几个)。多于 6 个抓最主要的 4-6 个,其余可在单台内通过 tab/导航到达 |
+| **布局** | 多台独立 iPhone 横向 `flexWrap` 并排,每台上方一行 italic 小字标签说明这是哪个界面 |
+| **每台交互** | 每台都是独立的迷你状态机:tab bar 可切、界面内按钮/卡片/开关可点、能弹 modal——不是静态摆拍 |
+
+**只有两种特例才偏离默认**(用户明确说了才走,否则一律默认):
+- 用户明确「只要静态截图 / 不用能点 / 就看 layout」→ 退回纯静态 overview(每台只渲染 `ScreenComponent`,不挂状态机)
+- 用户明确「只演示一条流程 / 走一遍 onboarding / 单机 demo」→ 单台 `AppPhone` 走完整 flow
+
+**默认骨架**(平铺多台,每台各自一个带 state 的 AppPhone):
+
+```jsx
+// 每台 = 一个独立状态机,初始落在自己负责的主界面
+function AppPhone({ initial }) {
+  const [screen, setScreen] = React.useState(initial);
+  const [modal, setModal] = React.useState(null);
+  // 按 screen 渲染对应 ScreenComponent,传入 onTabChange/onOpen/onClose/onToggle 等 callback
+  return (
+    <IosFrame>
+      <ScreenComponent
+        screen={screen}
+        onTabChange={setScreen}
+        onOpen={setModal}
+        onClose={() => setModal(null)}
+      />
+    </IosFrame>
+  );
+}
+
+// 平铺:4-6 台并排,每台 initial 落在不同主界面
+<div style={{display: 'flex', gap: 32, flexWrap: 'wrap', padding: 48, alignItems: 'flex-start'}}>
+  {mainScreens.map(s => (
+    <div key={s.id}>
+      <div style={{fontSize: 13, color: '#666', marginBottom: 8, fontStyle: 'italic'}}>{s.label}</div>
+      <AppPhone initial={s.id} />
+    </div>
+  ))}
+</div>
+```
+
+Screen 组件接 callback props(`onTabChange`、`onOpen`、`onClose`、`onToggle`、`onAnnotation`),不硬编码状态。TabBar、按钮、作品卡、开关加 `cursor: pointer` + hover 反馈。每台落在不同主界面,但 tab 切换后能到达彼此——平铺给全貌,点击给纵深。
+
+### 3. 交付前跑真实点击测试
+
+静态截图只能看 layout,交互 bug 要点过才发现。用 Playwright 跑 3 项最小点击测试:进入详情 / 关键标注点 / tab 切换。检查 `pageerror` 为 0 再交付。Playwright 可用 `npx playwright` 调用,或按本机全局安装路径(`npm root -g` + `/playwright`)。
+
+### 4. 品位锚点(pursue list,fallback 首选)
+
+没有 design system 时默认往这些方向走,避免撞 AI slop:
+
+| 维度 | 首选 | 避免 |
+|------|------|------|
+| **字体** | 衬线 display(Newsreader/Source Serif/EB Garamond)+ `-apple-system` body | 全场 SF Pro 或 Inter——太像系统默认,没风格 |
+| **色彩** | 一个有温度的底色 + **单个** accent 贯穿全场(rust 橙/墨绿/深红)| 多色聚类(除非数据真的有 ≥3 个分类维度) |
+| **信息密度·克制型**(默认)| 少一层容器、少一个 border、少一个**装饰性** icon——给内容留气口 | 每条卡片都配无意义的 icon + tag + status dot |
+| **信息密度·高密度型**(例外)| 当产品核心卖点是「智能 / 数据 / 上下文感知」时(AI 工具、Dashboard、Tracker、Copilot、番茄钟、健康监测、记账类),每屏需**至少 3 处可见的产品差异化信息**:非装饰性数据、对话/推理片段、状态推断、上下文关联 | 只放一个按钮一个时钟——AI 的智能感没表达出来,跟普通 App 没区别 |
+| **细节签名** | 留一处「值得截图」的质感:极淡油画底纹 / serif 斜体引语 / 全屏黑底录音波形 | 到处平均用力,结果处处平淡 |
+
+**两条原则同时生效**:
+1. 品位 = 一个细节做到 120%,其它做到 80%——不是所有地方都精致,而是在合适的地方足够精致
+2. 减法是 fallback,不是普适律——产品核心卖点需要信息密度支撑时(AI / 数据 / 上下文感知类),加法优先于克制。详见下文「信息密度分型」
+
+### 5. iOS 设备框必须用 `assets/ios_frame.jsx`——禁止手写 Dynamic Island / status bar
+
+做 iPhone mockup 时**硬性绑定** `assets/ios_frame.jsx`。这是已经对齐过 iPhone 15 Pro 精确规格的标准外壳:bezel、Dynamic Island(124×36、top:12、居中)、status bar(时间/信号/电池、两侧避让岛、vertical center 对齐岛中线)、Home Indicator、content 区 top padding 都处理好了。
+
+**禁止在你的 HTML 里自己写**以下任何一项:
+- `.dynamic-island` / `.island` / `position: absolute; top: 11/12px; width: ~120; 居中的黑圆角矩形`
+- `.status-bar` with 手写的时间/信号/电池图标
+- `.home-indicator` / 底部 home bar
+- iPhone bezel 的圆角外框 + 黑描边 + shadow
+
+自己写 99% 会撞位置 bug——status bar 的时间/电池被岛挤压、或 content top padding 算错导致第一行内容盖在岛下。iPhone 15 Pro 的刘海是**固定 124×36 像素**,留给 status bar 两侧的可用宽度很窄,不是你凭空估的。
+
+**用法(严格三步)**:
+
+```jsx
+// 步骤 1: Read 本 skill 的 assets/ios_frame.jsx(相对本 SKILL.md 的路径)
+// 步骤 2: 把整个 iosFrameStyles 常量 + IosFrame 组件贴进你的 <script type="text/babel">
+// 步骤 3: 你自己的屏组件包在 <IosFrame>...</IosFrame> 里,不碰 island/status bar/home indicator
+<IosFrame time="9:41" battery={85}>
+  <YourScreen />  {/* 内容从 top 54 开始渲染,下边留给 home indicator,你不用管 */}
+</IosFrame>
+```
+
+**例外**:只有用户明确要求「假装是 iPhone 14 非 Pro 的刘海」「做 Android 不是 iOS」「自定义设备形态」时才绕过——此时读对应 `android_frame.jsx` 或修改 `ios_frame.jsx` 的常量,**不要**在项目 HTML 里另起一套 island/status bar。

+ 15 - 0
references/video-export.md

@@ -230,3 +230,18 @@ GIF 只能 256 色。一次 pass 的 GIF 会把全动画色彩压到 256 色通
 | 「加水印」 | ffmpeg 加 `-vf "drawtext=..."` 或 `overlay=` 一个 PNG |
 | 「要透明背景」 | MP4 不支持 alpha;用 WebM VP9 + alpha 或 APNG |
 | 「要无损」 | CRF 改 0 + preset veryslow(文件会大 10 倍) |
+
+## Skill 推广水印模板(仅动画导出用)
+
+SKILL.md 规定动画 MP4/GIF 默认带水印,模板如下(深底改用 `rgba(255,255,255,0.35)`;第三方品牌动画前缀「非官方出品 · 」):
+
+```jsx
+<div style={{
+  position: 'absolute', bottom: 24, right: 32,
+  fontSize: 11, color: 'rgba(0,0,0,0.4)',
+  letterSpacing: '0.15em', fontFamily: 'monospace',
+  pointerEvents: 'none', zIndex: 100,
+}}>
+  Created by Huashu-Design
+</div>
+```