Reference
The veri/ on-disk format. Everything here is plain markdown with YAML frontmatter — readable raw, diffable, and owned by your repo, not by Veri.
Directory layout
your-project/
├── .mcp.json ← agent connection config (written by the app)
└── veri/
├── format ← format version marker (currently "1")
├── workflow.md ← WF-001, the project workflow
├── requirements/ ← REQ-001-….md
├── decisions/ ← DEC-001-….md
├── work-orders/ ← WO-001-….md
├── sources/ ← SRC-001-….md
└── templates/ ← seed bodies for new documents
The format file holds a single integer. Veri reads it before parsing anything: a project needing a newer Veri is stated as such (never misparsed), an older-format project is offered an explicit migration (veri migrate), and a directory created before the marker existed is treated as the oldest format, not rejected.
Document types and statuses
| Type | Id prefix | Statuses | Notes |
|---|---|---|---|
| requirement | REQ- | draft → accepted → retired | accepted requires an approved: date — the user's stamp. |
| decision | DEC- | proposed → active → superseded | active requires approved:; superseded must name its successor in superseded_by:. |
| work-order | WO- | backlog → in-progress → done | in-progress is entered only via veri dispatch — one human gesture that writes the approval stamp (approved:) and the claim (claimed_by/claimed_at — who holds the work) together; a stamp already on record is spent, never re-dated. done requires every acceptance box checked and at least one receipt. |
| source | SRC- | imported | External evidence; one status, no lifecycle. |
| workflow | WF- | draft → accepted → retired | One per project; scaffolded projects ship theirs pre-accepted. |
Frontmatter
---
id: WO-002
type: work-order
title: PDF export pipeline
status: in-progress
created: 2026-07-30
updated: 2026-08-06
links:
- id: REQ-002
rel: implements
- id: DEC-005
rel: constrained-by
binds:
paths:
- src/export/**
tests:
- tests/export.test.ts
---
id— type prefix plus a number of three or more digits, zero-padded to three below 1000 (REQ-001,REQ-1000). The prefix must matchtype. Ids are assigned by the app/CLI as the next free number and never reused.created/updated/approved—YYYY-MM-DDdates.approvedappears only when the user promotes a document.approved_by— the display name of the maintainer who stamped the approval. Written byveri approve --as, and byveri dispatch --byfor work orders; required (and validated against the workflow'smaintainers:list) only in projects that declare one — see the team workflow.links— outbound edges: a targetidand arel. Inbound links are derived, never stored.binds— (work orders, optional) the code this work order claims:pathsis repo-root-relative globs (*and?within a segment,**across segments, a bare directory claims everything under it);testsis test files proving it, as a path orpath::namewhere the name must appear in the file. See binding drift.- Unknown keys are preserved — Veri round-trips frontmatter it doesn't recognize, so your own fields are safe.
Links and rels
In document bodies, [[REQ-001]] references any document by id (the app autocompletes on [[); broken references are flagged by veri check. In frontmatter, rel is free text — use what reads truthfully — but these are the conventions in use:
| rel | Meaning (A → B) |
|---|---|
implements | A delivers what B requires (work order → requirement). |
constrained-by / constrains | B binds choices inside A (work order ↔ decision). |
informed-by | B is evidence behind A (anything → source). |
depends-on | A needs B to exist or hold first. |
extends / refines / builds-on / follows-from | A continues or narrows B (decision lineages, requirement families). |
designed-by | B is the design artifact for A. Load-bearing when a project enforces a design gate: work orders touching UI must carry one. |
Templates
veri/templates/ holds the seed body for each type; veri new and the app's New-document flow start from them, and veri check expects each document to keep its template's ## sections. The defaults:
- requirement — description, then
## Acceptance criteria - decision —
## Choice,## Rejected alternatives,## Rationale - work-order —
## Summary,## In scope,## Out of scope,## Acceptance tests,## Receipts(requirement links live in frontmatter, not a body section) - source — free-form imported material
Edit the templates and your project's new documents start your way; context packages include them so agents file documents in your shape too.
veri check rules
Zero issues is the bar — the app surfaces these live, and veri check exits non-zero in CI when any fire:
| Rule | Fires when |
|---|---|
duplicate-id | Two files claim the same id — the merge-collision case; the error names every claimant and the veri renumber resolution (see teams). |
broken-link | A frontmatter link, superseded_by, or inline [[ref]] targets an id no document has. |
wo-without-requirement | A work order links no requirement — unjustified work. |
unclaimed-wo | A work order is in-progress without claimed_by/claimed_at — no record of which session holds it. veri dispatch writes the claim. |
gated-wo | A work order moved forward while depending on a document still awaiting approval — approve the dependency first. |
missing-approval | A document sits in a promoted status (accepted, active) without the user's approved: stamp. |
unknown-approver | (Maintainers projects) approved_by names someone not on the workflow's maintainers: list. A promoted document missing approved_by only warns — pre-team stamps are grandfathered as an advisory. |
done-wo-violation | A work order is done with unchecked acceptance boxes or no receipt. |
ui-wo-without-design | (Design-gated projects) a started work order declares a design-gated path in binds.paths but has no resolvable designed-by link — the message names the declaration as its evidence. |
missing-section | A document lost a ## section its type's template expects. |
format-mismatch | The veri/format marker doesn't match what this Veri reads — migrate, or update Veri. |
Softer signals ship as advisories — shown greyed in the app, never failing the check.
Claims
The claim (claimed_by/claimed_at, written by veri dispatch) is a declaration in the knowledge base, not a lock — and two advisories watch it, needing no git:
| Advisory | Fires when |
|---|---|
shared-claim | One claim identity holds two in-progress work orders that do not reference each other — one session, one work order is the convention for parallel agent runs. A declared chain (either work order linking or citing the other) is exempt: splitting out a prerequisite and starting it is deliberate. |
stale-claim | A claimed in-progress work order's newest sign of life — the claim date or its latest receipt — is older than the staleness window (the same stale_after_days knob binding drift uses; default 14 days). A crashed or abandoned session leaves exactly this trace. |
Binding drift
When an in-progress work order declares binds, veri check also watches the code side of the contract. Three advisories — deterministic, derived from git history on demand, and never failing the check:
| Advisory | Fires when |
|---|---|
drift-unclaimed-change | A commit since the in-progress work began touches code that no in-progress work order's binds.paths matches and whose subject names no work order — code changing outside every declared claim. |
drift-stale-wo | An in-progress work order's bound paths have seen no commits for the staleness window (default 14 days; set stale_after_days on the workflow document to change it). |
drift-missing-test | A bound test no longer resolves: the file is gone, or the ::name no longer appears in it. |
"Since the in-progress work began" is derived, never stored: a commit whose subject names the work order and a form of "start" anchors it, falling back to the work order's created date. Work orders without binds change nothing — the detectors are inert until a project opts in. Outside a git repository they skip with a note.
Design gate
In projects that declare design_gate_paths on the workflow document, the gate's hard tier is the ui-wo-without-design issue above, read from each work order's own binds.paths declaration. Two advisories cover what a declaration cannot:
| Advisory | Fires when |
|---|---|
design-undeclared-touch | An in-progress work order's claimed commits (the WO-nnn: subject convention) touched a file under a gated path the work order neither declares in binds.paths nor covers with a designed-by link — gated work done while declaring nothing. Git-backed; outside a git repository it skips with a note. |
design-mention | A started work order that declares no binds.paths and links no design names a gated path in its prose (## Out of scope and ## Receipts excluded) — a nudge to declare the path or link the design before the work touches it. |
The CLI
veri init [--demo] [--starter <name>]
scaffold a veri/ directory (--demo: the sample
project; --starter: seed draft requirements, proposed
decisions, and a workflow tuned to a project type —
cli-tool, library, or web-app — all pending your
approval)
veri new <type> "<title>" [--approve [--as <maintainer>]]
create a document with the next free id; --approve:
when you are the author, the filing carries your
stamp — born promoted, same gates as veri approve,
one commit
veri check report knowledge-base issues (exit 1 if any)
veri approve <id> [--as <maintainer>]
approve a pending document (stamps approved: today,
and approved_by: in maintainers projects); work
orders refuse — they are dispatched, not approved
veri next print the backlog work order next awaiting your
dispatch judgment (id, title, path, tab-separated);
exit 1 when the backlog is empty
veri dispatch <WO-id> --as <session> [--by <maintainer>]
approve and start in one gesture: flip a backlog
work order to in-progress, writing the stamp and
the claim together (a stamp already on record is
spent, never re-dated); an already-claimed work
order is refused; --as may default from git
user.name
veri renumber <id> [--to <new-id>] [--file <path>] [--refs <path,path>]
move a document to a new id, rewriting the filename
and inbound links in one atomic pass (collision
resolution: see the team workflow page)
veri migrate bring veri/ to the current on-disk format
veri import [file] [--approve]
with a file: import it as a source document, the
original preserved; bare: print the kickoff prompt
for mining this repo into proposals (--approve is
accepted for symmetry — a source is born in play
and needs no stamp)
veri list [type] list documents: id, status, title
veri open [dir] open the project in the Veri desktop app
The CLI and the desktop app read and write the same files; everything above works identically from either.
The MCP server's tools
The stdio MCP server (@verikb/mcp) serves one project and exposes eighteen tools. Reads return documents exactly as on disk; writes can only produce pending documents — nothing an agent files becomes binding without your approval, and no tool approves, promotes, or dispatches.
| Tool | What it does |
|---|---|
get_context(id) | Context package for a work order: the project workflow first, then the work order, its linked requirements and decisions (2 hops), pending proposals labeled non-binding, source excerpts, and the project's document templates, with per-document and total token estimates. Superseded decisions are named as already rejected, bodies omitted; when the neighborhood is too large to inline, its outer ring arrives as a context map to retrieve from instead of full bodies. The same package veri context <WO-id> prints in a terminal. |
search(query) | Ranked, case-insensitive search over id, title, and body with the shared query grammar: multi-word queries AND-match each word, and composable filters narrow the corpus — req:/dec:/wo:/src: by type, is:<status> by lifecycle, related:<ID> to the 1-hop link neighborhood of an id. Hits return with their score and where they matched, capped at the top 25. |
get_document(id) | One document in full: its file path, then the file exactly as on disk (frontmatter and body). |
get_neighbors(id) | A document's outbound links and backlinks, each with its relation and whether it is declared in frontmatter, as an inline [[id]] mention, or by supersession. |
list_documents(type?, status?, updated_before?) | Enumerate the knowledge base by lifecycle facts rather than relevance: the optional filters combine, and every hit returns in id order with no truncation. Documents awaiting approval are marked pending. |
get_queue() | The judgment queue: backlog work orders awaiting your dispatch, then the in-progress work orders with the claim each session holds. Dispatch is human-only — veri dispatch <WO-id> --as <session> writes the approval stamp and the claim in one gesture, and no tool on this server can do it. |
get_receipts(id?) | Receipts as data: the pointers each work order carries into git — date, the commit SHAs cited, and the one-sentence summary. Pass an id for one work order, or omit it for every work order that has filed one. |
init_project(path?) | Create a knowledge base where there is none — the same scaffold veri init writes. The only tool that works before a knowledge base exists; refused when a veri/ is already there. |
file_decision(title, choice, …) | Record a decision with the next free DEC id, status: proposed (awaiting your approval), with the rejected alternatives. |
file_work_order(title, summary, …) | Propose a unit of work with the next free WO id, status: backlog. |
file_requirement(title, body, …) | Draft a requirement with the next free REQ id, status: draft (awaiting your acceptance). A bet is filed as a bet: kind: hypothesis with the outcome (metric and target) that would confirm or refute it. |
file_source(title, body, …) | File a source document: imported evidence with the paths, commit refs, and excerpts it rests on, plus its evidence class (kind: design, user-feedback, metric, external-eval, investigation, outcome, or reference). |
get_import_instructions() | The brownfield import instruction package: what to mine from an existing repo, the filing rules, and a census of what the knowledge base already holds. |
run_check() | The health check as structured JSON — the same derivation veri check runs: violations (the gate; any entry fails the CLI), advisories (inform, never block), and skipped checks named with reasons. The git-backed tier (provenance, drift) is skipped over MCP — the server spawns no subprocesses — so agents run it for the document gates and bound tests, and a terminal veri check covers the rest. |
supersede_decision(id, superseded_by) | Retire an active decision, naming the active decision that now governs — writes status: superseded and superseded_by together. A successor still proposed is refused: file and approve the replacement first. |
file_receipt(work_order_id, commit, files, summary) | Append a work-session receipt to a work order — or to an import manifest as an import's completion signal. Receipts accumulate, never overwrite. |
amend_document(id, …) | Revise a still-pending document — a draft requirement, proposed decision, or backlog work order: replace its title, body, and/or links. Approved, stamped, or started documents are refused; never a promotion. |
get_intent(path) | The documents governing a code path: work orders whose code bindings touch it, the module-registry entry covering it, and the requirements and decisions those work orders cite. |