mcpField
O
octopus-ui-ux-design

octopus-ui-ux-design

github.com/nyldn设计与 UI4.3k54 次安装今天更新
代码仓库

关于 octopus-ui-ux-design

面向 Codex CLI 的 UI/UX 设计技能,用于研究设计方向并制定设计系统。它要求先进行交互式需求确认和 BM25 搜索,再经过批判审查与修订后提出建议。

主要功能

  1. 01交互式设计需求提问
  2. 02基于 BM25 的设计研究
  3. 03条件允许时并行生成设计方案
  4. 04对抗式审查与修订
  5. 05设计令牌、组件和布局

适用场景

  1. 01根据产品简介确定视觉方向
  2. 02制定设计系统交付内容
  3. 03在实施前审查设计方案

MCP 相关

当用户提供 Figma URL 时,说明中会使用 Figma MCP 工具获取设计上下文和截图。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/nyldn/claude-octopus --skill octopus-ui-ux-design

安装后在 Claude Code 中输入/octopus-ui-ux-design确认已加载。

附带文件agents/openai.yaml

详细介绍

宿主:Codex CLI — 此技能最初为 Claude Code 设计,后适配至 Codex。 交叉引用命令在 Codex 中使用已安装的技能名称,而非 /octo:* 斜杠命令。 使用当前活动的 Codex shell 和子 Agent 工具。在当前会话未提供相应能力前,不要声称可使用某个提供方、模型或宿主子 Agent。 有关宿主工具的对应项,请参阅 skills/blocks/codex-host-adapter.md。

执行约定(强制 — 不可跳过)

**关键:在提出任何设计建议前,必须通过原生 shell 命令工具调用 BM25 搜索引擎(search.py)。不要只依赖自身的设计知识。搜索引擎提供经过整理、由数据驱动的设计情报。若未至少调用 3 次 search.py 就产出设计系统,即违反本约定。**

此技能使用强制执行模式。必须严格遵循以下顺序。

步骤 1:交互式提问(阻塞)

在执行任何其他操作之前,必须调用 AskUserQuestion。

AskUserQuestion({
  questions: [
    {
      question: "What type of product are you designing for?",
      header: "Product Type",
      multiSelect: false,
      options: [
        {label: "SaaS/Dashboard", description: "Analytics, admin panels, B2B tools"},
        {label: "E-commerce", description: "Shopping, marketplace, product pages"},
        {label: "Landing page", description: "Marketing, conversion, product launch"},
        {label: "Mobile app", description: "iOS/Android native or responsive"}
      ]
    },
    {
      question: "What tech stack are you using?",
      header: "Stack",
      multiSelect: false,
      options: [
        {label: "React + Tailwind (Recommended)", description: "React/Next.js with Tailwind CSS"},
        {label: "React + shadcn/ui", description: "React with shadcn component library"},
        {label: "HTML + Tailwind", description: "Static or server-rendered HTML"},
        {label: "Vue/Nuxt", description: "Vue.js or Nuxt framework"}
      ]
    },
    {
      question: "What design deliverables do you need?",
      header: "Deliverables",
      multiSelect: true,
      options: [
        {label: "Design tokens", description: "Colors, spacing, typography as CSS/Tailwind config"},
        {label: "Component specs", description: "Component anatomy, states, props"},
        {label: "Page layouts", description: "Wireframe-level layout specifications"},
        {label: "Style guide", description: "Visual style direction with rationale"}
      ]
    },
    {
      question: "How adventurous should the design be?",
      header: "Dials",
      multiSelect: false,
      options: [
        {label: "Conservative (v3 m2 d4)", description: "Familiar patterns, minimal motion — enterprise, gov, finance"},
        {label: "Balanced (v5 m4 d5)", description: "Contemporary but safe — most SaaS and product work"},
        {label: "Expressive (v7 m6 d5)", description: "Distinctive direction, noticeable motion — marketing, launch pages"},
        {label: "Maximal (v9 m8 d6)", description: "Take real aesthetic risks — portfolios, creative brands"}
      ]
    }
  ]
})

刻度答案会映射为 --variance/--motion/--density 值(上方的 v/m/d),并传递给每次 search.py 调用,同时在设计方向中说明。若用户的需求已经指定了视觉风格(例如“粗野主义”“活泼”或“企业风格”),则跳过刻度问题,并根据该风格推断这三个值。记录推断出的值。若同时有明确的用户答案,则明确答案优先于推断值。否则,照常询问刻度问题。

三个刻度值都必须是 1 到 10 之间的整数。根据指定风格进行推断时,使用以下预设;遇到近义风格时选择最接近的一行,并记录所选行及对应值:

风格线索变化度动效密度
企业 / 企业级 / 保守324
简洁 / 现代 / 均衡545
活泼 / 富有表现力 / 复古765
粗野主义 / 极繁 / 实验性986

每次调用 search.py 前,都必须验证取值范围。如果明确值或推断值缺失、非数字,或不在 1–10 范围内,则停止并获取有效值,不要强行限定到范围内。

步骤 2:显示横幅

强制要求:显示横幅前,必须使用原生 shell 命令工具运行此提供方检查。不要跳过,也不要假设其可用。

bash "${HOME}/.claude-octopus/plugin/scripts/helpers/check-providers.sh"

使用下方的实际结果。禁止只显示“🔵 Claude:可用 ✓”而不列出所有提供方。

🐙 **CLAUDE OCTOPUS ACTIVATED** - UI/UX Design Mode
🎨 Design: [Brief description from user prompt]

Pipeline:
🔍 Phase 1: Design Research (BM25 search + context detection)
🎯 Phase 2: Design Direction (synthesis + style selection)
🐙 Phase 2b: Design Critique (adversarial review before committing)
🛠️ Phase 3: Design System (tokens, components, layouts)
✅ Phase 4: Validation (accessibility, handoff specs)

Providers:
🔴 Codex CLI: [Available ✓ / Not installed ✗] — Implementation critique
🟡 Antigravity CLI: [Available ✓ / Not installed ✗] — Ecosystem critique
🧭 Antigravity CLI: [Available ✓ / Not installed ✗] — Additional external-model challenge
🔵 Claude (Sonnet): Available ✓ — Design + independent critique

Tools:
🔍 BM25 Design Intelligence: [checking...]
🎨 Figma MCP: [Available / Not configured]
🧩 shadcn MCP: [Available / Not configured]
步骤 3:检查设计情报
SEARCH_PY="${HOME}/.claude-octopus/plugin/vendors/ui-ux-pro-max-skill/src/ui-ux-pro-max/scripts/search.py"
if [ -f "$SEARCH_PY" ]; then
    python3 -c "import csv, re, math" 2>/dev/null && echo "READY" || echo "MISSING_PYTHON"
else
    echo "MISSING_SEARCH_PY"
fi

如果为 MISSING_SEARCH_PY:随附的设计情报文件缺失——告知用户重新安装或更新插件(vendors/ui-ux-pro-max-skill/ 目录以纯文件形式随插件提供)。 如果为 MISSING_PYTHON:告知用户设计情报需要 python3。

报告相应的解决方法后,以上两种缺失状态都会终止此工作流。只有预检结果为 READY 时,才能继续步骤 4。

步骤 4:阶段 1 — 探索(设计调研)

必须执行以下搜索中的至少 3 项,不可跳过。

SEARCH_PY="${HOME}/.claude-octopus/plugin/vendors/ui-ux-pro-max-skill/src/ui-ux-pro-max/scripts/search.py"

# 1. Product type search — what design patterns fit this product?
python3 "$SEARCH_PY" "<user's product description>" --domain product

# 2. Style search — what visual styles match?
python3 "$SEARCH_PY" "<user's aesthetic or product type>" --domain style

# 3. Color palette search — data-driven palette selection
python3 "$SEARCH_PY" "<user's product type or mood>" --domain color

# 4. Typography search — font pairings
python3 "$SEARCH_PY" "<user's product type>" --domain typography

# 5. UX guidelines search — relevant best practices
python3 "$SEARCH_PY" "<key user flow>" --domain ux

# 6. Stack-specific search (if user specified a stack)
python3 "$SEARCH_PY" "<user's requirements>" --stack <stack>

# 7. Full design-system draft with the dials from Step 1 (v2.11.0+)
python3 "$SEARCH_PY" "<user's product description>" --design-system \
  --variance <v> --motion <m> --density <d>

如果用户提供了 Figma URL,还要获取设计上下文:

  • 使用 Figma MCP 的 get_design_context 获取现有设计
  • 使用 get_screenshot 获取视觉参考

收集所有搜索结果后,再进入阶段 2。

STEP 4b:设计霰弹模式(有 3 个或更多可用提供方时自动启用)

当第 2 步的提供方检查检测到 3 个或更多可用提供方时(始终将 Claude 计为可用),此步骤会自动运行。 可用提供方少于 3 个时,跳到第 5 步并使用标准单方向模式。

将同一份设计简报并行分发给多个提供方。每个提供方独立生成一个设计方向,且不会看到其他提供方的成果。

使用宿主的子 Agent 工具并行启动 3 个或更多变体 Agent,并启用 background execution: true:

每个 Agent 接收:

Design a visual direction for: [user's product description]
Product type: [from Step 1]
Stack: [from Step 1]
Search context: [key findings from Step 4 BM25 searches]

Produce:
1. A style name (2-3 words, e.g., "Warm Minimalism", "Bold Industrial", "Cobalt Editorial")
2. Primary color palette (3-5 colors with hex values)
3. Font pairing (heading + body)
4. Layout philosophy (e.g., "generous whitespace with card-based content")
5. One paragraph describing the overall feel

Be distinctive — take a clear position rather than playing it safe.

Hard constraints (see skills/blocks/design-taste.md): do NOT produce any of the three
AI-slop looks (cream+serif+terracotta, near-black+acid accent, purple-violet gradients),
and do not default to Inter, Roboto, Space Grotesk, Fraunces, or Instrument Serif
without a brief-tied reason.

分发给不同的提供方,以实现最大程度的多样性:

  • 🔴 Codex:注重实现实用性的方向(哪些方案能快速构建并扩展)
  • 🧭 Antigravity:紧跟趋势的方向(设计生态中当下流行什么)
  • 🔵 Claude:以用户为中心的方向(什么最能服务目标受众)
  • 🟤 OpenCode / 🟢 Copilot / 🟣 Qwen:如有可用,可提供更多变体

所有变体返回后,将每份完整返回结果与对应的提供方绑定。 将提供方记录为 VARIANT_A_PROVIDER、VARIANT_B_PROVIDER 和 VARIANT_C_PROVIDER,并将对应的完整输出记录为 VARIANT_A_RESULT、VARIANT_B_RESULT 和 VARIANT_C_RESULT。每份结果都必须包含返回的风格名称、调色板、字体、布局理念和整体感受。如果缺少某个字段,请让对应的 Agent 补全结果;不要编造或替换为示例内容。使用这些实际值展示对比板:

🎨 **Design Shotgun — 3 Variants**

━━━ Variant A (${VARIANT_A_PROVIDER}) ━━━
${VARIANT_A_RESULT}

━━━ Variant B (${VARIANT_B_PROVIDER}) ━━━
${VARIANT_B_RESULT}

━━━ Variant C (${VARIANT_C_PROVIDER}) ━━━
${VARIANT_C_RESULT}

然后请用户选择:

AskUserQuestion({
  questions: [{
    question: "Which design direction do you prefer?",
    header: "Pick",
    multiSelect: false,
    options: [
      {label: "Variant A", description: "[style name] — [one-line feel]"},
      {label: "Variant B", description: "[style name] — [one-line feel]"},
      {label: "Variant C", description: "[style name] — [one-line feel]"},
      {label: "Mix & match", description: "Take elements from multiple variants"}
    ]
  }]
})

选择完成后,使用选定的变体作为设计方向继续第 5 步。 如果用户选择“混搭”,请先询问要组合哪些元素,再继续。

STEP 5:阶段 2 — 定义(设计方向)

将搜索结果(以及霰弹模式下选定的变体)综合为设计方向文档:

  1. 风格建议 — 哪种视觉风格最适合该产品(引用搜索结果)
  2. 调色板 — 选定的调色板,包含十六进制值和对比度
  3. 排版 — 标题与正文字体搭配,并附上 Google Fonts 导入语句
  4. 布局方案 — 网格系统、间距比例、响应式策略
  5. 设计原则 — 根据 UX 搜索结果总结出的 3-5 条指导原则
  6. 品味规范 — 用一句话确认该方向符合 skills/blocks/design-taste.md(不属于三种禁用风格;不使用缺乏合理依据的禁用默认字体;将大胆设计集中在一处)

输出:将设计方向写成结构化章节,供下一步参考。

STEP 5b:设计评审 — 三方对抗式评审(强制)

此步骤默认运行。 在确定设计方向之前,必须经受最多三种独立视角的对抗式评审。这有助于在问题固化到令牌和组件之前,发现无障碍设计缺陷、不切实际的选择以及 BM25 的盲点。

评审提示词(发送给所有参与者):

Review this proposed design direction and find problems. Be adversarial — your job is to catch flaws, not validate choices.

[The full design direction from Step 5]

Critique dimensions:
1. ACCESSIBILITY — Do the proposed colors meet WCAG AA contrast ratios (4.5:1 text, 3:1 large text)? Are the font sizes readable at the proposed scale? Are touch targets viable?
2. PRACTICALITY — Does this typography actually render well on the stated tech stack? Are the fonts available and performant (file size, loading)? Does the spacing scale work with the layout system?
3. FIT — Does the visual style actually match the product type and audience? Would a user of [product type] feel comfortable with this aesthetic?
4. GAPS — What did the research miss? Are there common UX patterns for this product type that aren't addressed? Are there competitive norms being ignored?
5. SLOP — Run the checklist in skills/blocks/design-taste.md. Is this one of the three AI-slop looks (cream+serif+terracotta, near-black+acid, purple gradients)? Banned default fonts without a stated reason? Would another model given the same brief land on the same palette and fonts? Two or more checklist misses fail the direction.

For each issue found, state: what's wrong, why it matters, and what to do instead.

三位参与者,并行运行:

# Check provider availability
providers=()
command -v codex >/dev/null 2>&1 && providers+=(codex)
command -v agy >/dev/null 2>&1 && providers+=(agy)

for provider in "${providers[@]}"; do
    safe_provider=$(printf '%s' "$provider" | tr -c '[:alnum:]_-' '_')
    "${HOME}/.claude-octopus/plugin/scripts/orchestrate.sh" spawn "$provider" \
      "<critique prompt>" > "/tmp/design-critique-${safe_provider}.md" &
done

wait

🔵 Claude (Sonnet) — 独立设计评审。 你还必须撰写自己的对抗式评审。不要只是总结外部提供方的意见。把设计方向当作不是自己创建的方案来审视——主动从全部五个维度寻找问题。这是你的独立综合视角,与 /octo:debate 中相同。

显示所有评审,并标明提供方:

🔴/🧭/🟡 **External Provider Critique:** [implementation, ecosystem, accessibility, and alternative approach concerns]
🔵 **Claude Critique:** [design concerns — accessibility gaps, fit issues, missing patterns]

如果只有 1–2 个提供方可用,就使用现有资源进行评审。即使只有 Claude 进行评审(最低配置)也很有价值,因为你明确地从“做出这些选择的设计师”切换为“发现问题的评审者”。

收集所有评审后,进行综合并修改:

  1. 分类问题 — 按严重程度分组(必须修复、应当修复、已知取舍)
  2. 修复必须修复的问题 — 调整颜色以改善对比度、换掉不实用的字体、补充缺失的模式
  3. 处理应当修复的问题 — 在可行的情况下纳入,并说明暂缓处理的理由
  4. 记录取舍 — 记录尽管收到评审意见仍决定保留的内容及其原因
  5. 展示差异 — 展示原始方向与修订后方向之间的变化:
📋 **Design Direction Revisions:**
- [Changed] Primary blue #2563EB → #1D4ED8 (contrast ratio 4.2:1 → 5.8:1, per external critique)
- [Added] Fallback font stack for body text (per external critique)
- [Kept] Glassmorphism style despite provider concern — appropriate for SaaS dashboard audience

修订后的设计方向将用于第 3 阶段。不得在未经评审的情况下继续。

STEP 6:第 3 阶段 — 开发(设计系统)

根据用户要求交付的内容生成设计系统:

设计令牌(如有要求):

  • CSS 自定义属性或 Tailwind 配置
  • 颜色阶(50–950)
  • 间距阶(以 4px 为基准)
  • 带行高的排版阶
  • 阴影、圆角和过渡令牌

组件规范(如有要求):

  • 组件结构图(ASCII)
  • 属性/变体表
  • 状态变体(默认、悬停、激活、禁用、错误、加载中)
  • 无障碍要求(ARIA、键盘、焦点)

页面布局(如有要求):

  • 基于网格的布局及响应式断点
  • 内容层级和视觉流
  • 首屏内容策略
  • 导航和交互模式

风格指南(如有要求):

  • 结合搜索结果证据说明视觉风格的依据
  • 带示例的注意事项和禁忌
  • 图标和插图指南
  • 动效原则

如果 shadcn MCP 可用,请搜索匹配的组件:

// Search shadcn registries for components matching the design system
mcp__shadcn__search_items_in_registries({ query: "<component name>" })
STEP 7:第 4 阶段 — 交付(验证)
  1. 无障碍审计 — 运行检查器,不要凭目测判断。 令牌集中的每一组文本/背景配色都必须通过对比度验证器检查:
python3 "${HOME}/.claude-octopus/plugin/scripts/helpers/contrast-check.py" \
  '<text-hex>:<bg-hex>' '<heading-hex>:<bg-hex>:large' '<muted-hex>:<bg-hex>' ...

退出码 1 表示至少有一组配色未达到 WCAG AA 标准——修正配色方案,并在交付前重新运行。将检查器输出作为证据纳入最终文档。

  1. 粗制滥造检查 — 按照 skills/blocks/design-taste.md 中的发布前检查清单执行;如果有两项或以上未通过,必须在交付前修订
  2. 完整性检查 — 确认所有要求的交付内容均已提供
  3. 实现就绪度 — 确认规范足够详细,便于前端开发者实施
  4. 推送到 Figma(如已连接)— 提议将设计令牌推送到 Figma
第 7b 步:AI 界面审查(界面会调用模型时)

只要正在设计的功能会向模型发送输入并展示结果,就要执行此步骤;尤其是它随后会根据结果采取行动时。样式指南和组件规范并未说明 AI 功能必须展示什么、必须允许用户控制什么;本步骤会回答这些问题。对于不涉及模型的界面,完全跳过此步骤。

逐一提出每个问题,并记录明确的答案。“不适用”是有效答案;不作答则不是。

1. 不确定性。 界面是否区分了有把握的答案和猜测?如果无法区分,就应明确说明,而不是暗示结果始终同样可靠。不要凭空设定数值阈值——应选择底层系统确实能够支持的表达方式。

2. 来源。 用户能否看到答案是依据什么得出的?检索和搜索功能需要引用来源;摘要功能需要展示被摘要的来源。没有可追溯来源的答案无法审核。

3. 中断。 如果输出会逐步生成,或任务运行时间较长,是否提供取消操作?取消操作是否真的会停止工作,而不只是将其隐藏?停止按钮如果只是放弃显示仍在运行的任务,就比没有按钮更糟,因为它会错误地反映系统状态。

4. 审核关卡。 人类应在哪里检查输出?这一位置是否至关重要?在不可逆操作后设置关卡,只是装饰。skill-intent-contract 已分别了解主动性、控制权和决策权——在此处复用这些答案,无需重新推导;如果这些答案与关卡位置不一致,应以契约为准。

5. 故障与降级。 模型响应缓慢、不可用、受速率限制或返回无法使用的内容时,界面会显示什么?每种情况都需要独立的状态。将它们合并为一个通用错误,会让用户学会忽略错误提示。

6. 同意与数据使用。 用户是否知道会发送什么数据、发送到哪里,以及数据是否会被保留?只要输入可能包含他人的数据,就必须说明。

7. 回滚。 如果功能会在现实世界中执行操作——处理文件、发送内容、付款或删除数据——如何撤销?用户是否能在执行操作前看到撤销方式,而不只是操作失败后才看到?

输出要求。 在最终交付的文档中回答以上七项,每项都要写明决定及其理由。如果底层系统无法支持某项要求,以致问题无法回答,应将其记录为发现,而不是留空:无法回答的回滚问题属于设计约束,不是遗漏。

归属说明。 本框架参考了 Brandon Harwood 的 AI Interaction Atlas(ai-interaction.com)。请借鉴,而不要照搬:Atlas 刻意不提供任何阈值——包括置信度界限和延迟预算——在此处自行编造这些数字,会让人误以为它们来自一个并未发布这些数字的来源。说明方向,引用来源,并由产品自行确定具体数值。

步骤 8:呈现结果并持久化

将最终设计系统整理为结构化文档,包含:

  • 执行摘要(风格方向及其依据)
  • 设计令牌(可直接复制粘贴)
  • 组件清单
  • 页面布局
  • 面向开发团队的实现说明
  • 来源(说明每项决策参考了哪些搜索结果)

持久化设计系统,使其在会话结束后仍然保留(约定:skill-design-lineage):

SLUG=$(basename "$(git rev-parse --show-toplevel 2>/dev/null || pwd)")
RAW_BRANCH=$(git branch --show-current 2>/dev/null || true)
REVISION=$(git rev-parse HEAD 2>/dev/null || printf 'unborn')
if [[ -n "$RAW_BRANCH" ]]; then
  BRANCH_KEY=$(printf '%s' "$RAW_BRANCH" | tr '/' '-')
else
  RAW_BRANCH="detached:${REVISION}"
  BRANCH_KEY="detached-${REVISION}"
fi
DATETIME=$(date -u +"%Y%m%d-%H%M%S")
DESIGNS_DIR="${HOME}/.claude-octopus/designs/${SLUG}"
mkdir -p "$DESIGNS_DIR"

# DESIGN_BODY must contain the complete structured design system from this step.
if [[ -z "${DESIGN_BODY:-}" ]]; then
  echo "Design persistence failed: DESIGN_BODY is empty." >&2
  exit 1
fi

# Serialize revision allocation per branch with an OS-managed lock. Closing the
# descriptor releases the lock even after SIGKILL or a process/host crash.
LOCK_DIGEST=""
if command -v sha256sum >/dev/null 2>&1; then
  LOCK_DIGEST=$(printf '%s' "$RAW_BRANCH" | sha256sum | awk '{print $(1)}') || LOCK_DIGEST=""
elif command -v shasum >/dev/null 2>&1; then
  LOCK_DIGEST=$(printf '%s' "$RAW_BRANCH" | shasum -a 256 | awk '{print $(1)}') || LOCK_DIGEST=""
else
  echo "Design persistence failed: no supported SHA-256 utility." >&2
  exit 1
fi
if [[ ! "$LOCK_DIGEST" =~ ^[[:xdigit:]]{64}$ ]]; then
  echo "Design persistence failed: could not derive the branch lock key." >&2
  exit 1
fi
LOCK_FILE="${DESIGNS_DIR}/.${LOCK_DIGEST}.lineage.lock"
LOCK_HELD=false
FILEPATH=""
TEMP_PATH=""
cleanup_design_persistence() {
  [[ -n "${TEMP_PATH:-}" && -f "$TEMP_PATH" ]] && rm -f "$TEMP_PATH"
  [[ -n "${FILEPATH:-}" && -f "$FILEPATH" && ! -s "$FILEPATH" ]] && rm -f "$FILEPATH"
  if [[ "$LOCK_HELD" == true ]]; then
    exec 9>&-
    LOCK_HELD=false
  fi
}
trap cleanup_design_persistence EXIT
trap 'cleanup_design_persistence; exit 1' HUP INT TERM

if ! exec 9>"$LOCK_FILE"; then
  echo "Design persistence failed: could not open the lineage lock." >&2
  exit 1
fi
if command -v flock >/dev/null 2>&1; then
  if flock -n 9; then LOCK_STATUS=0; else LOCK_STATUS=$?; fi
elif command -v lockf >/dev/null 2>&1; then
  if lockf -s -t 0 9; then LOCK_STATUS=0; else LOCK_STATUS=$?; fi
else
  exec 9>&-
  echo "Design persistence failed: no supported file-lock utility (flock or lockf)." >&2
  exit 1
fi
if [[ "$LOCK_STATUS" -ne 0 ]]; then
  exec 9>&-
  echo "Design persistence failed: another revision is being persisted for $RAW_BRANCH." >&2
  exit 1
fi
LOCK_HELD=true

# Discover the newest prior document for this exact branch or detached revision.
PRIOR=""
for candidate in "$DESIGNS_DIR"/*.md; do
  [[ -f "$candidate" ]] || continue
  candidate_branch=$(awk -F ': ' '$(1) == "branch" { print $(2); exit }' "$candidate")
  [[ "$candidate_branch" == "$RAW_BRANCH" ]] || continue
  [[ -z "$PRIOR" || "$candidate" -nt "$PRIOR" ]] && PRIOR="$candidate"
done
SUPERSEDES=""
[[ -n "$PRIOR" ]] && SUPERSEDES=$(basename "$PRIOR")

USER_NAME="${USER:-$(whoami)}"
REVISION_ID="${DATETIME}-$$-${RANDOM}"
FILEPATH="${DESIGNS_DIR}/${USER_NAME}-${BRANCH_KEY}-design-${REVISION_ID}.md"

# Reserve the final name atomically. The timestamp is readable; PID + RANDOM
# prevents same-second runs from choosing the same immutable revision.
if [[ -e "$FILEPATH" ]] || ! (set -o noclobber; : > "$FILEPATH") 2>/dev/null; then
  echo "Design persistence failed: revision target already exists: $FILEPATH" >&2
  exit 1
fi

if [[ -n "$SUPERSEDES" && "$SUPERSEDES" == "$(basename "$FILEPATH")" ]]; then
  rm -f "$FILEPATH"
  echo "Design persistence failed: a revision must not supersede itself." >&2
  exit 1
fi

if ! TEMP_PATH=$(mktemp "${FILEPATH}.tmp.XXXXXX"); then
  echo "Design persistence failed: could not allocate a temporary file." >&2
  exit 1
fi

if ! {
  printf '%s\n' '---'
  printf 'branch: %s\n' "$RAW_BRANCH"
  printf 'user: %s\n' "$USER_NAME"
  printf 'created: %s\n' "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
  printf 'git_revision: %s\n' "$REVISION"
  [[ -n "$SUPERSEDES" ]] && printf 'supersedes: %s\n' "$SUPERSEDES"
  printf '%s\n\n' '---'
  printf '%s\n' "$DESIGN_BODY"
} > "$TEMP_PATH"; then
  echo "Design persistence failed: could not write complete temporary document." >&2
  exit 1
fi

if [[ ! -s "$TEMP_PATH" ]]; then
  echo "Design persistence failed: temporary document is missing or empty." >&2
  exit 1
fi

PUBLISHED_PATH="$FILEPATH"
if ! mv "$TEMP_PATH" "$FILEPATH"; then
  echo "Design persistence failed: could not publish $FILEPATH." >&2
  exit 1
fi
TEMP_PATH=""
FILEPATH=""
exec 9>&-
LOCK_HELD=false
trap - EXIT HUP INT TERM
printf 'Persisted design: %s\n' "$PUBLISHED_PATH"

后续会话(以及 flow-develop / frontend-developer 交接)在选择最新版本前,必须筛选 ~/.claude-octopus/designs/<slug>/,只保留 branch: 与当前 Git 分支匹配的文档。在分离 HEAD 状态下,使用 detached:<full-commit> 作为分支值,并且只选择与该确切版本匹配的文档。 仅在筛选后的文档中遵循 supersedes。新版本会取代而非编辑先前的文档。

提供后续步骤:

  • “要我实现这些规格吗?” → 移交给 frontend-developer persona
  • “要调整配色方案吗?” → 使用调整后的查询重新进行颜色搜索
  • “要执行完整的 embrace 工作流吗?” → 转至 /octo:embrace

评论

支持 Markdown