Markdown PRD parser. The entry point for turning product requirements into a typed BlueprintGraph. The rest of the pipeline (analysis, execution, versioning) operates on the graph this package produces.
0.1.3. Active development.
@abhinav2203/codeflow-prd (parsePrd, buildBlueprintGraph)
@abhinav2203/codeflow-prd/build (buildBlueprintGraph)
The root barrel re-exports both parsePrd and buildBlueprintGraph. Most consumers use the root.
parsePrd(prdText: string): { nodes, edges, workflows, warnings } walks the markdown line by line. The parser recognizes five patterns:
- Headings become
modulenodes (#) or subnodes (##/###). Subheading text drives the node kind via keyword matching. - Inline tags like
api: POST /users/:idorfunction validateEmail(email: string): booleanbecome typed nodes with inferred contracts. - HTTP method patterns (
GET /path,POST /path,PUT /path,DELETE /path) becomeapinodes. - Signature lines (
name(params): returnType) become method specs on the most recent node. - Workflow lines (
a -> b -> cora ->> b -> c) becomecallsedges withconfidence: 0.7.
Each detected line becomes a BlueprintNode with:
- An
emptyContract()(zero attributes, zero methods, zero I/O) - An inferred contract built from the tag/signature, if applicable
- A
sourceRefs: [{ kind: 'prd', section, detail }]pointing back to the line
Warnings are emitted when the parser detects ambiguity (a heading matches multiple kind keywords, a signature has an unrecognized type, a workflow references an unknown node).
Keyword matching on heading text drives the kind:
| Keywords in heading | Kind |
|---|---|
screen, page, ui, frontend |
ui-screen |
api, endpoint, route, backend |
api |
class, service, controller, manager |
class |
function, method |
function |
module, component, domain |
module |
| (no match) | inherits from parent heading |
Inline tags override heading inference. If a heading says "API" and a line under it says function foo(), the function wins for that line.
buildBlueprintGraph(request: BuildBlueprintRequest) is the higher-level entry point. Currently consumes only request.prdText. The signature reserves space for future inputs:
type BuildBlueprintRequest = {
projectName: string;
prdText: string;
repoPath?: string; // reserved: triggers PRD + repo analysis merge
docsPath?: string; // reserved: triggers PRD + CodeRag merge
};The function:
- Runs
parsePrdon the text - Wraps the partial graph with
projectName,mode: 'spec',phase: 'spec',generatedAt - Calls
withSpecDraftsfromcodeflow-executionto backfillspecDraftplaceholders for any code-bearing node missing one - Returns the wrapped graph
mode: 'spec' flags the graph as a spec-only artifact. Callers can validate the graph passes the analyzer's parseBlueprintGraph before passing it downstream.
utils.ts ships pure helpers used during graph composition:
mergeContracts(a, b)- merge two contracts (fields, methods, I/O) into one. Used when the PRD and the repo define overlapping nodes.mergeSourceRefs(a, b)- concatenate and dedupe source provenance.mergeMethodSpecs(a, b)- merge two method spec lists.mergeFields(a, b)- merge two field lists, deduping by name.mergeStringLists(a, b)- concatenate and dedupe string arrays.dedupeEdges(edges)- remove duplicate edges by{from, to, kind}.
All merge helpers are deterministic and order-preserving. Two runs of the same merge over the same inputs produce identical output.
src/
├── index.ts # parsePrd, buildBlueprintGraph
├── prd.ts # parsePrd implementation
├── build.ts # buildBlueprintGraph
├── invoke.ts # barrel (alias of index)
├── utils.ts # merge helpers, slugify, createNodeId
├── prd.test.ts # parser tests
└── build.test.ts # build tests
To get the cleanest graph, follow these conventions in your PRD:
- Use one
#per top-level domain (e.g.# Auth Service). - Use
##for the next layer (e.g.## Login Flow). - Use a single inline tag per code line:
api: POST /path,function name(): type,screen: Name. - Put signatures on their own line, indented under the node.
- For workflows, use
a -> b -> cfor sync flows anda ->> bfor async.
A well-formed PRD gives you a graph that needs no manual repair.
- The parser is line-oriented. Multi-line signatures or block-level tags are not detected.
- Workflow lines use
confidence: 0.7. Downstream consumers should treat them as suggestions, not ground truth. - The parser does not validate referenced symbols. A workflow
auth -> billingproduces an edge even if noauthorbillingnode exists. The validator runs atbuildBlueprintGraphtime and emits warnings.
- Add a regex/keyword matcher in
prd.ts. - Emit a node or edge with the right kind and contract.
- Add a test in
prd.test.tsthat covers the new pattern. - Add a section to the PRD style guide above.
The keyword map in prd.ts is a frozen object. To add a domain-specific alias, fork the map and pass a custom parser config (a planned API, not yet shipped). For now, work around with inline tags.