编写一份针对 Warp 中重要用户面向功能的 PRODUCT.md 规范,侧重于详细行为和验证。当用户要求产品规范、期望行为文档或 PRD,希望在实现前定义功能行为,或者功能足够复杂或行为模糊以至于书面规范能改进实现或审查时使用。
write-product-spec
为 Warp 中的重要功能编写 PRODUCT.md 规范。
概述
产品规范应使期望行为足够明确,以便智能体能够正确实现并避免回归。纯粹从用户角度描述功能——用户看到、执行和体验的内容,以及必须保持的不变条件。不要包含实现细节(内部类型、状态布局、模块边界、数据流、算法)。
“用户”不限于 Warp 应用的最终用户。它指代所设计界面的任何消费者:
- 对于 UI/UX 功能:使用 Warp 的人。
- 对于数据模型:读取和写入该模型的代码。
- 对于 API、协议或库:该 API 的调用者——其他服务、客户端代码、插件或智能体。
- 对于 CLI 工具或开发者面向的界面:调用它的开发者。
规范应从该消费者的角度描述行为:界面的形状、可执行的操作、看到的反馈、可依赖的不变条件以及必须处理的边缘情况——而不规定界面在底层如何实现。
实现细节、验证和测试计划位于配套的 TECH.md 中,由 write-tech-spec 技能生成。编写产品规范通常是两步过程的第一步:一旦 PRODUCT.md 达成一致,调用 write-tech-spec 为同一功能生成 TECH.md(或告知用户这是预期的下一步)。产品规范应编写得足够清晰,以便技术规范可以直接基于它编写。
将规范写入 specs/<id>/PRODUCT.md,其中 <id> 是以下之一:
- Linear 工单号(例如
specs/APP-1234/PRODUCT.md) - GitHub issue ID,前缀为
gh-(例如specs/gh-4567/PRODUCT.md) - 短横线命名法(kebab-case)的功能名称(例如
specs/vertical-tabs-hover-sidecar/PRODUCT.md)
specs/ 应仅包含以 ID 命名的目录作为直接子目录——没有以工程师命名的子目录。
工单/issue 引用是可选的。如果用户有 Linear 工单或 GitHub issue,使用其 ID。如果没有,请询问用户一个功能名称作为目录名。仅在用户明确要求时创建新的 Linear 工单或 GitHub issue;在这种情况下,分别使用 Linear MCP 工具或 gh CLI(如果团队、标签或仓库不明确,则使用 ask_user_question)。
编写前
仅收集所需的上下文:目录 ID(Linear 工单、GitHub issue 或功能名称)、功能摘要、目标用户、关键行为、边缘情况以及如何验证功能。使用 ask_user_question 获取缺失的上下文,而不是猜测。
Figma 原型
如果功能有任何 UI 或交互设计,请在起草行为部分之前询问用户是否存在 Figma 原型,并在提供时在规范中包含链接。原型通常是视觉状态、间距和边缘情况布局最可靠的真相来源——不询问可能导致行为部分猜测设计师已确定的意图。
- 如果用户提供链接,将其放在简短的
## Figma部分下(或行为部分顶部附近),格式为Figma: <link>。 - 如果用户确认没有原型,注明
Figma: none provided,以便明确缺失而非模棱两可。 - 如果功能纯粹是后端(数据模型、API、无视觉界面的 CLI),跳过该问题并省略该部分。
不要默默丢弃设计上下文;在通常期望设计的功能上,明确的“无”比完全不提及更好。
结构
必需部分:
- 摘要 — 1–3 句话描述功能和期望结果。
- 行为 — 规范的核心。对功能如何工作的详尽英文描述,以编号的、可测试的不变条件形式编写。请参阅下面的“行为部分”——这是规范体现价值的地方,其他所有内容应保持精简以避免重复。
可选部分——仅当它们提供核心之外的额外信号时才包含。如果为空,则省略标题;不要写“无”作为占位符。
- 问题 — 仅当动机从摘要中不明显时包含。
- 目标/非目标 — 当范围模糊或存在争议时包含。
- Figma — 当存在链接时包含,或当设计重要但无原型时注明
Figma: none provided。对于非视觉功能完全省略。请参阅上面的“Figma 原型”。 - 开放问题 — 优先在相关行为旁边内联使用
**Open question:** …。仅当有多个未解决值得收集的问题时,才包含专门的部分。
不要包含验证、成功标准或测试部分。验证和测试计划位于配套的 TECH.md(由 write-tech-spec 生成)。将行为编写为可独立测试的编号不变条件——技术规范可以直接引用它们。
行为部分
行为是规范的核心。其他所有内容都是框架。
行为的目标是完整描述功能如何工作,详细到技术规范可以直接基于它编写,而无需作者猜测或重新推导产品意图。如果读者读完行为后仍对功能在某些情况下的行为有疑问,则该部分尚未完成。
至少描述:
- 默认行为和正常用户流程。
- 每个用户可见的状态及其之间的转换。
- 用户可提供的所有输入以及功能如何响应。
- 空状态、错误状态、加载/等待状态和取消。
- 合理的实现者不会想到询问的边缘情况——权限拒绝、离线、超时、状态变化之间的竞态、多个并发实例、过时或缺失数据、交互中途失去焦点、与相邻功能的交互。
- 键盘、可访问性和焦点期望(如相关)。
- 必须始终成立的不变条件以及不得回归的行为。
行为长度应与功能匹配。简单的功能可能只需要几个不变条件;复杂的功能可能需要很多,每个流程或状态有子部分。规范的其他部分应保持精简,以便行为可以像功能要求的那样详尽,而不会产生整体臃肿的文档。宁可多列举一个边缘情况,也不要少一个。
长度启发式
行为应如功能所需那样长——不要为了达到行数目标而截断边缘情况。以下启发式适用于行为周围的所有内容(摘要、可选部分):保持框架精简,以便规范的总长度反映功能的实际复杂性,而不是结构开销。
- 简单修复或狭窄的 UI 调整:无需规范。
- 小功能(单个模块,少量边缘情况):框架加行为通常总共约 30–60 行。
- 中等功能(跨模块,多个状态):通常总共约 80–150 行。
- 大型或行为丰富的功能:更长也可以,大部分长度应放在行为中。
如果你发现自己在摘要、问题、目标和行为中重复相同的想法,请压缩框架——而不是行为内容。
编写指导
- 优先使用具体、可观察的行为,而非理想化的措辞。
- 尽可能将行为编写为不变条件列表,而非散文。
- 捕捉不得回归的不变条件和容易遗漏的边缘情况。
- 除非 UX 不可避免,否则避免实现细节。
- 每个部分应证明其存在的价值——如果某个部分会重复另一个部分或仅包含模板内容,则省略它。
保持规范最新
批准的规范可以与实现在同一个 PR 中发布。随着实现的发展,当用户面向行为或 UX 细节发生变化时,在同一个 PR 中更新 PRODUCT.md。签入的规范应描述实际发布的功能。
对于大型功能,实现者可以选择保留一个 DECISIONS.md 文件,总结设计和实现过程中做出的具体决策。当它有助于未来的智能体时提供;否则跳过。
相关技能
implement-specswrite-tech-specspec-driven-implementation
示例行为部分
一个假设功能的示例行为部分:在 Warp 块列表中渲染 GitHub 风格的 Markdown 表格。它展示了预期的形式——编号的、可测试的、用户视角的不变条件,列举了默认值、边缘情况、格式错误的输入、流式传输、选择/复制、搜索、分享、主题和跨表面一致性,并包含一个内联开放问题。
## 行为
1. 当终端输出块包含 GitHub 风格的 Markdown 表格(一个标题行、一个由一或多个 `---` 段组成的分隔行,以及一个或多个正文行,全部由 `|` 分隔)时,该表格在块中渲染为视觉格式化的表格——而不是原始的管道分隔文本。
2. 表格渲染时具有:
- 视觉上不同的标题行。
- 基于分隔行的对齐列:`|:---|` 左对齐,`|:---:|` 居中,`|---:|` 右对齐。没有冒号的 `|---|` 回退到默认对齐(文本左对齐,数值内容右对齐)。
- 与活动主题一致的可见行分隔符(或等效间距)。
3. 单元格内的内联 Markdown 渲染为内联:粗体、斜体、内联代码、删除线和链接的渲染方式与周围块输出中的相同。单元格内的换行(`<br>` 或转义的 `\n`)渲染为单元格内换行。
4. 列宽选择以适应表格的自然内容,当内容适合块内时。如果单个单元格内容非常长,该单元格在其列内换行,而不是强制列达到不合理的宽度。
- **开放问题:** 当换行单元格导致行高不合理时,我们是裁剪并显示“展开”按钮,还是让行无限制增长?
5. 水平滚动:当表格总宽度超过块宽度时——多列或无法合理缩窄的宽列——表格在块内变为水平可滚动。水平滚动显示屏幕外的列,而不裁剪或截断它们。块的垂直滚动独立于表格滚动继续工作。
6. 当块大小调整时(终端调整大小、窗格拆分、侧边栏打开/关闭),表格重新流动到新宽度,而不丢失行或列顺序。
7. 空单元格渲染为视觉上为空(与周围单元格相同的行高,无占位符文本)。所有单元格均为空的行仍渲染为一行。
8. 只有标题和分隔行(零正文行)的表格渲染为仅标题表格,而不是原始文本。
9. 单列表格渲染为单列表格(不会折叠为项目符号列表或类似形式)。
10. 格式错误的表格优雅回退:
- 缺少分隔行 → 渲染为预格式化文本,而不是表格。
- 参差不齐的行(某些行的单元格少于或多于标题)→ 缺失的单元格渲染为空;多余的单元格显示,如果可能,标题行视觉上扩展。块不应静默丢弃数据。
- 未闭合的表格(最后一行在流中截断)→ 渲染为部分表格;参见 (11)。
11. 流式输出:当命令仍在生成行时,表格增量渲染。新行到达时追加。标题行在收到分隔行后立即锁定;分隔行之前的行渲染为纯文本,直到表格被识别。
12. 选择和复制:
- 使用鼠标或键盘跨单元格选择时,选择其可见文本内容。
- 复制选择时,默认生成制表符分隔的纯文本(每行一行,单元格由制表符分隔)。提供一个选项(上下文菜单、快捷键)让用户改为复制原始 Markdown 源。
- 复制整个块时,保留原始 Markdown 源逐字不变。
13. 块内搜索(find-in-block)匹配单元格文本内容。匹配项在渲染的单元格中高亮显示;导航匹配项将表格滚动到视图中,包括水平滚动(如果匹配项在屏幕外的列中)。
14. 分享或导出块(Warp Drive、分享链接、保存为文件)时,保留原始 Markdown 源,而不是渲染形式。
15. 主题:表格边框、标题背景、交替行着色(如有)以及链接/代码样式均来自活动 Warp 主题。无硬编码颜色。
16. Markdown 表格在块列表 Markdown 已渲染的任何地方一致渲染——命令输出、智能体响应以及任何其他支持内联 Markdown 的块类型。相同的输入在每个表面产生相同的表格。
17. 非表格的管道内容不会被误渲染为表格。包含 `|` 字符但没有有效标题-分隔行的文本保持为纯文本,即使它在视觉上类似表格。






