Understand 8.0¶
The install this project is measured on became Understand 8.0 (Build 1262) on 2026-09-05,
replacing 6.5 (Build 1204). Everything below is measured on that build unless it says
otherwise. 0.1.0a7 is the first release that works on it; 0.1.0a6 did not, in one
specific way described first.
What broke in 0.1.0a6, and how 0.1.0a7 fixed it¶
The metric catalogue. 8.0 changed understand.Metric.list() to return Metric objects
instead of id strings, made description an instance method, and added Metric.lookup(id)
(its "Breaking API changes in 8.0" page, item 1). The a6 worker sorted the objects without
complaint and died serialising the answer:
Every catalogue request exited 1 with that traceback and the wrapper reported an analysis
failure, exit 5. The catalogue is asked only when project.languages is configured, so a6
on a repository without that key ran on 8.0 as before, and on one with it never got past
configuration validation. The worker now takes ids off the objects and describes through
Metric.lookup(id).description(), with the 7.x spellings kept as the fallback.
The licence probe. und -isundlicensed prints 0 with exit status 2 on 8.0, where 6.5
exited 0. The wrapper required exit status 0, fell through to und license, and doctor
printed license: ok on a machine where every und analyze failed with No Server
Response. The digit is the answer now, whatever the exit status, and -isundlicensed is
the only licence switch the tool runs: the licence commands that list a licence's options
rewrote the licence file that morning, so an answer that is not 1 is quoted as the
problem, early, and nothing else is asked. See licensing is done from the command
line.
No Server Response, license is Invalid and CodeCheck's No checks in this configuration
are licensed to run are licensing texts now, mapped to exit 4 rather than to a broken
analysis.
A licence without the API option -- 1 from -isundlicensed, a clean und analyze,
NoApiLicense from understand.open -- is caught by doctor's analysis probe, which
analyses a one-file scratch project and then opens it through the API in the mode a check
would use, and by a check at its first metric read.
Three more differences, each with a test¶
| 8.0 does | 6.5 did | What the tool does |
|---|---|---|
understand.open on a bare .und directory raises DBUnableOpen |
raised DBEmpty |
the DBUnableOpen hint goes on to scitools-hook db rebuild |
ships CountParams as a HIS plugin metric, with a description |
answered "" |
the gate still computes its own count and describes it itself, because the plugin metric is unset for Python |
upython describes CountLineCode in 2892 characters; an ordinary CPython loading the same module answers 2006 |
the same | only the bundled interpreter finds the documentation resources and adds a <br>, an image and a "Targets By Language" list; the cross-mode contract compares descriptions with that block removed, and the metric lists to the character |
What did not change¶
und create,und add,und analyze, the shadow trees and the analysis cache.- The Python dialect pin.
undstill runs a barepythonfromPATH; none there still means the Python 2 model, where[first, *rest] = xsstill fails. The tool'sPATHdirectory holding apythonlink still works.-PythonVersionis not a switch on 8.0; its settings arePythonSetVersion Python2|Python3andPythonExe. - PEP 695 and PEP 654. 7.2 taught the parser type parameters,
typealiases andexcept*. The thirteen constructs fromreport/hints.pyanalyse withErrors:0under the pin. The 6.5 measurement stays in What this adds beyond ruff and mypy, dated, because the acknowledgement machinery was built against it; the ruff ignores and the acknowledgement suggestions are deliberately not lifted until an API-licensed run confirms that every routine after such a declaration is in the database, not only that the parse finishes. - A file no build reads still costs the rest of the file.
def generic(x:answersexpected identifier at token returnand thenexpected token ':' at token EOF, and the routine after it is gone from the database. That is the e2e fixture now, since the PEP 695 one parses.
Languages¶
und create -languages accepts the classic set plus Rust, which needs a Cargo project:
a bare .rs file analyses to nothing. Go, Dart, COBOL, Tcl, Perl, PL/M, Verilog and Delphi
are "not a valid language" on 8.0 as on 6.5. (-quiet hides that message; the first
measurement missed it for that reason.) The tool's language table is the one in
Languages; Rust is not in it yet.
Open on 8.0: CodeCheck¶
CodeCheck configurations are plugins under plugins/CodeCheck/{Configs,Published Standards};
the Sandbox configuration the 6.5 contract tests used does not exist. und codecheck
writes results.sarif and, by default, one CSV report, CodeCheckResultsByTable.csv, from
plugins/Solutions/codecheck6Compatability, with the columns
The three 6.5 CSV exports this tool reads by name are gone from und. The licence on the
measuring machine excludes CodeCheck, so the 8.0 output is unmeasured and the integration is
not adapted to it. The three CodeCheck contract tests expected-fail on such a build with
that reason, rather than skip, so the suite keeps saying the contract is open.
What 8.0 buys, measured¶
Everything below shipped in this release. Each row is a measurement on Build 1262, and each feature is off by default: a repository that changes no configuration behaves exactly as it did on 6.5.
| Feature | Key | What it is worth, measured |
|---|---|---|
| Understand's own SARIF beside the gate's | understand.sarif |
one upload carries three tools; GitHub tells them apart by tool.driver.name |
| The before side built from the base commit | understand.before_side |
reproducibility, not speed: on a warm run the before side already costs 0.0 s |
| Generated architectures as rule input | structure.architecture |
Git Stability groups files by how the code has behaved rather than by where it was filed |
| The 8.0 plugin metrics | any threshold naming one | CountGlobalsUsed and friends for Python routines, CountClassCoupledModified for classes |
| Unused routines | structure.unused_routines |
dead code an agent forgot to delete, as a warning |
| The accuracy of an analysis | analysis.accuracy_floor |
how much of the run to trust; never blocks |
| One extraction per side, cached | understand.snapshot_cache |
the warm one-line check went from 27.7 s to 13.0 s on this repository |
Understand's SARIF: a check concern, and a whole-project one¶
check --sarif PATH writes the gate's findings there and, with understand.sarif = true,
Understand's own documents beside it as PATH.understand-analysis.sarif and
PATH.understand-codecheck.sarif. They are never merged: GitHub code scanning accepts several
tools in one upload, and merging would mix fingerprints and rule ids from tools that know
nothing about each other.
explain has no SARIF output format, so the companions are a check concern only. Requirement
2.1 names "a check or explain run"; the reading taken is that the clause applies where SARIF
exists.
The analysis companion comes from a whole-project pass only. Measured: und analyze -sarif
reports the pass, not the database. A selective pass over one clean file writes a document
whose results array is empty while the database still holds three parse errors, and nothing
in the document says it is partial. Published, that is a clean bill of health for a repository
that has none. So a warm run writes no analysis companion and says why; a run over a cold
cache, or one after scitools-hook db rebuild, writes one.
The before side from a commit: what it changes about the file set¶
understand.before_side = "commit" builds the before database with und create -gitcommit
rather than by exporting a shadow tree. Two consequences an operator should know:
- The file set is the repository's, not the shadow's. Without
-refdbthere is no file set to copy, sound adddecides it underund -exclude, while the shadow isproject.include/project.excludeapplied by the synchroniser. The two pattern languages do not agree everywhere: measured,und -exclude 'build/**'excludes nothing while-exclude builddrops the tree. Where they differ, the before side sees a different project. -refdbcannot be used at all. It copies the reference's file paths, the gate's after database names its files under a shadow tree in your cache, and-gitcommitpins the contents only of files inside-gitrepo. A file outside it is read from disk, silently. The before database then held the working tree's code and a range check reporting eight ratchet findings reported one.
Comparison metrics: none exist yet¶
-refdb registers the two databases as a comparison pair, readable as Db.comparison_db().
Measured: no metric on 1262 reads it -- 108 ids across the file, function, class and project
kinds, none of them a comparison metric. The gate's own ratchet already answers the question
those metrics would: it compares each entity's value on the two sides and reports the ones that
got worse. Nothing is lost by not registering the pair.
Git architectures need a commit¶
Measured: the gate's own database, built over an exported shadow tree with
GitRepositoryDirectory set, exports Git Stability with zero members while exporting
Directory Structure with 260. The plugin runs git log and matches its output to the
database's file paths, and a shadow tree's paths are not paths git has heard of. So the gate
generates on a third database, rooted at the repository and pinned to the after side's commit,
and a --staged or --worktree check has no commit to pin: it says so rather than evaluating
against an empty architecture.
Still open on 8.0¶
CodeCheck. The licence on the measuring machine excludes it, so the 8.0 output is
specified from the shipped plugin sources and unverified. The gate reads violations from
results.sarif where a run wrote one and from the 6.5 CSV exports otherwise; the contract test
for a real inspection is an expected failure naming the licence, so the suite keeps saying the
contract is open. -gitfiles, -previous results.sarif and the PYTH_02 check are unreached
for the same reason.
Rust, once a Cargo project is in the fixtures. und create -languages accepts it; a bare
.rs file analyses to nothing.
For a contributor: two things deliberately left out¶
Both are outside the boundary this project works in rather than beyond its interest, and both are good first contributions for somebody whose machine is on the network.
undmcp, an MCP server over an Understand database. Probing it spawned two
undaiserver --tcp 56767 processes that had to be killed by hand. A gate that starts a
listening server as a side effect of a commit hook is not a gate anyone should install, so
whatever this becomes needs a lifecycle somebody has designed on purpose.
und ai, a local model that downloads weights over the network and is off by default. The
machine this project is measured on is kept off the network deliberately, for licensing
reasons, so nothing here can measure it. Neither feature is refused on its merits; both are
simply unmeasurable here, and an unmeasured feature is not one this project ships.