Claude
Skills
Sign in
Back

spec-formatter

Included with Lifetime
$97 forever

# Spec Formatter Skill

General

What this skill does

# Spec Formatter Skill

Deterministic formatting of specification documents in multiple output formats.

## Purpose

Converts structured spec data into consistent, well-formatted output documents.

## Supported Formats

- **Markdown** (default): Human-readable documentation
- **JSON**: Structured data for tooling
- **YAML**: Configuration-friendly format

## Markdown Template

```typescript
function formatMarkdown(spec: GeneratedSpec): string {
  return `
# ${spec.title}

> Generated from session: ${spec.sessionId}
> Completeness: ${spec.metadata.completeness}%
> Generated: ${spec.metadata.generatedAt}

## Problem Statement

**Pain Point:** ${spec.problem.pain}

**Target User:** ${spec.problem.targetUser}

**Current Workarounds:**
${spec.problem.workarounds.map(w => `- ${w}`).join('\n')}

**Success Criteria:**
${spec.problem.successCriteria.map(c => `- ${c}`).join('\n')}

---

## User Flow

${formatUserFlow(spec.userFlow)}

---

## Features

### MVP Features

${formatFeatures(spec.features.mvp)}

### V2 Features

${formatFeatures(spec.features.v2)}

---

## Input/Output Contracts

### Inputs

| Field | Type | Required | Validation | Description |
|-------|------|----------|------------|-------------|
${formatInputTable(spec.contracts.inputs)}

### Outputs

| Field | Type | Nullable | Description |
|-------|------|----------|-------------|
${formatOutputTable(spec.contracts.outputs)}

${spec.contracts.api ? formatApiContracts(spec.contracts.api) : ''}

---

## Edge Cases

| Scenario | Expected Behavior | Priority |
|----------|-------------------|----------|
${formatEdgeCases(spec.edgeCases)}

---

## Assumptions

> These assumptions were made during clarification. Validate with stakeholders.

${spec.assumptions.map((a, i) => `${i + 1}. **${a.topic}**: ${a.assumption} _(${a.reason})_`).join('\n')}

---

## Open Questions

${spec.openQuestions.map(q => `- [ ] ${q}`).join('\n')}

---

_Generated by Spec Iterator MCP_
`.trim();
}
```

## Helper Functions

### Format User Flow

```typescript
function formatUserFlow(flow: UserFlowStep[]): string {
  return flow.map((step, i) => {
    let line = `${i + 1}. **${step.actor}**: ${step.action} → ${step.outcome}`;
    if (step.alternatives) {
      line += '\n' + step.alternatives.map(alt =>
        `   - _If ${alt.condition}_ → ${alt.outcome}`
      ).join('\n');
    }
    return line;
  }).join('\n');
}
```

### Format Features

```typescript
function formatFeatures(features: Feature[]): string {
  return features.map(f => `
#### ${f.name}

${f.description}

**Acceptance Criteria:**
${f.acceptanceCriteria.map(ac => `- [ ] ${ac}`).join('\n')}

**Priority:** ${f.priority}
`).join('\n---\n');
}
```

### Format Tables

```typescript
function formatInputTable(inputs: InputField[]): string {
  return inputs.map(i =>
    `| ${i.name} | ${i.type} | ${i.required ? 'Yes' : 'No'} | ${i.validation || '-'} | ${i.description} |`
  ).join('\n');
}

function formatOutputTable(outputs: OutputField[]): string {
  return outputs.map(o =>
    `| ${o.name} | ${o.type} | ${o.nullable ? 'Yes' : 'No'} | ${o.description} |`
  ).join('\n');
}

function formatEdgeCases(cases: EdgeCase[]): string {
  return cases.map(c =>
    `| ${c.scenario} | ${c.handling} | ${c.priority} |`
  ).join('\n');
}
```

## JSON Format

```typescript
function formatJson(spec: GeneratedSpec): string {
  return JSON.stringify({
    $schema: "https://spec-iterator.dev/schema/v1",
    version: "1.0",
    ...spec
  }, null, 2);
}
```

## YAML Format

```typescript
function formatYaml(spec: GeneratedSpec): string {
  // Use a YAML library for proper formatting
  return yaml.stringify({
    version: "1.0",
    ...spec
  });
}
```

## Data Types

```typescript
interface GeneratedSpec {
  title: string;
  sessionId: string;
  problem: {
    pain: string;
    targetUser: string;
    workarounds: string[];
    successCriteria: string[];
  };
  userFlow: UserFlowStep[];
  features: {
    mvp: Feature[];
    v2: Feature[];
  };
  contracts: {
    inputs: InputField[];
    outputs: OutputField[];
    api?: ApiEndpoint[];
  };
  edgeCases: EdgeCase[];
  assumptions: Assumption[];
  openQuestions: string[];
  metadata: {
    completeness: number;
    generatedAt: string;
    sessionRounds: number;
  };
}

interface UserFlowStep {
  actor: string;
  action: string;
  outcome: string;
  alternatives?: {
    condition: string;
    outcome: string;
  }[];
}

interface Feature {
  name: string;
  description: string;
  acceptanceCriteria: string[];
  priority: 'critical' | 'important' | 'nice_to_have';
}

interface InputField {
  name: string;
  type: string;
  required: boolean;
  validation?: string;
  description: string;
}

interface OutputField {
  name: string;
  type: string;
  nullable: boolean;
  description: string;
}

interface EdgeCase {
  scenario: string;
  handling: string;
  priority: 'MVP' | 'V2';
}
```

## File Naming

```typescript
function generateFileName(requirement: string, format: string): string {
  const slug = requirement
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, '-')
    .replace(/^-|-$/g, '')
    .substring(0, 50);

  const extension = format === 'markdown' ? 'md' : format;
  return `${slug}-spec.${extension}`;
}
```

## Usage

```typescript
// In spec-compiler agent
const spec = compileSpec(session);
const formatted = formatMarkdown(spec);
const fileName = generateFileName(session.requirement, 'markdown');
writeFile(`outputs/specs/${fileName}`, formatted);
```

Related in General