Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 54 additions & 61 deletions docs/openprd.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,70 @@
# OpenPRD

OpenPRD is a lightweight, open standard for **product requirements documents** authored by humans or AI agents. It is maintained by Profullstack, Inc. as part of the LogicSRC open-standards surface.
OpenPRD is a lightweight, open standard for **product requirements documents** authored by humans or AI agents, maintained by Profullstack, Inc. as part of the LogicSRC open-standards surface.

Where [OpenSpec](./openspec-comparison.md) models a *change* as a multi-file bundle (proposal + design + specs + tasks + deltas), OpenPRD deliberately models a *product decision* as **one Markdown file**. It answers "what are we building and why", not "how the change is structured for implementation". The single-file shape is the point: it is the low-ceremony front door that a `prd` CLI command can produce in one step.
It borrows the shape of a BIP/EIP/DIP process: a repo keeps a **numbered, committed collection** of PRDs under `prd/`, each one a single Markdown file with a fixed set of sections and a lifecycle. Where [OpenSpec](./openspec-comparison.md) models a *change* as a multi-file bundle, OpenPRD models a *product decision* as **one numbered file** you can read a year from now to recover the *why*.

## Privacy
Tools such as the moshcode CLI consume this standard to publish PRDs into whatever repo you're working in.

**PRD documents are private by convention.** Only this standard is published. Generated PRDs live under a repo-local `prd/` directory that SHOULD be listed in `.gitignore`. Tools that write OpenPRD documents MUST NOT publish them anywhere by default.
## When to write one

## File layout
Write a PRD when a change introduces or reshapes a product capability — a new feature, surface, or user-facing behavior whose requirements deserve to be agreed *before* code lands. Small, obvious changes just get a PR. If you're unsure, write a short one; three paragraphs is fine.

## Directory layout

```txt
prd/
<slug>/
prd.md # one OpenPRD document (front-matter manifest + body)
README.md # index of PRDs (generated/maintained by tooling)
0000-template.md # the OpenPRD template — copy to start a new PRD
0001-<slug>.md # numbered PRDs, one file each
0002-<slug>.md
```

- `<slug>` is a kebab-case identifier, unique within the repo, and equal to the manifest `id`.
- A repo MAY contain many PRDs; each is a self-contained directory so attachments (mockups, notes) can sit beside `prd.md`.
- PRDs are **committed to the repo** (public within that repo) — like `dips/`, not gitignored.
- One file per PRD: `prd/<id>-<slug>.md`, where `<id>` is the four-digit number and `<slug>` is a kebab-case summary of the title.

## Numbering

Four-digit, zero-padded, monotonically increasing, no gaps: `0001`, `0002`, `0003`. `0000` is reserved for the template. Assign the next free number when the PRD is created — don't reserve in advance.

## Lifecycle

```txt
Draft → Review → Accepted → Final
↘ Rejected
↘ Withdrawn
↘ Superseded by NNNN
```

- **Draft** — author is still iterating.
- **Review** — open for discussion (typically on the PR that introduces the PRD).
- **Accepted** — requirements agreed; implementation may begin.
- **Final** — implementation shipped; the PRD is now historical record. Don't edit a Final PRD except for typos — open a follow-up that supersedes it.
- **Rejected / Withdrawn / Superseded** — kept on disk; the *why* is part of the record.

Status lives in the front-matter and is the source of truth.

## Manifest (front-matter)

Every `prd.md` opens with a YAML front-matter block validated by
Every PRD opens with a YAML front-matter block validated by
[`openprd-prd.schema.json`](../packages/schemas/schemas/openprd-prd.schema.json):

```yaml
---
openprd: "0.1" # standard version (required)
id: park-service-expansion # kebab-case slug == directory name (required)
title: Parked-domain service expansion # (required)
status: draft # draft | review | active | shipped | archived (required)
owner: did:key:… # optional DID/handle of the accountable owner
repo: moshcoder/moshcoding # optional target repo (owner/name)
created: 2026-07-12 # optional ISO date
updated: 2026-07-12 # optional ISO date
tags: [growth, monetization] # optional labels
supersedes: [old-slug] # optional ids this PRD replaces
openprd: "0.2" # standard version (required)
id: "0001" # 4-digit number == filename prefix (required)
title: Expand the parked-domain service # imperative title (required)
status: Draft # Draft|Review|Accepted|Final|Rejected|Withdrawn|Superseded (required)
authors: # at least one
- [email protected]
repo: moshcoder/moshcoding # optional target repo (owner/name)
created: 2026-07-12 # optional ISO date
updated: 2026-07-12 # optional ISO date
discussion: # optional URL to the PR/issue/thread
implementation: # optional URL to the impl PR/tracking issue
tags: [growth] # optional labels
supersedes: # optional 4-digit id this PRD replaces
superseded-by: # optional 4-digit id that replaces this PRD
---
```

Expand All @@ -52,53 +81,17 @@ The body is Markdown with a fixed, ordered set of `##` sections. All are require
7. `## Success Metrics` — how the goals will be measured.
8. `## Risks & Open Questions` — known risks and decisions still owed.

### Minimal example

```markdown
---
openprd: "0.1"
id: launch-flip
title: Coming-soon → live launch flip
status: draft
---

## Problem
Parked domains have no one-click path from coming-soon to a live site.

## Goals
Owners flip a domain live and notify its waitlist in a single action.

## Non-Goals
_Building the live site itself._

## Users
Domain owners running parked pages on the service.

## Requirements
- R1 [P0] A per-domain "go live" action publishes/redirects the domain.
- R2 [P0] Flipping live emails that domain's waitlist.
- R3 [P1] The action is reversible within a grace window.

## UX Notes
One button on the domain's admin row; confirm dialog shows the waitlist size.

## Success Metrics
Time-to-live per domain; waitlist → visit conversion after launch.

## Risks & Open Questions
- Email deliverability on bulk launch sends.
- Should redirects preserve `?dn=` analytics?
```
See [`0000-template.md`](./openprd/0000-template.md) for the copy-paste template.

## Relationship to LogicSRC

OpenPRD is intentionally decoupled from the rest of LogicSRC: a PRD is just a file and needs no service to exist. When coordination is wanted, a PRD's `Requirements` map cleanly onto LogicSRC `task` documents (each `R#` → one task), and the PRD `owner`/`repo` reuse LogicSRC identity and repo conventions. That bridge is optional and lives in tooling, not in this standard.
OpenPRD is intentionally decoupled from the rest of LogicSRC: a PRD is just a file and needs no service to exist. When coordination is wanted, a PRD's `Requirements` map cleanly onto LogicSRC `task` documents (each `R#` → one task), and `owner`/`repo` reuse LogicSRC identity and repo conventions. That bridge is optional and lives in tooling, not in this standard.

## Conformance

A document conforms to OpenPRD `0.1` when:
A document conforms to OpenPRD `0.2` when:

- it lives at `prd/<slug>/prd.md`,
- it lives at `prd/<id>-<slug>.md` with a four-digit `<id>`,
- its front-matter validates against `openprd-prd.schema.json`,
- `id` equals `<slug>`, and
- `id` equals the filename's numeric prefix, and
- all eight body sections are present in order.
50 changes: 50 additions & 0 deletions docs/openprd/0000-template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
openprd: "0.2"
id: "0000"
title: "Short imperative title — start with a verb if possible"
status: Draft
authors:
- [email protected]
created: 2026-01-01
updated: 2026-01-01
repo:
discussion:
implementation:
tags:
supersedes:
superseded-by:
---

## Problem

The user/business problem, and why it matters now. Cite the ask, the incident,
or the constraint — not aesthetics.

## Goals

What success looks like, as outcomes (not features).

## Non-Goals

Explicitly out of scope, to bound the work.

## Users

Who this is for; personas or segments.

## Requirements

- R1 [P0] First required capability.
- R2 [P1] Next capability.

## UX Notes

Flows, states, and constraints that shape the experience.

## Success Metrics

How the goals will be measured.

## Risks & Open Questions

- Known risk or decision still owed.
12 changes: 7 additions & 5 deletions packages/schemas/fixtures/openprd-prd.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
openprd: "0.1"
id: park-service-expansion
title: Parked-domain service expansion
status: draft
owner: moshcoder.coinpay
openprd: "0.2"
id: "0001"
title: Expand the parked-domain service
status: Draft
authors:
- [email protected]
repo: moshcoder/moshcoding
created: 2026-07-12
updated: 2026-07-12
tags:
- growth
- monetization
43 changes: 31 additions & 12 deletions packages/schemas/schemas/openprd-prd.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,41 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schemas.logicsrc.com/openprd-prd.schema.json",
"title": "OpenPRD Product Requirements Document",
"description": "The front-matter manifest of an OpenPRD document. OpenPRD is a deliberately lightweight, single-file PRD standard: one prd/<slug>/prd.md per product decision, authored by a human or an AI agent. The document body is Markdown with a fixed set of sections; this schema governs only the YAML front-matter. PRD documents are private by convention (gitignored) — only the OpenPRD standard itself is published.",
"description": "The front-matter manifest of an OpenPRD document. OpenPRD is a lightweight, DIP-style proposal standard: a repo publishes a numbered collection of PRDs under prd/ (prd/NNNN-slug.md), with a 0000-template.md and a README index, committed to the repo like a BIP/EIP/DIP process. This schema governs the YAML front-matter; the body is Markdown with a fixed set of sections.",
"type": "object",
"required": ["openprd", "id", "title", "status"],
"additionalProperties": false,
"properties": {
"openprd": {
"type": "string",
"pattern": "^\\d+\\.\\d+(\\.\\d+)?$",
"description": "OpenPRD standard version this document conforms to, e.g. '0.1'."
"description": "OpenPRD standard version this document conforms to, e.g. '0.2'."
},
"id": {
"type": "string",
"pattern": "^[a-z0-9][a-z0-9-]*$",
"description": "Kebab-case slug, unique within the repo. Also the directory name: prd/<id>/prd.md."
"pattern": "^\\d{4}$",
"description": "Four-digit zero-padded number, monotonically increasing with no gaps. Matches the filename prefix: prd/<id>-<slug>.md."
},
"title": {
"type": "string",
"minLength": 1,
"description": "Human-readable product/feature title."
"description": "Short imperative title — start with a verb where possible."
},
"status": {
"type": "string",
"enum": ["draft", "review", "active", "shipped", "archived"],
"description": "Lifecycle stage of the PRD."
"enum": ["Draft", "Review", "Accepted", "Final", "Rejected", "Withdrawn", "Superseded"],
"description": "Lifecycle stage. Draft → Review → Accepted → Final; or Rejected/Withdrawn/Superseded."
},
"authors": {
"type": "array",
"items": { "type": "string" },
"minItems": 1,
"uniqueItems": true,
"description": "Author identities — email, handle, or DID."
},
"owner": {
"type": "string",
"description": "Optional DID or handle of the accountable owner, e.g. a LogicSRC agent or account DID."
"description": "Optional DID or handle of the accountable owner (e.g. a LogicSRC account/agent DID)."
},
"repo": {
"type": "string",
Expand All @@ -45,17 +52,29 @@
"format": "date",
"description": "ISO date (YYYY-MM-DD) of the last substantive edit."
},
"discussion": {
"type": "string",
"description": "Optional URL to the PR/issue/thread where this PRD is discussed."
},
"implementation": {
"type": "string",
"description": "Optional URL/reference to the implementation PR or tracking issue."
},
"tags": {
"type": "array",
"items": { "type": "string" },
"uniqueItems": true,
"description": "Optional freeform labels for grouping PRDs."
},
"supersedes": {
"type": "array",
"items": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*$" },
"uniqueItems": true,
"description": "Optional ids of earlier PRDs this one replaces."
"type": "string",
"pattern": "^\\d{4}$",
"description": "Optional id of an earlier PRD this one replaces."
},
"superseded-by": {
"type": "string",
"pattern": "^\\d{4}$",
"description": "Optional id of a later PRD that replaces this one."
}
}
}
Loading