Raw observation
What was measured
Directly observed and never reinterpreted.
- complexity = 37
- file changed 7 times in 90 days
- region
applyDiscountschanged in 6 commits - collection failed at commit E
Dokimos · Code-quality assurance from Echelon Foundry
Dokimos records code-quality evidence at every commit and keeps it. It shows how quality changed, where risk is concentrating, and which observations and policies produced each conclusion.
The problem
Same file, same commit, two readings.
A static-analysis run answers one question: does this code break a rule right now? It cannot say whether the code is better or worse than last month, whether the team already proved it could do better, or whether a quiet number hides a file that is rewritten every week.
Those are the questions that decide where engineering attention should go. Answering them requires history, and history is only trustworthy if every observation is kept with the revision, analyzer, and metric definition that produced it.
| Question | Point-in-time report | Dokimos |
|---|---|---|
| Is complexity acceptable? | 37 is under the warn threshold of 45. Pass. | Pass against the threshold, and Warning against the ratchet: +6 points worse than the best demonstrated state (31 at D). |
| Which way is it moving? | Not answerable. | +4 since the previous snapshot; −5 since the baseline. |
| What happened when the analyzer failed? | No report, or a report that silently omits the file. | Commit E is recorded as Failed. Nothing was evaluated, and nothing was recorded as zero. |
| Is this file risky? | Not answerable. | Complex and changed in 7 commits in 90 days: a hotspot, with the same region rewritten repeatedly. |
What Dokimos inspects
Status is checked against the accepted baseline snapshot at build time.
How many decision paths does this code carry?
Is complexity rising or falling relative to earlier snapshots and the best demonstrated state?
Is a file growing, and does it lean on mutation?
Where do broad catch-all patterns hide distinct failure cases?
Where does structural complexity meet frequent change?
Is change weakening types, leaving scaffolding, or expanding dependencies without tests?
Which files are modified most often, and by how much?
Is the same hunk being rewritten again and again?
Which normalized blocks repeat across files?
Is the public surface growing, shrinking, or changing shape?
Do project references cross forbidden boundaries? Which packages arrived?
Does production change arrive with test change?
How long have debt markers survived in code that keeps changing?
Did the build introduce errors or warnings beyond the accepted state?
How entangled are modules, and do they hold together?
What code can never run?
Which constructs make code harder to read than it needs to be?
Implemented measurements are emitted in Dokimos's own accepted baseline. Experimental ones have tested logic that is not yet collected into snapshots. Planned ones are requirements only. Read every metric definition and its limitations.
Quality over time
Question answered: is this file better or worse than it has been, and does policy care?
Demonstration data. This history describes a fictional repository invented for demonstration. It is not a measurement of any real codebase.
Current (H)
37
points, lexical complexity proxy
Since previous (G)
+4
Deteriorated
Since baseline (A)
−5
Improved
Since best (D)
+6
Deteriorated
| Commit | Date | Change | Measurement | Value | Note |
|---|---|---|---|---|---|
| A · a41c09e | 2026-03-02 | Dokimos installed; first snapshot | Available | 42 | Baseline |
| B · b7d2f31 | 2026-03-16 | Extract discount calculation | Available | 39 | |
| C · c02e8a4 | 2026-04-06 | Replace nested rules with a table | Available | 34 | |
| D · d5f1b70 | 2026-04-27 | Split currency rounding into Money | Available | 31 | Best demonstrated |
| E · e93a6cd | 2026-05-11 | Analyzer upgrade failed in CI | Failed | — | Analyzer process exited before producing output. |
| F · f18c4e2 | 2026-06-01 | Add loyalty discount | Available | 33 | |
| G · a6e7d93 | 2026-06-22 | Rename discount tiers | Available | 33 | |
| H · b0c5a18 | 2026-07-13 | Add partner discount exception | Available | 37 | Current |
A universal threshold says 37 is fine because it is under 45. But this file reached 31 at commit D. A ratchet keeps that demonstrated state as the bar, so drifting back toward the old condition is visible instead of silently permitted.
The ratchet does not rewrite history or punish the baseline. Legacy debt can stay baselined while new deterioration is still caught. The disposition — observe only, warn, or fail — is policy, and it is chosen per metric.
From measurement to judgment
Policies can change without falsifying history.
Demonstration data. Examples use the fictional repository from the trajectory above.
A fact measured under a versioned definition: complexity.proxy-cyclomatic v1 = 37 for InvoiceRules.fs at b0c5a18.
Observations held in an immutable snapshot with provenance: repository, revision, collector, configuration, time.
A calculation over evidence: +4 since G; complexity plus change pressure forms a hotspot.
An explicit rule applied to the evidence: ratchet at 31, disposition Warn.
A durable object with a stable identity, a lifecycle state, and links back to all of the above.
Raw observation
Directly observed and never reinterpreted.
applyDiscounts changed in 6 commitsDerived assessment
Calculated from observations, and decomposable back into them.
Policy judgment
An explicit rule with a named disposition.
Read the full quality model, including measurement states, comparison compatibility, and baselines.
Hotspots
Question answered: where is risk concentrated right now?
Demonstration data. The same fictional repository, at commit H.
Complex code that nobody touches is a cost you pay rarely. Simple code that changes every week is cheap to change. The files that deserve attention are complex and repeatedly modified. Dokimos keeps both dimensions visible instead of collapsing them into one opaque score.
File-level churn is coarse: a routes file may change often because new routes are appended. When Git evidence allows, Dokimos tracks repeated changes to the same region, with a confidence value, because rewriting the same function again and again is stronger evidence than a busy file.
| File | Complexity | Commits (90 days) | Churn (lines) | Most-changed region | Classification |
|---|---|---|---|---|---|
src/Billing/InvoiceRules.fs |
37 | 7 | 412 | applyDiscounts: 6 commits (confidence 0.92) — repeated |
Complex and changing |
src/Billing/Statements.fs |
22 | 4 | 96 | renderLines: 2 commits (confidence 0.81) |
Simple, stable |
src/Api/Routes.fs |
7 | 9 | 230 | registerRoutes: 2 commits (confidence 0.88) |
Changing, simple |
src/Billing/TaxTables.fs |
48 | 1 | 12 | No region evidence | Complex, stable |
src/Core/Money.fs |
8 | 1 | 4 | No region evidence | Simple, stable |
Findings have histories
States are the ones defined in the Dokimos domain.
Demonstration data. Maintainability-hotspot finding for src/Billing/InvoiceRules.fs: present when complexity ≥ 30 and the file changed in ≥ 5 commits in 90 days.
A · a41c09e
First observed
Complexity 42, 6 commits. No earlier snapshot, so no transition is claimed.
B · b7d2f31
Improved
Complexity 39, 6 commits.
C · c02e8a4
Improved
Complexity 34, 5 commits.
D · d5f1b70
Resolved
Complexity 31, 4 commits.
E · e93a6cd
Not evaluated
No complexity value: no transition is recorded.
F · f18c4e2
Resurfaced
Complexity 33, 5 commits.
G · a6e7d93
Persistent
Complexity 33, 6 commits.
H · b0c5a18
Regressed
Complexity 37, 7 commits.
Dokimos does not claim the finding was introduced at A: there is no earlier evidence. At E the evidence is missing, so the state is not evaluated rather than assumed resolved.
Explainability
Open each level to follow the chain.
Demonstration data. A drill-down for the ratchet warning at commit H.
InvoiceRules.fs at Hcomplexity.proxy-cyclomatic, disposition WarnRule: the value must not exceed the best demonstrated state (31, commit D, d5f1b70). Actual 37. Result Warning. The universal threshold (warn above 45) independently evaluates to Pass.
Compared only with compatible observations (same metric, definition version 1, same unit). Commit E is excluded because collection failed; it is not treated as zero.
| Revision | Metric | Scope | State | Value | Collector |
|---|---|---|---|---|---|
| D · d5f1b70 | complexity.proxy-cyclomatic v1 | src/Billing/InvoiceRules.fs | Available | 31 | dokimos-cli/1 (illustrative) |
| E · e93a6cd | complexity.proxy-cyclomatic v1 | src/Billing/InvoiceRules.fs | Failed | — | dokimos-cli/1 (illustrative) |
| G · a6e7d93 | complexity.proxy-cyclomatic v1 | src/Billing/InvoiceRules.fs | Available | 33 | dokimos-cli/1 (illustrative) |
| H · b0c5a18 | complexity.proxy-cyclomatic v1 | src/Billing/InvoiceRules.fs | Available | 37 | dokimos-cli/1 (illustrative) |
Dokimos on Dokimos
Rendered from the accepted baseline in this repository at build time.
Real Dokimos evidence. Snapshot of kemiller2002/dokimos at 46c8385 (main), collected 2026-09-26 by dokimos-cli/1.
Observations
154
7 metrics across 22 F# files
Findings
2
maintainability-hotspot (present)
Ratchets
2
build.compiler-errors ≤ 0; build.compiler-warnings ≤ 0
| Scope | Finding | Evidence |
|---|---|---|
src/Dokimos.Cli/Program.fs | maintainability-hotspot (present) | structural-complexity 19, frequent-change 7, high-churn 101 |
src/Dokimos.Domain/Domain.fs | maintainability-hotspot (present) | structural-complexity 30, high-churn 116 |
Echelon ecosystem
Integration happens through explicit evidence boundaries.
Dokimos runs on its own. When an Echelon system is absent, Dokimos records that the evidence is unavailable; it never fails or fabricates data because a neighbour is missing. See the architecture and boundaries.
Start using Dokimos
Dokimos is built from source with the .NET 8 SDK. The CLI is deterministic and emits schema-versioned JSON.
git clone https://github.com/kemiller2002/dokimos.git
cd dokimos
dotnet build Dokimos.sln
git log --numstat --find-renames --format='commit %H %aI' -- src > history.txt
dotnet run --project src/Dokimos.Cli -- snapshot src --git-history history.txt \
--repository owner/repo --revision "$(git rev-parse HEAD)" --ref main