Skip to content

pt9912/d-check

Repository files navigation

d-check

🇬🇧 English · 🇩🇪 Deutsch

Consistency checker that verifies a repository's documentation against its actual state — Markdown references (links, images, anchors, identifiers) plus declarations (build targets, version pins, commit trace, planning). Deterministic, side-effect-free, shipped as a container image.

What is d-check?

d-check checks Markdown documentation as a verifiable invariant network: every machine-decidable documentation invariant is a rule module that can be enabled individually, with its own requirement in the requirements spec — from the reference network (links, anchors, ID link obligations, reference matrix) through Markdown hygiene (span artifacts, host-path leaks), content drift and immutability (content/core pins, git diff) to version-pin, commit-traceability, planning-lifecycle and tracked-status consistency:

  • links — local link and image references: target exists, no repo escape (DC-FA-LINK-001)
  • anchors — heading anchors (GitHub slug procedure) and inline HTML anchors (<a name>, id=) (DC-FA-ANCH-001)
  • ids — link obligation for identifiers (e.g. ADR-NNNN) per declared patterns (DC-FA-ID-001)
  • matrix — reference-direction rules between document classes (DC-FA-MTX-001), within an ordered class (order/directionmatrix-downward, DC-FA-MTX-002) and also as a bare ID token in the body (tokenmatrix-forbidden, DC-FA-MTX-003) plus status conditions; exceptions are structural (exclude-sections, allow-supersede-lineage) or declared via the provenance marker <!-- d-check:status-provenance -->
  • external — reachability of external URLs, strictly opt-in (DC-FA-EXT-001)
  • sources — content pin of external sources against upstream drift, opt-in and — besides external — the second network door: a source pinned to a sha256 (via the marker <!-- source-pin: … --> on its http(s) link or the config block sources:) is fetched, hashed and compared (source-drift with the full actual hash, source-unreachable on a network failure); single file or archive (unpack: zip) (DC-FA-SRC-001)
  • codepaths — explicit paths in inline code, opt-in; the opt-in check-lines verifies file:<from>-<to> line references (citation-out-of-range, citation-inverted-range) (DC-FA-CODE-001)
  • spans — Markdown span artifacts (unclosed code spans, nested links), opt-in (DC-FA-SPAN-001)
  • hostpaths — host-local absolute paths (machine-layout leaks), opt-in (DC-FA-HOST-001)
  • diagrams — identifier existence in diagram fences (e.g. mermaid): every identifier found in the diagram must be defined in its defined-in source, opt-in (DC-FA-DIAG-001)
  • versions — version-pin consistency: pinned ghcr image references must carry the current version (from version.md#aktuell), also reads fenced code, opt-in (DC-FA-VER-001)
  • pins — content pin against content drift: a link with <!-- dpin: … --> is checked against the hash of its target span (finding link-stale on drift), opt-in per link (DC-FA-PIN-001)
  • immutable — immutability pin against core drift: a file with <!-- immutable: … --> is checked against the hash of its normalized core (without the marker line + exclude-sections) (finding core-drift on drift), opt-in per file; hermetic (no git, read-only working tree) (DC-FA-IMM-001)
  • vcs — git-diff immutability of the core over a commit range: mechanizes the ADR immutability as a distributable module (core-drift-vcs), pure-Go git in the read-only .git (no git binary, no network), opt-in (DC-FA-VCS-001)
  • commits — traceability identifier in commit messages over a range (--range) or the pending message (--commit-msg): every commit message carries a DC-/ADR-/MR-/slice- ID (commit-untraceable), shares the VCS port with vcs, opt-in (DC-FA-COMMITS-001)
  • planning — roadmap-↔-in-progress lifecycle consistency: the idle marker sits in the ## Aktuelle Welle block exactly when no slice-* is in the directory (planning-drift); hermetic (no git), fail-closed on a missing/ambiguous heading, opt-in (DC-FA-PLAN-001)
  • tracked — tracked status of resolvable, existing link/image targets against the git index (target-untracked: an untracked/gitignored target is missing on every fresh clone); index truth (staged = tracked, no .gitignore interpretation), reads .git read-only without a range, opt-in (DC-FA-TRK-001)
  • targets — declaration consistency between docs and build targets: a make X claimed in a doc table row without a Makefile rule (gate-phantom), or a Makefile rule without an entry in the authority doc (gate-undocumented); hermetic (no git, no Makefile execution), fail-closed, opt-in (DC-FA-TGT-001)
  • citations — verbatim quote verification: the directive <!-- d-check:cite <path>:<from>-<to> --> marks the following quote (a >-blockquote or inline „…"/"…"); the whitespace-normalized quote must be a contiguous substring of the source span (citation-mismatch), opt-in (DC-FA-CITE-001)

Every finding names file, line, target and reason; exit codes: 0 clean, 1 findings, 2 environment or configuration error.

Why d-check?

Twelve functionally overlapping tool copies from three families (verify-doc-refs.sh — Shell, check_refs.py — Python, docs-check.js — JavaScript) grew across the sister repositories of the development workspace — each with its own feature set, its own drift, its own maintenance. d-check replaces them with one tool:

  • Configuration instead of fork: repo-specific behavior lives declaratively in .d-check.yml (DC-FA-CONF-001), not in copied scripts.
  • Replaceability is measurable: every legacy tool must be replaceable by d-check with matching configuration — at least the same real findings, no false positives that break a green CI (DC-QA-04).
  • One distribution path: container image with digest pin instead of n maintained copies (DC-FA-DIST-001).

Core idea

Documentation is a reference graph with verifiable invariants. Whether a link reaches its target, an anchor exists, an identifier links to its definition, or a document class points downward is machine-decidable — d-check turns these invariants into a gate instead of a review opinion.

The principle: report, never repair. d-check is a purely read-only tool (DC-QA-03); deterministic findings are fixed, not suppressed. An opt-out marker exists only where a non-existent target or an illustrative identifier can be documented intent (d-check:ignore, per line) — it silences exclusively the modules codepaths and ids (DC-FA-CODE-001, DC-FA-ID-001).

What makes it trustworthy?

A checking tool whose own statements wobble is worthless — determinism and side-effect freedom are therefore core contracts of the spec, and both are measured, not asserted:

  • Determinism: identical input ⇒ byte-identical output, stably sorted; tested over ten repeated runs with hash comparison (DC-QA-02).
  • Side-effect-free and network-free: never writes into the checked repository, opens no network connections except in the opt-in modules external and sources — measured in the gate run with a read-only mount and --network none (DC-QA-03).
  • No silent defaults: every invalid .d-check.yml aborts with exit 2; checking never proceeds with guessed configuration (DC-FA-CONF-001).
  • Dogfooding: d-check validates its own docs on every gate run — with the self-configuration fully built out (eight modules incl. reference matrix, span artifacts, host-path hygiene and version-pin consistency).
  • Container native-identical: the image's finding output and exit code are byte-identical to native execution, tested automatically (DC-FA-DIST-001); CI consumption via digest pin.

Usage

Distributed as a container image via GHCR (DC-FA-DIST-001):

docker run --rm -v "$PWD:/repo:ro" ghcr.io/pt9912/d-check:v0.51.1

CI pipelines pin to the digest from the release notes rather than to moving tags — details, options and exit codes: docs/user/operations.md and docs/user/releasing.md.

Configuration (.d-check.yml)

Optional in the repo root; without a file the default modules links + anchors run over docs/, spec/ and the root *.md:

scan:
  roots: ["."]                  # entire repo root
modules: [links, anchors, ids]  # external + sources stay strictly opt-in (network)
ids:
  patterns:
    - regex: 'ADR-\d{4}'
      target: docs/adr/         # identifiers must link here

The full schema with all keys, defaults and validation constraints is in the specification §.d-check.yml; a living example fully built out (incl. reference matrix) is this repo's self-configuration. Every invalid configuration aborts with exit 2 — checking never proceeds with silent defaults (DC-FA-CONF-001).

Getting started

Document Contents
docs/user/operations.md Invocation reference: options, exit codes, configuration
docs/user/releasing.md Release process, digest-pin consumption
spec/lastenheft.md Requirements (DC-FA-*, DC-QA-*), acceptance criteria
harness/README.md Harness entry: source precedence, guides, sensors
AGENTS.md Briefing for AI coding agents, hard rules
docs/plan/planning/in-progress/roadmap.md Waves and slices
CHANGELOG.md Change history

Development

The host needs only git, GNU make, bash and Docker (see AGENTS.md §3.1).

make help     # available targets
make gates    # all inner gates (mandatory before handoff)

License

This project is licensed under the MIT License.

About

Consistency checker that verifies a repository's documentation against its actual state — Markdown references (links, images, anchors, identifiers) plus declarations like build targets, version pins, commit trace and planning lifecycle. Hermetic, opt-in rule modules, shipped as a container.

Topics

Resources

License

Stars

2 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors