mirror of
https://github.com/profullstack/logicsrc.git
synced 2026-09-10 19:26:00 +00:00
OpenPRD 0.2 fixed eight body sections, none of which asked what the thing is
built on or how it earns. The stack got chosen in the first implementation PR
instead of at review, and a PRD could be filled out completely without anyone
writing down who pays. PRD 0006 had already grown a hand-rolled
`## Business model` section, which is the gap showing.
0.3 adds two required sections between `UX Notes` and `Success Metrics`:
- Tech Stack — languages, frameworks, datastores, third-party services, and
anything the work must not depend on. It makes the requirements costable.
- Monetization — the revenue model: who pays, for what, how much, and when.
`_None._` stays a valid answer, but it now has to be said out loud.
Adding required sections would normally invalidate every document already
written, so a document is now held to the section list its own `openprd:` key
fixes. A 0.2 document keeps conforming with eight sections, forever; a 0.3
document needs ten. Adoption is per document, and `logicsrc prd validate
--expect-version 0.3` (new flag, wiring up the validator option that already
existed) reports the stragglers as OP-L-VERSION.
The front-matter schema is untouched — both additions are body sections.
Conformance bundle proves both directions: invalid/missing-monetization.md
fails with OP-C-SECTION-MISSING, and valid/legacy-0-2.md passes unedited.
This repo's own PRDs 0001-0006 stay at 0.2 as standing evidence that the
compatibility rule holds. PRD 0007 records the decision at 0.3.
Claude-Session: https://claude.ai/code/session_017XRNNm6pK6nPi7rJ6bJNHu
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
168 lines
9 KiB
Markdown
168 lines
9 KiB
Markdown
# OpenPRD
|
|
|
|
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.
|
|
|
|
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*.
|
|
|
|
Tools such as the moshcode CLI consume this standard to publish PRDs into whatever repo you're working in. LogicSRC ships its own reference implementation — see [Implementation](#implementation).
|
|
|
|
## When to write one
|
|
|
|
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/
|
|
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
|
|
```
|
|
|
|
- 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 opens with a YAML front-matter block validated by
|
|
[`openprd-prd.schema.json`](../packages/schemas/schemas/openprd-prd.schema.json):
|
|
|
|
```yaml
|
|
---
|
|
openprd: "0.3" # 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
|
|
---
|
|
```
|
|
|
|
## Body sections
|
|
|
|
The body is Markdown with a fixed, ordered set of `##` sections. All are required (a section MAY be a single line such as `_None._`), which keeps every PRD skimmable and diffable. OpenPRD `0.3` fixes ten:
|
|
|
|
1. `## Problem` — the user/business problem, and why it matters now.
|
|
2. `## Goals` — what success looks like, as outcomes (not features).
|
|
3. `## Non-Goals` — explicitly out of scope, to bound the work.
|
|
4. `## Users` — who this is for; personas or segments.
|
|
5. `## Requirements` — numbered `R1`, `R2`, … each prefixed with a priority tag `[P0]`/`[P1]`/`[P2]`. One capability per line.
|
|
6. `## UX Notes` — flows, states, and constraints that shape the experience.
|
|
7. `## Tech Stack` — languages, frameworks, datastores, and third-party services the work will be built on, plus anything it must not depend on. Naming the stack in the PRD is what makes the requirements costable, and what stops the choice from being made silently in the first PR.
|
|
8. `## Monetization` — the revenue model: who pays, for what, how much, and when. Free, internal, or loss-leading work says so here (`_None._` is a valid answer, and a deliberate one); the section exists so that "how does this earn?" is answered before the code, not after the launch.
|
|
9. `## Success Metrics` — how the goals will be measured.
|
|
10. `## Risks & Open Questions` — known risks and decisions still owed.
|
|
|
|
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 `owner`/`repo` reuse LogicSRC identity and repo conventions. That bridge is optional and lives in tooling, not in this standard.
|
|
|
|
## Implementation
|
|
|
|
`@logicsrc/openprd` is the reference implementation, exposed through the LogicSRC CLI. A PRD is
|
|
still just a file: nothing below is required for a document to conform.
|
|
|
|
```bash
|
|
logicsrc prd init # create prd/ with the template and an index
|
|
logicsrc prd new "Expand the service" # next free number, filled front-matter, ten stub sections
|
|
logicsrc prd list # id, title, status, tags, requirement count
|
|
logicsrc prd show 0001 # front-matter, sections, and parsed requirements
|
|
logicsrc prd validate --strict # conformance + lint, exit 1 on error
|
|
logicsrc prd validate --expect-version 0.3 # flag PRDs still declaring an older version
|
|
logicsrc prd index --write # regenerate prd/README.md from what is on disk
|
|
logicsrc prd status 0001 Review # lifecycle move, refusing illegal transitions
|
|
logicsrc prd tasks 0001 # the optional LogicSRC task bridge
|
|
```
|
|
|
|
Validation separates the four conformance rules below from lint. Conformance failures are errors;
|
|
everything else — an empty section, a requirement with no priority tag, numbering that skips, a
|
|
stale index, a one-sided supersession link — is a warning or a note, and `--strict` promotes them.
|
|
Findings carry stable codes (`OP-C-SECTION-ORDER`, `OP-L-REQ-DUPLICATE`, …), the file, the line,
|
|
and a remediation hint. Exit codes: `0` ok, `1` invalid, `2` usage, `3` not found.
|
|
|
|
The lifecycle is enforced rather than advisory: `Draft` cannot jump to `Final`, terminal statuses
|
|
do not resume, and moving to `Superseded` requires naming the PRD that replaces it.
|
|
|
|
Requirement numbering, id uniqueness, and "no gaps" are checked across the whole collection, not
|
|
just per file — a repo with `0001` and `0003` and no `0002` fails.
|
|
|
|
### Task bridge
|
|
|
|
The optional mapping described above lives in tooling:
|
|
|
|
```bash
|
|
logicsrc prd tasks 0001 --priority P0 --format ndjson
|
|
```
|
|
|
|
Each `R#` becomes one `logicsrc.task` document, validated against `logicsrc-task.schema.json`
|
|
before it is emitted. The board defaults to `/prd/<id>`, `repo` carries over to `github_repo`, and
|
|
the creator DID is derived from the first author (`anthony@profullstack.com` →
|
|
`anthony.profullstack`) unless `--creator` says otherwise.
|
|
|
|
### Conformance bundle
|
|
|
|
`packages/schemas/fixtures/openprd/` holds fixtures a third-party implementation can run:
|
|
`conformance.json` lists documents that must validate and documents that must fail, each with the
|
|
error code it must produce. Because several rules depend on the filename, each fixture records the
|
|
name it must be validated as.
|
|
|
|
## Conformance
|
|
|
|
A document conforms to OpenPRD `0.3` when:
|
|
|
|
- it lives at `prd/<id>-<slug>.md` with a four-digit `<id>`,
|
|
- its front-matter validates against `openprd-prd.schema.json`,
|
|
- `id` equals the filename's numeric prefix, and
|
|
- all ten body sections are present in order.
|
|
|
|
## Versioning
|
|
|
|
A document is judged against the version it declares in its own `openprd:`
|
|
key, not against the newest one. That is what makes it safe to add a section:
|
|
|
|
| Version | Sections | Change |
|
|
| --- | --- | --- |
|
|
| `0.2` | eight | Problem … Risks & Open Questions |
|
|
| `0.3` | ten | adds `Tech Stack` and `Monetization` after `UX Notes` |
|
|
|
|
So a `0.2` document keeps conforming forever, and validators MUST hold it to
|
|
the eight sections `0.2` fixed. Adopting `0.3` in an existing collection is a
|
|
per-document edit: bump `openprd` to `"0.3"` and add the two sections, using
|
|
`_None._` where they do not apply. Nothing forces a whole collection to move at
|
|
once; a collection that wants uniformity asks for it with
|
|
`logicsrc prd validate --expect-version 0.3`, which reports every document
|
|
declaring something else as `OP-L-VERSION` (a warning, or an error under
|
|
`--strict`). Each document is still validated against the sections its own
|
|
version fixes.
|