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
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ apps/
packages/
cli logicsrc OpenSpec CLI
openontology OpenOntology reference engine (entities, claims, queries, change sets)
openprd OpenPRD reference implementation (numbered PRDs, lifecycle, task bridge)
logicsrc-mcp @profullstack/logicsrc-mcp standards MCP server
sdk SDK contract types and helpers
tui terminal UI
Expand Down Expand Up @@ -52,6 +53,24 @@ npm --workspace @profullstack/logicsrc-mcp run build
node packages/logicsrc-mcp/dist/index.js
```

## OpenPRD

[OpenPRD](docs/openprd.md) is a lightweight standard for product requirements documents: a repo
keeps a numbered, committed collection under `prd/`, one Markdown file each, with front-matter, a
fixed set of eight sections, and a lifecycle. `@logicsrc/openprd` implements it.

```bash
npm --workspace @logicsrc/cli run dev -- prd new "Expand the parked-domain service"
npm --workspace @logicsrc/cli run dev -- prd validate ./prd --strict
npm --workspace @logicsrc/cli run dev -- prd status 0001 Review
npm --workspace @logicsrc/cli run dev -- prd tasks 0001 --priority P0
```

Conformance failures (filename, front-matter, id match, the eight sections in order) are errors;
lint findings are warnings that `--strict` promotes. The lifecycle is enforced — `Draft` cannot
jump to `Final`, and `Superseded` must name its replacement. `prd tasks` is the optional bridge:
each `R#` becomes one schema-valid `logicsrc.task`.

## OpenOntology

[LogicSRC OpenOntology](docs/openontology.md) is an open contract for durable, source-backed domain
Expand Down
1 change: 1 addition & 0 deletions apps/logicsrc-web/src/app/sitemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const STATIC_ROUTES: Array<{
{ path: "/", changeFrequency: "weekly", priority: 1.0 },
{ path: "/docs", changeFrequency: "weekly", priority: 0.9 },
{ path: "/openontology", changeFrequency: "weekly", priority: 0.9 },
{ path: "/docs/openprd", changeFrequency: "weekly", priority: 0.8 },
{ path: "/openspec", changeFrequency: "weekly", priority: 0.8 },
{ path: "/agent-swarm", changeFrequency: "weekly", priority: 0.8 },
{ path: "/agentbyte", changeFrequency: "weekly", priority: 0.8 },
Expand Down
1 change: 1 addition & 0 deletions apps/logicsrc-web/src/components/site-shell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const NAV: Array<{ href: string; label: string; external?: boolean }> = [
{ href: "/agentbyte", label: "AgentByte" },
{ href: "/credential-sharing", label: "Credentials" },
{ href: "/openontology", label: "OpenOntology" },
{ href: "/docs/openprd", label: "OpenPRD" },
{ href: "/#cli", label: "CLI" },
{ href: "/docs", label: "Docs" },
{ href: "/blog", label: "Blog" },
Expand Down
1 change: 1 addition & 0 deletions apps/logicsrc-web/src/lib/docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const DOCS_DIR = resolve(process.cwd(), "../../docs");
// Curated, public-facing reference docs. Internal notes (roadmap, positioning,
// arcade) are intentionally excluded.
export const DOC_SLUGS = [
"openprd",
"openontology",
"openontology-governance",
"openontology-interoperability",
Expand Down
1 change: 1 addition & 0 deletions apps/logicsrc-web/src/lib/page-markup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ export function renderPageMarkup(): string {
<a href="/agentbyte">AgentByte</a>
<a href="/credential-sharing">Credentials</a>
<a href="/openontology">OpenOntology</a>
<a href="/docs/openprd">OpenPRD</a>
<a href="#cli">CLI</a>
<a href="/docs">Docs</a>
<a href="/blog">Blog</a>
Expand Down
50 changes: 49 additions & 1 deletion docs/openprd.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ OpenPRD is a lightweight, open standard for **product requirements documents** a

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.
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

Expand Down Expand Up @@ -87,6 +87,54 @@ See [`0000-template.md`](./openprd/0000-template.md) for the copy-paste template

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, eight 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 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.2` when:
Expand Down
17 changes: 17 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@
"apps/*"
],
"scripts": {
"build": "npm --workspace @logicsrc/schemas run build && npm --workspace @logicsrc/validators run build && npm --workspace @logicsrc/sdk run build && npm --workspace @logicsrc/agentad run build && npm --workspace @logicsrc/ans run build && npm --workspace @logicsrc/plugin-core run build && npm --workspace @logicsrc/agentstack run build && npm --workspace @logicsrc/agentswarm run build && npm --workspace @logicsrc/account-core run build && npm --workspace @logicsrc/plugin-coinpay run build && npm --workspace @logicsrc/plugin-ugig run build && npm --workspace @logicsrc/plugin-sh1pt run build && npm --workspace @logicsrc/plugin-c0mpute run build && npm --workspace @logicsrc/plugin-feed-discovery run build && npm --workspace @logicsrc/plugin-social-accounts run build && npm --workspace @logicsrc/plugin-email-accounts run build && npm --workspace @logicsrc/plugin-agentgit run build && npm --workspace @logicsrc/plugin-agentmail run build && npm --workspace @logicsrc/plugin-credential-sharing run build && npm --workspace @logicsrc/openontology run build && npm --workspace @logicsrc/tui run build && npm --workspace @logicsrc/cli run build && npm --workspace @profullstack/logicsrc-mcp run build && npm --workspace @logicsrc/commandboard-api run build && npm --workspace @logicsrc/commandboard-web run build && npm --workspace @logicsrc/web run build",
"build": "npm --workspace @logicsrc/schemas run build && npm --workspace @logicsrc/validators run build && npm --workspace @logicsrc/sdk run build && npm --workspace @logicsrc/agentad run build && npm --workspace @logicsrc/ans run build && npm --workspace @logicsrc/plugin-core run build && npm --workspace @logicsrc/agentstack run build && npm --workspace @logicsrc/agentswarm run build && npm --workspace @logicsrc/account-core run build && npm --workspace @logicsrc/plugin-coinpay run build && npm --workspace @logicsrc/plugin-ugig run build && npm --workspace @logicsrc/plugin-sh1pt run build && npm --workspace @logicsrc/plugin-c0mpute run build && npm --workspace @logicsrc/plugin-feed-discovery run build && npm --workspace @logicsrc/plugin-social-accounts run build && npm --workspace @logicsrc/plugin-email-accounts run build && npm --workspace @logicsrc/plugin-agentgit run build && npm --workspace @logicsrc/plugin-agentmail run build && npm --workspace @logicsrc/plugin-credential-sharing run build && npm --workspace @logicsrc/openontology run build && npm --workspace @logicsrc/openprd run build && npm --workspace @logicsrc/tui run build && npm --workspace @logicsrc/cli run build && npm --workspace @profullstack/logicsrc-mcp run build && npm --workspace @logicsrc/commandboard-api run build && npm --workspace @logicsrc/commandboard-web run build && npm --workspace @logicsrc/web run build",
"start": "npm --workspace @logicsrc/web run start",
"test": "npm run test --workspaces --if-present",
"check": "npm run build && npm run test",
"schemas:validate": "npm --workspace @logicsrc/validators run validate:fixtures",
"test:contract": "npm --workspace @logicsrc/commandboard-api run test:contract && npm --workspace @logicsrc/web run test:contract",
"test:e2e": "npm --workspace @logicsrc/commandboard-web run test:e2e && npm --workspace @logicsrc/web run test:e2e",
"build:cli": "npm --workspace @logicsrc/schemas run build && npm --workspace @logicsrc/validators run build && npm --workspace @logicsrc/plugin-core run build && npm --workspace @logicsrc/account-core run build && npm --workspace @logicsrc/plugin-coinpay run build && npm --workspace @logicsrc/plugin-ugig run build && npm --workspace @logicsrc/plugin-feed-discovery run build && npm --workspace @logicsrc/plugin-social-accounts run build && npm --workspace @logicsrc/plugin-email-accounts run build && npm --workspace @logicsrc/plugin-credential-sharing run build && npm --workspace @logicsrc/openontology run build && npm --workspace @logicsrc/tui run build && npm --workspace @logicsrc/cli run build"
"build:cli": "npm --workspace @logicsrc/schemas run build && npm --workspace @logicsrc/validators run build && npm --workspace @logicsrc/plugin-core run build && npm --workspace @logicsrc/account-core run build && npm --workspace @logicsrc/plugin-coinpay run build && npm --workspace @logicsrc/plugin-ugig run build && npm --workspace @logicsrc/plugin-feed-discovery run build && npm --workspace @logicsrc/plugin-social-accounts run build && npm --workspace @logicsrc/plugin-email-accounts run build && npm --workspace @logicsrc/plugin-credential-sharing run build && npm --workspace @logicsrc/openontology run build && npm --workspace @logicsrc/openprd run build && npm --workspace @logicsrc/tui run build && npm --workspace @logicsrc/cli run build"
},
"devDependencies": {
"@types/node": "^24.10.1",
Expand Down
1 change: 1 addition & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"dependencies": {
"@logicsrc/account-core": "file:../account-core",
"@logicsrc/openontology": "file:../openontology",
"@logicsrc/openprd": "file:../openprd",
"@logicsrc/plugin-coinpay": "file:../../plugins/coinpay",
"@logicsrc/plugin-core": "file:../plugin-core",
"@logicsrc/plugin-credential-sharing": "file:../../plugins/credential-sharing",
Expand Down
2 changes: 2 additions & 0 deletions packages/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { print, type OutputFormat } from "./format.js";
import { parsePositiveInteger } from "./numeric-options.js";
import { exportOpenSpecSummary, importOpenSpec, writeOpenSpecChange } from "./openspec.js";
import { registerOntologyCommands } from "./ontology.js";
import { registerPrdCommands } from "./prd.js";
import { defaultPluginRegistry } from "./registry.js";

process.stdout.on("error", (error: NodeJS.ErrnoException) => {
Expand Down Expand Up @@ -831,6 +832,7 @@ async function runYoloArcade(game: string, repo?: string) {
}

registerOntologyCommands(program);
registerPrdCommands(program);

program.parseAsync(process.argv).catch((error: unknown) => {
console.error(error instanceof Error ? error.message : String(error));
Expand Down
Loading
Loading