Gessa Docs

Documentation

Docs Validation Plan

The docs guards wired today, what each one actually enforces, and how the docs program hardens them.
engine v1.0.234since v1Copy for LLM

Documentation is a product contract, so it is guarded like code: with deterministic, file-walking checks that exit non-zero and print actionable findings. This page describes the validation suite that runs today, states honestly what each guard enforces (which is sometimes narrower than the rule it defends), and points at the docs program work that hardens it. Every check walks files, compares against an in-repo source of truth, and fails loudly; none touch the network.

For the three-tier source-of-truth model these checks defend, see the Documentation Contract Architecture.

Guards Wired Today

Six guards are wired. One is the generated-drift guard, run standalone; the other five run under npm run check:docs. Both gen-docs:check and check:docs are part of the global npm run check chain.

Generated-docs drift (npm run gen-docs:check)

  • Guards: that every Tier-2 generated file is a byte-exact projection of its Tier-1 source.
  • How it works: runs each scripts/gen-*-docs.ts generator in --check mode (plus scripts/check-spec-drift.ts and the AI-context manifest generator), regenerating the output in memory and failing if the committed file differs. This is the mechanism behind the GENERATED FILE: do not edit by hand. banner and the real drift guard for the whole generated surface.
  • Status: implemented and in the global chain.

Scaffold existence (npm run check:docs-contract-scaffold)

  • Guards: that the documentation contract scaffolding exists and is structurally intact: every required scaffold file (the four docs-system pages, all docs/product/v1/ pages, and all docs/ai-context/v1/ files), a set of load-bearing exact H1 titles (index.md H1 "Gessa Product Documentation (v1)", README.md H1 "Gessa AI Context (v1)", llms.txt first line "# Gessa", and the four docs-system H1s), and that ai-context-manifest.json parses as JSON and carries the literal engineVersion string v1 with a files array.
  • How it works: a deterministic file walk (scripts/check-docs-contract-scaffold.ts) that asserts each required path exists, parses the manifest, and verifies each critical heading appears verbatim; exits non-zero listing any missing path, invalid manifest, or mismatched title.
  • Enforcement gap: it checks the manifest against the literal string v1, not against ENGINE_VERSION_MAJOR. It is an existence and shape gate, not a dynamic version check.
  • Status: implemented and, because it runs inside check:docs, in the global chain.
  • Guards: that every relative Markdown link in the hand-authored surface (docs/docs-system, docs/product/v1, docs/ai-context/v1) resolves to a real path on disk.
  • How it works: scripts/check-docs-links.ts walks the .md and .txt files, extracts each link, skips external and pure-anchor links, strips titles and anchor fragments, and fails on any target that does not exist.
  • Status: implemented and in the global chain via check:docs.

Markdoc tags (npm run check:docs-markdoc)

  • Guards: that every custom Markdoc tag used in prose is one of the eleven, is well-formed (required attributes present, no unknown attributes, enumerated values in range), and, for a binding tag, resolves into its generated file. Tags shown inside fenced code blocks are skipped.
  • How it works: scripts/check-docs-markdoc.ts parses each page with Markdoc, walks the tree, and checks each prose tag against the TAG_SCHEMAS and BINDING_TAGS exports in scripts/markdoc/tags.ts.
  • Enforcement gap: a binding tag resolves by naive substring .includes() over the generated file, so a name or id that is a substring of unrelated text resolves even when there is no matching table row. The version tag's coordinate and hash are free strings that no check validates against packages/engine-version.
  • Status: implemented and in the global chain via check:docs.

Example markers (npm run check:docs-examples)

  • Guards: that every fenced ts, tsx, typescript, js, javascript, or json block in the hand-authored surface carries an or marker in the three lines directly above the opening fence. Blocks in text, bash, sh, mermaid, yaml, or markdoc are exempt.
  • How it works: scripts/check-docs-examples.ts scans line by line for fences and their languages and fails on an unmarked marked-language block.
  • Enforcement gap: this is a marker-presence check only. It does not compile, type-check, or byte-compare any block against a source file; the marker is a promise the guard does not verify.
  • Status: implemented and in the global chain via check:docs.

Public claims (npm run check:docs-claims)

  • Guards: over docs/product/v1 and docs/ai-context/v1, that a fixed list of banned over-claim phrases never appears in prose, and that a {% contract %} or {% proof %} tag does not carry an accepting status while the v1 readiness ledger has zero accepted rows.
  • How it works: scripts/check-docs-claims.ts scans the claim roots for the banned phrases and, while the ledger has no accepted rows, parses each page and fails on a contract with an accepting status or a proof with status present.
  • Enforcement gap: the accepting-status rule has an accepted-rows bypass. It counts accepted rows in docs/cycles/v1-engine-readiness-loop/FEATURE_LEDGER.json and, the moment the first row is accepted, stops checking tag status entirely. It protects only the pre-launch window and does not tie a specific claim to the specific ledger row that would justify it. The banned-phrase list stays in force regardless.
  • Status: implemented and in the global chain via check:docs.

What the Docs Program Hardens

The docs program is the cycle that turns the guards above from shape checks into contract checks. Its planned additions and upgrades:

Docs version equals engine version (check:docs-version-freeze)

  • Guards: the flagship invariant that nothing enforces today. It asserts that the export manifest, the version archives (versions.json), the changelog, and the since-ledger agree with ENGINE_VERSION and releases.json, that the docs folder set equals v${ENGINE_VERSION_MAJOR}, and that a removed coordinate carries a deletion tombstone.
  • Status: added by the docs program; wired into the chain and into deploy.sh.

Closure in both directions (check:docs-closure)

  • Guards: code to docs (every registry entry's anchor resolves as a heading in its generated file at the pinned version) and docs to code (every identifier-shaped token in prose resolves to a registry id, every Markdoc binding tag resolves to a heading rather than a substring, and no integer sits next to a catalog noun outside a count tag).
  • Status: added by the docs program in warn mode with a sorted shrink-only baseline, then flipped to error for new and edited nodes.

Examples that earn their marker (check:docs-examples, upgraded; docs:examples:nightly)

  • Guards: that a verbatim block byte-matches its cited symbol span, that a replay example passes preflight, and, on a nightly lane, that a compile block type-checks against the SDK and that tutorials run in Playwright against the QA stack.
  • Status: upgrades today's marker-presence check into a content check.

Binding resolution by row, not substring (check:docs-markdoc, hardened)

  • Guards: that a component, action, capability, or mcp-tool reference resolves to an actual table row or heading in its generated file, and that a version coordinate resolves against packages/engine-version.
  • Status: replaces the substring resolution described above.

Claims tied to ledger rows (check:docs-claims, extended)

  • Guards: that a capability claim names the specific readiness-ledger row that justifies it, rather than relying on the global accepted-rows bypass. The banned-phrase list is retained.
  • Status: extended by the docs program alongside the parity-page binding resolver.

Registry-side DocContract parsing

  • Guards: that no surface loads without a purpose, anchor, stability, and audience. DocContractSchema (added to packages/engine-version) is spread into the five registries, and each registry's import fails when an entry omits a contract field.
  • Status: landed as warn behind the closure baseline, then flipped per registry when its baseline reaches zero.

Behavioral tier stays current (check:docs-dossier-currency)

Dossiers under docs/spec/dossiers are snapshots of engine behavior, so they are policed for staleness instead of regenerated. Each unit carries a symbols twin of every citation and a receipt with the sha256 of every cited source file. The gate fails hard when a cited symbol no longer resolves or a unit has no receipt, and reports a unit as stale when a cited file changed since its stamp. The doctor collects the strict form; check:docs-version-freeze refuses to pin a release while any unit is stale or broken. Units re-trace against a paused tree at the release point, then re-stamp with --stamp <unit> (decision D26 in the docs program).

Zero em dashes (check:docs-em-dash)

The corpus trees carry no U+2014, code fences included, because a fence is copied verbatim by readers and by the examples gate. Chained into check:docs with a self-test; the engineering record under docs/cycles is out of scope by design.

Wiring Discipline

Checks join the build incrementally, never as a big-bang flip.

  • gen-docs:check is already part of npm run check. Any new generator registers a --check mode and is appended to the gen-docs:check chain (and to gen-docs).
  • A new content check lands first as a standalone scripts/check-* gate that can be run in isolation, is validated deterministic and green on the current tree, and only then is appended to the global chain. Warn-mode gates carry a sorted shrink-only baseline so two lanes burning down different entries both pass.
  • check:docs (which runs the five hand-authored-surface guards) is in the global chain today. The earlier plan to keep check:docs-contract-scaffold out of the global chain no longer holds: it runs inside check:docs and therefore inside npm run check.

Status

Six guards run today: gen-docs:check plus the five under check:docs (contract-scaffold, links, markdoc, examples, claims), all in the global npm run check chain. Their enforcement is honest but narrow in three places: binding tags resolve by substring, example markers are not verified against source, and the public-claims status rule bypasses once the ledger accepts a row. The docs program hardens each of these and adds the docs-version freeze that no check enforces today. The Markdoc Schema Plan defines the tags several of these checks validate, and the Documentation Contract Architecture defines the three-tier model they defend.

Was this helpful?Report an issueContact support

On this page