feat(openprd): revise standard to DIP-style numbered proposals (0.2) (#96)

Reshape OpenPRD from a private single-file (prd/<slug>/prd.md, gitignored) into a
published, numbered proposal collection like BIP/EIP/DIP: prd/NNNN-slug.md +
0000-template.md + a README index, committed to the repo, with a lifecycle
(Draft → Review → Accepted → Final; Rejected/Withdrawn/Superseded).

Tools (e.g. moshcode /prd) consume this to publish PRDs into whatever repo the
user is working in.

- docs/openprd.md — rewritten: numbering, lifecycle, directory layout, conformance.
- docs/openprd/0000-template.md — the canonical template.
- packages/schemas/schemas/openprd-prd.schema.json — 4-digit id, status enum,
  authors, discussion/implementation, supersedes/superseded-by.
- fixture updated to 0.2.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Anthony Ettinger 2026-07-12 08:55:19 -07:00 committed by GitHub
parent 9346d02a39
commit 756c3f6f21
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 142 additions and 78 deletions

View file

@ -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
- anthony@profullstack.com
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
---
```
@ -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.

View file

@ -0,0 +1,50 @@
---
openprd: "0.2"
id: "0000"
title: "Short imperative title — start with a verb if possible"
status: Draft
authors:
- you@example.com
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.