MeDiVa
DocsRecipes

Validate a status table

Enforce the columns, allowed values, required cells, and uniqueness of a Markdown table.

A status board that lets you type "sleeping" in the reactor's Status column is not a status board. It's a rumour.

Plenty of contracts live in a Markdown table: a systems board, an on-call roster, an API surface, a dependency inventory. mediva can lock the table's shape and its cell values, so a half-filled or made-up row never passes review.

The contract

systems-board.mdv.md
<!-- mdv: table required cols=System,Owner,Status minRows=1 noExtraCols col.System.unique col.Owner.required col.Status.oneof=nominal,degraded,offline -->
## Systems Board

| System | Owner | Status |
| ------ | ----- | ------ |
| Reactor | Dana | nominal |
| Life Support | Cole | nominal |
<!-- mdv: endtable -->

Every atom on that one table directive earns its place:

  • required — the Systems Board section must exist and hold a table.
  • cols=System,Owner,Status — those columns must appear, in that order. They're matched as an ordered subsequence, so extra columns are tolerated unless you also lock the set.
  • noExtraCols — locks it: a stray Notes column is now [table-extra-columns].
  • minRows=1 — the board can't be empty (pair with maxRows=N to cap it).
  • col.System.unique — no two rows can name the same system.
  • col.Owner.required — every row needs an owner; an empty Owner cell fails.
  • col.Status.oneof=nominal,degraded,offline — Status must be one of the three real states. "sleeping" is a rumour, and it's rejected.

What it catches

Point the contract at a board where someone fudged a row:

systems-board.md — every cell tells a small lie
## Systems Board

| System | Owner | Status | Notes |
| ------ | ----- | ------ | ----- |
| Reactor | Dana | sleeping | |
| Reactor |  | nominal | dup |
systems-board.md:3  error  [table-extra-columns] The "Systems Board" table has an unexpected column "Notes".
systems-board.md:3  error  [table-cell-duplicate] In the "Systems Board" table, column "System" repeats "Reactor".
systems-board.md:3  error  [table-cell-required] In the "Systems Board" table, column "Owner" is required but has an empty cell.
systems-board.md:3  error  [table-cell-invalid] In the "Systems Board" table, column "Status" has "sleeping", which is not allowed.

Four lies, four diagnostics, exit code 1. Fix the cells and the board passes clean.

The column constraints

Each col.<column>.<constraint> atom targets one named column:

ConstraintSyntaxChecks
requiredcol.Owner.requiredthe cell is non-empty in every row
oneofcol.Status.oneof=open,donethe cell is one of the listed values
matchescol.Version.matches=/^\d+\.\d+\.\d+$/the cell matches a regex
uniquecol.ID.uniqueno value repeats down the column

Empty cells are skipped by oneof, matches, and unique — only required objects to a blank. So you can demand a format without demanding a value: add both col.X.required and col.X.matches=/.../ when a cell must be present and well-formed. A constraint naming a column the table doesn't have raises a [table-unknown-column] warning, so a typo in the contract surfaces instead of silently passing.

Run it in CI

Keep the contract beside the file as systems-board.mdv.md and the zero-config scan picks it up, or check it explicitly:

npx mediva check systems-board.md --schema systems-board.mdv.md

Variations

  • For a roster where each person may own several systems, drop col.System.unique but keep col.Owner.required.
  • To allow a column the schema doesn't enumerate, omit noExtraColscols= still requires the named columns, but extras are tolerated.
  • Combine a table contract with sibling block sections in the same file: the table is just one tag among the document's slots.

On this page