mcpField
S
shaping

shaping

github.com/rjs开发1.4k531 次安装5 周前更新
代码仓库

关于 shaping

这是一套协作方法,用于定义需求、探索解决方案、检查适配度,并将选定设计拆分为实现切片。它适合需要保持不同详细层级规划文档一致的团队。

主要功能

  1. 01迭代整理需求与解决方案
  2. 02通过二元适配检查比较方案
  3. 03细化选定方案的功能与连线
  4. 04将面包板化设计转为实现切片
  5. 05保持不同抽象层级文档的一致

适用场景

  1. 01为明确的问题探索解决方案
  2. 02依据需求比较备选方案
  3. 03将选定设计拆分为实现切片

安装

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

$npx skills add https://github.com/rjs/shaping-skills --skill shaping

安装后在 Claude Code 中输入/shaping确认已加载。

详细介绍

塑造方法论

一种用于协作式定义问题并探索解决方案的结构化方法。


多层级一致性(至关重要)

塑造过程会产出不同抽象层级的文档。各层级之间必须保持事实一致。

文档层级(从高到低)
  1. 塑造文档 — R、方案、组成部分和适配性检查的事实依据
  2. 切片文档 — 切片定义和面包板的事实依据
  3. 各切片计划(V1-plan 等)— 实现细节的事实依据
原则

每个层级都会总结或呈现其下层级的内容。较低层级包含更多细节;较高层级则经过设计,便于快速了解上下文。

变更会双向传递:

  • 高层级变更 → 逐层传递: 如果你修改了塑造文档中的组成部分表格,也要更新切片文档。
  • 低层级变更 → 逐层向上传递: 如果切片计划揭示了新的机制,或改变了某个切片的范围,则切片文档和塑造文档都必须反映这一点。
实践

每次进行变更时:

  1. 确认你正在修改哪个层级
  2. 询问:“这会影响上层或下层文档吗?”
  3. 在同一次操作中更新所有受影响的层级
  4. 绝不让文档彼此脱节

只有各层级彼此保持一致,这套系统才能发挥作用。


开始会话

开启新的塑造会话时,向用户提供两个入口:

  • 从 R(需求)开始 — 描述问题、痛点或约束条件。逐步建立需求,并让方案逐渐显现。
  • 从 S(方案)开始 — 勾勒已有构想的解决方案。将其记录为一个方案,并在过程中提取需求。

没有规定的顺序。塑造是迭代过程 — R 和 S 会始终相互影响。

使用现有的塑造文档

如果塑造文档中已有选定方案:

  1. 仅展示所选方案的适配性检查 — 展示 R × [所选方案](例如 R × F),而不是所有方案
  2. 总结尚未解决的问题 — 指出任何状态为 Undecided 的需求,或所选方案中标记为 ❌ 的需求

这样可以让用户立即了解当前塑造进展以及需要关注的事项。


核心概念

R:需求

一组编号条目,用于定义问题空间。

  • R0、R1、R2…… 是需求集合中的成员
  • 需求通过协作协商确定 — 不会自动填入
  • 跟踪状态:核心目标、待定、倾向是/否、必需、优先考虑、排除
  • 从适配性检查中提取的需求应独立成项(不依赖于任何特定方案)
  • R 表示需要什么,而不是已满足什么 — 是否满足始终通过适配性检查(R × S)展示
  • 分组策略: 顶层需求不得超过 9 项。当 R 超过 9 项时,将相关需求归入组,并拆分为子需求(R3.1、R3.2 等),使顶层需求保持在 9 项或以内。这样便于快速浏览需求,并促成有意义的分组。
S:方案(解决方案选项)

用字母表示互斥的解决方案路径。

  • A、B、C…… 是顶层方案选项(选择其中一个)
  • C1、C2、C3…… 是方案 C 的组成部分/部分(可以组合使用)
  • C3-A、C3-B、C3-C…… 是组成部分 C3 的备选方案(选择其中一个)
方案标题

为方案起一个简短且有描述性的标题,概括其方法。展示方案时,同时显示标题:

## E: Modify CUR in place to follow S-CUR

| Part | Mechanism |
|------|-----------|
| E1 | ... |

好的标题能用几个词概括方案的核心:

  • ✅ “E:原位修改 CUR,使其遵循 S-CUR”
  • ✅ “C:两个数据源搭配混合分页”
  • ❌ “E:解决方案”(过于笼统)
  • ❌ “E:通过替换……为 widget-grid 添加搜索”(过长)
符号层级
层级符号含义关系
需求R0、R1、R2...问题约束属于集合 R
方案形态A、B、C...解决方案选项从 S 中选择一个
组件C1、C2、C3...方案形态的组成部分在方案形态内组合
替代方案C3-A、C3-B...组件的不同做法每个组件选择一个
符号延续

将符号贯穿始终,作为审计轨迹。定稿时,通过引用先前的组件来组合新选项(例如,“方案形态 E = C1 + C2 + C3-A”)。

阶段

方案设计分为两个阶段:

Shaping → Slicing
阶段目的输出
方案设计探索问题和解决方案空间,选择并细化一种方案形态包含 R、方案形态、适配检查和面包板的方案设计文档
切片拆分工作以便实现可演示 UI 的垂直切片
阶段转换

满足以下条件时,从方案设计 → 切片:

  • 已选定一种方案形态(通过适配检查,且感觉合适)
  • 已将方案形态通过面包板细化为具体的交互方式
  • 需要规划实现顺序

没有经过面包板细化的方案形态,就无法进行切片。


适配检查(决策矩阵)

适配检查是一个将所有方案形态与所有需求进行比较的唯一表格。需求作为行,方案形态作为列。我们据此决定要推进哪种方案形态。

格式
## Fit Check

| Req | Requirement | Status | A | B | C |
|-----|-------------|--------|---|---|---|
| R0 | Make items searchable from index page | Core goal | ✅ | ✅ | ✅ |
| R1 | State survives page refresh | Must-have | ✅ | ❌ | ✅ |
| R2 | Back button restores state | Must-have | ❌ | ✅ | ✅ |

**Notes:**
- A fails R2: [brief explanation]
- B fails R1: [brief explanation]
约定
  • 始终显示完整的需求文本——在适配检查中绝不缩写或概括需求
  • 适配检查采用二元判断——通过用 ✅ 表示,未通过用 ❌ 表示。不使用其他值。
  • 方案形态列中只能包含 ✅ 或 ❌——不添加行内说明;解释应放在“备注”部分
  • 适配检查中绝不使用 ⚠️ 或其他符号——⚠️ 仅用于“部件”表中标记的列
  • 备注尽量简短——只解释未通过的情况
比较组件内的替代方案

比较特定组件的替代方案(例如 C3-A 与 C3-B)时,使用相同格式,但范围仅限于该组件:

## C3: Component Name

| Req | Requirement | Status | C3-A | C3-B |
|-----|-------------|--------|------|------|
| R1 | State survives page refresh | Must-have | ✅ | ❌ |
| R2 | Back button restores state | Must-have | ✅ | ✅ |
缺失的需求

如果某种方案形态通过所有检查,但感觉仍不合适,说明缺少一项需求。将隐含约束明确表述为新的 R,然后重新运行适配检查。

宏观适配检查

这是一种独立于标准适配检查的工具,用于在高层级处理分块需求和早期方案形态,此时大多数机制仍标记为 ⚠️。仅在明确要求时使用。

宏观适配检查中,每种方案形态有两列,而不是一列:

  • 是否涉及?——方案形态中的某个部分是否在高层级上回应了这项需求?
  • 是否有答案?——能否追溯到具体做法?机制是否已明确说明?

格式:

## Macro Fit Check: R × A

| Req | Requirement | Addressed? | Answered? |
|-----|-------------|:----------:|:---------:|
| R0 | Core goal description | ✅ | ❌ |
| R1 | Guided workflow | ✅ | ❌ |
| R2 | Agent boundary | ⚠️ | ❌ |

约定:

  • 仅显示顶层需求(R0、R1、R2...),不显示子需求
  • 不设备注列——保持表格精简,便于快速浏览
  • “是否涉及”使用 ✅(是)、⚠️(部分)或 ❌(否)
  • “是否有答案”使用 ✅(是)或 ❌(否)
  • 宏观适配检查后另附一张差距表,列出具体缺失部分及其相关子需求

可执行的操作

这些操作可以按任意顺序进行:

  • 收集 R——随着需求逐渐明确而收集需求
  • 勾勒方案形态——提出高层级的做法(A、B、C...)
  • 细化(组件)——将一种方案形态拆分为组件(B1、B2...)
  • 细化(交互方式)——将选定的方案形态扩展为具体的 UI/非 UI 交互方式和连接关系
  • 探索替代方案——为某个组件确定不同选项(C3-A、C3-B...)
  • 检查适配情况——构建适配检查(决策矩阵),将各选项与 R 进行对照
  • 提取 R——当适配检查揭示隐含需求时,将其作为独立条目加入 R
  • 制作面包板——绘制系统映射图,了解变更发生的位置,并使方案形态更加具体
  • Spike——调查未知事项,找出所需的具体步骤
  • 决策——选择替代方案,组合最终解决方案
  • 切片——将经过面包板细化的方案形态拆分为可实现的垂直切片

沟通

显示完整表格

显示 R(需求)或任何 S(形状)时,始终展示所有行,绝不总结或缩写。完整表格才是交付物;只展示部分内容会丢失信息,并破坏协作流程。

  • 展示所有需求,即使数量很多
  • 展示所有形状部分,包括子部分(E1.1、E1.2……)
  • 展示适配检查中的所有备选方案
这为何重要

塑造是一个协作协商过程。用户需要看到全貌,以便:

  • 发现遗漏的需求
  • 注意到不一致之处
  • 做出明智的决定
  • 跟踪已确定的事项

摘要会隐藏细节,并将控制权从用户手中转移。

用 🟡 标记变更

修改后重新呈现需求表或形状表时,用 🟡 标记每一行变更或新增内容。将 🟡 放在变更单元格内容的开头。这样可以轻松跟进迭代完善,用户无需在脑中对比表格,就能立即发现差异。

调研任务

调研任务是为了了解现有系统的工作方式,以及实现某个组件需要哪些具体步骤。对于机制或可行性存在不确定性的情况,请使用调研任务。

文件管理

始终将调研任务单独保存为一个文件(例如,spike.md 或 spike-[topic].md)。调研任务是独立的调查文档,可以独立于塑造文档分享或处理。

目的
  • 了解相关领域中现有系统的工作方式
  • 明确我们需要做什么才能达成目标
  • 支持对是否继续进行做出明智的决定
  • 不涉及工作量;工作量已隐含在具体步骤中
  • 先调查,再提出方案——了解已有内容;你可能会发现系统已经满足需求
结构
## [Component] Spike: [Title]

### Context
Why we need this investigation. What problem we're solving.

### Goal
What we're trying to learn or identify.

### Questions

| # | Question |
|---|----------|
| **X1-Q1** | Specific question about mechanics |
| **X1-Q2** | Another specific question |

### Acceptance
Spike is complete when all questions are answered and we can describe [the understanding we'll have].
验收指南

验收描述的是我们将获得的信息或理解,而不是结论或决定:

  • ✅ “……我们可以描述用户如何设置语言,以及非英文标题会出现在哪里”
  • ✅ “……我们可以描述实现 [component] 所需的步骤”
  • ❌ “……我们可以回答这是否是阻碍因素”(这是决定,不是信息)
  • ❌ “……我们可以决定是否应该继续”(决定应在调研任务之后做出)

调研任务负责收集信息;之后再根据这些信息做出决定。

问题指南

好的调研问题应询问具体机制:

  • “[X] 逻辑位于哪里?”
  • “需要做哪些改动才能实现 [Y]?”
  • “我们如何 [执行 Z]?”
  • “是否存在会影响 [approach] 的限制?”

避免询问:

  • 工作量估算(“这需要多长时间?”)
  • 模糊的问题(“这很难吗?”)
  • 无法揭示具体机制的是非题

面包板

使用 /breadboarding 技能来绘制现有系统,或将某个形状细化为具体的功能点。面包板会生成:

  • UI 功能点表
  • 非 UI 功能点表
  • 按位置分组的接线图

在以下情况下,请使用面包板:

  • 绘制现有代码,以了解改动会落在哪里
  • 将高层级形状转化为具体功能点
  • 揭示彼此正交的关注点(互相独立的部分)
表格是唯一事实来源

功能点表(UI 和非 UI)定义了面包板。Mermaid 图会将其呈现出来。

收到关于面包板的反馈时:

  1. 首先——更新功能点表(添加、移除或修改功能点,更新 Wires Out)
  2. 然后——更新 Mermaid 图,以反映这些变更

绝不要将图视为主要交付物。变更应从表格流向图,而不是反过来。

CURRENT 是保留的形状名称

使用 CURRENT 描述现有系统。这样可以为理解提议的变更如何融入现有系统提供基线。

形状部分

标记为未知(⚠️)

可以从较高层面描述某个机制,却尚未真正理解它。标记列用于跟踪这一点:

部分机制标记
F1创建 widget(组件、定义、注册)
F2魔术认证处理程序⚠️
  • 空白 = 已理解该机制——我们确切知道如何构建它
  • ⚠️ = 标记为未知——我们已经描述了要做什么,但还不知道怎么做

为什么标记为未知的部分无法通过适配检查:

  1. ✅ 表示声称已掌握——意思是“我们知道这个方案如何满足这项要求”
  2. 满足要求需要一种机制——某个能具体实现该要求的部分
  3. 标记表示我们不知道怎么做——我们描述了想要什么,而不是如何构建
  4. 不能声称自己知道未知之事——因此必须标记为 ❌

适配检查始终是二元的——只能是 ✅ 或 ❌,没有第三种状态。标记为未知的部分在解决之前都算失败。

这一区分了“我们有个草案”和“我们确实知道该怎么做”。早期方案(A、B、C)通常有很多标记部分——探索阶段这样很正常。但选定的方案不应有任何标记(所有 ❌ 都已解决),或者应明确列出用于解决它们的探索任务。

部分必须是机制

方案的各个部分描述的是我们要构建或更改的内容,而不是意图或约束:

  • ✅ “将 childType === 'letter' 路由到 typesenseService.rawSearch()”(机制)
  • ❌ “类型不变”(约束——应归入 R)
避免 R 和 S 之间的同义反复

R 描述需求或约束(需要什么结果)。S 描述实现机制(如何实现)。如果两者说的是同一件事,方案部分就没有提供额外信息。

  • ❌ R17:“管理员可以批量请求成员签署” + C6.3:“管理员可以批量请求成员签署”
  • ✅ R17:“管理员可以将现有成员纳入弃权书跟踪” + C6.3:“批量请求界面支持成员筛选,并批量创建 WaiverRequests”

需求描述所需的能力。方案部分描述提供该能力的具体机制。如果你发现自己在把 R 中的文字复制到 S 中,请停下来——方案部分应具体说明 如何 实现。

各部分应是垂直切片

避免使用“数据模型”这类将所有表归到一起的水平分层。应将数据模型与其支持的功能放在一起:

  • ❌ B4:数据模型——Waivers 表、WaiverSignatures 表、WaiverRequests 表
  • ✅ B1:签署处理程序——包含 WaiverSignatures 表和处理程序逻辑
  • ✅ B5:请求跟踪——包含 WaiverRequests 表和跟踪逻辑

每个部分都应是一个垂直切片,包含机制及其所需的数据。

提取共享逻辑

当同一逻辑出现在多个部分中时,应将其提取为独立部分,供其他部分引用:

  • ❌ 在 B1 和 B2 中重复“签署处理程序:创建 WaiverSignature + 设置布尔值”
  • ✅ 将其提取为 B1:签署处理程序,然后在 B2 和 B3 中注明“→ 调用 B1”
| **B1** | **Signing handler** |
| B1.1 | WaiverSignatures table: memberId, waiverId, signedAt |
| B1.2 | Handler: create WaiverSignature + set member.waiverUpToDate = true |
| **B2** | **Self-serve signing** |
| B2 | Self-serve purchase: click to sign inline → calls B1 |
| **B3** | **POS signing via email** |
| B3.1 | POS purchase: send waiver email |
| B3.2 | Passwordless link to sign → calls B1 |
层级标记法

从扁平标记法开始(E1、E2、E3……)。只有在以下情况下才引入层级(E1.1、E1.2……):

  • 部分太多,难以理解
  • 你正在得出结论,并希望展示结构
  • 对相关机制进行分组有助于沟通
标记法含义
E1方案 E 的顶层组件
E1.1、E1.2E1 的子部分(需要时再添加)

层级分组示例(在方案成熟时使用):

部分机制
E1替换数据源
E1.1修改后端索引器
E1.2将 letters 路由到新服务
E1.3将 posts 路由到新服务
E2添加搜索输入框
E2.1添加带防抖的输入框

细化方案

选定方案后,可以将其展开为具体的实现手段。这称为细化。

标记法

使用“Detail X”(而不是新字母),以表明这是对方案 X 的分解,而非替代方案:

## A: First approach
(shape table)

## B: Second approach
(shape table)

## Detail B: Concrete affordances
(affordance tables + wiring)
细化的产出

使用 /breadboarding 技能来产出:

  • UI 交互元素表 — 用户可以看到并与之交互的内容(输入框、按钮、显示内容)
  • 非 UI 交互元素表 — 数据存储、处理程序、查询、服务
  • 连接图 — 展示各处交互元素如何连接
为什么用“细化 X”而不是“C”

形状字母(A、B、C……)代表互斥的备选方案——你需要从中选一个。细化并非备选方案,而是对已选形状进行更深入的拆解。使用新字母会错误地暗示它是一个并列选项。

A, B, C = alternatives (pick one)
Detail B = expansion of B (not a choice)

文档

塑形过程最多会产出四份文档。每份文档的作用各不相同:

文档内容用途
框架来源、问题、结果“为什么”——简明扼要,面向利益相关者
塑形文档需求、形状(CURRENT/A/B/...)、交互元素、面包板、适配检查工作文档——在此进行探索和迭代
切片文档切片详情、每个切片的交互元素表、连接图实施计划——如何逐步构建
切片计划V1-plan.md、V2-plan.md 等各切片的独立实施计划
文档生命周期
Frame (problem/outcome)
    ↓
Shaping (explore, detail, breadboard)
    ↓
Slices (plan implementation)

框架可以先行编写——在任何解决方案工作开始前,它会记录“为什么”。其中包含:

  • 来源 — 促成本项工作的原始请求、引述或材料(原文照录)
  • 问题 — 存在哪些故障或痛点(从来源提炼)
  • 结果 — 成功的样子(高层次描述,不限定具体解决方案)
记录来源材料

用户在框定阶段提供来源材料时(用户请求、引述、电子邮件、Slack 消息等),务必在框架文档顶部的“来源”部分原文记录。

## Source

> I'd like to ask again for your thoughts on a user scenario...
>
> Small reminder: at the moment, if I want to keep my country admin rights
> for Russia and Crimea while having Europe Center as my home center...

> [Additional source material added as received]

---

## Problem
...

原因:

  • 来源是事实依据——问题和结果都是解读
  • 保留可能在后续工作中有用的上下文
  • 如果提炼过程有所遗漏,可以重新查看原始请求
  • 框定过程中收到更多来源材料时,可以继续添加

需要记录的情况:

  • 用户粘贴了请求或引述
  • 用户分享了利益相关者的电子邮件或消息
  • 用户描述了别人告诉他们的场景
  • 任何有助于形成框架的原始材料

塑形文档是开展实际工作的地方。所有探索、需求收集、形状比较、面包板设计和适配检查都在此进行。这是 R、形状、组成部分和适配检查的工作文档与事实依据。

切片文档在所选形状完成面包板设计并准备好构建时创建。其中包含切片拆分、每个切片的交互元素表以及详细连接关系。

文件管理
  • 塑形文档:迭代时可随时更新——这是事实依据
  • 切片文档:准备好切片时创建,并在切片范围明确后更新
  • 切片计划:各自独立的文件(V1-plan.md 等),包含实施细节
Frontmatter

每份塑形文档(塑形文档、框架、切片文档)的 YAML frontmatter 都必须包含 shaping: true。这会启用工具钩子(例如 ripple-check 提醒),帮助维护文档间的一致性。

---
shaping: true
---

# [Feature Name] — Shaping
...
保持文档同步

请参阅本文档顶部的多层级一致性。任何层级的变更都必须向上传递至受影响的层级,并向下传递。

切片

完成形状的面包板设计后,将其切分为垂直实现增量。使用 /breadboarding 技能进行切片——该技能定义了什么是垂直切片、创建步骤以及可视化格式。

流程:

  1. 组成部分 → 形状中的高级机制
  2. 面包板设计 → 带连线的具体操作能力(使用 /breadboarding)
  3. 切片 → 每个都可演示的垂直增量(使用 /breadboarding 的切片部分)

关键原则: 每个切片都必须以可演示的 UI 告终。没有可见输出的切片是水平层,而非垂直切片。

文档产出:

  • 切片文档 — 切片定义、每个切片的操作能力表、切片后的面包板
  • 切片计划 — 单独的实现计划(V1-plan.md、V2-plan.md 等)

示例

用户正在设计一项搜索功能:

---
shaping: true
---

## Requirements (R)

| ID | Requirement | Status |
|----|-------------|--------|
| R0 | Make items searchable from index page | Core goal |
| R1 | State survives page refresh | Undecided |
| R2 | Back button restores state | Undecided |

---

## C2: State Persistence

| Req | Requirement | Status | C2-A | C2-B | C2-C |
|-----|-------------|--------|------|------|------|
| R0 | Make items searchable from index page | Core goal | — | — | — |
| R1 | State survives page refresh | Undecided | ✅ | ✅ | ❌ |
| R2 | Back button restores state | Undecided | ✅ | ✅ | ✅ |

**Notes:**
- C2-C fails R1: in-memory state lost on refresh
- C2-B satisfies R2 but requires custom popstate handler

评论

支持 Markdown