首页
/ gstack /plan-design-review 深度解析:用 7 轮交互式评审把设计计划从"看起来还行"推进到"可以开工"

gstack /plan-design-review 深度解析:用 7 轮交互式评审把设计计划从"看起来还行"推进到"可以开工"

2026-09-06 16:29:02作者:卓艾滢Kingsley

本篇以 gstack 仓库中 plan-design-review/sections/review-sections.md 为核心,完整讲解 /plan-design-review 技能在范围确认后执行的 7 轮设计评审(信息架构、状态覆盖、用户旅程、AI Slop 风险、设计系统对齐、响应式与可访问性、未决设计决策),以及配套的先验学习检索、JSONL 任务产物、评审日志与就绪度仪表盘机制。读完后,你将理解 gstack 如何用"评分—修复—再评分"循环、AskUserQuestion 强制门和跨模型共识来防止 AI 生成的通用化 UI,并能直接复用其中的设计硬规则清单。

这个文档在整个技能里扮演什么角色

/plan-design-review 是 gstack(一个把 Claude Code 变成虚拟工程团队的 CLI 工具集)中的"设计师之眼"计划评审技能,其 SKILL.md 的 frontmatter 标注 interactive: trueversion: 2.0.0,定位是"评审一份 PLAN——而不是线上站点",输出是"一份更好的计划,而不是一份关于计划的文档"。

整个技能采用"决策树骨架 + 按需加载章节"的结构:SKILL.md 中的 Section index 规定,只有当"7 轮设计评审、必需产出与评审报告(仅在 Step 0 范围达成一致之后)"这一情况出现时,才去读 sections/review-sections.md 并完整执行,且明确警告"不要凭记忆工作——该章节是这一步的 source of truth"。这个约定由三处机制保证:

  1. plan-design-review/sections/manifest.json 是被动注册表,登记了唯一章节 review-sections,其 trigger 字段即"running the 7 design passes, required outputs, and review report (only after Step 0 scope is agreed)";
  2. SKILL.md 末尾的 > STOP. 块与 "Section self-check" 要求:如果凭记忆产出了评审发现或评审报告,必须停下来重新 Read 该章节文件;
  3. SKILL.md 的 "EXIT PLAN MODE GATE (BLOCKING)" 自检,要求计划文件最后一个 ## 标题必须是 ## GSTACK REVIEW REPORT,否则不得调用 ExitPlanMode。

review-sections.md 文件本身头部两行声明:

<!-- AUTO-GENERATED from review-sections.md.tmpl — do not edit directly -->
<!-- Regenerate: bun run gen:skill-docs -->

即它是从 review-sections.md.tmpl 生成的产物(生成脚本为 scripts/gen-skill-docs.ts)。这也解释了仓库中大量评审文本为何在多个技能间高度一致——它们来自共享的 resolver,例如 scripts/resolvers/review.ts 中的 generateReviewDashboardgeneratePlanFileReviewReportgenerateExitPlanModeGategenerateAntiShortcutClause,分别生成本文档中的"Review Readiness Dashboard""Plan File Review Report""EXIT PLAN MODE GATE""Anti-shortcut clause"四段文字。下面进入文档主体内容。

反跳过规则与反捷径条款:7 轮评审为什么一个都不能少

review-sections.md 开头用两条加粗规则框定了整个评审的执行纪律:

Anti-skip rule(反跳过规则):无论计划类型(strategy、spec、code、infra),任何一轮评审(1-7)都不允许被压缩、缩略或跳过。"这是策略文档,所以设计评审不适用"这种说法永远错误——设计缺口正是实现崩溃的地方。某一轮如果确实零发现,可以说 "No issues found" 然后继续——但你必须评估过它。

Anti-shortcut clause(反捷径条款):计划文件是交互式评审的输出,而不是评审的替代品。"把所有发现一次性写进计划文件然后直接 ExitPlanMode、全程不触发 AskUserQuestion",正是文档所说的 2026 年 5 月 transcript bug 的精确失败模式——模型做了探索、发现了问题,却把它们倾倒进交付物,而没有带着用户逐一过堂。条款的硬约束是:只要任何评审小节存在非平凡发现,从"发现"到"ExitPlanMode"的路径必须穿过 AskUserQuestion;全部小节零发现才是唯一可以绕过 AskUserQuestion 的路径。这条文字由 scripts/resolvers/review.tsgenerateAntiShortcutClause 统一生成,注入到所有 plan 评审技能中。

配套的提问纪律在文档后半部分(见下文"提问协议"一节):一个问题 = 一次 AskUserQuestion 调用,绝不合并;每个发现用"问题编号 + 选项字母"(如 "3A"、"3B")标注。

Prior Learnings:先检索历史经验,再开始评审

评审开始前,先检索之前会话沉淀的经验(review-sections.md):

_CROSS_PROJ=$(~/.claude/skills/gstack/bin/gstack-config get cross_project_learnings 2>/dev/null || echo "unset")
echo "CROSS_PROJECT: $_CROSS_PROJ"
if [ "$_CROSS_PROJ" = "true" ]; then
  ~/.claude/skills/gstack/bin/gstack-learnings-search --limit 10 --cross-project 2>/dev/null || true
else
  ~/.claude/skills/gstack/bin/gstack-learnings-search --limit 10 2>/dev/null || true
fi

行为规则:

  • 如果 CROSS_PROJECTunset(首次运行),用 AskUserQuestion 询问是否启用跨项目学习(数据只留在本机)。选项 A 启用(推荐,适合单人开发者),选项 B 仅项目内。选择后分别执行 gstack-config set cross_project_learnings true/false,再用对应标志重新检索。
  • 找到经验后,将其并入分析。当某条评审发现命中一条历史经验时,必须显示 "Prior learning applied: [key] (confidence N/10, from [date])"——这是为了让"复利"可见:用户应看到 gstack 正在对自己的代码库越用越聪明。

7 轮评审:每一轮的评分、修复与停止点

每轮遵循同一模式:先按 0-10 打分,说明"10 分长什么样",然后把计划修复到 10(FIX TO 10),并在每轮末尾 STOP,对每个问题单独调用一次 AskUserQuestion(不批量),给出推荐及理由,等用户回应后才继续。这个 0-10 评分法在 SKILL.md 中定义为六步循环:评分 → 说明缺口 → 编辑计划 → 重评分 → 真正的设计选择用 AskUserQuestion 解决 → 再修复,直到 10 分或用户说"够了,继续"。

Pass 1: Information Architecture(信息架构)

  • 评分问题(0-10):计划是否定义了用户第一、第二、第三看到什么?
  • FIX TO 10:为计划添加信息层级。包含屏幕/页面结构与导航流的 ASCII 图。应用"约束崇拜(constraint worship)"——如果你只能展示 3 样东西,是哪 3 样?

Pass 2: Interaction State Coverage(交互状态覆盖)

  • 评分问题:计划是否指定了 loading、empty、error、success、partial 各状态?
  • FIX TO 10:向计划加入交互状态表:
  FEATURE              | LOADING | EMPTY | ERROR | SUCCESS | PARTIAL
  ---------------------|---------|-------|-------|---------|--------
  [each UI feature]    | [spec]  | [spec]| [spec]| [spec]  | [spec]
  • 每个状态描述用户看到什么,而不是后端行为。空状态是功能——必须指定温度感(warmth)、主操作、上下文。

Pass 3: User Journey & Emotional Arc(用户旅程与情感弧线)

  • 评分问题:计划是否考虑了用户的情感体验?
  • FIX TO 10:加入用户旅程故事板:
  STEP | USER DOES        | USER FEELS      | PLAN SPECIFIES?
  -----|------------------|-----------------|----------------
  1    | Lands on page    | [what emotion?] | [what supports it?]
  ...
  • 应用时间尺度设计:5 秒的直觉反应(visceral)、5 分钟的行为层(behavioral)、5 年的反思层(reflective)三层同时设计。这一条呼应了 SKILL.md 中"Cognitive Patterns"第 10 条(Norman 情感设计的三层级)。

Pass 4: AI Slop Risk(AI 泔水风险)——规则密度最高的一轮

  • 评分问题:计划描述的是具体、有意为之的 UI,还是通用模式?
  • FIX TO 10:用具体方案改写模糊的 UI 描述。

这一轮的核心是一整套"设计硬规则",执行顺序是先分类,再套用对应规则集review-sections.md):

分类器(Classifier)

  • MARKETING/LANDING PAGE(hero 驱动、品牌前置、转化导向)→ 应用 Landing Page Rules;
  • APP UI(工作区驱动、数据密集、任务导向:dashboard、admin、settings)→ 应用 App UI Rules;
  • HYBRID(营销外壳 + 类应用区块)→ hero/营销区块用 Landing Page Rules,功能区块用 App UI Rules。

硬性拒绝标准(Hard rejection criteria)——7 条 instant-fail 模式,命中任意一条即标记:

  1. 以通用 SaaS 卡片网格作为第一印象;
  2. 漂亮的图但品牌薄弱;
  3. 强标题但无明确行动;
  4. 文字背后是喧闹的图像;
  5. 各区块重复同一种情绪陈述;
  6. 没有叙事目的的轮播;
  7. 用堆叠卡片拼出来的 App UI 而不是布局。

试金石检验(Litmus checks)——每条回答 YES/NO,用于跨模型共识评分:

  1. 首屏能否一眼认出品牌/产品?
  2. 是否存在一个强视觉锚点?
  3. 只扫标题能否读懂整页?
  4. 每个区块是否只有一个职责?
  5. 卡片是否真的必要?
  6. 动效是否改善了层级或氛围?
  7. 去掉所有装饰性阴影后,设计是否仍显高级?

Landing page 规则(classifier = MARKETING/LANDING 时):首屏读起来是一幅构图而不是 dashboard;品牌优先的层级(brand > headline > body > CTA);字体要有表达力、拒绝默认字体栈(Inter、Roboto、Arial、system);不用平涂单色背景——用渐变、图像、细腻纹理;Hero 全出血(full-bleed、edge-to-edge),禁止 inset/平铺/圆角变体;Hero 预算:品牌、一个标题、一句支撑文案、一组 CTA、一张图;Hero 里不放卡片,卡片只在该卡片本身就是交互时使用;一个区块一个职责(一个目的、一个标题、一句短支撑文案);动效至少 2-3 个有意为之的(入场、滚动联动、hover/reveal);颜色用 CSS 变量、避免紫白默认配色、默认一个强调色;文案用产品语言而非设计评论,"如果删掉 30% 文案会更好,就继续删";默认美学:构图优先、品牌是最响亮的文字、最多两种字体、默认无卡片、首屏是海报不是文档。

App UI 规则(classifier = APP UI 时):平静的表面层级、强排版、少量颜色;密集但可读、最小 chrome;组织方式为主工作区、导航、次要上下文、一个强调色;避免 dashboard 卡片马赛克、粗边框、装饰性渐变、装饰性图标;文案用工具语言——方位、状态、动作,而非情绪/品牌/愿景;卡片只在卡片即交互时使用;区块标题陈述"这块区域是什么、用户能做什么"(如 "Selected KPIs"、"Plan status")。

通用规则(Universal rules,适用于所有类型):用 CSS 变量定义颜色系统;禁用默认字体栈(Inter、Roboto、Arial、system);一个区块一个职责;"删 30% 文案能变好就继续删";卡片必须挣得自己的存在——不要装饰性卡片网格;永远不用小字号低对比正文(正文 < 16px 或对比度 < 4.5:1 直接违规);永远不把 placeholder 作为表单字段唯一标签(字段有内容时标签必须可见);必须保留已访问/未访问链接的颜色区分;永远不让标题悬浮在两段正文之间(标题必须视觉上更靠近它引入的区块)。

AI Slop 黑名单——"一看就是 AI 生成"的 10+1 种模式:

  1. 紫/罗兰/靛蓝渐变背景或蓝紫配色方案;
  2. 三列特性网格:彩色圆圈里的图标 + 粗体标题 + 两行描述,对称重复 3 次——最容易被识别的 AI 布局;
  3. 彩色圆圈图标作为区块装饰(SaaS 起步模板既视感);
  4. 一切居中(标题、描述、卡片全部 text-align: center);
  5. 所有元素统一的大圆角;
  6. 装饰性 blob、漂浮圆、波浪 SVG 分隔线(区块太空需要的是内容,不是装饰);
  7. Emoji 作为设计元素(标题里的火箭、作为项目符号的 emoji);
  8. 卡片左侧彩色边框(border-left: 3px solid <accent>);
  9. 通用 hero 文案("Welcome to [X]"、"Unlock the power of..."、"Your all-in-one solution for...");
  10. 一刀切的区块节奏(hero → 3 特性 → 用户评价 → 定价 → CTA,每个区块同高);
  11. 把 system-ui 或 -apple-system 当主字体——"我放弃排版了"的信号,要选真正的设计字体。

文档注明该黑名单的参考来源包括 OpenAI 的 "Designing Delightful Frontends with GPT-5.4" 博文(2026 年 3 月)与 gstack 自身的设计方法论。此外,对模糊描述有四个追问模板:"Cards with icons" → 它和所有 SaaS 模板的区别是什么?"Hero section" → 什么让这个 hero 像这个产品?"Clean, modern UI" → 无意义,替换为实际设计决策;"Dashboard with widgets" → 什么让它不是又一个 dashboard?若 Step 0.5 已生成视觉 mockup,则用 Read 工具逐张读图,对照黑名单检查是否落入通用模式(三列网格、居中 hero、图库照片感),命中就标记并提供用 $D iterate --feedback "..." 按更具体的方向重新生成。

Pass 5: Design System Alignment(设计系统对齐)

  • 评分问题:计划是否与 DESIGN.md 对齐?
  • FIX TO 10:如果存在 DESIGN.md,用具体 token/组件为计划加注;如果不存在,标记该缺口并推荐先跑 /design-consultation。任何新组件都要过审——它是否符合现有设计词汇?

gstack 仓库自身就是 Pass 5 的活案例:根目录的 DESIGN.md 定义了完整的 token 体系——字体栈(Satoshi 展示 / DM Sans 正文 / JetBrains Mono 数据,明确写着 "Not Inter, not Geist",恰好对应 Pass 4 通用规则"禁用默认字体栈")、11 级字号比例、amber 强调色 + zinc 中性色板、4px 基础间距与 2xs-3xl 间距比例、12px 卡片圆角等。评审任何计划时,这些就是可逐条对照的"具体 tokens"。

Pass 6: Responsive & Accessibility(响应式与可访问性)

  • 评分问题:计划是否指定了移动端/平板、键盘导航、读屏器?
  • FIX TO 10:按视口写响应式规格——不是"移动端堆叠",而是有意图的布局变化。加入 a11y 规格:键盘导航模式、ARIA landmarks、触摸目标尺寸(最小 44px)、颜色对比要求。44px 与"用户如何真实行为"一节(SKILL.md 中"Mobile: Same Rules, Higher Stakes")相互印证:移动端没有 hover,可点击性必须靠形状、位置、格式来传达。

Pass 7: Unresolved Design Decisions(未决设计决策)

把那些"会折磨实现者"的模糊点显性化:

  DECISION NEEDED              | IF DEFERRED, WHAT HAPPENS
  -----------------------------|---------------------------
  What does empty state look like? | Engineer ships "No items found."
  Mobile nav pattern?          | Desktop nav hides behind hamburger
  ...

如果 Step 0.5 生成过 mockup,就把它们作为证据引出来——mockup 让决策变得具体,例如"你批准的 mockup 显示侧边栏导航,但计划没写移动端行为:375px 下这个侧边栏怎么办?"每个决策 = 一次带推荐、理由和替代方案的 AskUserQuestion,并在做出决策时就地编辑计划。

Post-Pass: 更新 Mockups(如已生成)

若 Step 0.5 生成过 mockup,且评审轮显著改变了设计决策(信息架构重构、新增状态、布局变化),一次性(不是循环)提议重新生成:用 AskUserQuestion 告知"评审轮改变了 [列出主要变化],要不要重新生成 mockup 以反映更新后的计划?"。若同意,用 $D iterate(带概括变化的反馈)或 $D variants(带更新后的 brief),保存到同一个 $_DESIGN_DIR 目录。这些 $D 命令(generate/variants/compare/iterate/check/evolve)属于 gstack 的 designer 二进制,其可用性由 SKILL.md 的 DESIGN SETUP 检查决定:能找到可执行的 design/dist/design 就打印 DESIGN_READY,否则 DESIGN_NOT_AVAILABLE 并回退到纯文本评审。

提问协议:CRITICAL RULE 与格式规则

文档的 "CRITICAL RULE — How to ask questions"(review-sections.md)规定了设计评审专属的提问纪律:

  • 一个问题 = 一次 AskUserQuestion 调用,绝不把多个问题合并成一条;
  • 具体描述设计缺口——缺了什么、如果不写用户将会经历什么;
  • 给 2-3 个选项,每个选项标注"现在明确的成本"与"延后的风险";
  • 映射到设计原则:一句话把推荐连接到某条具体原则;
  • 用问题编号 + 选项字母标注("3A"、"3B");
  • 零发现:小节零发现就明说 "No issues, moving on" 继续;否则每个缺口都要问——"显然能修"的缺口依然是缺口,落进计划前仍需用户批准;
  • 永远不用 AskUserQuestion 问"你更喜欢哪个变体"。必须先建对比板($D compare --serve)并在浏览器中打开:板上有评分控件、评论、remix/重生成按钮和结构化反馈输出。AskUserQuestion 只用来通知用户板已打开并等待其完成——把变体直接列在问题里问偏好,是体验降级。

这与 SKILL.md 的 "Comparison Board + Feedback Loop" 配套:$D compare --images "..." --output .../design-board.html --serve 在后台起 HTTP 服务并打印 BOARD_URL;用户提交后读取 $_DESIGN_DIR/feedback.json(含 preferredratingscommentsoverall 字段),点 Regenerate/Remix 则读 feedback-pending.json 再迭代。

文档末尾的 Formatting Rules 补充:问题编号用数字、选项用字母;每个选项最多一句话;每轮评审后暂停等待反馈;每轮都给出修复前后的评分以便扫读。

Required Outputs:三份必写产出

1. "NOT in scope" 区块:列出被考虑过但明确延后的设计决策,每条附一行理由。

2. "What already exists" 区块:列出计划应复用的现有 DESIGN.md、UI 模式与组件。

3. TODOS.md 更新:全部评审轮完成后,每个潜在 TODO 作为独立的一次 AskUserQuestion 呈现——绝不批量,绝不静默跳过。设计债包括:缺失的 a11y、未解决的响应式行为、被延后的空状态。每个 TODO 必须带六要素:

  • What:一行描述;
  • Why:解决的具体问题或解锁的价值;
  • Pros:做这件事的收益;
  • Cons:成本、复杂度或风险;
  • Context:足够让三个月后接手的人理解动机;
  • Depends on / blocked by:前置条件。

然后给出三个选项:A) 加入 TODOS.md;B) 跳过——价值不够;C) 现在就在这个 PR 里做,不延后。gstack 仓库根目录就有一份真实的 TODOS.md 可作为产物形态参考。

Implementation Tasks:Markdown 清单 + JSONL 双产物

收尾前,必须把发现综合成一份"扁平的、可直接开建的任务清单":每个任务源自某条具体发现——不注水。同时产出两个东西:一份 Markdown 区块(总是输出),和一份 JSONL 产物(总是写入,即使零任务),后者供 /autoplan 跨阶段聚合。

Markdown 区块模板:

## Implementation Tasks
Synthesized from this review's findings. Each task derives from a specific
finding above. Run with Claude Code or Codex; checkbox as you ship.

- [ ] **T1 (P1, human: ~2h / CC: ~15min)** — <component> — <imperative title>
  - Surfaced by: <section name> — <specific finding text or line reference>
  - Files: <paths to touch>
  - Verify: <test command or manual check>
- [ ] **T2 (P2, human: ~30min / CC: ~5min)** — ...

规则:P1 阻塞发布;P2 应与 P1 同分支落地;P3 是后续 TODO。某条发现若没有可行动任务,不要硬造;某小节零发现,就输出 _No new tasks from <section>._。工时用 CLAUDE.md 的 AI 压缩表(human 与 CC 双标尺)。

JSONL 产物的写入脚本要求用 jq -nc 序列化(标题与来源发现中可能含引号、换行、反斜杠,手工 echo/printf 会破坏 JSON),完整命令如下(review-sections.md):

eval "$(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)"
TASKS_DIR="${HOME}/.gstack/projects/${SLUG:-unknown}"
mkdir -p "$TASKS_DIR"
TASKS_FILE="$TASKS_DIR/tasks-design-review-$(date +%Y%m%d-%H%M%S).jsonl"
COMMIT=$(git rev-parse HEAD 2>/dev/null || echo unknown)
BRANCH=$(git branch --show-current 2>/dev/null || echo unknown)
RUN_ID="$(date -u +%Y%m%dT%H%M%SZ)-$$"

# Repeat ONE jq invocation per task identified during this review.
# Substitute the placeholders inline with shell variables you set per task:
#   TASK_ID (T1, T2, ...), PRIORITY (P1/P2/P3), COMPONENT, TITLE,
#   SOURCE_FINDING, EFFORT_HUMAN, EFFORT_CC, FILES_JSON (a JSON array literal
#   like '["browse/src/sanitize.ts","browse/src/server.ts"]').
jq -nc \
  --arg phase 'design-review' \
  --arg run_id "$RUN_ID" \
  --arg branch "$BRANCH" \
  --arg commit "$COMMIT" \
  --arg id "$TASK_ID" \
  --arg priority "$PRIORITY" \
  --arg component "$COMPONENT" \
  --arg effort_human "$EFFORT_HUMAN" \
  --arg effort_cc "$EFFORT_CC" \
  --arg title "$TITLE" \
  --arg source_finding "$SOURCE_FINDING" \
  --argjson files "$FILES_JSON" \
  '{phase:$phase, run_id:$run_id, branch:$branch, commit:$commit, id:$id, priority:$priority, component:$component, files:$files, effort_human:$effort_human, effort_cc:$effort_cc, title:$title, source_finding:$source_finding}' \
  >> "$TASKS_FILE"

两条边界规则:jq 未安装时跳过 JSONL 写入并提醒用户安装(绝不手写 JSONL);零任务时也要 touch 出空文件: > "$TASKS_FILE"),让聚合器区分"跑了、零发现"与"没跑"。

Completion Summary 与 Approved Mockups

评审结束输出完成度摘要(每轮给出修复前后分数):

  +====================================================================+
  |         DESIGN PLAN REVIEW — COMPLETION SUMMARY                    |
  +====================================================================+
  | System Audit         | [DESIGN.md status, UI scope]                |
  | Step 0               | [initial rating, focus areas]               |
  | Pass 1  (Info Arch)  | ___/10 → ___/10 after fixes                |
  | Pass 2  (States)     | ___/10 → ___/10 after fixes                |
  | Pass 3  (Journey)    | ___/10 → ___/10 after fixes                |
  | Pass 4  (AI Slop)    | ___/10 → ___/10 after fixes                |
  | Pass 5  (Design Sys) | ___/10 → ___/10 after fixes                |
  | Pass 6  (Responsive) | ___/10 → ___/10 after fixes                |
  | Pass 7  (Decisions)  | ___ resolved, ___ deferred                 |
  +--------------------------------------------------------------------+
  | NOT in scope         | written (___ items)                         |
  | What already exists  | written                                     |
  | TODOS.md updates     | ___ items proposed                          |
  | Approved Mockups     | ___ generated, ___ approved                  |
  | Decisions made       | ___ added to plan                           |
  | Decisions deferred   | ___ (listed below)                          |
  | Overall design score | ___/10 → ___/10                             |
  +====================================================================+

判定口径:所有轮 8+ 分 → "Plan is design-complete. Run /design-review after implementation for visual QA.";任何一轮低于 8 → 注明什么未解决、为什么(用户选择延后)。

另有两处必写内容:

  • Unresolved Decisions:任何未获回答的 AskUserQuestion 记在这里,绝不静默默认到某个选项;
  • Approved Mockups:如本次评审产生过 mockup,向计划文件追加一张表——屏幕/区块、mockup 路径(~/.gstack/projects/$SLUG/designs/[folder]/[filename].png)、方向描述、评审约束。路径写全,实现者据此知道该从哪张视觉稿开建;这些记录跨会话、跨工作区持久。未生成 mockup 则省略该区块。

Review Log 与 Review Readiness Dashboard:评审结果如何被持久化和消费

写日志(PLAN MODE EXCEPTION — ALWAYS RUN):完成度摘要之后持久化评审结果。该命令写入 ~/.gstack/(用户配置目录而非项目文件),与技能 preface 写 ~/.gstack/sessions/~/.gstack/analytics/ 是同一模式;评审仪表盘依赖这份数据,跳过它会让 /ship 里的评审就绪仪表盘失效:

~/.claude/skills/gstack/bin/gstack-review-log '{"skill":"plan-design-review","timestamp":"TIMESTAMP","status":"STATUS","initial_score":N,"overall_score":N,"unresolved":N,"decisions_made":N,"commit":"COMMIT"}'

字段替换规则:TIMESTAMP 为当前 ISO 8601 时间;STATUS 在总评分 8+ 且未决数为 0 时为 "clean",否则 "issues_open"initial_score 为修复前总设计分;overall_score 为修复后总分;unresolved 为未决设计决策数;decisions_made 为加入计划的设计决策数;COMMITgit rev-parse --short HEAD 输出。

读日志并显示仪表盘:执行 ~/.claude/skills/gstack/bin/gstack-review-read,解析输出。对每个技能(plan-ceo-review、plan-eng-review、review、plan-design-review、design-review-lite、adversarial-review、codex-review、codex-plan-review)取最近一条,忽略 7 天前的条目。合并规则:Eng Review 行取 review(diff 范围)与 plan-eng-review(计划阶段)中较新者,状态后追加 "(DIFF)" 或 "(PLAN)";Adversarial 行取 adversarial-review(新自动扩缩)与 codex-review(旧版)较新者;Design Review 行取 plan-design-review(完整视觉审计)与 design-review-lite(代码级检查)较新者,追加 "(FULL)" 或 "(LITE)";Outside Voice 行取最近一条 codex-plan-review。若最近条目带 via 字段(如 via:"autoplan"via:"ship"),状态标签追加来源,显示为 "CLEAR (PLAN via /autoplan)"。autoplan-voicesdesign-outside-voices 条目仅用于审计留痕,不显示、不被任何消费者检查。

+====================================================================+
|                    REVIEW READINESS DASHBOARD                       |
+====================================================================+
| Review          | Runs | Last Run            | Status    | Required |
|-----------------|------|---------------------|-----------|----------|
| Eng Review      |  1   | 2026-03-16 15:00    | CLEAR     | YES      |
| CEO Review      |  0   | —                   | —         | no       |
| Design Review   |  0   | —                   | —         | no       |
| Adversarial     |  0   | —                   | —         | no       |
| Outside Voice   |  0   | —                   | —         | no       |
+--------------------------------------------------------------------+
| VERDICT: CLEARED — Eng Review passed                                |
+====================================================================+

评审层级:Eng Review 默认必需,是唯一卡发布的评审(可用 gstack-config set skip_eng_review true 全局关闭);CEO Review 可选,用于大产品/业务变更、新用户可见功能、范围决策,bug 修复/重构/基础设施/清理则跳过;Design Review 可选,推荐用于 UI/UX 变更,纯后端/基础设施/prompt 变更跳过;Adversarial Review 自动开启,每个 diff 都获得 Claude 对抗子代理 + Codex 对抗质询,200+ 行的大 diff 额外获得带 P1 门的 Codex 结构化评审;Outside Voice 可选,来自不同模型的独立计划评审,Codex 不可用时回退 Claude 子代理,永不卡发布。

判定逻辑:CLEARED 当且仅当 7 天内存在 reviewplan-eng-review 的 "clean" 条目(或 skip_eng_review 为 true);缺失、过期(>7 天)或有未决问题则 NOT CLEARED;CEO/Design/Codex 仅作上下文展示,不阻塞发布;skip_eng_review 为 true 时 Eng Review 显示 "SKIPPED (global)" 且判定 CLEARED。

**陈旧检测(staleness detection)**是这套机制最精巧的部分,核心是"内容优先"规则:

  • 对 diff 范围行(reviewadversarial-reviewcodex-review、ship 阶段条目):解析输出的 ---WTREE------DIRTY--- 段。若条目有 wtree 字段且等于当前 ---WTREE--- 值,则评审为 CURRENT——内容完全一致,与提交数、rebase、amend、是否已提交无关(wtree 相等本身就证明内容相同,这是基石性质),跳过提交数启发式、不显示陈旧提示;
  • 计划层行(plan-ceo-review、plan-eng-review、plan-design-review)评的是计划文件而非仓库树——永不应用 wtree 规则,保留 7 天新鲜度逻辑;若条目带 plan_sha256 字段,可与当前计划文件的 sha256 对比,不一致时提示 "plan changed since review";
  • 回退(无 wtree 或不匹配):解析 ---HEAD--- 段取当前 HEAD;对带 commit 字段的条目,若与 HEAD 不同则用 git rev-list --count STORED_COMMIT..HEAD 数出间隔提交数;命令失败(被 rebase 掉的提交)则判 UNKNOWN 并按陈旧处理,不报错,显示 "Note: {skill} review from {date} may be stale — {N} commits since review";
  • commit 字段的遗留条目:提示其无提交追踪,建议重跑;全部 CURRENT 时不显示任何陈旧提示。

源码级佐证:这段 wtree 机制并非纸上谈兵,仓库测试 test/review-log.test.ts 对其有直接验证——gstack-review-log 会替调用方权威盖章 commit_fulltreewtreedirty 四个绑定字段,且调用方伪造的同名字段一律被忽略(test/review-log.test.ts#L88-L111);gstack-wtree 指纹满足两条关键性质:新增未跟踪源文件会改变指纹,gitignore 文件不会,而提交相同内容不改变指纹(test/review-log.test.ts#L161-L183)——这正是"wtree 相等 ⇒ 内容相同"基石性质的测试保障;gstack-review-read 则保证输出 ---HEAD------WTREE------TREE------DIRTY--- 四个解析段(test/review-log.test.ts#L195-L211)。

Plan File Review Report:把评审状态写回计划文件

显示完仪表盘后,还要更新计划文件本身,让任何读计划的人都能看到评审状态。计划文件从会话上下文中检测(宿主在系统消息中提供计划文件路径),找不到就静默跳过——并非每次评审都运行在 plan mode。

Findings 列的字段映射(各技能日志字段不同,review-sections.md 给出逐技能规则):

  • plan-ceo-reviewstatusunresolvedcritical_gapsmodescope_proposedscope_acceptedscope_deferredcommit → "{scope_proposed} proposals, {scope_accepted} accepted, {scope_deferred} deferred"(scope 字段为 0 或缺失时输出 "mode: {mode}, {critical_gaps} critical gaps")
  • plan-eng-reviewstatusunresolvedcritical_gapsissues_foundmodecommit → "{issues_found} issues, {critical_gaps} critical gaps"
  • plan-design-reviewstatusinitial_scoreoverall_scoreunresolveddecisions_madecommit → "score: {initial_score}/10 → {overall_score}/10, {decisions_made} decisions"
  • plan-devex-reviewstatusinitial_scoreoverall_scoreproduct_typetthw_currenttthw_targetmodepersonacompetitive_tierunresolvedcommit → "score: {initial_score}/10 → {overall_score}/10, TTHW: {tthw_current} → {tthw_target}"
  • devex-reviewstatusoverall_scoreproduct_typetthw_measureddimensions_testeddimensions_inferredboomerangcommit → "score: {overall_score}/10, TTHW: {tthw_measured}, {dimensions_tested} tested/{dimensions_inferred} inferred"
  • codex-reviewstatusgatefindingsfindings_fixed → "{findings} findings, {findings_fixed}/{findings} fixed"

然后生成如下报告({...} 为占位符):

## GSTACK REVIEW REPORT

| Review | Trigger | Why | Runs | Status | Findings |
|--------|---------|-----|------|--------|----------|
| CEO Review | `/plan-ceo-review` | Scope & strategy | {runs} | {status} | {findings} |
| Codex Review | `/codex review` | Independent 2nd opinion | {runs} | {status} | {findings} |
| Eng Review | `/plan-eng-review` | Architecture & tests (required) | {runs} | {status} | {findings} |
| Design Review | `/plan-design-review` | UI/UX gaps | {runs} | {status} | {findings} |
| DX Review | `/plan-devex-review` | Developer experience gaps | {runs} | {status} | {findings} |

表下追加三行,其中 CODEX 与 CROSS-MODEL 可选(空则省略),VERDICT 必在:

  • CODEX:(仅当 codex-review 跑过)一行总结 codex 修复;
  • CROSS-MODEL:(仅当 Claude 与 Codex 评审都存在)重叠分析;
  • VERDICT: 列出 CLEAR 的评审(如 "CEO + ENG CLEARED — ready to implement");若 Eng Review 未 CLEAR 且未全局跳过,追加 "eng review required"。

未决决策状态行(强制,不可省略,且必须是报告最后一个非空行):VERDICT 之后,报告以且仅以二者之一收尾——精确的、不加粗的 NO UNRESOLVED DECISIONS(加粗版本不算数),或 **UNRESOLVED DECISIONS:** 头 + 每个未决项一条 bullet(最后一条 bullet 即末行;仅当 N > 0 时追加 + N unresolved from prior reviews)。计数规则避免重复计算:本次评审的未决项从上下文列;历史评审则对每个技能取最新的新鲜行(7 天窗口)求和 unresolved,且先剔除当前技能自己的行;两边都为零才发哨兵行。这段内容位于 ## GSTACK REVIEW REPORT 标题之下——是粗体标签而非新的 ## 标题,且豁免"空则省略"规则。

写回流程(PLAN MODE EXCEPTION — ALWAYS RUN):计划文件是 plan mode 中唯一允许编辑的文件,评审报告是计划"活状态"的一部分。报告必须永远是计划文件的最后一个区块,执行"删除后追加"单流程:1) Read 计划文件全文,搜索任意位置的 ## GSTACK REVIEW REPORT 标题;2) 若存在,用 Edit 从该标题删到下一个 ## 标题或文件末尾,替换为空串——无论它当前在文件哪个位置,中途删除是有意设计;Edit 失败(并发编辑)则重读重试一次;3) 在文件末尾追加新报告;4) 用 Read 验证 ## GSTACK REVIEW REPORT 是最后一个 ## 标题,若不是,重复步骤 2-3 一次。严禁就地替换——"中途替换"正是旧版本让报告停留在文件中段的 bug 路径。这也与 scripts/resolvers/review.ts 生成的文本逐字对应,并被 SKILL.md 的 EXIT PLAN MODE GATE 强制校验。

Capture Learnings 与 Brain 机制

记录学习:本会话若发现非显而易见的模式、陷阱或架构洞见,为未来会话记录:

~/.claude/skills/gstack/bin/gstack-learnings-log '{"skill":"plan-design-review","type":"TYPE","key":"SHORT_KEY","insight":"DESCRIPTION","confidence":N,"source":"SOURCE","files":["path/to/relevant/file"]}'
  • typepattern(可复用方法)、pitfall(不要做什么)、preference(用户声明的)、architecture(结构性决策)、tool(库/框架洞见)、operational(项目环境/CLI/工作流知识);
  • sourceobserved(你在代码里发现的)、user-stated(用户告知的)、inferred(AI 推断的)、cross-model(Claude 与 Codex 均同意);
  • confidence:1-10,要诚实——代码中验证过的 observed 模式给 8-9,不确定的推断给 4-5,用户明确声明的偏好给 10;
  • files:列出该学习引用的具体文件路径,用于陈旧检测——这些文件日后被删,学习可被标记失效;
  • 只记录真正的发现:不记显然的事、不记用户已知的。判据:这条洞见能否在未来的会话中省时间?能就记。

Brain Calibration Write-Back(Phase 2 / 受门控):当技能做出值得追踪的类型化预测(范围决策、TTHW 目标、架构押注、wedge 承诺)时,可以向 brain 写一条 kind=bet 的 take,让校准画像随时间积累。双重门控:1) 活动端点的 brain trust policy 为 personal(经 gstack-config get brain_trust_policy@<endpoint-hash> 检查)——共享 brain 跳过写回,避免污染团队校准;2) 功能标志 BRAIN_CALIBRATION_WRITEBACK 已设置(文档注明当前为 false,待上游 gbrain v0.42+ 交付 takes_add MCP 操作后翻转)。双门通过时,写回路径用 mcp__gbrain__takes_add 记录权重 0.5 的 take(按 SKILL_CALIBRATION_WEIGHTS);MCP 操作不可用时回退到 mcp__gbrain__put_page 加 gstack:takes fence 块(更丑但有文档的路径)。take frontmatter 的必选形状:

kind: bet
holder: <user identity from whoami>
claim: <one-line prediction the skill is making>
weight: 0.5
since_date: <today's date>
expected_resolution: <date in 1-3 months depending on skill>
source_skill: plan-design-review

写回后失效受影响摘要,让下次 preflight 反映新状态:

eval "$(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)" 2>/dev/null || true
~/.claude/skills/gstack/bin/gstack-brain-cache invalidate brand --project "$SLUG" 2>/dev/null || true

Brain Cache Background Refresh:技能工作完成(且遥测已记录)后,为接近 TTL 的缓存摘要发起后台刷新。非阻塞——用户不等待,下次调用受益于热缓存:

eval "$(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)" 2>/dev/null || true
(~/.claude/skills/gstack/bin/gstack-brain-cache refresh --project "$SLUG" 2>/dev/null &) || true

Next Steps — Review Chaining:评审如何串成流水线

显示完 Review Readiness Dashboard 后,根据本次设计评审的发现推荐下一步评审——读仪表盘输出,看哪些评审已跑过、是否已陈旧:

  • 推荐 /plan-eng-review(除非 eng review 被全局跳过):检查仪表盘输出的 skip_eng_review;若为 true 则用户已退出,不再推荐。否则 eng review 是必需的发布门。若本次设计评审新增了大量交互规格、新用户流或改变了信息架构,强调 eng review 需要验证其架构影响。若已存在 eng review 但其提交哈希早于本次设计评审,注明它可能已陈旧、应重跑;
  • 考虑推荐 /plan-ceo-review——仅当发现根本性产品方向缺口时:具体条件是总设计分起始低于 4/10、信息架构有重大结构性问题、或评审暴露出"是否在解决正确问题"的疑问,且仪表盘中尚无任何 CEO review。这是选择性推荐——大多数设计评审不应触发 CEO 评审;
  • 两者都需要时,先推荐 eng review(必需门);
  • 适时推荐设计探索技能:/design-shotgun 与 /design-html 产出设计产物(mockup、HTML 预览)而非应用代码,属于 plan mode 中应放在评审旁边的技能。若本次评审发现适合探索新方向的视觉问题,推荐 /design-shotgun;若已有批准的 mockup 需要变成可运行的 HTML,推荐 /design-html。

用 AskUserQuestion 呈现下一步,只包含适用选项:A) 先跑 /plan-eng-review(必需门);B) 跑 /plan-ceo-review(仅当发现根本性产品缺口);C) 跑 /design-shotgun——为发现的问题探索视觉变体;D) 跑 /design-html——从批准的 mockup 生成 Pretext 原生 HTML;E) 跳过——我自己处理后续。

小结:把"设计师之眼"变成可执行的工程纪律

回看 plan-design-review/sections/review-sections.md 的全貌,它的价值不在任何单条规则,而在于把设计评审拆成了一整套可验证的契约:7 轮各有明确评分问题与"FIX TO 10"动作、每轮 STOP 点强制 AskUserQuestion(反捷径条款从机制上堵死"把发现直接写进计划"的捷径);Pass 4 的三套规则集 + 7 条硬拒 + 7 条试金石 + 11 项黑名单,把"AI 泔水"从审美争论变成了可逐条打勾的检查表;Implementation Tasks 的 jq JSONL 产物让评审结果能被 /autoplan 聚合;gstack-review-log/gstack-review-read 加上 wtree 内容指纹让"评审是否仍然有效"可被机器判定(并由 test/review-log.test.ts 持续验证);而 ## GSTACK REVIEW REPORT 必须落在计划文件末尾的规则,则让评审状态成为计划文档的常驻部分。

对使用者的实际意义:在装有 gstack 的环境中,对一份含 UI 的计划运行 /plan-design-review,它会先过范围门与 Step 0 评估(0-10 初始评分、DESIGN.md 状态、既有设计复用、重点聚焦区),有 designer 二进制时先生成 mockup 并走对比板反馈循环,再逐轮执行本文覆盖的 7 轮评审与全部收尾产物;对仓库维护者而言,该文本是 review-sections.md.tmpl 的生成产物,修改评审行为应改模板与 scripts/resolvers/ 中的共享 resolver,再运行 bun run gen:skill-docs 重新生成,而不是直接编辑 review-sections.md

登录后查看全文
热门项目推荐
相关项目推荐