AI SkillWrite specsProduct & Engineering

When a feature needs specifying, /product-specs-writer drafts the full PRD, so you can move straight to engineering review. — Claude Skill

A Claude Skill for Claude Code by Nick Jensen — run /product-specs-writer in Claude·Updated

Compatible withChatGPT·Claude·Gemini·OpenClaw

Draft PRDs, user stories, acceptance criteria, and technical specs from a brief.

  • Generates PRDs with goals, non-goals, milestones, and success metrics
  • Breaks features into user stories with Gherkin acceptance criteria
  • Produces edge case matrices covering error states and boundary conditions
  • Drafts API endpoint specs with request/response schemas
  • Creates feature flag rollout plans with percentage ramps and kill switches

Who this is for

What it does

PRD from scratch

Give /product-specs-writer a one-paragraph feature idea and get a structured PRD with problem statement, proposed solution, milestones, metrics, and open questions.

User story breakdown

Paste your PRD into /product-specs-writer to get 8-15 user stories with acceptance criteria in Given/When/Then format, grouped by epic.

Edge case analysis

Run /product-specs-writer on a feature spec to produce a matrix of 20+ edge cases covering null inputs, rate limits, concurrent edits, and permission boundaries.

API documentation

Describe your endpoints to /product-specs-writer and receive OpenAPI-style specs with request schemas, response examples, error codes, and auth requirements.

Feature flag plan

Feed /product-specs-writer your rollout context to get a staged flag plan: internal dogfood, 5% canary, 25% beta, 100% GA, with rollback triggers at each stage.

How it works

1

Provide a feature brief, existing doc, or product area you need specified.

2

The skill identifies which spec artifacts are needed — PRD, stories, acceptance criteria, API docs, or flag plans.

3

It generates each artifact with consistent cross-references, linking stories back to PRD goals and acceptance criteria to edge cases.

4

You review, add constraints or context, and re-run to refine until the spec is engineering-ready.

Example

Feature brief
Add a 'schedule send' feature to our email composer. Users pick a date/time, the email queues, and sends at that time. Support timezone selection and cancellation before send.
PRD excerpt
Problem statement
Users in distributed teams compose emails outside recipients' working hours. 34% of surveyed users requested delayed delivery to land in-inbox at optimal times.
User stories
US-1: As a composer, I want to pick a future date and time so my email arrives when the recipient is active.
AC: Given I select a valid future datetime, when I click 'Schedule,' then the email moves to the Scheduled queue with status 'pending.'

US-2: As a composer, I want to cancel a scheduled email before it sends so I can edit or discard it.
AC: Given a scheduled email with status 'pending,' when I click 'Cancel,' then it returns to Drafts and the queue job is deleted.
Edge cases
1. User selects a time in the past → show inline error, keep modal open.
2. Timezone changes between scheduling and send time → use UTC internally, display in user's current tz.
3. Server downtime at scheduled time → retry 3x over 15 min, then notify user.

Works with

Product Specs Writer

Comprehensive product documentation expertise — from strategic PRDs to implementation-ready specifications that engineering teams can actually build from.

Philosophy

Great product specs bridge the gap between vision and execution. They're not bureaucratic documents; they're communication tools that align teams and prevent expensive misunderstandings.

The best product specifications:

  1. Start with the why — Context before requirements
  2. Are testable — Every requirement has clear acceptance criteria
  3. Anticipate questions — Edge cases, errors, and constraints documented upfront
  4. Evolve with the product — Living documents, not static artifacts
  5. Respect the reader — Engineers, designers, and stakeholders can all understand them

How This Skill Works

When invoked, apply the guidelines in rules/ organized by:

  • prd-* — Product Requirements Documents, vision, scope
  • stories-* — User stories, personas, jobs-to-be-done
  • criteria-* — Acceptance criteria, definition of done
  • technical-* — Technical specifications, architecture decisions
  • api-* — API specifications, contracts, versioning
  • edge-* — Edge cases, error handling, failure modes
  • design-* — Design handoff, component specs, interactions
  • rollout-* — Feature flags, rollout plans, experiments
  • metrics-* — Success metrics, KPIs, measurement plans
  • maintenance-* — Documentation lifecycle, versioning, deprecation

Core Frameworks

Specification Hierarchy

┌─────────────────────────────────────────┐
│              VISION                     │  ← Why are we building this?
│         (Problem & Opportunity)         │
├─────────────────────────────────────────┤
│               PRD                       │  ← What are we building?
│      (Requirements & Constraints)       │
├─────────────────────────────────────────┤
│          USER STORIES                   │  ← Who benefits and how?
│       (Personas & Journeys)             │
├─────────────────────────────────────────┤
│      ACCEPTANCE CRITERIA                │  ← How do we know it's done?
│      (Testable Conditions)              │
├─────────────────────────────────────────┤
│      TECHNICAL SPECS                    │  ← How do we build it?
│   (Architecture & Implementation)       │
└─────────────────────────────────────────┘

Document Types by Audience

DocumentPrimary AudiencePurposeUpdate Frequency
PRDLeadership, PM, DesignAlign on what and whyPer milestone
User StoriesEngineering, QADefine scope and valuePer sprint
Acceptance CriteriaQA, EngineeringDefine donePer story
Technical SpecEngineeringDefine howPer feature
API SpecFrontend, External devsDefine contractsPer version
Design HandoffEngineeringDefine UI/UXPer component
Rollout PlanEngineering, OpsDefine deploymentPer release
Success MetricsLeadership, DataDefine successPer quarter

The INVEST Criteria (User Stories)

CriteriaQuestionExample
IndependentCan it be built alone?No dependencies on unfinished stories
NegotiableIs scope flexible?Details can be refined with engineering
ValuableDoes user benefit?Clear value proposition stated
EstimableCan we size it?Enough detail to estimate effort
SmallFits in a sprint?Can be completed in 1-5 days
TestableCan we verify it?Has clear acceptance criteria

Specification Completeness Checklist

PRD Completeness:
├── Problem Statement         □ Clearly defined user pain
├── Success Metrics          □ Measurable outcomes defined
├── User Stories             □ All personas covered
├── Scope                    □ In-scope and out-of-scope clear
├── Constraints              □ Technical and business limits stated
├── Dependencies             □ External dependencies identified
├── Risks                    □ Known risks and mitigations
├── Timeline                 □ Milestones and deadlines set
└── Open Questions           □ Unknowns explicitly listed

Technical Spec Completeness:
├── Architecture             □ System design documented
├── Data Model               □ Schema and relationships defined
├── API Contracts            □ Endpoints and payloads specified
├── Edge Cases               □ Failure modes documented
├── Security                 □ Auth, encryption, compliance covered
├── Performance              □ SLAs and benchmarks defined
├── Monitoring               □ Observability strategy clear
└── Rollback Plan            □ Recovery procedures documented

Error Handling Taxonomy

Error TypeExampleDocumentation Required
ValidationInvalid email formatError message, field highlighting
AuthorizationUser lacks permissionError state, escalation path
ResourceItem not foundEmpty state, recovery action
SystemDatabase timeoutRetry strategy, user feedback
Business LogicInsufficient balanceError explanation, next steps
ExternalThird-party API downFallback behavior, degraded mode

Specification Templates

Minimal PRD Structure

# Feature: [Name]

## Problem
What user problem are we solving?

## Solution
High-level approach (1-2 paragraphs)

## Success Metrics
- Primary: [Metric] from X to Y
- Secondary: [Metric] from X to Y

## User Stories
- As a [user], I want [goal] so that [benefit]

## Scope
**In scope:** [List]
**Out of scope:** [List]

## Open Questions
- [ ] Question 1
- [ ] Question 2

User Story Template

**As a** [persona/user type]
**I want** [capability/action]
**So that** [benefit/value]

**Acceptance Criteria:**
- Given [context], when [action], then [result]
- Given [context], when [action], then [result]

**Edge Cases:**
- What if [edge case]? Then [behavior]

**Out of Scope:**
- [Explicit exclusion]

Anti-Patterns

  • Spec by committee — Over-collaboration produces vague documents
  • Premature optimization — Specifying implementation details too early
  • Missing the why — Requirements without context for decisions
  • Kitchen sink scope — Trying to solve everything in one release
  • One-way documentation — Specs that don't get updated as learnings emerge
  • Assumption blindness — Not documenting implicit assumptions
  • Designer/Engineer telephone — No direct communication, only docs
  • Success theater — Metrics chosen because they're easy, not meaningful
  • Spec as contract — Treating specs as unchangeable legal documents
  • Documentation debt — Outdated specs worse than no specs

Reference documents


title: Section Organization

1. PRD Writing (prd)

Impact: CRITICAL Description: Product Requirements Documents that align stakeholders on vision, scope, and success criteria. The foundation for all downstream specifications.

2. User Stories (stories)

Impact: CRITICAL Description: User-centric requirements that capture who benefits, what they need, and why it matters. The bridge between business goals and engineering work.

3. Acceptance Criteria (criteria)

Impact: CRITICAL Description: Testable conditions that define when a story is complete. The contract between PM, engineering, and QA.

4. Technical Specifications (technical)

Impact: HIGH Description: Architecture decisions, system design, and implementation guidance. How the solution will be built.

5. API Specifications (api)

Impact: HIGH Description: API contracts, request/response formats, versioning, and documentation. The interface between systems and teams.

6. Edge Cases & Error Handling (edge)

Impact: HIGH Description: Failure modes, error states, and exception handling. What happens when things go wrong.

7. Design Handoff (design)

Impact: MEDIUM-HIGH Description: Component specifications, interaction states, and responsive requirements. Translating designs to implementation.

8. Feature Flags & Rollout (rollout)

Impact: MEDIUM-HIGH Description: Progressive rollout strategies, feature flags, experiments, and kill switches. Safe deployment patterns.

9. Success Metrics (metrics)

Impact: HIGH Description: KPIs, measurement plans, and success criteria. How we know if we built the right thing.

10. Documentation Maintenance (maintenance)

Impact: MEDIUM Description: Documentation lifecycle, versioning, deprecation, and update workflows. Keeping specs accurate over time.


title: API Specifications impact: HIGH tags: api, rest, openapi, documentation, contracts

API Specifications

Impact: HIGH

API specs are contracts between services, teams, and external developers. Clear specs prevent integration bugs, reduce back-and-forth, and enable parallel development of frontend and backend.

API Design Principles

  1. Consistency — Same patterns across all endpoints
  2. Predictability — Developers can guess behavior
  3. Discoverability — Self-documenting responses
  4. Evolvability — Can change without breaking clients
  5. Debuggability — Errors help developers fix issues

API Specification Components

ComponentPurposeRequired
EndpointURL path and HTTP methodYes
DescriptionWhat this endpoint doesYes
AuthenticationAuth requirementsYes
RequestHeaders, params, bodyYes
ResponseSuccess and error formatsYes
ExamplesReal request/response samplesYes
Rate LimitsThrottling rulesIf applicable
VersioningAPI version infoYes

Good API Spec Example (OpenAPI Style)

# POST /workspaces/{workspace_id}/invitations
# Create a new workspace invitation

summary: Invite a user to a workspace
description: |
  Sends an invitation email to the specified address. The recipient
  can accept the invitation to join the workspace with the specified
  permission level. Invitations expire after 7 days.

  Requires Owner permission on the workspace.

tags:
  - Workspace Sharing

security:
  - BearerAuth: []

parameters:
  - name: workspace_id
    in: path
    required: true
    description: The unique identifier of the workspace
    schema:
      type: string
      format: uuid
    example: "550e8400-e29b-41d4-a716-446655440000"

requestBody:
  required: true
  content:
    application/json:
      schema:
        type: object
        required:
          - email
          - permission_level
        properties:
          email:
            type: string
            format: email
            description: Email address of the person to invite
            example: "[email protected]"
          permission_level:
            type: string
            enum: [viewer, editor, owner]
            description: Permission level to grant
            example: "editor"
          message:
            type: string
            maxLength: 500
            description: Optional personal message to include in email
            example: "Welcome to the team! Check out our Q4 planning workspace."

responses:
  201:
    description: Invitation created successfully
    content:
      application/json:
        schema:
          type: object
          properties:
            id:
              type: string
              format: uuid
            workspace_id:
              type: string
              format: uuid
            email:
              type: string
            permission_level:
              type: string
            invited_by:
              type: string
              format: uuid
            expires_at:
              type: string
              format: date-time
            created_at:
              type: string
              format: date-time
        example:
          id: "d290f1ee-6c54-4b01-90e6-d701748f0851"
          workspace_id: "550e8400-e29b-41d4-a716-446655440000"
          email: "[email protected]"
          permission_level: "editor"
          invited_by: "7c9e6679-7425-40de-944b-e07fc1f90ae7"
          expires_at: "2024-01-22T10:30:00Z"
          created_at: "2024-01-15T10:30:00Z"

  400:
    description: Invalid request
    content:
      application/json:
        schema:
          $ref: '#/components/schemas/Error'
        examples:
          invalid_email:
            summary: Invalid email format
            value:
              error:
                code: "INVALID_EMAIL"
                message: "The email address format is invalid"
                field: "email"
          workspace_full:
            summary: Workspace at member limit
            value:
              error:
                code: "WORKSPACE_FULL"
                message: "This workspace has reached its member limit (50)"
                limit: 50
                current: 50

  401:
    description: Authentication required
    content:
      application/json:
        schema:
          $ref: '#/components/schemas/Error'
        example:
          error:
            code: "UNAUTHORIZED"
            message: "Authentication token is missing or invalid"

  403:
    description: Permission denied
    content:
      application/json:
        schema:
          $ref: '#/components/schemas/Error'
        example:
          error:
            code: "FORBIDDEN"
            message: "Only workspace owners can send invitations"
            required_permission: "owner"
            your_permission: "editor"

  404:
    description: Workspace not found
    content:
      application/json:
        schema:
          $ref: '#/components/schemas/Error'
        example:
          error:
            code: "WORKSPACE_NOT_FOUND"
            message: "Workspace with ID '550e8400-...' does not exist"

  409:
    description: Conflict - user already invited or member
    content:
      application/json:
        schema:
          $ref: '#/components/schemas/Error'
        examples:
          already_member:
            summary: User is already a member
            value:
              error:
                code: "ALREADY_MEMBER"
                message: "This user is already a workspace member"
                existing_permission: "editor"
          pending_invitation:
            summary: Invitation already pending
            value:
              error:
                code: "INVITATION_PENDING"
                message: "An invitation is already pending for this email"
                invitation_id: "d290f1ee-6c54-4b01-90e6-d701748f0851"
                expires_at: "2024-01-22T10:30:00Z"

  429:
    description: Rate limit exceeded
    content:
      application/json:
        schema:
          $ref: '#/components/schemas/Error'
        example:
          error:
            code: "RATE_LIMITED"
            message: "Invitation limit exceeded. Try again later."
            retry_after: 3600
    headers:
      Retry-After:
        description: Seconds until rate limit resets
        schema:
          type: integer
        example: 3600

x-rate-limit:
  requests: 10
  window: 3600
  scope: workspace

x-changelog:
  - version: "2024-01-15"
    changes:
      - Added optional message field
  - version: "2023-11-01"
    changes:
      - Initial release

Bad API Spec Example

# POST /invite
# Invite user

request:
  email: string
  level: string

response:
  success: boolean

Why it fails:

  • No endpoint description
  • No authentication documented
  • No parameter details or constraints
  • Missing error responses
  • No examples
  • No versioning information
  • Vague response schema

Error Response Standards

Consistent Error Schema:

{
  "error": {
    "code": "MACHINE_READABLE_CODE",
    "message": "Human readable explanation",
    "details": {
      "field": "problematic_field",
      "reason": "Specific validation failure"
    },
    "request_id": "req_abc123",
    "documentation_url": "https://docs.api.com/errors/CODE"
  }
}

Standard Error Codes:

HTTP StatusCodeUse Case
400VALIDATION_ERRORInvalid input
400INVALID_FORMATMalformed JSON, wrong content type
401UNAUTHORIZEDMissing or invalid auth
401TOKEN_EXPIREDAuth token expired
403FORBIDDENValid auth, insufficient permissions
404NOT_FOUNDResource doesn't exist
409CONFLICTResource state conflict
422UNPROCESSABLEValid format, invalid semantics
429RATE_LIMITEDToo many requests
500INTERNAL_ERRORServer-side failure
503SERVICE_UNAVAILABLEMaintenance or overload

API Versioning Strategies

StrategyExampleProsCons
URL path/v1/usersClear, cacheableURL pollution
HeaderAPI-Version: 2024-01Clean URLsLess visible
Query param/users?version=1Easy testingCache issues
Content typeAccept: application/vnd.api.v1+jsonRESTfulComplex

Recommended: URL path versioning for major versions, header-based for minor changes.

Request/Response Examples

List Endpoint Pattern:

// GET /workspaces/{id}/members?limit=20&cursor=abc123

// Response
{
  "data": [
    {
      "id": "user-1",
      "email": "[email protected]",
      "permission_level": "editor",
      "joined_at": "2024-01-10T10:00:00Z"
    },
    {
      "id": "user-2",
      "email": "[email protected]",
      "permission_level": "owner",
      "joined_at": "2024-01-05T08:00:00Z"
    }
  ],
  "pagination": {
    "cursor": "def456",
    "has_more": true,
    "total_count": 47
  }
}

Single Resource Pattern:

// GET /workspaces/{id}

// Response
{
  "data": {
    "id": "workspace-123",
    "name": "Q4 Planning",
    "created_at": "2024-01-01T00:00:00Z",
    "updated_at": "2024-01-15T10:30:00Z",
    "owner": {
      "id": "user-1",
      "email": "[email protected]"
    },
    "member_count": 12,
    "settings": {
      "visibility": "private",
      "allow_guest_access": false
    }
  },
  "_links": {
    "self": "/workspaces/workspace-123",
    "members": "/workspaces/workspace-123/members",
    "invitations": "/workspaces/workspace-123/invitations"
  }
}

Pagination Standards

StyleBest ForExample
CursorLarge datasets, real-time data?cursor=eyJpZCI6MTIzfQ
OffsetStable datasets, jump-to-page?offset=40&limit=20
KeysetOrdered results, efficient DB?after_id=123&limit=20

Always include:

  • Current page indicator
  • Has more indicator
  • Total count (if performant)

API Documentation Checklist

Endpoint Documentation
├── □ HTTP method and path
├── □ Summary (one line)
├── □ Description (detailed)
├── □ Authentication requirements
├── □ Path parameters (with types, constraints)
├── □ Query parameters (with defaults)
├── □ Request body schema
├── □ Response schemas (all status codes)
├── □ Real examples (copy-pasteable)
└── □ Error codes and meanings

API-Wide Documentation
├── □ Authentication guide
├── □ Rate limiting policy
├── □ Versioning policy
├── □ Pagination guide
├── □ Error handling guide
├── □ Changelog
└── □ SDK/client library links

Anti-Patterns

  • Undocumented endpoints — "It's obvious from the code"
  • Example-free specs — Schema without concrete examples
  • Error amnesia — Only documenting 200 responses
  • Version neglect — No versioning strategy until breaking change
  • Inconsistent naminguser_id in one endpoint, userId in another
  • Kitchen sink responses — Returning everything instead of what's needed
  • Chatty APIs — Multiple calls needed for one logical operation
  • Undocumented limits — Rate limits, pagination, max sizes not specified
  • Stale specs — Documentation doesn't match implementation
  • Internal exposure — Leaking implementation details in error messages

title: Acceptance Criteria impact: CRITICAL tags: acceptance-criteria, testing, qa, definition-of-done, gherkin

Acceptance Criteria

Impact: CRITICAL

Acceptance criteria define the contract between PM, engineering, and QA. They answer: "How do we know this story is done?" Without clear criteria, you get endless debates, missed requirements, and rework.

Purpose of Acceptance Criteria

  1. Shared understanding — Everyone agrees what "done" means
  2. Testable conditions — QA can verify each criterion
  3. Scope boundaries — Prevents feature creep during development
  4. Estimation input — Engineers understand complexity upfront

Given-When-Then Format (Gherkin)

The gold standard for testable acceptance criteria:

Given [precondition/context]
When [action/trigger]
Then [expected outcome]

Multiple Conditions:

Given [precondition]
  And [additional precondition]
When [action]
Then [outcome]
  And [additional outcome]
  But [exception/exclusion]

Acceptance Criteria Patterns

PatternUse WhenExample
Happy PathDescribing normal flowUser logs in successfully
Error StateInvalid input/failureWrong password shows error
Edge CaseBoundary conditionsCart with 999 items
PermissionAccess controlAdmin-only action blocked for user
State ChangeBefore/after conditionsDraft → Published
PerformanceSpeed requirementsPage loads in <2 seconds

Good Acceptance Criteria Examples

Feature: Password Reset

Scenario: Successful password reset request
Given I am on the login page
  And I have a registered account with email "[email protected]"
When I click "Forgot Password"
  And I enter my email address
  And I click "Send Reset Link"
Then I see confirmation message "Check your email for reset instructions"
  And I receive an email within 60 seconds
  And the email contains a unique reset link valid for 24 hours

Scenario: Password reset with unregistered email
Given I am on the forgot password page
When I enter an email not in our system
  And I click "Send Reset Link"
Then I see the same confirmation message (security: don't reveal if email exists)
  And no email is sent

Scenario: Password reset link expiration
Given I requested a password reset more than 24 hours ago
When I click the reset link in my email
Then I see "This link has expired"
  And I see option to request a new reset link

Scenario: New password validation
Given I clicked a valid reset link
When I enter a new password
Then the password must be at least 8 characters
  And contain at least one uppercase letter
  And contain at least one number
  And show strength indicator (weak/medium/strong)

Scenario: Successful password change
Given I entered a valid new password
When I click "Reset Password"
Then my password is updated
  And I am logged in automatically
  And I receive confirmation email
  And all other sessions are invalidated

Feature: Shopping Cart

Scenario: Add item to empty cart
Given my cart is empty
When I add a product priced at $25.00
Then my cart shows 1 item
  And the subtotal shows $25.00
  And the cart icon shows badge with "1"

Scenario: Add same item multiple times
Given I have 2 units of "Blue Widget" in my cart
When I add another "Blue Widget"
Then my cart shows 3 units of "Blue Widget"
  And the quantity is consolidated (not separate line items)

Scenario: Add item exceeding inventory
Given a product has 5 units in stock
  And I already have 5 in my cart
When I try to add another
Then I see "Maximum available quantity reached"
  And my cart quantity remains at 5

Scenario: Cart persistence across sessions
Given I am logged in with items in my cart
When I log out and log back in
Then my cart items are preserved
  And quantities match what I had before

Scenario: Price change after adding to cart
Given I added an item priced at $50.00
  And the price later changes to $45.00
When I view my cart
Then I see the current price of $45.00
  And I see "Price reduced from $50.00" notice

Bad Acceptance Criteria Examples

Too Vague:

- User can reset password
- It should be secure
- Good user experience

Why it fails: Not testable. What does "secure" mean? What's "good"?

Too Implementation-Specific:

- When POST /api/auth/reset is called with valid email,
  return 200 and insert row into password_reset_tokens table
  with SHA-256 hashed token

Why it fails: Dictates implementation details. Focus on behavior, not code.

Missing Edge Cases:

Given I enter my email
When I click reset
Then I get an email

Why it fails: What if email invalid? What if not registered? What if rate limited?

Incomplete:

- User can add items to cart

Why it fails: Add how many? What about inventory limits? Does it persist? What feedback do they see?

Acceptance Criteria Checklist

For each user story, ensure criteria cover:

Functional Requirements
├── □ Happy path (normal success flow)
├── □ Validation (input requirements)
├── □ Error states (what can go wrong)
├── □ Edge cases (boundaries, limits)
├── □ Permissions (who can/cannot)
└── □ State transitions (before/after)

Non-Functional Requirements
├── □ Performance (speed, limits)
├── □ Accessibility (screen reader, keyboard)
├── □ Security (auth, data protection)
└── □ Compatibility (browsers, devices)

User Experience
├── □ Feedback (success/error messages)
├── □ Loading states (spinners, skeletons)
└── □ Empty states (no data scenarios)

Acceptance Criteria Table Format

For simpler features, tables can be effective:

Login Validation:

InputExpected Result
Valid email + correct passwordLogin succeeds, redirect to dashboard
Valid email + wrong password"Invalid credentials" error, remain on login
Invalid email format"Please enter valid email" inline error
Empty email"Email is required" inline error
Empty password"Password is required" inline error
Account locked (5+ failed attempts)"Account locked. Reset password or wait 30 min"
Unverified email account"Please verify your email first" + resend option

Definition of Done vs Acceptance Criteria

ConceptScopeExample
Acceptance CriteriaPer story"Given X, when Y, then Z"
Definition of DoneAll storiesCode reviewed, tests pass, docs updated

Definition of Done (team-wide):

□ All acceptance criteria pass
□ Code reviewed and approved
□ Unit tests written (>80% coverage)
□ Integration tests pass
□ No critical/high security issues
□ Accessibility audit pass
□ Documentation updated
□ Deployed to staging
□ PM sign-off

Writing Criteria for Different Story Types

UI/Frontend Stories:

  • Include visual states (loading, error, success, empty)
  • Specify responsive behavior
  • Note animation/transition expectations
  • Reference design specs

API/Backend Stories:

  • Include request/response formats
  • Specify error codes and messages
  • Define rate limits and quotas
  • Note caching behavior

Integration Stories:

  • Define handoff points
  • Specify retry/fallback behavior
  • Document timeout expectations
  • Clarify data format conversions

Anti-Patterns

  • Criteria as requirements — Writing new requirements in AC instead of the story
  • Gold plating — Adding criteria not related to the story
  • Assumption hiding — Criteria that assume shared knowledge ("handles the usual cases")
  • Test case masquerading — Low-level test steps instead of behavior
  • Changing mid-sprint — Adding criteria after development started
  • Checkbox syndrome — Criteria so broad they're always "met" ("it works")
  • Missing negatives — Only happy paths, no error scenarios
  • Copy-paste templates — Same boilerplate criteria on every story

title: Design Handoff Documentation impact: MEDIUM-HIGH tags: design, handoff, ui, ux, components, specifications

Design Handoff Documentation

Impact: MEDIUM-HIGH

Design handoff docs bridge the gap between design files and working code. They translate visual designs into implementable specifications, preventing the "that's not what I meant" rework cycle.

Design Handoff Components

ComponentPurposeWho Creates
Component SpecsIndividual UI element detailsDesigner
Interaction SpecsBehaviors, transitions, animationsDesigner
Responsive SpecsBreakpoints, layout changesDesigner
Content SpecsCopy, microcopy, character limitsProduct/Design
Accessibility SpecsWCAG requirements, screen readerDesigner
Asset HandoffIcons, images, fontsDesigner
Edge State SpecsLoading, empty, error statesProduct/Design

Component Specification Template

## Component: [Name]

### Visual Reference
[Screenshot or Figma link]

### Properties

| Property | Type | Default | Options |
|----------|------|---------|---------|
| variant | string | "primary" | primary, secondary, ghost |
| size | string | "medium" | small, medium, large |
| disabled | boolean | false | - |
| loading | boolean | false | - |
| icon | string | null | icon name or null |
| fullWidth | boolean | false | - |

### Anatomy

[Diagram showing component parts]

| Part | Token/Value | Notes |
|------|-------------|-------|
| Container | padding-x: 16px, padding-y: 8px | |
| Text | font-body-medium | Truncate with ellipsis |
| Icon | 20x20px | Left-aligned, 8px gap |
| Border | 1px solid gray-300 | Only for secondary |

### States

| State | Visual Change | Token |
|-------|---------------|-------|
| Default | - | bg-primary |
| Hover | Darken 10% | bg-primary-hover |
| Active | Darken 20% | bg-primary-active |
| Focus | 2px ring | ring-focus |
| Disabled | 50% opacity | opacity-50 |
| Loading | Spinner replaces text | - |

### Responsive Behavior

| Breakpoint | Behavior |
|------------|----------|
| Mobile (<640px) | Full width, stacked icons |
| Tablet (640-1024px) | Auto width, inline icons |
| Desktop (>1024px) | Fixed width options available |

### Accessibility

- Role: button
- Keyboard: Enter/Space to activate
- Focus: Visible focus ring
- Screen reader: Announce loading state
- Color contrast: Minimum 4.5:1

### Usage Guidelines

**Do:**
- Use primary for main actions
- One primary button per section
- Use loading state for async actions

**Don't:**
- Don't use multiple primary buttons together
- Don't disable without explaining why
- Don't use ghost for important actions

Good Design Handoff Example

# Design Handoff: Workspace Invitation Modal

## Overview
Modal for workspace owners to invite new team members. Appears when
clicking "Invite" button in workspace header.

**Figma:** [Link to designs]
**Prototype:** [Link to prototype]

## Modal Container

| Property | Value | Token |
|----------|-------|-------|
| Width | 480px | - |
| Max Height | 80vh | - |
| Padding | 24px | spacing-6 |
| Border Radius | 12px | radius-lg |
| Background | White | bg-surface |
| Shadow | Large | shadow-lg |
| Backdrop | 50% black | overlay-50 |

### Animation

| Action | Animation |
|--------|-----------|
| Open | Fade in (200ms) + scale from 95% |
| Close | Fade out (150ms) |
| Backdrop click | Close modal |
| Escape key | Close modal |

## Header Section

┌─────────────────────────────────────────┐ │ [Icon] Invite to Workspace [X] │ │ Add team members to "Q4 Planning" │ └─────────────────────────────────────────┘


| Element | Spec |
|---------|------|
| Title | text-lg, font-semibold, gray-900 |
| Subtitle | text-sm, gray-600 |
| Close button | 24x24, gray-500, hover: gray-700 |
| Icon | 20x20, primary color |
| Gap between title/subtitle | 4px |

## Form Section

### Email Input

| Property | Value |
|----------|-------|
| Label | "Email address" |
| Placeholder | "[email protected]" |
| Type | email |
| Validation | Real-time email format |
| Error | Inline, below input |

**States:**
| State | Border | Background | Text |
|-------|--------|------------|------|
| Default | gray-300 | white | gray-900 |
| Focus | primary-500 | white | gray-900 |
| Error | red-500 | red-50 | gray-900 |
| Disabled | gray-200 | gray-50 | gray-500 |

### Permission Dropdown

| Property | Value |
|----------|-------|
| Label | "Permission level" |
| Default | "Editor" |
| Options | Viewer, Editor, Owner |
| Width | Full width |

**Option Display:**

┌─────────────────────────────────┐ │ Editor ▼ │ ├─────────────────────────────────┤ │ Viewer │ │ Can view content │ ├─────────────────────────────────┤ │ Editor ✓ │ │ Can view and edit content │ ├─────────────────────────────────┤ │ Owner │ │ Full access including settings │ └─────────────────────────────────┘


### Optional Message (Collapsed by Default)

| Property | Value |
|----------|-------|
| Toggle | "Add a personal message" link |
| Textarea | 3 rows default, auto-expand |
| Character limit | 500 |
| Counter | "0/500" aligned right |

## Footer Section

┌─────────────────────────────────────────┐ │ [Cancel] [Send Invite]│ └─────────────────────────────────────────┘


| Button | Variant | Behavior |
|--------|---------|----------|
| Cancel | Ghost | Close modal, no action |
| Send Invite | Primary | Validate, submit, close |

**Button States:**
| State | Send Invite |
|-------|-------------|
| Default | Enabled |
| Invalid form | Disabled, tooltip: "Enter valid email" |
| Submitting | Loading spinner, text: "Sending..." |
| Success | Close modal, show toast |

## Edge States

### Empty State
N/A (modal always has form)

### Loading State
While checking if email is already member:
- Show spinner in email input
- Disable submit button

### Error States

| Error | Display |
|-------|---------|
| Invalid email | Inline error: "Please enter a valid email" |
| Already member | Inline error: "This person is already a member" |
| Invitation pending | Inline warning: "Invitation pending. Resend?" |
| Workspace full | Banner at top: "Member limit reached (50/50)" |
| Network error | Toast: "Couldn't send. Check connection." |

### Success State
- Modal closes
- Toast: "Invitation sent to [email protected]"
- Members list updates (if visible)

## Responsive Behavior

| Breakpoint | Changes |
|------------|---------|
| Desktop (>768px) | Centered modal, 480px width |
| Tablet (640-768px) | Centered modal, 90% width |
| Mobile (<640px) | Full screen drawer from bottom |

### Mobile Drawer Specifics
- Slides up from bottom
- Full width, rounded top corners
- Max height 90vh
- Handle bar at top for drag-to-close

## Accessibility Checklist

- [ ] Focus trapped inside modal when open
- [ ] First focusable element (email input) auto-focused
- [ ] Escape key closes modal
- [ ] aria-labelledby points to title
- [ ] aria-describedby points to subtitle
- [ ] Close button has aria-label="Close"
- [ ] Form inputs have associated labels
- [ ] Error messages linked with aria-describedby
- [ ] Submit button announces loading state

## Content Specifications

| Element | Copy | Character Limit |
|---------|------|-----------------|
| Modal title | "Invite to Workspace" | 30 |
| Subtitle | "Add team members to [Workspace Name]" | Dynamic |
| Email label | "Email address" | - |
| Email placeholder | "[email protected]" | - |
| Permission label | "Permission level" | - |
| Message toggle | "Add a personal message" | - |
| Cancel button | "Cancel" | - |
| Submit button | "Send Invite" | - |
| Submit loading | "Sending..." | - |
| Success toast | "Invitation sent to [email]" | Dynamic |

## Assets Required

| Asset | Format | Sizes |
|-------|--------|-------|
| Invite icon | SVG | 20x20 |
| Close icon | SVG | 24x24 |
| Dropdown arrow | SVG | 12x12 |
| Checkmark | SVG | 16x16 |
| Spinner | SVG/CSS | 16x16 |

## Implementation Notes

- Use existing Modal component from design system
- Email validation should match backend regex
- Debounce email check (500ms) to reduce API calls
- Pre-fill email if inviting from contact list

Bad Design Handoff Example

# Invitation Modal

See Figma for designs.

Buttons should work.
Make it look good on mobile.

Why it fails:

  • No specifications, just pointers
  • No states or interactions documented
  • No responsive behavior details
  • No accessibility requirements
  • No content specifications

Design Token Reference

Include token mappings for consistency:

## Design Tokens Reference

### Spacing
| Token | Value | Use |
|-------|-------|-----|
| spacing-1 | 4px | Tight grouping |
| spacing-2 | 8px | Related elements |
| spacing-4 | 16px | Section padding |
| spacing-6 | 24px | Large gaps |

### Typography
| Token | Value | Use |
|-------|-------|-----|
| text-xs | 12px/16px | Captions |
| text-sm | 14px/20px | Secondary text |
| text-base | 16px/24px | Body |
| text-lg | 18px/28px | Subheadings |
| text-xl | 20px/28px | Headings |

### Colors
| Token | Value | Use |
|-------|-------|-----|
| gray-50 | #F9FAFB | Background |
| gray-500 | #6B7280 | Secondary text |
| gray-900 | #111827 | Primary text |
| primary-500 | #3B82F6 | Primary actions |
| red-500 | #EF4444 | Errors |
| green-500 | #22C55E | Success |

Handoff Checklist

Visual Specs
├── □ All states documented (default, hover, active, focus, disabled)
├── □ Spacing and dimensions specified
├── □ Typography tokens referenced
├── □ Color tokens referenced
├── □ Border radius and shadows noted

Interaction Specs
├── □ Animations/transitions defined
├── □ Keyboard interactions noted
├── □ Touch interactions noted
├── □ Loading states designed
├── □ Error states designed
├── □ Empty states designed

Responsive Specs
├── □ Breakpoints defined
├── □ Layout changes per breakpoint
├── □ Touch target sizes verified (min 44px)

Accessibility Specs
├── □ Color contrast verified (4.5:1 text, 3:1 UI)
├── □ Focus states visible
├── □ Screen reader content specified
├── □ Keyboard navigation flow defined

Content Specs
├── □ All copy provided
├── □ Character limits defined
├── □ Error messages written
├── □ Success messages written

Assets
├── □ Icons exported (SVG)
├── □ Images exported (proper formats/sizes)
├── □ Fonts documented

Anti-Patterns

  • Figma-only handoff — "Everything is in Figma" (engineering shouldn't have to interpret)
  • Missing states — Only designing happy path, no loading/error/empty
  • Pixel-perfect tyranny — Specs so rigid they ignore platform conventions
  • No responsive specs — Desktop designs with "make it work on mobile"
  • Accessibility afterthought — No a11y specs until audit fails
  • Undocumented animations — "It should feel smooth" without timing
  • Missing content — Lorem ipsum in production
  • No edge cases — What happens with 100 characters? 1000?
  • Stale handoffs — Designs change, specs don't update

title: Edge Cases and Error Handling impact: HIGH tags: edge-cases, errors, error-handling, failure-modes, resilience

Edge Cases and Error Handling

Impact: HIGH

Edge cases and error handling separate polished products from frustrating ones. Documenting failure modes upfront prevents surprises in production and reduces debugging time.

Why Document Edge Cases

  1. Prevent production surprises — Known unknowns are better than unknown unknowns
  2. Enable QA coverage — Testers need to know what to test
  3. Guide error messages — Users need helpful feedback
  4. Inform monitoring — Know what to alert on
  5. Reduce tech debt — Handle cases properly the first time

Edge Case Categories

CategoryDescriptionExample
BoundaryMin/max limits0 items, max characters
TimingRace conditions, expirationConcurrent edits, expired session
StateInvalid transitionsCancel paid order, edit deleted item
DataMissing, corrupt, unexpectedNull values, unicode, large files
ExternalThird-party failuresAPI down, timeout, rate limited
PermissionAccess edge casesDeleted user, transferred ownership
NetworkConnectivity issuesOffline, slow connection, timeout
ConcurrencySimultaneous operationsDouble submit, parallel updates

Edge Case Documentation Template

## Edge Case: [Name]

**Category:** [Boundary/Timing/State/Data/External/Permission/Network/Concurrency]
**Likelihood:** [Common/Occasional/Rare]
**Impact:** [Critical/High/Medium/Low]

**Scenario:**
[Describe the specific situation]

**Current Behavior:**
[What happens now, if anything]

**Desired Behavior:**
[What should happen]

**User Message:**
[Exact error message to display]

**Recovery Action:**
[What user can do to resolve]

**Technical Notes:**
[Implementation considerations]

Comprehensive Edge Case Example

Feature: File Upload

## Edge Cases: File Upload

### Boundary Cases

| Case | Limit | Behavior | User Message |
|------|-------|----------|--------------|
| File too large | >100MB | Reject before upload | "File exceeds 100MB limit. Try compressing or splitting." |
| File name too long | >255 chars | Truncate with hash | N/A (silent truncation) |
| Zero-byte file | 0 bytes | Allow (may be intentional) | N/A |
| Filename with special chars | Unicode, spaces | Sanitize on backend | N/A (accept as-is, sanitize storage name) |

### Timing Cases

| Case | Trigger | Behavior | User Message |
|------|---------|----------|--------------|
| Upload timeout | >5 min upload | Retry with resume | "Upload interrupted. Resuming..." |
| Session expires mid-upload | Auth token expires | Complete upload, fail on save | "Session expired. Please log in and retry." |
| User navigates away | Browser tab closed | Cancel upload | Confirmation: "Upload in progress. Leave anyway?" |

### State Cases

| Case | Trigger | Behavior | User Message |
|------|---------|----------|--------------|
| Folder deleted during upload | Target deleted | Create folder or reject | "Destination folder no longer exists. Select new location." |
| Storage quota exceeded | Plan limit | Reject upload | "Storage limit reached. Upgrade plan or delete files." |
| Duplicate filename | Same name exists | Prompt for resolution | "File already exists. Replace, rename, or cancel?" |

### Data Cases

| Case | Trigger | Behavior | User Message |
|------|---------|----------|--------------|
| Corrupt file | Invalid header | Attempt upload, warn on view | "File may be corrupt. Upload anyway?" |
| Unsupported format | Blocked extension | Reject | "File type .exe not allowed. Supported: pdf, doc, jpg..." |
| Malware detected | Virus scan positive | Reject, log security event | "File flagged as potentially harmful. Contact support." |
| Image with EXIF data | Privacy concern | Strip EXIF on upload | N/A (silent strip) |

### External Dependency Cases

| Case | Trigger | Behavior | User Message |
|------|---------|----------|--------------|
| S3 unavailable | AWS outage | Queue for retry | "Upload processing. You'll be notified when complete." |
| Virus scanner timeout | Scan service slow | Allow with async scan | "File uploaded. Security scan in progress." |
| CDN propagation delay | New file not available | Show from origin | N/A (transparent fallback) |

### Network Cases

| Case | Trigger | Behavior | User Message |
|------|---------|----------|--------------|
| Connection lost | Network drop | Pause, auto-retry | "Connection lost. Will resume when online." |
| Slow upload (<100kb/s) | Poor connection | Show warning, continue | "Slow connection detected. Upload may take longer." |
| Packet loss | Unstable network | Retry chunks | N/A (transparent retry) |

### Concurrency Cases

| Case | Trigger | Behavior | User Message |
|------|---------|----------|--------------|
| Double click upload | User impatience | Debounce, single upload | N/A (ignore duplicate click) |
| Same file from two tabs | Multiple sessions | Both succeed, detect duplicate | "This file was uploaded in another tab." |
| Replace file during download | Concurrent access | Version old file | N/A (serve consistent version) |

Error Taxonomy

Organize errors by recoverability:

TypeUser Can Fix?Response Strategy
ValidationYesInline errors, clear instructions
AuthenticationYesRedirect to login
AuthorizationSometimesExplain permission, link to request access
Not FoundSometimesSearch suggestions, "did you mean"
ConflictYesShow current state, resolution options
Rate LimitWaitShow when to retry
Server ErrorNoApologize, suggest retry, link to status page
MaintenanceNoEstimated return time

Error Message Guidelines

Structure:

[What happened] + [Why it matters] + [What to do next]

Good Error Messages:

SituationGood Message
Invalid email"Please enter a valid email address (e.g., [email protected])"
Payment failed"Payment declined by your bank. Try another card or contact your bank."
Permission denied"You need Editor access to modify this document. Request access from Sarah M."
Rate limited"You've made too many requests. Please wait 5 minutes before trying again."
Server error"Something went wrong on our end. We've been notified. Try again in a few minutes."

Bad Error Messages:

BadWhyBetter
"Error"No information"Unable to save changes"
"Error 403"Technical jargon"You don't have permission"
"Invalid input"Vague"Username must be 3-20 characters"
"Request failed"No next step"Request failed. Check connection and retry."
"null reference exception"Exposes internals"Something went wrong. Try again."

Error Handling Matrix

Error TypeLog LevelAlert?User FeedbackAuto Retry?
ValidationDebugNoInline errorNo
Auth failureInfoNoModal/redirectNo
Not foundWarnIf patternEmpty stateNo
Rate limitWarnIf excessiveToastYes (delayed)
TimeoutWarnIf SLA breachToastYes (3x)
DB errorErrorYesGeneric errorYes (2x)
CriticalFatalYes (PagerDuty)Maintenance pageNo

Documenting Failure Modes

For each integration/dependency:

## Dependency: Stripe Payment API

### Failure Modes

| Failure | Detection | Impact | Mitigation |
|---------|-----------|--------|------------|
| API timeout (>10s) | HTTP timeout | Payment stuck | Retry 3x, then queue |
| Invalid API key | 401 response | All payments fail | Alert, manual fix |
| Card declined | Decline code | Single payment fails | Show user message |
| Rate limited | 429 response | Slowdown | Exponential backoff |
| Webhook missed | No event received | Data out of sync | Polling reconciliation |
| API deprecation | Warning header | Future breakage | Log, plan upgrade |

### Fallback Behavior

- Primary: Stripe API direct call
- Retry: 3 attempts with exponential backoff (1s, 2s, 4s)
- Queue: If all retries fail, queue for background processing
- Alert: If queue depth > 100 or age > 1 hour
- Manual: Admin can force-retry or refund

### Recovery Procedures

1. Check Stripe status page
2. Verify API key validity
3. Check rate limit headers
4. Review recent code changes
5. Escalate to Stripe support if needed

Edge Case Discovery Checklist

When specifying a feature, ask:

Inputs
├── □ What if input is empty/null?
├── □ What if input is at minimum value?
├── □ What if input is at maximum value?
├── □ What if input exceeds maximum?
├── □ What if input has unexpected characters?
├── □ What if input has malicious content?
└── □ What if input is in wrong format?

Timing
├── □ What if action is very slow?
├── □ What if action times out?
├── □ What if action is interrupted?
├── □ What if session expires during action?
└── □ What if two users act simultaneously?

State
├── □ What if resource doesn't exist?
├── □ What if resource was just deleted?
├── □ What if resource is locked/in use?
├── □ What if user loses permission during action?
└── □ What if related resources change?

External
├── □ What if third-party service is down?
├── □ What if third-party returns unexpected data?
├── □ What if network is unavailable?
└── □ What if response is slow?

Anti-Patterns

  • Happy path only — Only documenting success scenarios
  • Generic errors — "Something went wrong" for everything
  • Silent failures — Errors swallowed without feedback
  • Technical messages — Showing stack traces to users
  • Unhandled states — Loading forever, no empty states
  • Inconsistent handling — Same error, different treatment
  • No recovery path — Errors without guidance on fixing
  • Over-alerting — Every error pages on-call
  • Under-logging — No audit trail when things go wrong
  • Blame the user — "Invalid input" without explaining what's valid

title: Documentation Maintenance impact: MEDIUM tags: maintenance, versioning, deprecation, lifecycle, documentation

Documentation Maintenance

Impact: MEDIUM

Documentation that's not maintained becomes worse than no documentation — it actively misleads. Establish clear processes for keeping specs current, versioning changes, and deprecating outdated content.

Documentation Lifecycle

┌─────────┐    ┌─────────┐    ┌─────────┐    ┌─────────┐    ┌─────────┐
│  Draft  │───▶│ Review  │───▶│ Active  │───▶│  Stale  │───▶│ Archived│
└─────────┘    └─────────┘    └─────────┘    └─────────┘    └─────────┘
     │              │              │              │              │
  Writing       Feedback      In Use         Outdated       Historical
  in progress   & approval    reference      needs update   reference only

Document Status System

Every spec document should have a status:

StatusBadgeMeaningAction Required
Draft[DRAFT]Work in progressDo not rely on
Review[REVIEW]Ready for feedbackProvide feedback by date
ActiveNoneCurrent, accurateUse as reference
Needs Update[NEEDS UPDATE]Known to be outdatedUpdate before using
Deprecated[DEPRECATED]Being phased outSee replacement doc
Archived[ARCHIVED]Historical onlyDo not use

Documentation Header Template

---
title: [Document Title]
status: active
version: 1.2.0
last_updated: 2024-01-15
owner: @username
reviewers: @reviewer1, @reviewer2
related_docs:
  - [PRD: Feature Name](link)
  - [Technical Spec](link)
---

# Document Title

> **Status:** Active
> **Version:** 1.2.0
> **Last Updated:** January 15, 2024
> **Owner:** Product Team (@username)

## Changelog

| Version | Date | Author | Changes |
|---------|------|--------|---------|
| 1.2.0 | 2024-01-15 | @username | Added mobile specs |
| 1.1.0 | 2024-01-10 | @username | Updated error handling |
| 1.0.0 | 2024-01-05 | @username | Initial release |

Versioning Strategy

Semantic Versioning for Docs:

VersionWhen to BumpExample Change
Major (X.0.0)Breaking changes, major restructureCompletely new approach
Minor (x.Y.0)New sections, significant additionsAdded API section
Patch (x.y.Z)Corrections, clarificationsFixed typo, updated date

When to Create New Version vs. Update:

  • Same document: Minor clarifications, corrections
  • New version: Significant changes to approach or scope
  • New document: Completely different feature or requirement

Review Schedule

Document TypeReview FrequencyTrigger Events
PRDPer milestoneScope change, pivot
Technical SpecPer releaseArchitecture change
API SpecPer versionBreaking changes
User StoriesPer sprintRefinement changes
RunbooksQuarterlyIncident learnings
Style GuidesSemi-annuallyDesign system updates

Documentation Review Checklist

## Quarterly Doc Review: [Document Name]

**Reviewer:** @username
**Review Date:** 2024-01-15
**Document Version:** 1.2.0

### Accuracy Check
- [ ] All links work (no 404s)
- [ ] Code examples still work
- [ ] Screenshots match current UI
- [ ] Referenced features still exist
- [ ] Metrics/numbers are current

### Completeness Check
- [ ] Covers current scope (nothing major missing)
- [ ] Edge cases still relevant
- [ ] Error handling still accurate
- [ ] Integration points current

### Relevance Check
- [ ] Still serving its purpose
- [ ] Audience still needs this
- [ ] Not superseded by another doc

### Action Items
- [ ] [List specific updates needed]
- [ ] [Assign owners and dates]

### Verdict
- [ ] **Active:** No changes needed
- [ ] **Needs Update:** Specific updates identified
- [ ] **Deprecate:** Superseded or no longer needed

Deprecation Process

When a document is being retired:

# [DEPRECATED] Original Document Title

> **DEPRECATED:** This document is no longer maintained.
> **Reason:** Replaced by [New Document Title](link)
> **Deprecated Date:** January 15, 2024
> **Removal Date:** April 15, 2024

---

## Why This Was Deprecated

[Brief explanation of why this document is being phased out]

## Migration Guide

| Old Concept | New Location | Notes |
|-------------|--------------|-------|
| Section A | [New Doc, Section X](link) | Mostly unchanged |
| Section B | Removed | No longer applicable |
| Section C | [Different Doc](link) | Significantly updated |

## Original Content Below

[Keep original content for reference during transition period]

Documentation Debt Indicators

Signs your docs are becoming tech debt:

IndicatorRed FlagAction
AgeNo updates in 6+ monthsSchedule review
AccuracyKnown inaccuracies not fixedPrioritize fix
CompletenessMajor sections marked "TBD"Complete or remove
RelevanceFeature was deprecatedArchive doc
OwnershipNo clear ownerAssign owner
UsageNo views in 3 monthsConsider archiving
FeedbackRepeated questions about same topicImprove clarity

Documentation Maintenance Automation

Automated Checks:

CheckFrequencyAlert
Broken linksWeeklySlack notification
Stale docs (no updates in X days)MonthlyEmail to owner
Orphaned docs (no links to them)QuarterlyReview queue
Missing ownersOn changeBlock merge
Expired review datesDailyReminder notification

Suggested Tooling:

  • Link checkers: Built into most doc platforms
  • Freshness tracking: Custom metadata + scripts
  • Analytics: Doc platform analytics or custom
  • Ownership: CODEOWNERS-style files for docs

Good Documentation Maintenance Example

# Documentation Maintenance Log: Workspace Sharing

## Active Documents

| Document | Version | Last Updated | Next Review | Owner |
|----------|---------|--------------|-------------|-------|
| PRD | 2.1.0 | 2024-01-15 | 2024-04-15 | @pm |
| Tech Spec | 1.3.0 | 2024-01-10 | 2024-02-10 | @eng |
| API Spec | 1.0.0 | 2024-01-05 | 2024-04-05 | @eng |
| Runbook | 1.1.0 | 2024-01-12 | 2024-04-12 | @sre |

## Recent Changes

### January 2024

**PRD v2.1.0 (Jan 15)**
- Added mobile sharing flow requirements
- Updated success metrics based on beta learnings
- Removed deprecated "public link" references

**Tech Spec v1.3.0 (Jan 10)**
- Updated architecture diagram with caching layer
- Added performance optimization section
- Fixed incorrect database schema

**Runbook v1.1.0 (Jan 12)**
- Added troubleshooting for invitation email delays
- Updated escalation contacts

## Upcoming Reviews

- [ ] Tech Spec review due Feb 10 (@eng)
- [ ] Quarterly PRD review due Apr 15 (@pm)

## Archived Documents

| Document | Archived Date | Reason | Replacement |
|----------|---------------|--------|-------------|
| Sharing RFC | 2024-01-01 | Converted to spec | Tech Spec v1.0 |
| Design Brief | 2024-01-05 | Incorporated into PRD | PRD Section 5 |

## Open Documentation Debt

| Item | Priority | Owner | Due |
|------|----------|-------|-----|
| Add mobile examples to API spec | Medium | @eng | Jan 31 |
| Update screenshots for new UI | Low | @design | Feb 15 |

Bad Documentation Maintenance Example

# Sharing Feature Docs

Last updated: sometime last year probably

See:
- sharing-spec.doc (on someone's machine)
- the wiki page (not sure which one)
- ask Jake, he knows

TODO: update this

Why it fails:

  • No version control
  • No clear locations
  • No ownership
  • No review process
  • Uncertain accuracy

Documentation Cleanup Rituals

Monthly:

  • Review "Needs Update" tagged docs
  • Check for broken links
  • Update stale screenshots

Quarterly:

  • Full review of active docs
  • Archive completed project docs
  • Update documentation index

Per Release:

  • Update version numbers
  • Add changelog entries
  • Review all referenced docs

Per Project Completion:

  • Archive project-specific docs
  • Extract learnings into permanent docs
  • Update style guides if patterns emerged

Anti-Patterns

  • Write once, read never — Docs created and forgotten
  • Sacred documents — Fear of updating "official" docs
  • Tribal knowledge — "Everyone knows" instead of documenting
  • Documentation sprawl — Same info in multiple places
  • Perfectionism paralysis — Not publishing until perfect
  • Owner orphans — Docs without assigned maintainers
  • Fake freshness — Updating date without actual review
  • Archive aversion — Keeping outdated docs "just in case"
  • Review theater — Marking reviewed without actually reading
  • Wiki wilderness — No structure, search is only navigation

title: Success Metrics Definition impact: HIGH tags: metrics, kpis, measurement, analytics, success-criteria

Success Metrics Definition

Impact: HIGH

Success metrics answer the most important question: "Did we build the right thing?" Without clear metrics, you're shipping features into a void and can't learn or iterate effectively.

Why Define Metrics Upfront

  1. Alignment — Everyone agrees what success looks like
  2. Prioritization — Focus on what moves metrics
  3. Learning — Understand what works and what doesn't
  4. Accountability — Clear ownership of outcomes
  5. Resource allocation — Data-driven investment decisions

Metric Types

TypePurposeExampleTimeframe
PrimaryCore success measureConversion ratePer feature
SecondarySupporting indicatorsTime to first actionPer feature
GuardrailEnsure no regressionPage load timeAlways
InputLeading indicatorsSignup attemptsShort-term
OutputLagging resultsRevenueLong-term

The Metrics Hierarchy

                    ┌─────────────────────┐
                    │   North Star        │
                    │ (Company success)   │
                    └──────────┬──────────┘
                               │
            ┌──────────────────┼──────────────────┐
            │                  │                  │
     ┌──────┴──────┐    ┌──────┴──────┐    ┌──────┴──────┐
     │   Pillar 1  │    │   Pillar 2  │    │   Pillar 3  │
     │ Acquisition │    │  Activation │    │  Retention  │
     └──────┬──────┘    └──────┬──────┘    └──────┬──────┘
            │                  │                  │
     ┌──────┴──────┐    ┌──────┴──────┐    ┌──────┴──────┐
     │  Feature    │    │  Feature    │    │  Feature    │
     │  Metrics    │    │  Metrics    │    │  Metrics    │
     └─────────────┘    └─────────────┘    └─────────────┘

SMART Metrics Framework

Every metric should be:

CriteriaQuestionBad ExampleGood Example
SpecificWhat exactly are we measuring?"Engagement""DAU/MAU ratio"
MeasurableCan we actually track it?"User happiness""NPS score"
AchievableIs the target realistic?"100% retention""85% 30-day retention"
RelevantDoes it matter for this feature?"Total users" (for niche feature)"Feature adoption rate"
Time-boundWhen do we measure?"Eventually improve""Increase 10% by Q2"

Metrics Definition Template

## Metric: [Name]

### Definition
| Property | Value |
|----------|-------|
| Name | Active Team Workspaces |
| Definition | Workspaces with ≥2 members and activity in last 7 days |
| Formula | COUNT(workspaces WHERE member_count >= 2 AND last_activity > now() - 7d) |
| Type | Primary |
| Owner | Product Team |

### Context
**Why this metric matters:**
Measures whether teams are getting value from the sharing feature.
Directly tied to team plan retention.

**How it connects to business goals:**
North Star: Weekly Active Teams
Pillar: Team Activation
This metric: Feature-level success

### Measurement

**Data Source:** Analytics warehouse (Snowflake)
**Calculation Frequency:** Daily
**Dashboard:** [Link to dashboard]
**Alert Threshold:** <90% of target for 3 consecutive days

### Targets

| Period | Baseline | Target | Stretch |
|--------|----------|--------|---------|
| Launch (Week 1) | 0 | 100 | 200 |
| Month 1 | 100 | 500 | 750 |
| Month 3 | 500 | 2,000 | 3,000 |
| Month 6 | 2,000 | 5,000 | 7,500 |

### Segments

Track this metric by:
- Plan type (Free, Teams, Enterprise)
- Company size (1-10, 11-50, 51-200, 200+)
- Acquisition cohort (month signed up)
- Geography (US, EU, APAC, Other)

### Caveats
- Excludes test/demo accounts
- "Activity" = any create/edit/view event
- Gaming risk: Low (activity definition is broad)

Good Metrics Specification Example

# Success Metrics: Workspace Sharing Feature

## Overview

| Metric Type | Metric | Target | Measurement |
|-------------|--------|--------|-------------|
| Primary | Team activation rate | 30% | % of Teams accounts using sharing |
| Secondary | Time to first invite | <24 hours | Median time from workspace creation |
| Guardrail | Workspace load time | <2s p95 | No regression from adding sharing |
| Input | Invitations sent | 1,000/week | Leading indicator of adoption |

## Primary Metric: Team Activation Rate

### Definition
Percentage of Teams plan accounts that have invited at least one
member to at least one workspace within 30 days of signing up.

### Formula

team_activation_rate = COUNT(teams_accounts WHERE invited_member = true AND account_age <= 30d) / COUNT(teams_accounts WHERE account_age <= 30d)


### Why This Metric
- Directly measures if teams are getting value
- Predictive of retention (correlated 0.7)
- Actionable (we can improve invitation flow)
- Not gameable (requires real action)

### Current State
- Baseline: N/A (new feature)
- Comparable: Email invitation rate = 15%
- Industry benchmark: Team features ~25-35%

### Targets

| Milestone | Target | Rationale |
|-----------|--------|-----------|
| Week 1 | 5% | Early adopters only |
| Month 1 | 15% | Ramp with awareness |
| Month 3 | 25% | Optimization based on learning |
| Month 6 | 35% | Mature adoption |

### Segmentation
- By plan tier (Teams vs Enterprise)
- By company size
- By acquisition channel
- By industry vertical

## Secondary Metric: Time to First Invite

### Definition
Median time from workspace creation to first invitation sent,
for workspaces that eventually have invitations.

### Formula

time_to_first_invite = MEDIAN( first_invitation_timestamp - workspace_created_timestamp WHERE workspace.invitation_count > 0 )


### Why This Metric
- Measures friction in invitation flow
- Faster = better user experience
- Can optimize specific steps

### Current State
- Baseline: N/A (new feature)
- Hypothesis: <24 hours is healthy

### Targets

| Milestone | Target | Rationale |
|-----------|--------|-----------|
| Launch | <48 hours | Initial discovery |
| Month 1 | <24 hours | Improved onboarding |
| Month 3 | <12 hours | Streamlined flow |

## Guardrail Metric: Workspace Load Time

### Definition
95th percentile page load time for workspace pages.

### Why This Metric
Ensure sharing feature doesn't regress core experience.

### Threshold
- Current baseline: 1.8s p95
- Maximum acceptable: 2.0s p95
- Alert if: >2.0s for 15 minutes

### Action if Breached
1. Roll back sharing feature
2. Investigate performance
3. Optimize before re-enabling

## Input Metric: Invitations Sent

### Definition
Total number of workspace invitations sent per week.

### Why This Metric
Leading indicator of adoption. If invitations drop, investigate
before it affects activation rate.

### Targets

| Week | Target | Notes |
|------|--------|-------|
| 1 | 100 | Internal + alpha |
| 2 | 300 | Beta expansion |
| 3 | 700 | Wider beta |
| 4 | 1,500 | GA |
| Steady state | 2,000+/week | Ongoing |

## Metric Dependencies

Invitations Sent (Input) │ ▼ Invitations Accepted (Conversion) │ ▼ Active Team Workspaces (Engagement) │ ▼ Team Activation Rate (Primary) │ ▼ Team Plan Retention (Business Outcome)


## Dashboard Requirements

### Real-time View
- Invitations sent (last 24 hours)
- Error rates
- Load times

### Daily View
- Activation rate trend
- Time to first invite distribution
- Funnel conversion rates

### Weekly View
- Segment breakdown
- Cohort analysis
- Feature usage patterns

## Analytics Events

| Event | Trigger | Properties |
|-------|---------|------------|
| `invitation_sent` | Invite submitted | workspace_id, permission_level |
| `invitation_accepted` | Invite clicked and accepted | workspace_id, days_pending |
| `invitation_expired` | 7-day expiration | workspace_id |
| `member_added` | User joins workspace | workspace_id, source |
| `member_removed` | User removed/leaves | workspace_id, reason |

Bad Metrics Specification Example

# Metrics: Sharing Feature

We will track:
- Number of users
- Engagement
- Customer satisfaction

Success = people use it.

Why it fails:

  • No specific definitions
  • No targets or baselines
  • "Engagement" and "satisfaction" undefined
  • No timeframes
  • No measurement plan

Common Metrics by Feature Type

Feature TypePrimary MetricSecondary Metrics
OnboardingActivation rateTime to first value, drop-off points
EngagementDAU/MAU ratioSession length, feature usage
ConversionConversion rateFunnel step rates, time to convert
RetentionD7/D30 retentionChurn rate, resurrection rate
RevenueARPU, LTVUpgrade rate, expansion revenue
PerformancePage load timeError rate, availability
SupportTicket volumeResolution time, CSAT

Metrics Pitfalls to Avoid

PitfallProblemSolution
Vanity metricsBig numbers that don't matterFocus on actionable metrics
GamingMetric improves without real progressUse multiple metrics, monitor behavior
Short-termismOptimize metric, hurt long-termAdd guardrail metrics
Over-measurementTrack everything, act on nothingLimit to 3-5 key metrics
Stale targetsTargets don't evolve with learningReview quarterly

Metrics Review Cadence

FrequencyReviewParticipants
DailyReal-time dashboardsEngineering
WeeklyMetric trends, anomaliesProduct + Engineering
MonthlyProgress to targetsLeadership
QuarterlyTarget recalibrationExec team

Anti-Patterns

  • Metric theater — Tracking metrics without acting on them
  • Goal post moving — Changing targets when you miss them
  • Survivor bias — Only measuring users who stuck around
  • Correlation confusion — Assuming causation from correlation
  • Local optimization — Improving metric while hurting overall experience
  • Metric debt — Accumulating measurements nobody uses
  • Undefined baseline — Targets without knowing where you're starting
  • Success by omission — Not measuring what might show failure
  • Proxy obsession — Optimizing proxy instead of real outcome
  • Launch and forget — Setting metrics at launch, never reviewing

title: PRD Writing impact: CRITICAL tags: prd, requirements, product, vision, scope

PRD Writing

Impact: CRITICAL

A PRD is the single source of truth for what you're building and why. It aligns stakeholders, prevents scope creep, and gives engineering the context they need to make good decisions.

The PRD Purpose

A PRD answers these questions:

  1. Why are we building this? (Problem, opportunity)
  2. What are we building? (Solution, scope)
  3. For whom are we building? (Users, personas)
  4. How will we know it works? (Metrics, success criteria)
  5. What are the constraints? (Timeline, resources, dependencies)

PRD Structure Framework

SectionPurposeLength
Executive SummaryQuick overview for skimmers2-3 sentences
Problem StatementWhy this matters1-2 paragraphs
Goals & Success MetricsHow we measure successBulleted list
User PersonasWho we're building for1-2 personas
User StoriesWhat users can do5-15 stories
ScopeWhat's in and outTwo lists
RequirementsDetailed needsCategorized list
ConstraintsLimitations and dependenciesBulleted list
TimelineKey milestonesTable or list
Open QuestionsUnresolved decisionsBulleted list
AppendixSupporting research, mocksAs needed

Problem Statement Formula

Template:

[User segment] struggles with [problem] when trying to [goal].
Currently, they [workaround], which results in [pain/cost].
By building [solution], we can [benefit], which will [business impact].

Good PRD Example

# PRD: Team Workspace Sharing

## Executive Summary
Enable teams to share workspaces with granular permissions, reducing the
current friction of workspace duplication and manual access management.

## Problem Statement
Teams of 5+ members struggle with workspace collaboration. Currently,
users duplicate workspaces or share account credentials, leading to:
- 40% of support tickets related to access issues
- Average 3.2 duplicate workspaces per team
- Security risk from shared credentials

Customer interviews (n=23) identified this as the #1 requested feature.

## Goals & Success Metrics

**Primary Goal:** Reduce workspace duplication by 60% within 90 days of launch

| Metric | Current | Target | Measurement |
|--------|---------|--------|-------------|
| Duplicate workspaces per team | 3.2 | 1.3 | Analytics |
| Access-related support tickets | 40% | 15% | Zendesk |
| Team collaboration NPS | 32 | 50 | Survey |

**Secondary Goals:**
- Increase team plan upgrades by 25%
- Reduce time-to-collaborate for new team members by 50%

## User Personas

**Primary: Team Lead (Sarah)**
- Manages 5-10 team members
- Needs to control who sees what
- Pain: Spends 2+ hours/week managing access manually

**Secondary: Team Member (Alex)**
- Joins existing teams
- Needs quick access to relevant workspaces
- Pain: Waits 1-2 days for access requests

## User Stories
[See stories-* rules for detailed format]

1. As a team lead, I want to invite members to my workspace so that
   they can collaborate without creating duplicates
2. As a team lead, I want to set permission levels so that I can
   control who can edit vs. view
3. As a team member, I want to see all workspaces shared with me
   so that I can quickly find what I need

## Scope

**In Scope (v1):**
- Workspace invitation by email
- Three permission levels: Owner, Editor, Viewer
- Invitation management (revoke, modify)
- Shared workspace indicator in UI

**Out of Scope (v1):**
- Public/link sharing
- Workspace transfer (change owner)
- Permission inheritance (folders)
- Guest access (external users)

## Requirements

### Functional Requirements
- FR-1: Users can invite up to 50 members per workspace
- FR-2: Invitations expire after 7 days if not accepted
- FR-3: Owners can modify permissions at any time
- FR-4: Members receive email notification on invitation

### Non-Functional Requirements
- NFR-1: Invitation flow completes in <2 seconds
- NFR-2: Permission changes apply within 30 seconds
- NFR-3: Support 1000 concurrent workspace members

## Constraints

**Technical:**
- Must integrate with existing auth system (Auth0)
- Cannot modify current workspace data model significantly

**Business:**
- Must ship before Q3 for enterprise sales push
- Design resources limited to 2 weeks

**Dependencies:**
- Email service capacity increase (Ops team)
- Auth0 plan upgrade for group claims

## Timeline

| Milestone | Date | Deliverable |
|-----------|------|-------------|
| Design complete | June 15 | Figma specs approved |
| API complete | July 1 | Backend ready for integration |
| Beta launch | July 15 | 10% rollout to Teams plan |
| GA launch | August 1 | 100% rollout |

## Open Questions

- [ ] Should free plans have sharing? (Decision: Product leadership)
- [ ] Max members per workspace? (Proposed: 50, pending Eng review)
- [ ] Email template ownership? (Marketing or Product?)

## Appendix

- [Customer interview summary](link)
- [Competitive analysis](link)
- [Design explorations](link)

Bad PRD Example

# PRD: Sharing Feature

## Overview
We need to add sharing to workspaces because customers want it.

## Requirements
- Add sharing
- Make it fast
- Should be secure
- Users should like it

## Timeline
ASAP - this is high priority

## Notes
Talk to engineering about what's possible.

Why this fails:

  • No problem statement or business justification
  • No success metrics or acceptance criteria
  • Vague requirements ("fast", "secure", "like it")
  • No scope boundaries — everything is implied
  • No user context or personas
  • Timeline without milestones

PRD Review Checklist

Before sharing a PRD, verify:

□ Problem is validated with data or research
□ Success metrics are specific and measurable
□ Scope clearly states what's OUT as well as IN
□ All user personas are represented in stories
□ Technical constraints are documented
□ Dependencies are identified with owners
□ Timeline has specific milestones
□ Open questions are explicitly listed
□ Stakeholders are identified for sign-off

PRD Versioning

VersionTriggerDocumentation
DraftInitial creationMark as "[DRAFT]" in title
ReviewReady for feedbackShare with stakeholders
ApprovedStakeholder sign-offRecord approvers and date
UpdatedScope changeChangelog section, version bump
DeprecatedFeature shipped/cancelledMark as "[ARCHIVED]"

Anti-Patterns

  • The Novel — 30-page PRDs nobody reads. Keep it scannable.
  • The Wishlist — Everything the customer ever mentioned. Prioritize ruthlessly.
  • The Solution Spec — Jumping to "how" before establishing "what" and "why"
  • The Orphan — PRD without clear owner or stakeholders
  • The Frozen Doc — PRD that never updates as learnings emerge
  • The Assumption Factory — Missing validation, just "we think" statements
  • The Feature Factory — Requirements without business outcomes
  • Spec by Jira — Tickets without the connecting narrative

title: Feature Flags and Rollout Plans impact: MEDIUM-HIGH tags: feature-flags, rollout, deployment, experiments, releases

Feature Flags and Rollout Plans

Impact: MEDIUM-HIGH

Feature flags and rollout plans turn risky big-bang releases into controlled, reversible deployments. They enable experimentation, gradual rollouts, and instant rollbacks.

Why Feature Flags

  1. Risk reduction — Limit blast radius of bugs
  2. Faster iteration — Ship code without exposing features
  3. Experimentation — A/B test with real users
  4. Operational control — Disable features without deploys
  5. Customer control — Enable for specific accounts

Feature Flag Types

TypePurposeLifespanExample
ReleaseGate unreleased featuresShort (weeks)sharing_v2_enabled
ExperimentA/B testingShort (days-weeks)checkout_flow_experiment
OpsCircuit breakers, load sheddingPermanentheavy_report_enabled
PermissionPlan/role-based accessPermanententerprise_analytics
Kill SwitchEmergency disablePermanentthird_party_integration

Feature Flag Naming Convention

{scope}_{feature}_{purpose}

Examples:
- release_workspace_sharing_enabled
- experiment_pricing_page_variant
- ops_batch_processing_enabled
- permission_custom_domains_access
- kill_switch_stripe_integration

Feature Flag Specification Template

## Feature Flag: [Name]

### Overview
| Property | Value |
|----------|-------|
| Flag Name | `release_workspace_sharing_enabled` |
| Type | Release |
| Owner | Product Team |
| Created | 2024-01-15 |
| Expected Removal | 2024-03-01 |

### Description
Gates access to the new workspace sharing feature, including:
- Invite modal in workspace header
- Members tab in workspace settings
- Sharing-related API endpoints

### Targeting Rules

| Stage | Audience | Percentage | Start Date |
|-------|----------|------------|------------|
| Internal | @company.com emails | 100% | Jan 15 |
| Alpha | Specific accounts (list below) | 100% | Jan 22 |
| Beta | Teams plan users | 10% → 50% | Feb 1 |
| GA | All users | 100% | Feb 15 |

**Alpha Account List:**
- Acme Corp (acct_123)
- Beta Inc (acct_456)
- Gamma LLC (acct_789)

### Fallback Behavior
When flag is OFF:
- "Invite" button hidden in workspace header
- Sharing API endpoints return 404
- Direct links to sharing pages redirect to workspace

### Dependencies
| Dependency | Status |
|------------|--------|
| Sharing Service deployed | Required |
| Email templates ready | Required |
| Analytics events tracked | Required |

### Rollback Criteria
Immediately disable if:
- Error rate >1% on sharing endpoints
- >50 support tickets related to sharing
- Data integrity issues detected

### Metrics to Monitor
- `sharing.invitations.sent` — Expected increase
- `sharing.invitations.errors` — Should stay <0.1%
- `workspace.load_time` — Should not increase >100ms
- Support ticket volume — Monitor for sharing issues

### Cleanup Plan
After 100% rollout for 2 weeks:
1. Remove flag checks from code
2. Remove flag from configuration
3. Update documentation
4. Archive this spec

Rollout Plan Template

# Rollout Plan: [Feature Name]

## Overview
| Property | Value |
|----------|-------|
| Feature | Workspace Sharing |
| PRD Link | [Link] |
| Tech Spec Link | [Link] |
| Feature Flag | `release_workspace_sharing_enabled` |
| Target GA Date | February 15, 2024 |

## Pre-Launch Checklist

### Engineering Readiness
- [ ] Code merged to main
- [ ] Feature flag created and tested
- [ ] Database migrations complete
- [ ] Performance testing passed
- [ ] Security review approved
- [ ] Monitoring/alerting configured

### Product Readiness
- [ ] User documentation published
- [ ] Help center articles updated
- [ ] In-app tooltips configured
- [ ] Email templates approved

### Support Readiness
- [ ] Support team briefed
- [ ] FAQ document created
- [ ] Escalation path defined
- [ ] Known issues documented

### Marketing Readiness
- [ ] Announcement blog post drafted
- [ ] Social media posts scheduled
- [ ] Email campaign prepared (if applicable)

## Rollout Stages

### Stage 1: Internal Testing (Jan 15-21)

**Audience:** Internal employees only
**Goal:** Validate core functionality, find obvious bugs

| Task | Owner | Status |
|------|-------|--------|
| Enable for @company.com | Eng | |
| Conduct internal testing | QA | |
| Fix critical bugs | Eng | |
| Document known issues | PM | |

**Go/No-Go Criteria:**
- [ ] No critical bugs
- [ ] Core flows work end-to-end
- [ ] Internal team sign-off

### Stage 2: Alpha (Jan 22-31)

**Audience:** 10 design partner accounts
**Goal:** Validate with real users, gather feedback

| Task | Owner | Status |
|------|-------|--------|
| Enable for alpha accounts | Eng | |
| Schedule feedback calls | PM | |
| Monitor error rates | Eng | |
| Iterate on feedback | Team | |

**Alpha Accounts:**
1. Acme Corp — Sarah (PM), [email protected]
2. Beta Inc — John (CTO), [email protected]
3. [...]

**Go/No-Go Criteria:**
- [ ] NPS >30 from alpha users
- [ ] Error rate <0.5%
- [ ] No data integrity issues
- [ ] Alpha user sign-off

### Stage 3: Beta (Feb 1-14)

**Audience:** Teams plan users, gradual percentage rollout
**Goal:** Validate at scale, stress test

| Day | Percentage | Users | Notes |
|-----|------------|-------|-------|
| Feb 1 | 5% | ~500 | Initial beta |
| Feb 5 | 10% | ~1,000 | If no issues |
| Feb 8 | 25% | ~2,500 | Expand |
| Feb 12 | 50% | ~5,000 | Final beta |

**Monitoring:**
- Hourly check: Error rates, latency
- Daily check: Support tickets, user feedback
- Weekly: Analytics review

**Pause/Rollback Triggers:**
- Error rate >1% for 30 minutes
- Latency p99 >500ms for 30 minutes
- >10 support tickets/hour related to feature
- Any data corruption detected

### Stage 4: General Availability (Feb 15)

**Audience:** All users
**Goal:** Feature fully launched

| Task | Owner | Status |
|------|-------|--------|
| Ramp to 100% | Eng | |
| Publish announcement | Marketing | |
| Monitor closely (48 hours) | Eng | |
| Begin flag cleanup | Eng | |

## Rollback Plan

### Rollback Procedure

1. **Decision Maker:** On-call eng or PM
2. **Action:** Disable flag in LaunchDarkly
3. **Impact:** Feature immediately hidden for all users
4. **Data:** No data loss; existing memberships preserved
5. **Communication:** Status page update within 15 minutes

### Rollback Communication Templates

**Status Page (Incident):**

We are temporarily disabling workspace sharing while we investigate an issue. Existing workspace configurations are preserved. We expect to re-enable the feature within [timeframe].


**Customer Email (if needed):**

Subject: Temporary pause on Workspace Sharing

We've temporarily paused the new workspace sharing feature while we address an issue we discovered. Your existing workspace setup is safe and will work normally when we re-enable the feature.

We expect to have this resolved within [timeframe].


## Post-Launch

### Success Criteria (2 weeks post-GA)
- [ ] 20% of Teams accounts have used sharing
- [ ] Workspace duplication down 30%
- [ ] Access-related tickets down 25%
- [ ] No P0/P1 bugs outstanding

### Cleanup Tasks
- [ ] Remove feature flag from code (by Mar 1)
- [ ] Archive rollout documentation
- [ ] Retrospective meeting scheduled
- [ ] Share learnings with team

Rollout Strategies

StrategyUse CaseRisk Level
Big BangSimple changes, low riskHigh
PercentageGradual exposureMedium
RingEmployee → Beta → GALow
GeographyTest in single region firstLow
AccountSpecific customersVery Low
Time-basedEnable during low trafficLow

Good Rollout Example

## Rollout: New Checkout Flow

### Strategy: Ring-based with percentage

Ring 1 (Week 1): Internal employees
├── 100% of @company.com
├── Validate all payment paths
└── Success: No checkout failures

Ring 2 (Week 2): Friendly customers
├── 50 accounts who opted in
├── Collect qualitative feedback
└── Success: NPS >40, no critical bugs

Ring 3 (Week 3): Canary
├── 1% of production traffic
├── Compare conversion rate to control
├── Success: Conversion within 5% of baseline

Ring 4 (Week 4): Gradual rollout
├── 1% → 5% → 10% → 25% → 50% → 100%
├── 24 hours between each stage
└── Success: Conversion improved or neutral

Rollback: Instant flag disable, fallback to old checkout

Bad Rollout Example

## Rollout: New Checkout Flow

Ship it on Monday. If there are problems, we'll fix them.

Why it fails:

  • No staged rollout
  • No success criteria
  • No monitoring plan
  • No rollback plan
  • No communication plan

Feature Flag Hygiene

Lifecycle StageAction
CreationDocument purpose, owner, expected removal date
ActiveReview monthly, update targeting rules
StaleAfter 90 days at 100%, schedule cleanup
RemovalDelete flag, remove code checks, archive docs

Technical Debt Warning Signs:

  • Flags older than 6 months
  • Flags with no recent evaluations
  • Flags with no documented owner
  • Code checking multiple flags for same feature

Anti-Patterns

  • Flag forever — Never removing flags, code becomes unmaintainable
  • Flag explosion — Too many flags, impossible to understand state
  • No rollback testing — Rollback plan not actually tested
  • Big bang despite flags — Having flags but going 0→100%
  • Flag as security — Using flags instead of proper auth
  • Coupling flags — Flag A requires Flag B, creating dependencies
  • Silent rollout — No monitoring during gradual rollout
  • Premature celebration — Declaring success before cleanup
  • No owner — Flags without clear ownership decay
  • Flag naming chaos — Inconsistent names impossible to search

title: User Story Creation impact: CRITICAL tags: user-stories, agile, requirements, personas, jtbd

User Story Creation

Impact: CRITICAL

User stories translate business requirements into engineering work. They're not just ticket templates — they're communication tools that capture who benefits, what they need, and why it matters.

The Story Structure

Classic Format:

As a [persona/user type]
I want [capability/action]
So that [benefit/value]

Enhanced Format:

As a [persona] with [context/situation]
I want to [action/capability]
So that I can [immediate benefit]
Which enables [business outcome]

The INVEST Criteria

Every user story should be:

CriteriaQuestionRed Flag
IndependentCan it ship alone?"Blocked by Story #47"
NegotiableCan scope flex?Over-specified implementation
ValuableDoes user benefit?Technical task disguised as story
EstimableCan we size it?Too vague or too large
SmallFits in a sprint?Multi-week estimate
TestableCan we verify done?No acceptance criteria

Story Sizing Guide

SizeDaysCharacteristics
XS0.5Config change, copy update
S1-2Single component, clear path
M3-5Multiple components, some unknowns
L5-8Cross-system, needs breakdown
XL8+Epic-level, must be split

Rule of thumb: If you can't complete it in one sprint, it's not a story — it's an epic.

Good User Story Examples

E-commerce: Add to Cart

**Story:** Add product to shopping cart

**As a** shopper browsing products
**I want to** add items to my cart without leaving the product page
**So that** I can continue browsing without losing my selections

**Acceptance Criteria:**
- Given I'm on a product page with available inventory
  When I click "Add to Cart"
  Then the item is added and cart count updates within 500ms

- Given I'm on a product page with size variants
  When I click "Add to Cart" without selecting a size
  Then I see an inline error prompting size selection

- Given I already have 10 of this item in cart
  When I try to add another
  Then I see a message about quantity limits

**Edge Cases:**
- Product goes out of stock between page load and add
- User is not logged in
- Network failure during add

**Out of Scope:**
- Wishlist functionality
- Product recommendations
- Guest checkout flow

SaaS: Team Invitation

**Story:** Invite team member to workspace

**As a** workspace owner
**I want to** invite colleagues by email
**So that** they can collaborate on projects without creating duplicates

**Acceptance Criteria:**
- Given I have owner permissions
  When I enter a valid email and click "Invite"
  Then an invitation email is sent within 60 seconds

- Given the email is already a workspace member
  When I try to invite them
  Then I see "This person is already a member" message

- Given I've sent an invitation
  When I view pending invitations
  Then I see the email, sent date, and option to resend/revoke

**Technical Notes:**
- Use existing email service (SendGrid)
- Invitations expire after 7 days
- Max 50 members per workspace

**Dependencies:**
- Email template (Design: due June 10)

Bad User Story Examples

Too Vague:

As a user
I want better search
So that I can find things

Why it fails: Who is the user? What does "better" mean? What things? No acceptance criteria.

Too Technical:

As a developer
I want to refactor the auth module to use JWT tokens
So that the code is cleaner

Why it fails: This is a technical task, not a user story. No user value. Reframe as: "As a user, I want to stay logged in across devices..."

Too Large:

As an admin
I want to manage all users, roles, permissions, and audit logs
So that I can control access to the system

Why it fails: This is an epic. Split into: manage users, manage roles, manage permissions, view audit logs.

Missing Context:

As a user
I want to export data
So that I can use it elsewhere

Why it fails: Export what data? In what format? What's "elsewhere"? Add: "As a marketing manager, I want to export campaign analytics as CSV so that I can create reports in Excel."

Persona-Based Story Writing

Define personas before writing stories:

PersonaDescriptionGoalsFrustrations
Admin AmyIT administrator, 5+ yearsMaintain security, reduce ticketsManual processes, unclear audit
Power User PaulHeavy daily userSpeed, keyboard shortcutsFriction in common tasks
Newbie NinaJust joined, learningQuick onboardingConfusing UI, hidden features
Executive EveOccasional user, decision-makerQuick insights, dashboardsToo much detail, slow reports

Then write stories from their perspective:

  • "As Admin Amy, I want to bulk deactivate users so that offboarding is efficient"
  • "As Power User Paul, I want keyboard shortcuts for common actions so that I can work faster"

Jobs-to-Be-Done Integration

Combine JTBD with user stories:

JTBD Format:

When [situation/trigger]
I want to [motivation/job]
So I can [expected outcome]

Example:

When I'm preparing for a client meeting in 10 minutes
I want to quickly pull last quarter's metrics
So I can answer questions confidently without fumbling through dashboards

This becomes the story:

As a sales rep preparing for client meetings
I want to see a one-page summary of key account metrics
So that I can quickly reference performance data during calls

Story Mapping

Organize stories into a map:

            ┌─────────────────────────────────────────────────┐
User        │  Discovery  │  Selection  │  Purchase  │ Use   │
Journey     └─────────────────────────────────────────────────┘
                  │             │            │           │
            ┌─────┴─────┐ ┌─────┴─────┐ ┌────┴────┐ ┌────┴────┐
Release 1   │  Search   │ │  Compare  │ │ Checkout│ │Dashboard│
(MVP)       │  Browse   │ │  Details  │ │ Payment │ │ Basic   │
            └───────────┘ └───────────┘ └─────────┘ └─────────┘
                  │             │            │           │
            ┌─────┴─────┐ ┌─────┴─────┐ ┌────┴────┐ ┌────┴────┐
Release 2   │  Filters  │ │  Reviews  │ │ Save CC │ │ Reports │
            │  Sort     │ │  Compare  │ │ Express │ │ Export  │
            └───────────┘ └───────────┘ └─────────┘ └─────────┘

Story Splitting Techniques

When a story is too large, split by:

TechniqueExample
Workflow stepsRegister → Verify email → Set password
Business rulesBasic validation → Complex validation
Data variationsSingle item → Bulk items
OperationsCreate → Read → Update → Delete
User typesAdmin → User → Guest
PlatformsWeb → Mobile → API
PerformanceWorks → Works fast

Anti-Patterns

  • Story as task — "Implement login API" (where's the user value?)
  • Compound stories — "As a user, I want X and Y and Z" (split them)
  • Gold plating — Over-specified acceptance criteria that constrain solutions
  • Missing "so that" — Stories without stated value are features without purpose
  • Copy-paste personas — "As a user" everywhere instead of specific personas
  • Story as spec — 500-word stories that leave no room for negotiation
  • Orphan stories — Stories not connected to epics or goals
  • Zombie stories — Old stories that linger in backlog, never prioritized or removed

title: Technical Specifications impact: HIGH tags: technical-spec, architecture, system-design, engineering

Technical Specifications

Impact: HIGH

Technical specs translate product requirements into engineering blueprints. They document architectural decisions, system interactions, and implementation approaches before code is written.

When to Write Technical Specs

ComplexitySpec Needed?Approach
Small (<1 day)NoInline comments, PR description
Medium (1-5 days)LightweightBrief design doc section
Large (1-2 weeks)YesFull technical spec
Critical (any size)YesFull spec + review

Always write a spec when:

  • Multiple teams/systems involved
  • Breaking changes to existing APIs
  • New infrastructure or services
  • Security-sensitive features
  • Performance-critical paths

Technical Spec Structure

# Technical Spec: [Feature Name]

## Overview
[2-3 sentence summary of what and why]

## Goals
[What this design achieves]

## Non-Goals
[What this design explicitly does NOT address]

## Background
[Context needed to understand the problem]

## Detailed Design
[The meat of the spec: architecture, components, flows]

## Data Model
[Schema changes, new models, relationships]

## API Design
[Endpoints, contracts, error handling]

## Security Considerations
[Auth, encryption, vulnerabilities, compliance]

## Observability
[Logging, metrics, alerting]

## Rollout Plan
[Deployment strategy, feature flags, migrations]

## Alternatives Considered
[Other approaches and why they were rejected]

## Open Questions
[Unresolved decisions]

## References
[Related docs, RFCs, PRDs]

Good Technical Spec Example

# Technical Spec: Workspace Sharing Service

## Overview
Build a sharing service that enables workspace owners to invite team members
with granular permissions. This supports the "Team Collaboration" initiative
targeting 25% increase in team plan conversions.

## Goals
- Enable workspace sharing with Owner/Editor/Viewer permissions
- Support up to 50 members per workspace
- Sub-second permission checks on workspace access
- Zero-downtime migration for existing workspaces

## Non-Goals
- Public link sharing (planned for v2)
- Cross-organization sharing
- Real-time collaboration features (separate initiative)

## Background
Currently, users share workspaces by sharing credentials (security risk) or
duplicating workspaces (data sync issues). Support tickets related to access
management are 40% of total volume.

See: [PRD: Team Workspace Sharing](link)

## Detailed Design

### Architecture Overview

┌─────────────────────────────────────────────────────────────┐
│                     API Gateway                             │
└────────────────────────┬────────────────────────────────────┘
                         │
         ┌───────────────┼───────────────┐
         │               │               │
         ▼               ▼               ▼
┌─────────────┐  ┌─────────────┐  ┌─────────────┐
│  Workspace  │  │   Sharing   │  │    Auth     │
│   Service   │  │   Service   │  │   Service   │
│  (existing) │  │    (new)    │  │  (existing) │
└──────┬──────┘  └──────┬──────┘  └─────────────┘
       │                │
       │         ┌──────┴──────┐
       │         │             │
       ▼         ▼             ▼
┌─────────────────────┐  ┌─────────────┐
│   PostgreSQL        │  │    Redis    │
│  (permissions)      │  │   (cache)   │
└─────────────────────┘  └─────────────┘

### Component Responsibilities

| Component | Responsibility |
|-----------|----------------|
| **Sharing Service** | Invitation CRUD, permission management |
| **Workspace Service** | Add permission checks to existing endpoints |
| **Auth Service** | Issue tokens with workspace claims |
| **Redis** | Cache permission lookups |

### Permission Model

Three permission levels (bitmask for efficient storage):

| Level | Value | Capabilities |
|-------|-------|--------------|
| Viewer | 1 | Read workspace, view history |
| Editor | 3 | Viewer + create/edit/delete content |
| Owner | 7 | Editor + manage members, settings, delete workspace |

Permission inheritance:
- Owner > Editor > Viewer
- Each level includes all lower permissions

### Invitation Flow

1. Owner submits invitation request (email, permission level)
2. Sharing Service validates:
   - Owner has permission
   - Email format valid
   - Workspace not at member limit
3. Generate invitation token (cryptographic random, 32 bytes)
4. Store invitation in pending_invitations table
5. Queue email via existing notification service
6. Invitee clicks link → validates token → creates membership
7. Token invalidated after use or expiration (7 days)

### Permission Check Flow

On every workspace request:

1. Extract workspace_id from request
2. Check Redis cache: `workspace:{id}:user:{user_id}`
3. If miss → query PostgreSQL → cache for 5 minutes
4. Deny if no permission record exists
5. Check operation against permission level
6. Log access attempt (success/failure)

Performance target: <10ms for cached, <50ms for uncached

## Data Model

### New Tables

-- Workspace memberships
CREATE TABLE workspace_memberships (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    workspace_id UUID NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    permission_level SMALLINT NOT NULL DEFAULT 1,
    invited_by UUID REFERENCES users(id),
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    UNIQUE(workspace_id, user_id)
);

CREATE INDEX idx_memberships_workspace ON workspace_memberships(workspace_id);
CREATE INDEX idx_memberships_user ON workspace_memberships(user_id);

-- Pending invitations
CREATE TABLE workspace_invitations (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    workspace_id UUID NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
    email VARCHAR(255) NOT NULL,
    permission_level SMALLINT NOT NULL DEFAULT 1,
    token VARCHAR(64) NOT NULL UNIQUE,
    invited_by UUID NOT NULL REFERENCES users(id),
    expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    accepted_at TIMESTAMP WITH TIME ZONE
);

CREATE INDEX idx_invitations_token ON workspace_invitations(token);
CREATE INDEX idx_invitations_workspace ON workspace_invitations(workspace_id);

### Migration Strategy

1. Create new tables (non-blocking)
2. Backfill existing workspace owners into memberships table
3. Deploy permission checks in shadow mode (log but don't enforce)
4. Verify no legitimate access would be blocked
5. Enable enforcement with feature flag

## API Design

See [api-specs.md] for full OpenAPI specification.

Key endpoints:
- POST /workspaces/{id}/invitations - Create invitation
- GET /workspaces/{id}/members - List members
- PATCH /workspaces/{id}/members/{user_id} - Update permission
- DELETE /workspaces/{id}/members/{user_id} - Remove member

## Security Considerations

### Authentication
- All endpoints require valid JWT
- Invitation tokens are single-use, time-limited

### Authorization
- Permission checks on every workspace operation
- Owner-only operations: invite, remove, change permissions, delete workspace
- Audit log of all permission changes

### Data Protection
- Email addresses encrypted at rest
- Invitation tokens hashed in database
- Rate limiting: 10 invitations per hour per workspace

### Compliance
- GDPR: Include membership data in export/deletion
- SOC2: Audit trail requirements met

## Observability

### Metrics
- `sharing.invitations.sent` - Counter, by workspace
- `sharing.invitations.accepted` - Counter
- `sharing.permission_checks` - Histogram, by result (allowed/denied)
- `sharing.cache_hit_rate` - Gauge

### Logging
- All permission changes logged with actor, target, before/after
- Failed permission checks logged with request context

### Alerts
- Cache hit rate <80% for 5 minutes
- Permission check latency p99 >100ms
- Invitation accept rate <50% over 24 hours

## Rollout Plan

| Phase | Audience | Duration | Success Criteria |
|-------|----------|----------|------------------|
| Alpha | Internal team | 1 week | No blockers |
| Beta | 5% of Teams plan | 2 weeks | <0.1% error rate |
| GA | 100% | 1 week ramp | Metrics nominal |

Feature flag: `workspace_sharing_enabled`
Kill switch: Disable sharing service, fallback to owner-only access

## Alternatives Considered

### 1. Extend existing auth service
**Rejected:** Auth service is critical path, don't want to add complexity.
Separate service allows independent scaling and deployment.

### 2. Real-time permission sync (websockets)
**Rejected:** Adds complexity without clear user benefit.
5-minute cache TTL is acceptable for permission propagation.

### 3. Document-level permissions
**Rejected:** Out of scope for v1. Workspace-level granularity sufficient
based on user research.

## Open Questions

- [ ] Rate limit for invitations per workspace? (Proposed: 50/day)
- [ ] Allow users to leave workspaces? (Leaning yes)
- [ ] Notification when permissions changed? (Needs PM input)

## References

- [PRD: Team Workspace Sharing](link)
- [RFC: Permission System Evolution](link)
- [Auth Service Documentation](link)

Bad Technical Spec Example

# Tech Spec: Sharing

We need to add sharing to workspaces.

## Design
Add a new table for permissions. Add API endpoints for sharing.
Use Redis for caching.

## Security
Make it secure.

## Rollout
Deploy when ready.

Why it fails:

  • No context or goals
  • No architecture diagram
  • Missing data model details
  • No API contracts
  • Vague security section
  • No rollout strategy
  • No alternatives considered

Technical Spec Review Checklist

Architecture
├── □ Clear component diagram
├── □ Responsibilities well-defined
├── □ Integration points identified
├── □ Dependencies documented
└── □ Scalability considered

Data Model
├── □ Schema defined with types
├── □ Indexes specified
├── □ Migration strategy clear
└── □ Backwards compatibility addressed

API Design
├── □ Endpoints documented
├── □ Request/response formats
├── □ Error handling defined
└── □ Versioning strategy

Security
├── □ Auth/authz approach
├── □ Data protection
├── □ Threat model considered
└── □ Compliance requirements

Operational
├── □ Metrics defined
├── □ Logging strategy
├── □ Alerting thresholds
├── □ Runbook considerations
└── □ Rollback plan

Process
├── □ Reviewed by stakeholders
├── □ Open questions resolved
├── □ Alternatives documented
└── □ Timeline realistic

Anti-Patterns

  • Design by committee — Spec becomes vague to accommodate all opinions
  • Premature optimization — Designing for scale you don't have yet
  • Missing context — Spec without PRD link or business justification
  • Implementation masquerading — Writing code in spec instead of design
  • Solo authorship — No review from affected teams
  • Scope creep — Spec expands to cover "nice to haves"
  • Analysis paralysis — Perfect spec that never ships
  • Dead doc — Spec not updated as implementation diverges