图像与设计
给 Web / Android Compose /…
当需要为已有界面添加动效 / 微交互 / 视觉升级(hover、滚动视差、页面转场、视觉识别)时,用「扫栈 → 发现意图 → 定范围 → 立交互论点并可视化验证 → 加载对应子技能 → 实现(中/大范围先出变体)→ 审计」这套流程来做。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
给 Web / Android Comp特定
解决思路
- 先定说话口吻:执行过程中用简短、沉浸式的旁白(如 "Scanning stack..."、"Casting parallax on hero scroll.");但报告、最终总结、审计结果里完全去掉修辞,只讲改了什么、动了哪些文件、下一步(如 "Done. Hero uses GSAP scroll-triggered parallax. Files: Hero.tsx, hero.module.css. LCP: -8%.")。
- SCAN:跑探测脚本确定技术栈——`cat package.json | grep` 查动画库(gsap|motion|framer-motion|three|@react-three/fiber|@react-three/drei|animejs|popmotion|lenis|locomotive-scroll)、框架(react|vue|svelte|next|nuxt|astro|solid-js|qwik)、CSS 方案(tailwindcss|styled-components|@emotion|sass|less|vanilla-extract|panda);`ls build.gradle.kts build.gradle settings.gradle.kts settings.gradle` 并 grep `androidx.compose` 判 Android Compose;grep `org.jetbrains.compose` / `kotlin("multiplatform")` 判 Compose Multiplatform;`ls *.xcodeproj *.xcworkspace Package.swift` 加 grep `import SwiftUI|@main.*App` 判 SwiftUI,再用 `.iOS(`/`.macOS(` 或 pbxproj 的 `SDKROOT` 区分 iOS 与 macOS。
- SCAN 续:再 grep viewport / `@media pointer: coarse` / max-width 与 `public/manifest.json`、`public/sw.js` 判移动 web 上下文;grep `.xib`、`.storyboard`、`res/layout/*.xml`、`setContentView(R.layout.*)` 记录 legacy 混用情况(只提及、不自动加载)。
- 映射扫描结果:动画库、框架、CSS、原生 Android(Compose)、原生 Apple(SwiftUI,再分 iOS/macOS)、Compose Multiplatform、移动/桌面上下文、legacy 混用;注意 `motion` 与 `framer-motion` 是同一库的两个包名(Framer Motion 已改名 Motion),记录项目里装的是哪一个,两者都在说明项目正在迁移,要跟随你正在编辑的文件已导入的那个。
- DISCOVER 只在请求模糊、开放、可能多方向时做("让这个页面更有生命力"、"给 hero 做点酷的");请求具体且自包含("给这个按钮加 hover scale")时跳过,直接进 SCOPE。
- 发现阶段一次只问一个问题,绝不打包,连"就两个小问题"也不行;先问最没搞清的那一面:情绪/感觉、参考站点、约束(性能预算、无障碍、浏览器支持)、范围边界(做什么、明确不做什么)。
- 处理模糊回答的三种做法:给具体选项("Modern 可以指 Linear 那种干净过渡、Vercel 的戏剧化揭示,还是 Stripe 的流动渐变?")、换个角度问("什么会让你觉得*不对*?")、说明后果("这个选择决定我是纯 CSS 还是引入 GSAP,值得先定下来");绝不把模糊回答静默当作确认,不确定就直说不确定。
- 停止提问的判据:当你能写出一句用户会点头的交互论点时就停;如果还得靠猜,就继续问。
- 若检测到 legacy 混用(XIB / storyboard / layout XML / setContentView(R.layout.*)),只问一个问题:"本次任务是留在纯 Compose/SwiftUI,还是集成进 legacy 界面?";若选 legacy,就写桥接(Compose 用 `AndroidView`,SwiftUI 用 `UIViewControllerRepresentable`)把现代代码暴露进旧界面,绝不生成新的 legacy 代码(不写 XML、不写 XIB、不用 setContentView)。
- SCOPE 分档控制投入:Light(孤立组件,如 hover/toggle/dropdown)最多 1-2 个子技能、不出变体;Medium(页面或区块,如 hero/画廊/导航)2-3 个子技能、2-3 个变体;Full(整个应用或视觉重塑)走完整流水线、2-3 个变体;绝不为一个 hover 效果搬出重炮(GSAP + ScrollTrigger + Lenis)。
- 在第一个视觉关卡前只问一次用户想怎么看,并标注推荐默认:A. Artifact(活页面:真实 easing 曲线、真实时长、元素真的在动);B. Live preview(项目里的一次性路由,真实栈真实 token,原生用 `@Preview`/`#Preview` 草稿文件);C. Inline(直接写在对话里)。默认建议:轻量范围选 C;中/全范围 web 选 A;中/全范围 Compose/SwiftUI 选 B、A 为次选;涉及完整视觉识别或设计系统选 A;没有 dev server 或仓库不能写入选 A;宿主是 Cowork 且没有可写的项目 checkout 选 A(并说明 B 为何不可用)。
- 这个查看模式整个会话固定:之后每个关卡只用一句话声明模式("Variants in artifact.")就继续,不重开菜单;用户随时可以改("用文字给我看"、"放进 artifact"、"直接说"),立即照做,改后成为新的会话默认。
- 产出预览前先廉价地检测一次宿主:`if [ -d /mnt/skills/user ]; then GENJUTSU_HOST=claude-ai; elif [ -d /mnt/.claude/skills ] || [ -n "$(find /sessions -maxdepth 6 -type d -path '*/.claude/skills' 2>/dev/null | head -1)" ]; then GENJUTSU_HOST=cowork; elif [ -n "${CLAUDE_PLUGIN_ROOT:-}" ] || [ -d "$HOME/.claude/plugins" ]; then GENJUTSU_HOST=claude-code; else GENJUTSU_HOST=unknown; fi`;必须在 Claude Code 之前先判 Cowork,因为两者都可能有 `~/.claude` 树,只有 Cowork 有 session-rooted skills mount。
- 按宿主产出预览并逐级降级、永不失败:claude.ai 原生渲染 artifact、inline 写在对话里;Cowork 用宿主持久 artifact(设计系统需要它跨轮次存在)、inline 用宿主内联 widget;Claude Code 在 `Artifact` 工具可用时用它,否则写对话;unknown 写自包含 HTML 到临时路径并交回路径;渲染不了就沿表往下退,inline 预览总好过中止。
- 预览里只放句子承载不了的东西:论点关卡放 SVG 画的 easing 曲线+精确数值、真的执行该交互的元素+重播按钮、裸数字(duration/delay/stagger/spring 参数)、reduced-motion 开关与降级版本;变体关卡把同一张卡每个变体并排、用一个全局触发器同时触发以便比较+每变体重播;视觉识别放色板(hex+相对背景的对比度)、真实字号阶梯的字体样张、间距条、圆角与阴影样本、一个真按钮和一张真卡片;设计系统渲染每一类 token、每个基础组件的五种状态(default/hover/focus/active/disabled)、明暗并排。
- 预览必须遵守的规则:它是一次性的、永不成为实现(要从验证过的论点和加载的子技能重建,绝不移植预览 markup;Compose/SwiftUI 上要在页面上说明 HTML 只近似时序与曲线、不近似渲染);验证后删除 live-preview 路由(除非用户要求保留);不为做预览安装任何依赖;不询问不启动 dev server;只展示论点里有的值(不在论点里的数字没有资格进预览,否则预览就成了第二个没人验证过的论点)。
- THESIS:在写代码前写出一句捕捉交互意图的话,例如"这个下拉用 150ms CSS 微过渡、slide+fade,干脆现代"、"hero 用 GSAP 滚动视差+文字错落揭示做电影感"、"Compose hero 用 SharedTransitionLayout + spring(stiffness=StiffnessMedium, dampingRatio=0.85)"、"macOS 仪表盘用 100ms 透明度 hover(桌面克制,不做缩放)+ Cmd+1-9 快捷键切面板";这就是第一个视觉关卡,在选定模式里呈现它并等待验证;被拒时不要推倒重来,问清楚哪里感觉不对再调整。
- LOAD:在同一个 Bash 调用里重新发射整段环境检测块再调 `load_skill`(`$SKILL_BASE` 和 `load_skill` 只存在于那一次调用,跨调用不保留):再解析子技能目录时按优先级探测——`/mnt/skills/user` 下的 `_jutsu` bundle → `/mnt/skills/user` → `${CLAUDE_PLUGIN_ROOT}/skills/_jutsu` → `~/.claude/plugins/cache` 里最新的数字版本目录 → 先沿 `$PWD` 向上最多 24 层找 `.claude/skills/*/_jutsu`,再查 `$HOME/.claude/skills` 与 `/mnt/.claude/skills`(maxdepth 2),最后查 `/sessions`(maxdepth 8 的 `*/.claude/skills/*/_jutsu`);不要缓存路径(插件更新后旧版本目录仍在磁盘上,缓存会静默加载上一版子技能)。
- 解析失败要明确报错并列出所有试过的根目录和各宿主对应的修复动作(claude.ai 重新上传 ZIP、Claude Code 重装插件后 `/reload-plugins`、Cowork 检查 `_jutsu` 挂载);`load_skill` 函数同时尝试 `$SKILL_BASE/<name>/SKILL.md` 和 `GUIDE.md`(打包会改名),缺失时警告并继续,而不是静默失败。
- 加载子技能:始终 `load_skill motion-principles`;按上下文加载 `mobile-principles`(移动 web 或原生 iOS/Android)、`desktop-principles`(macOS 或无移动特征的桌面 web)、`design-audit`(明确要求审计或 scope=full)、`ui-ux-pro-max`(高级 UI/UX 问题);按栈加载 `gsap` / `framer-motion`(`motion` 或 `framer-motion`)/ `css-native`(纯 CSS/Tailwind/无库)/ `threejs-r3f` / `canvas-generative` / `compose-motion`(Android 必加)、`compose-multiplatform`、`swiftui-motion`。
- 再按"高级论点"触发图形子技能:论点里出现 `shader`、`Metal`、`AGSL`、`RuntimeShader`、`MSL`、`liquid-glass`、`glassEffect`、`morphing transition`、`M3 Expressive`、`MotionScheme`、`colorEffect`、`distortionEffect`、`layerEffect`、生成式 Canvas、`holographic`、`CRT`、`displacement`、`ripple` 等词时,加载 `compose-graphics`(scope=full 或论点高级)或 `swiftui-graphics`;否则只用基础动效子技能。
- IMPLEMENT:Light 直接实现、不出变体;Medium/Full 先提 2-3 个变体再写代码——格式为 "Variant A — [名字](subtle)+ 一句感觉和技法"、"Variant B — [名字](balanced)"、"Variant C — [名字](impressive)";内联模式就写这段文本,artifact / live preview 模式就把三个变体并排渲染、用一个全局触发器同时触发保持可比,文本作为它们的说明;等用户选完再实现,始终遵守已验证的论点。
- 遵守几条硬性约束:没有验证过的交互论点绝不写代码;拒绝通用/AI 味(不要彩虹渐变、无意义的玻璃拟态、"现代简约"式空话);未经询问绝不安装依赖(先提议、解释原因、等绿灯);复杂度匹配范围;始终优先性能(60fps 或不做);没检测到动画库时优先用栈原生 API 再提依赖;检测到动画库时尊重开发者选择,不提议替换、不擅自把 `framer-motion` 迁到 `motion`;不要在实现时顺手加额外动画造成 scope creep。
- AUDIT 第一组自己检查,逐条按 `检查项 - 结论 - 证据` 报告(证据是跑过的 grep、算出的数值或 `file:line`;查不了的写"未检查",不打勾):reduced motion 真的降级(Web 是有实际降级逻辑的 `prefers-reduced-motion` 块而非空块,SwiftUI 用 `accessibilityReduceMotion`,Compose 用基于 `ValueAnimator.areAnimatorsEnabled()` / `Settings.Global.ANIMATOR_DURATION_SCALE` 的辅助);凡有卸载处都有退出动画;没有动画 `width`/`height`/`top`/`left`/`margin`/`padding`(用 transform / opacity / `graphicsLayer`);交互元素焦点可见且无裸 `outline: none`;交互元素五种状态齐全;颜色与间距来自项目 token(有 MASTER.md 就用它)而非魔法数字;对比度至少正文 4.5:1、大字与 UI 边界 3:1 且要算出数值(如 `#831843 on #FDF2F8 = 9.4:1`);语义正确(web 可点 div 要有 role、装饰性动效加 `aria-hidden`,Compose 自定义交互组件加 `Modifier.semantics`,SwiftUI 无文本控件加 `.accessibilityLabel`);web 的条件渲染用 `AnimatePresence` 或等价物包裹、`will-change` 少用且动画后移除。
- AUDIT 第二组写成交接块并标 **UNVERIFIED**,不勾选、不软化、不因为其余部分干净就省略:Web 在 Chrome DevTools > Performance 录整段交互(无帧超过 16.7ms)、在 375/768/1024/1440 检查无横向滚动与截断、开系统 reduce motion 验证降级路径真的跑;Compose 用 Layout Inspector > Component Tree > View Options > Show Recomposition Counts(滚动时重组次数稳定)、对中端机跑 `androidx.benchmark.macro` Macrobenchmark(60fps <16.67ms、120fps <8.33ms);SwiftUI 用 Instruments > Animation Hitches、并在 Reduce Motion 开+Dynamic Type 200% 下检查;macOS 用指针遍历每个交互元素、键盘走完整个视图检查 hover 与焦点环与快捷键。
- 若预览或 dev server 已经在跑且用户同意,亲自驱动浏览器收 web 那几行比交接更好,但绝不为审计专门启动 dev server 或安装任何东西;最后把两组分开报告并给计数(例如"9 项已查、发现 2 个问题、8 项交接"),单一列打勾不是诚实审计。
- 警惕这些红旗想法并当场纠正:"请求够清楚,直接开始写"(先问有没有论点、用户验没验)、"把问题一次问完省时间"(一次一个,第二个问题依赖第一个答案)、"这需要 GSAP+ScrollTrigger+Lenis"(先看 scope 是不是 Full)、"加点玻璃拟态让它 pop"(那是论点还是 AI 味默认值)、"用户急,跳过发现"、"顺手再加几个动画"、"审计项看着都没问题就打勾"、"不能 profile 就略过这部分"、"论点一句话挺清楚,直接写出来"(先给预览菜单)、"再问一次他们想怎么看"、"预览效果不错,直接移植进应用"。
- 最终交付按快速决策树收敛:SCAN 判栈 → 请求模糊就 DISCOVER、清楚就跳过 → SCOPE 分档 → 询问一次预览模式 → THESIS 在选定模式里展示并等验证(被拒就问哪里不对再调)→ LOAD 动效原则与栈相关子技能 → IMPLEMENT(中/全范围先出变体并按选定模式呈现,选完再写)→ AUDIT 动效、无障碍、一致性、性能。
适用边界 · 注意事项
- 纯后端 / 非 UI 动效类的普通业务开发任务不适合用这套流程(它只服务界面动效与微交互)。
- 无法与用户交互或不能等待验证时(例如必须一次性无人值守直接改代码),核心的 DISCOVER「一次一问」与 THESIS 视觉关卡无法完成,流程会被卡住。
- 未安装 genjutsu 插件/技能包、`_jutsu` 子技能目录解析不到,或宿主无法渲染任何预览时,按栈加载子技能与预览关卡这两步只能降级进行。