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.
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.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.
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.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.Compare compatible snapshots
dokimos comparereads 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.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.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.jsononly 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.
| Command | Produces | Exit 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.