# PRD Writing Phase (Step 4)

**Precondition:** Discovery complete. UI Design complete or skipped.

Mark task 3 as `in_progress`.

## Write PRD

1. Create directory `${paths.prd_dir}/<slug>/` if it doesn't exist.
2. **Obsidian spec note (if present):** if the state file `## Obsidian Spec Note`
   section has `status` other than `none` (i.e. `detected`, `provisional-written`, or
   `back-reference-written` — a note was given), add a row to the Canonical Sources table
   in the PRD using its `wikilink:` value:
   `| Obsidian spec | [[Note Name]] |`
   This preserves traceability from the user's original spec note to the final PRD, and
   the same note receives the end-of-run back-reference snippet (validation-phase Step 7.6).
3. **Resolve canonical sources** before writing:
   - Read `${paths.references_dir}/ssot-registry.md` to identify the macro feature and any
     existing canonical docs.
   - If a Canonical Ownership Matrix exists for this project, check the path defined in
     `.baldart/overlays/prd.md § Canonical Ownership Matrix`; if absent, skip with a note.
   - Identify which existing PRDs, ADRs, reference docs, or backlog cards are canonical
     for this feature area.
   - **Mockup-derived canonical sources** (when `mockups.status` ∈ {`provided`, `partial`}
     in state file): treat `${paths.prd_dir}/<slug>/mockups/` as a canonical visual
     reference. Add a row to the PRD Canonical Sources table:
     `| Original mockups | ${paths.prd_dir}/<slug>/mockups/ |`. If chat images were
     analyzed without being copied to disk, add: `| Mockup chat | inline in PRD session — see Design Reference section |`.
3.5. **Schema Verification Gate (MANDATORY if feature touches the persistence layer)**

   Read `stack.database` from `baldart.config.yml`. If empty AND the feature
   description mentions data persistence, ASK the user which database is in
   use (once). If the user's answer is not a recognized database type or they
   answer "I don't know", log a one-line diagnostic, degrade to the universal
   vocabulary (`entity`/`field`), and proceed — do NOT loop. Persist a valid
   answer to `baldart.config.yml` (offer `npx baldart configure` if multiple
   keys are missing). Skip this gate when `stack.database: none` or the feature
   is stateless.

   The vocabulary in this gate adapts to `stack.database`:
   - Firestore / MongoDB / DynamoDB → "collections" / "documents" / "fields"
   - Postgres / Supabase / MySQL / SQLite → "tables" / "rows" / "columns"
   The procedure below uses **{entity}** = collection|table and **{field}** =
   field|column.

   If any of the following apply: new {entity}, modified {field}s, compound
   queries, or reading/writing existing rows/documents — run this gate before
   writing Section 5 (Data Model).

   **Procedure:**
   1. Identify every {entity} the feature uses or modifies.
   2. For each {entity}: read the project schema registry. The path is
      project-specific — common locations: `${paths.references_dir}/field-registry.json`
      (Firestore-style projects), `${paths.references_dir}/schema.md` (SQL),
      `${paths.references_dir}/collections/*.md` (per-collection markdown), or
      the migrations dir for SQL projects (`migrations/`, `db/migrate/`,
      `prisma/schema.prisma`, `supabase/migrations/`). Resolution order: check
      `.baldart/overlays/prd.md § Schema Registry` first if defined; otherwise
      pick the convention matching `stack.database`.
   3. Build a `## Schema Verification` section in the PRD (see template below).
   4. Mark each {field}: `✅ existing` | `🆕 new` | `❌ NOT FOUND`.
   5. **GATE**: if ANY {field} is `❌ NOT FOUND` and NOT marked as `🆕 new`:
      - STOP — do not advance to Section 5 (Data Model).
      - Ask the user: "Is `{fieldName}` in {entity} `{entityName}` a new {field} or a naming error?"
      - If new: add full schema definition in PRD Section 5 (Data Model) and mark `🆕`.
      - If error: correct the name.

   **Template `## Schema Verification`** (insert after PRD Acceptance Criteria section):

   ```markdown
   ## Schema Verification
   > Source: {schema-registry-path} — verified on {YYYY-MM-DD}
   > Database: {stack.database}
   > Complexity: HIGH | MEDIUM | LOW

   ### {entity}: {entityName}

   | {field} | Type | Status | Note |
   |---------|------|--------|------|
   | `fieldName` | string | ✅ existing | — |
   | `newField` | string | 🆕 new | schema in Section 5 |
   | `~~oldField~~` | — | ❌ NOT FOUND | rename mismatch |

   ### Open issues
   - (none) — or list of ❌ with required action
   ```

   **Universal fields:** auto-PK/ID, `createdAt`/`created_at`,
   `updatedAt`/`updated_at` are universal in their stack — do not require
   verification.

4. **Incorporate research findings** (if `## Research Findings` in state file is populated):
   - Reference best practices in data model, API, and architecture decisions.
   - Cite sources in PRD rationale sections.
   - Add anti-patterns from research to "Edge cases and failure modes" table.
   - If regulatory findings exist: add a dedicated "Compliance Requirements" section.
   - Include a "Research-Informed Decisions" subsection listing decisions influenced
     by research, with brief rationale and source reference.
5. Write `${paths.prd_dir}/<slug>/PRD.md` using the template from `assets/prd-template.md`.

### PRD sections checklist

Every PRD MUST include these sections (remove only when genuinely N/A):

- Problem statement
- Strategic rationale (Section 1b — from `## Business Rationale` in state file)
- Goals / non-goals
- Personas
- User stories
- Data model (type definitions matching the language stack, persistence-layer
    schema changes, validation rules, **Database Indexes & Query Optimization
    table** — MANDATORY if any compound query / multi-column index exists. Pick
    the variant matching `stack.database`: Firestore Composite, Postgres B-tree,
    MongoDB compound, DynamoDB GSI/LSI. See `assets/prd-template.md § 5`.)
- API contract changes (ALL endpoints — new routes are NOT exempt — request/response, validation)
- **Design Reference & Mockup Inventory** (if UI impact ≠ N/A — populate from
    `mockups.*`, `mockup_analysis.*`, `step_3_mode`, and `screens_in_scope[]` in
    the state file. Include the screen inventory table, the component mapping
    table when `features.has_design_system: true`, and the source-files
    traceability list. When `mockups.status: none`, the section is still present
    with the table empty and a note "Design generated in Step 3 — see design.html".)
- UI specifications (if applicable — when `## UI Element Inventory` is present in the
    state file, include the full inventory table verbatim and map each UI element to
    the requirement it satisfies; when `step_3_mode: skipped` the inventory is absent —
    populate this section from `mockups/` directory contents or, if no mockups exist,
    write a placeholder noting "UI design deferred — populate before implementation".
    Reference `design.html` path when available. Do NOT duplicate the screen list from
    the Design Reference section above — link to it.)
- i18n specification (dictionary keys, locale files)
- Acceptance criteria (grouped by area: one group per persona drawn from
    `identity.audience_segments[]`, plus cross-cutting groups: API, i18n,
    Observability if relevant)
- Edge cases and failure modes (table format)
- Out of scope
- Dependencies (table with type and status)
- Pipeline touchpoints (implementation summary table)
- Integration Surface Map (ISA) — from discovery dimension 9: every existing-code
  touchpoint that must reference the new feature, with risk levels and card mapping.
  Every ISA entry MUST map to at least one backlog card.
- Canonical Sources (macro feature, requirements owner, refs)
- Implementation References (exact file paths with relevance)
- Documentation Impact — which reference docs, indexes, registry entries, or ADRs
  need follow-up updates. Flag ADR-worthy decisions: DB schema changes, API contract
  changes, new external dependencies, auth changes.
- Backlog Links — epic/card links (placeholders if cards not yet created)
- Open questions (only genuine unresolved items)

### Navigation and freshness pass

Before presenting the PRD:

- Verify canonical sources resolve through ssot-registry or valid backlog links.
- Flag any `REGISTRY_GAP` (feature not yet in ssot-registry).
- Remove temp/local/absolute paths from canonical sections.

## Step 4.5 — API Performance Gate

**Precondition:** PRD written (Step 4 complete).

Before presenting the PRD to the user, run the API Performance Gate to catch
cost and performance anti-patterns while they are still cheap to fix.

**Delegated to the `api-perf-cost-auditor` agent** — `api-perf-gate.md` is its gate
specification, not an inline checklist the orchestrator runs itself.

### Procedure

1. **Spawn the `api-perf-cost-auditor` agent** via the Task tool (`subagent_type: api-perf-cost-auditor`,
   `mode: bypassPermissions`). Pass it: (a) the PRD path, (b) the instruction to run the
   full 5-gate protocol defined in `framework/.claude/skills/prd/references/api-perf-gate.md`
   as its spec, and (c) the resolved `stack.database` / `stack.deployment` from
   `baldart.config.yml` for the pricing/cost model. Gate 5 (Text Scan) ALWAYS runs; Gates 1-4
   (Data Model, Query & Index, Serverless, Caching) run when Gate 5 matches OR the PRD has
   API/data-model sections — otherwise the agent records the Gate 5 result and notes the 1-4 skip.
2. **Read the agent's returned findings** (severity-tagged: CRITICAL/HIGH/MEDIUM/LOW).
3. Apply the findings to the PRD (the orchestrator owns the edits — the agent only reports):
   - CRITICAL/HIGH: edit the PRD directly (add NFR, modify API contract, add edge case) before
     the user sees it.
   - MEDIUM: add to the edge-cases table.
   - LOW: note in state file only.
4. If CRITICAL findings were resolved, add a `### Performance-Informed Decisions` subsection to the PRD.
5. Update state file `## API Performance Gate` (status + findings) so the card-level audit
   (audit-phase Step 6) can read prior gate verdicts.

**Gate (BLOCKING):** all CRITICAL findings must be resolved in the PRD before Present & Confirm —
do NOT present a PRD with an unresolved CRITICAL performance/cost finding.

## Present and Confirm

1. Update state file `## Confirmed Specs` with FR/NFR lists.
2. Present structured summary to user: all FR + NFR + visual specs.
3. If API Performance Gate ran, include a brief summary:
   `**Performance Gate**: N findings integrated in PRD (X critical resolved, Y high as NFR).`

**STOP.** Wait for user confirmation. If user requests changes, edit PRD.md and
re-present. Do NOT proceed to backlog cards without explicit user approval.

**Gate:** explicit user confirmation of specs.

Mark task 3 as `completed`. Update state file status to `cards-writing`.
