markdown-contract
Teams keep decision records, runbooks, and planning docs in markdown — but nothing guarantees those documents keep the shape your team and tooling rely on. markdown-contract lets you declare a contract per document type (frontmatter fields, section structure, table shapes, custom rules) and gives you back two things from one parse:
- Validation — findings with
path:linepositions, as human text, JSON, or SARIF, with CI-ready exit codes. - A typed model — the contract that checks a document also types it:
doc.frontmatter.status,doc.body.summary.text(), iterable typed table rows.
import { contract, sections, section } from "markdown-contract";import { z } from "zod";
const decision = contract({ frontmatter: z.object({ status: z.enum(["proposed", "accepted"]) }), body: sections({ allowUnknown: true }, [section("Summary"), section("Decision")]),});
decision.validate(src, { path: "D-0001.md" }); // findings with path:line positionsdecision.read(src, { path: "D-0001.md" }); // typed Doc: frontmatter + body modelContracts can also be pure YAML — no code at all — and a declarative config maps directories and globs to contracts, so validating a whole docs tree is configuration. See Getting started.
Start here
Section titled “Start here”- Why markdown-contract — the gap it fills and the design drivers.
- How it works — one parse, three validation planes, one finding shape, and the typed model.
- Getting started — validate a folder from the terminal, then author a contract in YAML or TypeScript.
Learn it by example
Section titled “Learn it by example”The example catalog is a curriculum: eight short ladders of small, runnable examples, each rung building on the one before it. Every shipped artifact is regression-checked against the real CLI and library, so what you read is what the tool actually does.
- CLI Quickstart: Validate from the Terminal — 12 rungs, starting with CLI-01: Validate one clean file, see exit 0.
- Scaffold and Guard: init, Inference, and Drift Checks — 10 rungs, starting with INFERENCE-INIT-01: Scaffold a contract from a folder of notes.
- Declarative YAML: Contracts and Corpus Config, No Code — 20 rungs, starting with DECLARATIVE-YAML-01: Validate one required frontmatter field by type.
- Authoring Contracts in Code: Structure, Content, and Custom Rules — 17 rungs, starting with VALIDATION-PLANES-01: Parse markdown into a DocTree.
- Consume as Typed Data: Reading the Document as a Model — 11 rungs, starting with CONSUME-AS-DATA-01: Open the read() door for typed frontmatter.
- Dialect: Anchors, Wikilinks, and Vault References — 11 rungs, starting with DIALECT-01: Anchor a block, resolve it with byAnchor.
- Embed and Automate: the Runner Library and CI Gates — 11 rungs, starting with EMBED-AND-CI-01: Run the corpus in-process.
- Real-World Schemas: Document Templates and Cross-Document Governance — 16 rungs, starting with REAL-WORLD-SCHEMAS-01: ADR: require the four sections in order.