DOCS
Prose that can’t quietly go stale
A diagram cannot drift from the schema, because it is generated from it. Prose can, and always does. So vibex docs treats documentation as a set of claims, each one a sentence with its source attached. A claim tied to code is pinned by a content hash. When that code changes, the claim is flagged and CI goes red.
What drift looks like
The Relay document says “A van attempts a door twice before the parcel stops moving.” That claim is anchored to MAX_ATTEMPTS in AttemptPolicy.java. We changed the constant from 2 to 3 and ran the check again:
Nobody had to remember that the sentence existed. The hash of the anchored lines stopped matching, so the claim went from verified to needs re-reading and the command exited 1.
The check reads files, hashes them and asks git what changed. That is all it does: fs, path, crypto and git, with no model and no network. The run above covered 153 claims in under a tenth of a second, Node startup included.
Three kinds of claim
Every claim says where its truth comes from. The skill works down this list and stops at the first kind that fits.
Computed from a diagram spec
One of ten fixed generators reads a spec and writes the sentence. It cannot disagree with the diagram next to it, because it is built from the same spec. Column counts, keys, cardinalities, routes and transitions are always derived, never typed out by hand.
Pinned to a file and a symbol
A method or a constant, held by a content hash. Where whitespace is not syntax (TypeScript, Java, Go, JSON), the hash ignores it, so reformatting moves nothing. In Python, YAML and any file type vibeX does not recognise, indentation counts.
A person’s decision, dated
For what no file can prove. It carries the name of the person who stands behind it and the date they confirmed it, and it expires after review_window_days (180 by default).
The ten generators are erd.entities, erd.relationships, c4.elements, c4.relationships, c4.boundaries, endpoints.operations, endpoints.types, lifecycle.states, lifecycle.transitions and coverage. Each diagram page shows sentences they produced for Relay, word for word.
Confidence is computed, never written
A claim cannot declare how much to trust it. The build works that out from the evidence and the clock, and the validator rejects any claim that tries to rate itself.
- ● verifiedverified
- Derived from a spec, or anchored and the hash still matches.
- ● statedasserted
- A person said so, inside the review window. Nothing checks it.
- ● needs re-readingstale
- The anchored code changed. Somebody has to read it and decide whether the claim still holds.
- ● out of dateexpired
- Nobody has reconfirmed the assertion inside its review window.
- ● unverifiablebroken
- The file or symbol is gone, or the build was not given
--repoto check against.
The small grey name under each label is the machine ID, the one you would grep for in docs.json or CI logs.
How it reads
Prose that cites its claims
Each section has a narrative in Markdown. It cites claims inline with [[claim-id]], and each citation renders as a coloured pip showing that claim's confidence. A reader can tell which words are backed by evidence and which are just connecting them. A long narrative that cites nothing gets a warning.
It says what it does not cover
Every document renders three lists: the specs it read, what is out of scope and why, and what the build noticed but could not account for, such as nodes nobody wrote a claim about. If a document leaves out its gaps, readers assume it is complete.
One document per question
auth.docs.json, payments.docs.json. Each becomes its own entry in the dashboard, next to one shallow system overview.
Two readers, one artefact
People read the dashboard panel. Agents read docs.json, where every fact appears once, has an address and has its edges resolved. “What is known about this node?” becomes a lookup instead of a search.
Markdown that survives a paste
--md writes Markdown with no raw HTML, so it pastes cleanly into Confluence, a wiki or a README. Regenerate it rather than editing it; the spec is the source.
Proposals, marked as such
Set meta.proposed to document a design that does not exist yet. It renders with a banner and a stamp that stays on exported images, its claims read proposed, and the drift check skips it.
A claim, in the spec
{
"id": "policy.two-attempts",
"text": "A van attempts a door twice before the parcel stops moving.",
"subject": "parcel.lifecycle#attempt_failed",
"source": {
"kind": "anchored",
"path": "dispatch/src/main/java/relay/AttemptPolicy.java",
"symbol": "MAX_ATTEMPTS",
"hash": "7963a8b1a6c8"
}
}This is the claim from the drift example, exactly as it sits in relay.docs.json. The subject ties it to a state in the lifecycle diagram, and in the dashboard it carries a chip that opens that state.
Nobody writes the hash by hand. You write zeros and run --reanchor, which pins it to the code as it is now.
The validator keeps claims small. It warns about a sentence that hedges (“should”, “probably”), one that makes two assertions at once, and one over 300 characters. One claim is one fact, so it can be cited, checked and retracted on its own.
In CI, and when it fails
Locally, docs.lock.json records the commit each anchor was last verified at, so a rebuild only re-reads what git says moved. CI passes --no-lock on purpose: a lock file comes from a contributor's machine claiming things were verified, and CI re-reads every anchor rather than taking that on trust.
When a claim goes needs re-reading, read the code. If the claim is still true, run --reanchor. If not, rewrite it, or replace it with one that supersedes it. Re-anchoring without reading re-certifies a claim that may now be false.
What it does not do
It catches staleness, not initial error.
If the first draft misreads the code, the hash still matches, CI stays green, and the wrong claim can stay verified indefinitely. Reviewing the spec once, when it is written, is the only thing that establishes that it is true.
So the skill hands over a review list along with the document: every asserted claim and whose name is on it, every anchor that covers a whole file, and anything it inferred rather than read. It may never write an asserted claim in someone's name unless that person said it in the conversation or signed it in a file.
The honest version: you get a reviewable first draft in one pass. After you have read it once, arithmetic keeps it honest.
What it connects to
The facts come from them
A docs spec lists the diagram specs it covers. Generators can only read those, so the coverage report can say exactly what was looked at.
What a release did to the docs
With --specs, release notes list claims written, reworded, superseded and removed.
“This claim is wrong”
Every claim has a report link that opens an issue already naming the claim, its confidence and the commit.
Intake →