mirror of
https://github.com/profullstack/logicsrc.git
synced 2026-09-10 19:26:00 +00:00
Add Tech Stack and Monetization sections to OpenPRD (0.3) (#144)
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>
This commit is contained in:
parent
ca0283caa9
commit
91834179b7
36 changed files with 679 additions and 80 deletions
|
|
@ -34,8 +34,10 @@ numbered, committed collection under prd/, one Markdown file each.
|
|||
for the template.
|
||||
- Front-matter carries openprd, id, title, status, authors, and optional repo,
|
||||
dates, discussion, implementation, tags, supersedes, superseded-by.
|
||||
- The body has eight required sections in order: Problem, Goals, Non-Goals,
|
||||
Users, Requirements, UX Notes, Success Metrics, Risks & Open Questions.
|
||||
- The body has ten required sections in order: Problem, Goals, Non-Goals,
|
||||
Users, Requirements, UX Notes, Tech Stack, Monetization, Success Metrics,
|
||||
Risks & Open Questions. (0.2 documents have eight: no Tech Stack, no
|
||||
Monetization. They are validated against the version they declare.)
|
||||
- Requirements are numbered R1, R2, … each tagged [P0], [P1], or [P2].
|
||||
- Lifecycle: Draft → Review → Accepted → Final, or Rejected / Withdrawn /
|
||||
Superseded. Status lives in front-matter and is the source of truth.
|
||||
|
|
@ -69,7 +71,7 @@ export function registerOpenPrd(server: McpServer): void {
|
|||
"logicsrc://openprd/spec",
|
||||
{
|
||||
title: "OpenPRD specification",
|
||||
description: "Numbered PRDs: layout, front-matter, the eight sections, and the lifecycle.",
|
||||
description: "Numbered PRDs: layout, front-matter, the ten sections, and the lifecycle.",
|
||||
mimeType: "text/markdown"
|
||||
},
|
||||
async () => ({
|
||||
|
|
@ -136,7 +138,7 @@ export function registerOpenPrd(server: McpServer): void {
|
|||
{
|
||||
title: "Validate the PRD collection",
|
||||
description:
|
||||
"Checks conformance — filename, front-matter, id match, the eight sections in order — plus collection rules.",
|
||||
"Checks conformance — filename, front-matter, id match, the sections in order — plus collection rules.",
|
||||
inputSchema: { strict: z.boolean().optional() },
|
||||
annotations: { readOnlyHint: true, openWorldHint: false }
|
||||
},
|
||||
|
|
@ -235,12 +237,18 @@ export function registerOpenPrd(server: McpServer): void {
|
|||
type: "text" as const,
|
||||
text: `Draft an OpenPRD document for the change the user describes.
|
||||
|
||||
Front-matter: openprd "0.2", a four-digit id matching the filename, an imperative
|
||||
Front-matter: openprd "0.3", a four-digit id matching the filename, an imperative
|
||||
title starting with a verb, status Draft, and at least one author.
|
||||
|
||||
Then all eight sections, in this order, none omitted:
|
||||
Problem, Goals, Non-Goals, Users, Requirements, UX Notes, Success Metrics,
|
||||
Risks & Open Questions. A section may be a single line such as _None._
|
||||
Then all ten sections, in this order, none omitted:
|
||||
Problem, Goals, Non-Goals, Users, Requirements, UX Notes, Tech Stack,
|
||||
Monetization, Success Metrics, Risks & Open Questions. A section may be a single
|
||||
line such as _None._
|
||||
|
||||
Tech Stack names the languages, frameworks, datastores, and third-party services
|
||||
the work will be built on, and anything it must not depend on. Monetization
|
||||
states the revenue model: who pays, for what, how much, and when — or _None._
|
||||
when the change does not earn on its own.
|
||||
|
||||
Requirements are numbered R1, R2, … contiguously, each tagged [P0], [P1], or [P2],
|
||||
one capability per line. Goals are outcomes, not features. Non-Goals bound the work.
|
||||
|
|
@ -263,13 +271,16 @@ they are settled.`
|
|||
type: "text" as const,
|
||||
text: `Review this PRD.
|
||||
|
||||
Check the shape first: all eight sections present and in order, requirements numbered
|
||||
contiguously with priority tags, front-matter complete.
|
||||
Check the shape first: every section the declared openprd version requires, present
|
||||
and in order, requirements numbered contiguously with priority tags, front-matter
|
||||
complete.
|
||||
|
||||
Then the substance: are the Goals outcomes rather than features? Do the Non-Goals
|
||||
actually bound the work? Is every P0 requirement testable? Do the Success Metrics
|
||||
measure the Goals? Do the Risks name real decisions still owed, or is that section
|
||||
decoration? Say what you would change and why.`
|
||||
measure the Goals? Is the Tech Stack specific enough to cost the Requirements, or
|
||||
is it a wish list? Does Monetization say who pays and how much, or does it dodge?
|
||||
Do the Risks name real decisions still owed, or is that section decoration? Say
|
||||
what you would change and why.`
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ describe("MCP: OpenPRD", () => {
|
|||
it("reports the next free id and the allowed lifecycle moves", async () => {
|
||||
const client = await connect();
|
||||
// Asserted against the live prd/ directory, so this advances with every PRD added.
|
||||
expect(toolText(await client.callTool({ name: "prd_next_id", arguments: {} }))).toBe("0007");
|
||||
expect(toolText(await client.callTool({ name: "prd_next_id", arguments: {} }))).toBe("0008");
|
||||
|
||||
const moves = await client.callTool({ name: "prd_next_statuses", arguments: { ref: "0001" } });
|
||||
const payload = JSON.parse(toolText(moves)) as { status: string; allowedNext: string[] };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue