PDD version 0.34.1

The Product Model

A Product Model is a folder of Markdown files, product-model/, that says what one product does today: for whom, where, with what, and under which rules. It lives in your repository, changes in pull requests, and is checked by pdd-kit lint, which reports every rule a file breaks.

It describes the product, not the code: no files, frameworks or endpoints, only what a person using the product could confirm.

The shape of a model

Each file is one resource, and the folder it sits in decides its type.

product-model/
├── product.md              # the one Product
├── coverage.md             # which code the model accounts for
├── interfaces/             # where people and systems meet the Product
│   └── customer-web/
│       ├── interface.md
│       └── experiences/storefront/
│           ├── experience.md
│           └── screens/order-status.md
├── entities/               # what the Product keeps, including who acts
├── domains/                # optional subject areas
├── capabilities/           # what the Product can do
│   └── place-order/
│       ├── capability.md
│       └── scenarios/complete-checkout.md
├── journeys/               # goals that need several Capabilities
├── business-rules/         # what must stay true, and who may act
├── variations/             # supported alternatives, and what picks one
├── config.yaml  taxonomies.yaml  README.md  .gitignore

Two trees and a few cross-links. Where: Interface → Experience → Screen. What: Capability → Scenario, and Journey → Scenario. A Capability's availability (the places, each an Interface or Experience, where it is offered) joins the two, Domains group by subject, and Business Rules and Variations attach across everything.

What belongs in a model

Resource typeHow manyWhat it's for
ProductExactly oneThe product's promise and its boundary
EntityAt least one that actsA thing the Product keeps: what it knows about it and the states it moves through. An Entity that acts (a person or a system) is an Actor
InterfaceAt least oneA surface the Product offers: a web app, a mobile app, a CLI, an API, a webhook
ExperienceWhen an Interface needs dividingA context inside one Interface with its own audience and access
ScreenOptionalA place: what an Actor sees and can do there
DomainOptionalA subject area grouping Capabilities and Entities
CapabilityAt least oneSomething the Product can do, proven by its Scenarios
JourneyOptionalAn Actor's goal that takes several Capabilities
Business RuleOptionalSomething that must stay true, and the only place that says who may act
VariationOptionalTwo or more supported ways, and what decides which applies

Capabilities and Journeys each own Scenarios: concrete cases with a trigger, Steps and an outcome. A Step names the place it happens: a Screen, Experience or Interface.

Create an optional type only when it says something real. A small model is still a valid one.

Which type is this?

What you're looking atModel it as
A thing someone would call "this one", such as an order or a refundAn Entity
A person or system that starts something in the ProductAn Entity that acts
Something the Product calls out to, like a payment APINo Interface: the Capability that calls it says so in its prose
A surface that receives requests, such as an app, a CLI or a webhookAn Interface
Signed-out and signed-in parts of one InterfaceTwo Experiences
An empty or unauthorized viewA condition in the Scenario that meets it, not a Screen
One thing the Product doesA Capability
One case of it (success, refusal, edge)A Scenario of that Capability
A goal that takes several CapabilitiesA Journey
A rule shared by two or more behaviors, or any "who may"A Business Rule
A constraint true of one behavior only (not a "who may")A condition Step in its Scenario
A navigation section with two or more CapabilitiesA Domain
A flag, plan or setting that switches between supported ways (not one that only decides who may)A Variation
Looks, layout, copyNothing: design, attached as a Reference, a link to a file or page

Authoring conventions

  • Compact or expanded. A resource is <id>.md. When it gains children or files of its own, move it to <id>/<type>.md: place-order.md becomes place-order/capability.md. Never both.
  • The path is the id, and owns every parent: a Scenario never names its Capability. Interfaces, Experiences and Screens join their path with ::, as in customer-web::storefront::order-status.
  • The H1 is the title, and the paragraph under it the description (Journeys and Scenarios use their own sections instead).
  • Frontmatter holds relations; prose holds meaning. Unknown frontmatter keys are errors, not ignored.
  • ## Intent says why a resource exists and which outcome it protects ("Complete a purchase without confirming an unpaid order"), not what it does.
  • The model holds the present. No plans, priorities, metrics, or rejected options; those stay in the conversation or your planning tool.

Naming

  • Things that happen are verb-noun: Capabilities, Journeys and Scenarios (browse-catalog, not catalog-browsing).
  • Everything else is a bare noun: shopper, ordering, customer-web. A Business Rule reads as a statement, never a command: refunds-need-an-operator.
  • Use the Product's own words, from its screens and menus, never API values or code names: a role the screens call Editor is editor, even if the API sends member.
  • Name a Capability after its button (Archive, Share, Publish). Where the button only says Save, never use update: a Profile page in Settings saved with one button is change-profile-settings; a form editing one thing's own facts is edit-<thing>.
  • The title may read naturally; the id stays verb-noun: the Capability titled Catalog browsing has the id browse-catalog.
  • Reuse declared nouns: install-agent-skills, not install-skills, when agent-skills is already an Interface.

Is this replacing my PRD?

No. A PRD argues for a change; a Product Model describes the product. A PRD is future tense, one initiative, and history once the decision is made. The model is present tense, covers the whole product, and is either true now or wrong.

The model holds no timeline, priority, metrics, market case or risk: real product work, but not what the product does. The PRD's requirements section is the overlap, and pdd-ideate writes it straight into the model. Attach the PRD itself as a prdReference with role: intent.

Coverage

Coverage is about code, not the product. coverage.md says which of the repository's code the model accounts for, at the highest level that still tells an agent where to look and what to ignore. What the Product is or is not belongs in product.md.

coverage.md
---
scope: The storefront and order services.
method: Static inspection of source and documentation.
covered:
  - description: Checkout and order tracking code.
    paths: [src/checkout/, src/orders/]
exclusions:
  - description: The design system and email templates.
    paths: [src/ui/, emails/]
unmapped:
  - description: Background fulfillment jobs.
    paths: [server/jobs/]
limitations: []
---

# Coverage
FieldSays
scopeHow much of the code the model accounts for
methodHow the code was inspected, in one line, or ""
coveredCode whose behavior the model describes
exclusionsCode that is not product behavior, such as presentation or packaging
unmappedCode with behavior the model does not describe yet
limitationsCode whose behavior could not be established

Every field is required, and every entry names its code: a unique one-line description of the code area and its paths, usually folders. pdd-map writes coverage when it maps a repository. A model with no code yet — a Blueprint, or one you design first with pdd-ideate — has empty coverage until something maps its code. Known gaps never relax any other check.

What lint checks

All of these are errors:

  • product.md (or product/product.md), coverage.md, config.yaml, taxonomies.yaml, README.md and a .gitignore ignoring build/ and cache/ exist; there is at least one Interface and one Capability.
  • A resource has one shape: <id>.md and <id>/<type>.md never both, and an expanded folder has its <type>.md.
  • No unknown frontmatter keys, and each recognized ## section at most once.
  • coverage.md has every field, unique descriptions, and only # Coverage in its body; every entry names at least one path, and scope is set whenever there is an entry. With no entry, scope and method are both "".

Warnings:

  • An expanded folder with nothing in it yet.
  • A behavioral id that reads as a noun phrase, a cross-cutting id that opens with a verb, or a noun the model already declares more fully.