Rigor, Vouch, Stages Spec GitHub npm

RIGOR.md format specification — v1.0

A RIGOR.md is a file at the root of a repository in which the people behind the code state, in their own name, how carefully it was made, whether they vouch for it, and who did which stage of the work. This document specifies that file: its layout, its stamp fields, the validation rules a conforming tool applies, and the prose a conforming tool generates.

A stamp declares its version with spec: "1.0". That is the only accepted value. rigor.schema.json, shipped beside this document and identified by https://rigor.diaconou.com/1.0/rigor.schema.json, is the canonical structural schema; where prose and schema disagree, the schema wins.

1. File layout

A RIGOR.md is a Markdown document. Two regions are defined:

All other content is free prose. A tool must not read it. A line under the heading that names the convention and links to this specification is recommended, so a reader who finds the file cold knows what it is; init writes one.

1.1 Locating the stamp

  1. Find every line matching ^##\s+Stamp\s*$. The last one is the stamp heading.
  2. After that line, the first line matching ^```ya?ml\s*$ opens the block.
  3. After the open, the first line matching ^```\s*$ closes it.
  4. The lines between the fences are the stamp.

Scanning is line by line, never a regular expression applied across the whole file. A missing heading, open fence, or close fence is the error No stamp found. Expected a '## Stamp' section with a fenced yaml block.

1.2 Parsing the stamp

The stamp is YAML 1.2 under the core schema. A conforming parser must reject:

Condition Error
more than 65536 bytes of UTF-8 Stamp is too large (N bytes; limit is 65536).
a YAML syntax error Stamp is not valid YAML: <detail>
a duplicate mapping key as a YAML syntax error
any anchor or alias Stamp uses YAML anchors/aliases, which are not allowed.
a document that is not a mapping Stamp parsed but is not a mapping of fields.

The anchor and alias check runs before the tree is materialized, so an expansion attack cannot detonate during validation.

Under the core schema, bare yes and no are already strings, and a bare date is a string. Three normalizations follow the parse:

2. Stamp fields

Field Required Shape
signed yes a name, or a list of names (2.5)
rigor yes one level name (2.1)
vouch yes one claim, or a mapping (2.2)
checks no mapping, any subset of five keys (2.3)
stages no mapping, any subset of four stages (2.4)
forked_from no the project this was forked from (2.6)
notes no string
spec no "1.0"
assessed no YYYY-MM or YYYY-MM-DD

Unknown keys are rejected at every level of the stamp.

2.1 rigor

Five level names, in order: unexamined, skimmed, comprehended, engineered, owned. The name is the canonical encoding; a tool must emit the name and must not emit an ordinal. comprehended and above are above the comprehension line.

2.2 vouch

Either a scalar — yes, neutral, or withheld — or a mapping with the required key claim holding one of those three, and the optional key why holding a string.

2.3 checks

Keys: comprehended, quality_reviewed, security_reviewed, tested, owned. Any subset may appear.

Each value is one of six strings, never a boolean:

Value Meaning
yes done, actor unstated
human done by a human
ai done by an AI
human-with-ai done by a human with an AI
no not done
not-applicable does not apply

The first four are the done states.

A check may instead be a pair, [before LLMs, since LLMs]: who did it before the advent of AI, and who has done it since. Only human, ai and human-with-ai may appear in a pair, and a pair has exactly two entries. A single value is a fact about the code as it stands.

2.4 stages

Stage Keys Values
idea by, depth, inspired_by by: human, human-with-ai, ai, upstream (2.6), or a pair [before LLMs, since LLMs]; depth: one-shot, considered, deep; inspired_by: free text, what the idea grew from
plan by, depth as idea, without inspired_by
implementation by human, human-with-ai, ai, upstream (2.6), or a pair [before LLMs, since LLMs]
maintenance by, activity, scope by: human, human-with-ai, ai, none; activity: active, dormant; scope: evolving, complete

2.5 signed

Who makes the statement: a string, or a non-empty list of strings. Every name must be non-empty. With one name the generated prose speaks as I; with more than one it speaks as we, and every sentence that carries a pronoun takes its co-signed form from section 4.2. Names join as a, a and b, or a, b and c.

2.6 forked_from

The project this one was forked from: a non-empty string, a name with or without a URL. When present, idea, plan and implementation may name the actor upstream, meaning that project, alone or in a pair. upstream without forked_from is an error (3.2). forked_from without any upstream actor is legal: a fork rewritten entirely. maintenance and the checks never take upstream; they are the signers' own attestations.

3. Validation

Validation checks form and consistency. It does not check truth. Every value in a stamp is a self-report.

A validator reports errors, which make the stamp invalid, and warnings, which do not. Strict mode promotes one case noted in 3.2.

3.1 Structural

The stamp must satisfy rigor.schema.json: required fields present, no unknown keys, every value drawn from its vocabulary. Structural errors stop validation; semantic rules do not run against a malformed stamp.

3.2 Semantic

A headline level implies checks. The level may not exceed the checks that back it.

rigor Required check Acceptable values
unexamined — —
skimmed — —
comprehended comprehended yes, human, human-with-ai
engineered comprehended yes, human, human-with-ai
quality_reviewed done states
security_reviewed done states
tested done states, not-applicable
owned all of engineered as above
owned done states

comprehended excludes ai: an AI that comprehends code does not put a human above the comprehension line.

Where a check is a pair, the rules below read its since-LLMs actor: the level is a claim about the code as it stands. Three rules apply to each required check:

  1. Present with an unacceptable value — error: rigor 'L' requires 'K' to be one of ["a", "b"], but it is 'v'. The value list is bracketed, comma and space separated, each element double quoted.
  2. Absent while rigor is engineered or owned — error: rigor 'L' claims 'K' but it is not surfaced — show your working (add 'K:' under checks:). Above the line, a claim must show its working.
  3. Absent otherwise — warning in strict mode, silent by default. At or below comprehended, a terse stamp stays legal.

Two further semantic errors: stages.maintenance.by is none while activity is present — no one responds, so activity does not apply; and a story stage names upstream while forked_from is absent.

3.3 Warnings

Condition Warning
quality_reviewed or security_reviewed is ai while rigor is engineered or owned an AI-only review is a different claim from a human one at this level
stages.maintenance.by is ai while rigor is engineered or owned unattended maintenance rarely sustains this level
no spec key add spec: "1.0"

The first names every affected check in one warning, not one warning per check, and reads the since-LLMs actor of a pair.

3.4 Drift

The generated prose of section 4 is derived from the stamp, so the two can never be allowed to disagree.

Comparison collapses runs of whitespace, including line breaks, to one space and trims the ends; it is otherwise exact.

4. Generated prose

The sentences below are fixed. A conforming tool must reproduce them byte for byte, because section 3.4 compares generated text against stored text.

Each table with a pronoun has two columns. Signed by one is the voice of a stamp with a single name under signed; co-signed is the voice when there are several. The voice is chosen once and applied to every sentence.

4.1 Summary block

<!-- rigor:summary -->
**<summary>**
<!-- /rigor:summary -->

<summary> is the sentences of 4.2, in this order, joined by one space, and wrapped by the author tool at 80 columns so the file reads as text. Line breaks inside the block are not significant: the drift comparison of 3.4 collapses runs of whitespace to one space before comparing. A sentence whose source field is absent is omitted:

  1. This is a fork of <forked_from>. — only when forked_from is present; a fork's history begins before the signers', so it opens the summary
  2. The idea was <stage phrase>.
  3. The plan was <stage phrase>.
  4. the implementation sentence
  5. the level sentence — always present
  6. the checks sentence
  7. the maintenance sentence
  8. the scope sentence
  9. This assessment is as of <assessed>.
  10. the vouch sentence — always present
  11. Why: <why> — a full stop is appended unless <why> already ends with one
  12. Statement made by: <names>. — always present

When any stage or check is a pair, the summary is told in two eras instead (4.3): the era-less stage sentences, then Before LLMs, ..., then Since LLMs, ..., then the maintenance and scope sentences, then the level sentence, then items 8 to 11. The checks sentence of item 5 is absorbed into the eras.

4.2 Sentence tables

Level, from rigor:

Value Signed by one Co-signed
unexamined I have not examined this code. It ran; that is all I claim. We have not examined this code. It ran; that is all we claim.
skimmed I have run and skimmed this code, but I have not read it properly. No human has understood it line by line. We have run and skimmed this code, but we have not read it properly. No human has understood it line by line.
comprehended I have read and understood this code; I can explain every line of it. We have read and understood this code; we can explain every line of it.
engineered I understand this code; it was deliberately reviewed for quality and for security, issues found were fixed, and it has tests I trust. We understand this code; it was deliberately reviewed for quality and for security, issues found were fixed, and it has tests we trust.
owned I stand behind this code as soundly engineered and hold architectural responsibility for it. We stand behind this code as soundly engineered and hold architectural responsibility for it.

Vouch, from the claim:

Value Signed by one Co-signed
yes I recommend this for use; I put my name behind it. We recommend this for use; we put our names behind it.
neutral I make no recommendation either way about depending on it. We make no recommendation either way about depending on it.
withheld I am specifically not recommending you depend on this. We are specifically not recommending you depend on this.

Stage phrase, for idea and plan. With both keys it is the owner phrase followed by the depth tail; with by alone it is the owner phrase; with depth alone it is the depth-alone phrase; with neither the sentence is omitted. When idea carries inspired_by, , inspired by <text> follows the owner phrase (or the depth-alone phrase), before any depth tail: The idea was mine, inspired by the query objects of X, and worked in depth over iterations.

by Owner phrase, signed by one Co-signed
human mine ours
human-with-ai mine, developed with an AI ours, developed with an AI
ai an AI's an AI's
upstream the upstream's the upstream's
depth Tail (after an owner phrase) Alone
one-shot , and taken as it first came taken as it first came
considered , and thought through thought through
deep , and worked in depth over iterations worked in depth over iterations

Implementation, from stages.implementation.by:

Value Signed by one Co-signed
human The implementation was written by me. The implementation was written by us.
human-with-ai The implementation was written by me with an AI. The implementation was written by us with an AI.
ai The implementation was generated by an AI. The implementation was generated by an AI.
upstream The implementation was inherited from the upstream. The implementation was inherited from the upstream.

Actor phrases, used by the checks sentence and by the eras of 4.3:

Actor Signed by one Co-signed
human by me by us
human-with-ai by me with an AI by us with an AI
ai by an AI by an AI
upstream by the upstream by the upstream

Checks. The sentence is It was <groups>., built from the done checks among quality_reviewed, security_reviewed, and tested; the other checks contribute nothing, and the sentence is omitted when no check is done.

Check Phrase
quality_reviewed reviewed for quality
security_reviewed reviewed for security
tested tested

A group is the checks that share an actor. Within a group, both reviews merge to reviewed for quality and for security; that and tested join with , and , two single phrases with and. The actor phrase from the table above (by me, by us, by an AI, ...) follows: bare after one check, , both <phrase> after two, , all <phrase> after three. An unstated actor (yes) adds nothing. Groups join with ; , the last introduced by ; and .

Checks Reads
quality human, security human, tested yes It was reviewed for quality and for security, both by me; and tested.
all three ai It was reviewed for quality and for security, and tested, all by an AI.
quality human, tested ai It was reviewed for quality by me; and tested by an AI.

Maintenance. When activity is dormant, the sentence is:

Signed by one Co-signed
Nothing has needed changing lately; I still use this and would respond if it broke. Nothing has needed changing lately; we still use this and would respond if it broke.

Otherwise, when by is present:

by Signed by one Co-signed
human I drive changes myself now. We drive changes ourselves now.
human-with-ai I now make changes with an AI. We now make changes with an AI.
ai Changes are now made by an AI unattended. Changes are now made by an AI unattended.
none No one maintains this. No one maintains this.

Scope, from stages.maintenance.scope. It is independent of by and of activity, so its sentence stands alongside whichever sentence the rule above produced, including the dormant one. It has no pronoun, so one form serves both voices.

Value Sentence
evolving The project is still evolving.
complete The project is complete; it will not gain new features.

Attribution. The summary always ends with Statement made by: <names>., the names joined as in section 2.5.

4.3 The two eras

A pair on idea, plan, implementation or a check means the work changed with the advent of AI, and the summary is then told era by era rather than field by field, so the reader never travels back in time mid-paragraph.

  1. Era-less stages first: every stage with a single actor, as its sentence of 4.2. A single-valued stage is a whole-life fact.
  2. Before LLMs, <clauses>. — for each paired stage in order, its 4.2 sentence from the first actor, as a clause (lowercase opening, no full stop); then it was <groups> from the first actor of every paired check. Clauses join with ; .
  3. Since LLMs, <clauses>. — the paired stages grouped by their second actor, as <subjects> has been reworked <phrase> (have for more than one subject; subjects the idea, the plan, the implementation, joined as a, a and b, a, b and c), the groups joined with ; ; then it has been <groups> from the second actor of every paired check and the value of every single-valued done check — a single-valued check is a present fact. The two parts join with , and .
  4. The maintenance sentence, then the scope sentence. The maintenance sentence is omitted when its actor is the implementation's since-LLMs actor, because the era has already said who makes changes now; the dormant sentence is never omitted.
  5. The level sentence, then items 8 to 11 of 4.1.

So plan: {by: [human, human-with-ai], depth: deep}, implementation: {by: [human, human-with-ai]}, every check [human, human-with-ai], and maintenance: {by: human-with-ai, activity: active, scope: complete} read:

The idea was mine. Before LLMs, the plan was mine, and worked in depth over iterations; the implementation was written by me; it was reviewed for quality and for security, and tested, all by me. Since LLMs, the plan and the implementation have been reworked by me with an AI, and it has been reviewed for quality and for security, and tested, all by me with an AI. The project is complete; it will not gain new features. I stand behind this code as soundly engineered and hold architectural responsibility for it. ...

4.4 README line

The README line is the level sentence and the vouch sentence, plus Why: when the stamp carries one, in the stamp's voice. It is not the full summary. The signers attribute the quotation from outside it, so the quoted text carries no name.

<!-- rigor:line -->
> "<level sentence> <vouch sentence>[ Why: <why>.]" — <names>, [RIGOR.md](RIGOR.md)
<!-- /rigor:line -->

5. Conformance

A conforming validator must:

  1. Locate and parse the stamp by section 1, with every rejection in 1.2.
  2. Enforce rigor.schema.json (3.1) and the semantic rules (3.2).
  3. Report the warnings of 3.3 without invalidating the stamp.
  4. Compose the prose of section 4 byte for byte, and enforce the drift rules of 3.4 wherever the markers are present.

A conforming author tool must additionally regenerate the summary block in place, so a stamp and its prose stay in agreement.

6. Changes from v0.3

Version 1.0 supersedes v0.3 directly. A v0.4 was drafted and served briefly but never released as a tool; its changes are folded in here.