How it works

Evidence first. Judgment second.

A Dokimos run collects observations, writes them into an immutable snapshot, and only then compares and evaluates them. Each stage can be inspected on its own, which is what makes a conclusion explainable.

Analysis lifecycle

Seven stages from source to decision.

Stages 1–5 and 7 run in Dokimos's own CI today. Stage 6 is implemented and tested but not yet a CI gate.

  1. Collect source and history

    Dokimos reads source files under a directory (F# today; analyzers are adapters, and the domain is language-neutral) and a Git history exported with git log --numstat --find-renames. History is an input, not an afterthought: churn, commit frequency, first and last change, and renames come from it.

    Source: src/Dokimos.Core/GitHistory.fs, src/Dokimos.Core/Temporal.fs.

  2. Measure

    Analyzers produce observations per file: size, mutable bindings, broad catch-all patterns, a lexical complexity proxy, type-weakening and scaffolding indicators. Each observation names its metric, the metric's definition version, its unit, and its scope.

    A measurement is available with a value, unavailable with a reason, or failed with an error code. These are different states, and none of them is zero.

  3. Write an immutable snapshot

    Observations are written into a canonical, schema-versioned snapshot identified by repository, revision, ref, collection time, and collector version. Snapshots are never edited. Re-running with a newer analyzer creates new evidence instead of rewriting old evidence.

    Schema: schemas/dokimos-snapshot.schema.json.

  4. Correlate structural and temporal evidence

    Correlation rules combine independent signals. A maintainability hotspot requires structural complexity and temporal change pressure; neither alone is enough. Each resulting finding carries the signals that produced it, so it can be decomposed rather than trusted.

    Source: src/Dokimos.Core/Correlation.fs.

  5. Compare compatible snapshots

    dokimos compare reads a baseline snapshot and a current snapshot. For every metric it reports added, removed, improved, deteriorated, unchanged, changed, or not comparable; for every finding it reports introduced, resolved, or persistent. Metrics without an inherent direction, such as complexity, are reported as changed: whether lower is better there is a policy decision, not an analyzer assumption.

    Observations are keyed by metric, definition version, and scope, so a definition change starts a new series instead of producing a false trend. Source: src/Dokimos.Core/CanonicalComparison.fs.

  6. Evaluate policy

    Thresholds and ratchets are applied to observations, producing Pass, Warning, Failure, or Not evaluated. Missing evidence is never evaluated as passing. The policy logic is implemented and tested; wiring it into CI as a gate against the accepted baseline is the next planned step.

    Source: src/Dokimos.Core/Policy.fs, policy: config/dokimos-policy.json.

  7. Accept a new baseline deliberately

    Baselines only move when someone authorises it. In Dokimos's own CI, a new canonical snapshot is promoted to baselines/accepted-snapshot.json only when an explicit marker file is present and the run succeeds. The acceptance is a commit, so the history of accepted states is itself evidence.

Command line

Deterministic, non-interactive, machine-readable.

Usage as printed by src/Dokimos.Cli/Program.fs.

Dokimos CLI commands. All output is indented JSON on standard output.
CommandProducesExit codes
dokimos measure <source-file>Structural, quality, complexity, and agent-pattern measurements for one file.0 on success; 2 on invalid arguments.
dokimos analyze <source-directory> [--git-history <numstat-file>]Repository analysis: per-file measurements, correlations, and duplicate blocks.0 on success; 2 on invalid arguments.
dokimos snapshot <source-directory> --git-history <file> --repository <owner/repo> --revision <sha> --ref <ref>A canonical schema-versioned snapshot with metrics and findings.0 on success; 2 on invalid arguments.
dokimos compare <before-snapshot> <after-snapshot>A comparison of two canonical snapshots.0 on success; 3 with a JSON unavailable result when a snapshot is malformed or uses an unsupported schema; 2 on invalid arguments.

Run from source with dotnet run --project src/Dokimos.Cli -- <command>. Dokimos targets .NET 8 and treats compiler warnings as errors.

In continuous integration

When a prerequisite fails, the evidence says so.

From .github/workflows/ci.yml in this repository.

Dokimos's own pipeline builds and tests the solution, measures every F# source file, captures Git history, analyzes the repository, writes a canonical snapshot, and compares it with the accepted baseline. All of it is uploaded as a build artifact tied to the commit.

If the build fails, the pipeline does not skip the evidence or write zeros. It writes an explicit record such as {"state":"unavailable","reason":"snapshot-prerequisite-failed"}. A later reader can see that evidence is missing and why, instead of mistaking silence for health.

dotnet build Dokimos.sln --configuration Release
dotnet test Dokimos.sln --configuration Release --no-build
git log --numstat --find-renames --format='commit %H %aI' -- src > artifacts/dokimos/git-history.txt
dotnet run --project src/Dokimos.Cli/Dokimos.Cli.fsproj -- snapshot src \
  --git-history artifacts/dokimos/git-history.txt \
  --repository "$GITHUB_REPOSITORY" --revision "$GITHUB_SHA" --ref "$GITHUB_REF_NAME" \
  > artifacts/dokimos/snapshot.json
dotnet run --project src/Dokimos.Cli/Dokimos.Cli.fsproj -- compare \
  baselines/accepted-snapshot.json artifacts/dokimos/snapshot.json > artifacts/dokimos/comparison.json

Next: the quality model defines each object these stages produce.