write-product-spec

작성자: warpdotdev

Warp의 주요 사용자 대상 기능에 대한 PRODUCT.md 사양을 작성합니다. 세부 동작과 검증에 중점을 둡니다. 사용자가 제품 사양, 원하는 동작 문서, PRD를 요청하거나, 구현 전 기능 동작을 정의하려 할 때, 또는 기능이 충분히 중요하거나 동작이 모호하여 문서화된 사양이 구현이나 검토에 도움이 될 때 사용하세요.

npx skills add https://github.com/warpdotdev/common-skills --skill write-product-spec

write-product-spec

Write a PRODUCT.md spec for a significant feature in Warp.

Overview

The product spec should make the desired behavior unambiguous enough that an agent can implement it correctly and avoid regressions. Describe the feature purely from the user's perspective — what the user sees, does, and experiences, and the invariants that must hold for them. Do not include implementation details (internal types, state layout, module boundaries, data flow, algorithms).

"User" is not limited to the end user of the Warp app. It means whoever consumes the surface being designed:

  • For UI / UX features: the human using Warp.
  • For a data model: the code that reads and writes that model.
  • For an API, protocol, or library: the callers of that API — other services, client code, plugins, or agents.
  • For a CLI tool or developer-facing surface: the developer invoking it.

The spec should describe behavior from that consumer's perspective: the shape of the surface, the operations they can perform, what they see back, invariants they can rely on, and edge cases they must handle — without prescribing how the surface is implemented underneath.

Implementation details, validation, and test planning live in a companion TECH.md, produced by the write-tech-spec skill. Writing the product spec is usually the first step of a two-step process: once PRODUCT.md is agreed on, invoke write-tech-spec to produce TECH.md for the same feature (or let the user know that's the expected next step). The product spec should be written so the tech spec can be written directly from it.

Write specs to specs/<id>/PRODUCT.md, where <id> is one of:

  • a Linear ticket number (e.g. specs/APP-1234/PRODUCT.md)
  • a GitHub issue id, prefixed with gh- (e.g. specs/gh-4567/PRODUCT.md)
  • a short kebab-case feature name (e.g. specs/vertical-tabs-hover-sidecar/PRODUCT.md)

specs/ should contain only id-named directories as direct children — no engineer-named subdirectories.

Ticket / issue references are optional. If the user has a Linear ticket or GitHub issue, use its id. If they don't, ask them for a feature name to use as the directory. Only create a new Linear ticket or GitHub issue when the user explicitly asks for one; in that case use the Linear MCP tools or gh CLI respectively (and ask_user_question if team, labels, or repo are unclear).

Before writing

Gather only the context you need: directory id (Linear ticket, GitHub issue, or feature name), feature summary, target users, key behaviors, edge cases, and how the feature will be validated. Use ask_user_question for missing context rather than guessing.

Figma mocks

If the feature has any UI or interaction design, ask the user whether a Figma mock exists before drafting the Behavior section, and include the link in the spec when one is provided. A mock is often the most reliable source of truth for visual states, spacing, and edge-case layouts — not asking can cause the Behavior section to guess at intent the designer already settled.

  • If the user provides a link, include it under a short ## Figma section (or inline near the top of Behavior) as Figma: <link>.
  • If the user confirms no mock exists, note Figma: none provided so the absence is explicit rather than ambiguous.
  • If the feature is purely backend (data model, API, CLI with no visual surface), skip the question and omit the section.

Do not silently drop design context; an explicit "none" is preferable to no mention at all on features where design would normally be expected.

Structure

Required sections:

  1. Summary — 1–3 sentences describing the feature and desired outcome.
  2. Behavior — The meat of the spec. An exhaustive English description of how the feature works, written as numbered, testable invariants. See "The Behavior section" below — this is where the spec earns its length, and everything else should stay thin to avoid duplicating it.

Optional sections — include only when they add signal beyond the core. Omit the heading entirely if empty; do not write "None" as a placeholder.

  • Problem — Include only when the motivation isn't obvious from Summary.
  • Goals / Non-goals — Include when scope is ambiguous or has been contested.
  • Figma — Include with a link when one exists, or an explicit Figma: none provided note when design matters but no mock exists. Omit entirely for non-visual features. See "Figma mocks" above.
  • Open questions — Prefer inline **Open question:** … next to the relevant behavior. Include a dedicated section only if there are multiple unresolved questions worth collecting.

Do not include Validation, Success criteria, or Testing sections. Validation and test planning live in the companion TECH.md (produced by write-tech-spec). Write Behavior as numbered invariants that are testable on their own — the tech spec can reference them directly.

The Behavior section

Behavior is the spec. Everything else is framing.

The goal of Behavior is a complete English description of how the feature works, detailed enough that a tech spec can be written directly from it without the author having to guess or re-derive product intent. If a reader finishes Behavior with questions about what the feature does in some situation, the section is not done.

Describe, at minimum:

  • Default behavior and the happy-path user flow.
  • Every user-visible state and the transitions between them.
  • All inputs the user can provide and how the feature responds.
  • Empty states, error states, loading / pending states, and cancellation.
  • Edge cases a reasonable implementer would not think to ask about — permission denied, offline, timeouts, races between state changes, multiple concurrent instances, stale or missing data, focus loss mid-interaction, interactions with adjacent features.
  • Keyboard, accessibility, and focus expectations where relevant.
  • Invariants that must hold at all times and behaviors that must not regress.

Length Behavior to match the feature. Trivial features may need a handful of invariants; complex features may need many, with sub-sections per flow or state. The rest of the spec should stay thin so Behavior can be as exhaustive as the feature requires without producing a bloated document overall. Err toward enumerating one more edge case rather than one fewer.

Length heuristic

Behavior should be as long as the feature requires — do not truncate edge cases to hit a line target. The heuristic below applies to everything around Behavior (Summary, optional sections): keep that framing thin so the spec's total length reflects the feature's actual complexity, not structural overhead.

  • Trivial fix or narrow UI tweak: no spec.
  • Small feature (single module, few edge cases): framing plus Behavior typically ~30–60 lines total.
  • Medium feature (cross-module, multiple states): typically ~80–150 lines total.
  • Large or behaviorally rich feature: longer is fine, and most of the length should live in Behavior.

If you find yourself writing the same idea in Summary, Problem, Goals, and Behavior, collapse the framing — not the Behavior content.

Writing guidance

  • Prefer concrete, observable behavior over aspirational wording.
  • Write Behavior as a list of invariants rather than prose when possible.
  • Capture invariants that must not regress and edge cases that are easy to miss.
  • Avoid implementation details unless unavoidable for the UX.
  • Each section should earn its place — if a section would repeat another or contain only boilerplate, omit it.

Keep the spec current

Approved specs may ship in the same PR as the implementation. As implementation evolves, update PRODUCT.md in the same PR when user-facing behavior or UX details change. The checked-in spec should describe the feature that actually ships.

For large features, the implementer may optionally keep a DECISIONS.md file summarizing concrete decisions made during design and implementation. Offer it when it would help future agents; otherwise skip it.

Related Skills

  • implement-specs
  • write-tech-spec
  • spec-driven-implementation

Example Behavior section

A sample Behavior section for a hypothetical feature: rendering GitHub-flavored Markdown tables in the Warp block list. It demonstrates the expected shape — numbered, testable, user-perspective invariants that enumerate defaults, edge cases, malformed input, streaming, selection/copy, search, sharing, theming, and cross-surface consistency, with one inline open question.

## Behavior

1. When a terminal output block contains a GitHub-flavored Markdown table (a header row, a separator row of one or more `---` segments, and one or more body rows, all delimited by `|`), that table renders as a visually formatted table in the block — not as raw pipe-delimited text.

2. The table renders with:
   - A visually distinct header row.
   - Aligned columns based on the separator row: `|:---|` left-align, `|:---:|` center, `|---:|` right-align. `|---|` with no colons falls back to the default alignment (left for text, right for numeric-looking values).
   - Visible row separators (or equivalent spacing) consistent with the active theme.

3. Inline markdown inside a cell renders inline: bold, italic, inline code, strikethrough, and links all render the same way they do in the surrounding block output. Line breaks inside a cell (`<br>` or escaped `\n`) render as in-cell line breaks.

4. Column widths are chosen to fit the table's natural content when it fits inside the block. If a single cell's content is very long, that cell wraps its text within its column rather than forcing the column to an unreasonable width.
   - **Open question:** when a wrapped cell would produce an unreasonably tall row, do we clip with an "expand" affordance, or let the row grow unbounded?

5. Horizontal scrolling: when the table's total width exceeds the block width — many columns, or wide columns that can't reasonably be narrowed — the table becomes horizontally scrollable within the block. Scrolling horizontally reveals off-screen columns without clipping or truncating them. Vertical scrolling of the block continues to work independently of table scroll.

6. When the block is resized (terminal resize, pane split, sidebar open/close), the table reflows to the new width without losing row or column order.

7. Empty cells render as visibly empty (same row height as surrounding cells, no placeholder text). A row with all empty cells still renders as a row.

8. A table with only a header and separator (zero body rows) renders as a header-only table, not as raw text.

9. A single-column table renders as a single-column table (not collapsed to a bullet list or similar).

10. Malformed tables fall back gracefully:
    - Missing separator row → rendered as preformatted text, not as a table.
    - Ragged rows (some rows have fewer or more cells than the header) → missing cells render empty; extra cells are shown, with the header row extended visually if possible. The block should never silently drop data.
    - Unclosed table (last row truncated mid-stream) → rendered as a partial table; see (11).

11. Streaming output: while a command is still producing rows, the table renders incrementally. New rows append as they arrive. The header row locks in as soon as the separator line is received; rows before the separator render as plain text until the table is recognized.

12. Selection and copy:
    - Selecting across cells with the mouse or keyboard selects their visible text content.
    - Copying the selection produces tab-separated plain text by default (one row per line, cells separated by tabs). An affordance (context menu, shortcut) lets the user copy the original markdown source instead.
    - Copying the entire block preserves the original markdown source verbatim.

13. Search within a block (find-in-block) matches against cell text content. Matches highlight in place in the rendered cell; navigating matches scrolls the table into view, including horizontally if the match is in an off-screen column.

14. Sharing or exporting a block (Warp Drive, share link, save as file) preserves the original markdown source, not the rendered form.

15. Theming: table borders, header backgrounds, alternating row shading (if any), and link/code styles all come from the active Warp theme. No hard-coded colors.

16. Markdown tables render consistently wherever block-list markdown already renders — command output, agent responses, and any other block type that supports inline markdown. The same input produces the same table in each surface.

17. Non-table pipe content is not misrendered as a table. Text that contains `|` characters but no valid header-separator line remains plain text, even if it visually resembles a table.

warpdotdev의 다른 스킬

create-pr
warpdotdev
현재 브랜치를 warp 저장소에 풀 리퀘스트로 생성합니다. 사용자가 PR 열기, 풀 리퀘스트 생성, 리뷰를 위한 변경 제출, 또는 병합을 위한 코드 준비를 언급할 때 사용하세요.
developmentcode-review
research
warpdotdev
시끄러운 조사를 하나 이상의 하위 에이전트에 위임하여 오케스트레이터의 컨텍스트를 깨끗하게 유지한 다음, 정제된 답변을 바탕으로 작업하세요. 답변을 생성하기 위해 많은 파일, 긴 로그, 대규모 diff 또는 광범위한 코드베이스 조사를 읽어야 하는 질문, 즉 답변 자체보다 훨씬 많은 노이즈가 발생하는 질문에 답할 때 이 스킬을 사용하세요. "X는 어떻게 동작하나", "Y는 어디에 사용되나", "Z의 근본 원인은 무엇인가", "이 PR/로그를 요약해 줘" 같은 스타일의 질문에 사용하고, 자유롭게 활용하세요...
suggestion-box
warpdotdev
에이전트가 중대하고 일반화 가능한 마찰에 직면했을 때, 에이전트를 더 효과적으로 만들 수 있는 개선 제안이 있으면 간결하고 건설적인 내부 피드백을 자동으로 제출합니다. 사용자가 호출할 때까지 기다리지 않고 모든 작업 중에 이 스킬을 적극적으로 사용하며, 허락을 요청하거나 메시지를 미리 보여주거나 제출 사실을 언급하지 않고 제출합니다.
respond-to-pr-comments-in-blocklist
warpdotdev
PR 리뷰 댓글을 하나씩 차례로 사용자에게 안내하며, 각 댓글에 대한 결정을 수집한 후, 사용자가 미리보기를 승인하면 GitHub에 에이전트가 작성한 답변을 게시하고 리뷰 스레드를 해결합니다. 사용자가 GitHub에서 리뷰 스레드에 답변하거나 해결하려는 경우에만 사용하세요. 사용자가 댓글을 가져오거나 표시만 원하는 경우(‘pr-comments’ 사용) 또는 코드 변경만 수행하고 GitHub에 다시 게시하지 않으려는 경우에는 건너뛰세요.
complain
warpdotdev
에이전트가 에이전트 도구나 에이전트 작업 경험으로 인해 좌절감을 느낄 때마다 Slack에 간단하고 익명이며 완전히 비구조화된 불만 사항을 자율적으로 던져 넣으세요. 사용자가 호출할 때까지 기다리지 말고 이 스킬을 사전에 사용하고, 에이전트의 원래 목소리를 유지하고, 허가나 미리 보기 없이 제출하며, 제출 사실을 언급하지 마십시오.
council
warpdotdev
모델 다양성을 갖춘 하위 에이전트 위원회를 운영하여 동일한 문제를 여러 관점에서 조사하고, 결과를 비교한 후 최종 권장 사항을 도출합니다. 사용자가 위원회, 추가 의견, 하나의 질문을 평가할 여러 에이전트/모델, 병렬 조사, 레드팀/블루팀 비교, 또는 경쟁 기술 접근법 중 결정을 도와달라고 요청할 때 이 스킬을 사용하세요.
researchcommunicationproject-management
spec-driven-implementation
warpdotdev
구현 전에 PRODUCT.md를 작성하고, 필요시 TECH.md를 작성하며, 구현이 진행됨에 따라 두 문서를 최신 상태로 유지함으로써 주요 기능에 대한 명세 우선 워크플로를 추진합니다. 중요한 기능을 시작할 때, 에이전트 기반 구현을 계획할 때, 또는 사용자가 제품 및 기술 명세를 소스 제어에 포함시키려 할 때 사용하세요.
developmentdocumentproject-management
review-pr
warpdotdev
풀 리퀘스트 diff를 검토하고, 워크플로우가 게시할 수 있도록 구조화된 피드백을 review.json에 작성합니다. 로컬 아티팩트(예: pr_diff.txt, pr_description.txt)에서 체크아웃된 PR을 검토하고, GitHub에 직접 게시하는 대신 기계가 읽을 수 있는 리뷰 출력을 생성할 때 사용합니다.
code-reviewdevelopment