← livingedenframeworks.com
The core engine's change-log
What changed in LEF SI Engine's core, and why: how it reads records and judges what it finds. Each build
carries its own copy of the engine, so a change reaches a build when that build is regenerated or the idea is carried
over and proven again.
0.84.3 2026-11-06
A run's validity report on Public Services comes back complete again
On the public site the validity report beside a run could come back empty, because one part of the engine would not load on the Python version the site runs. That part now loads, and the report is written.
0.84.2 2026-11-03
The engine's repeat check no longer raises a false alarm on very large files
Every read repeats itself in a second process and says whether the result was the same. On a very large file, where the search reads part of the file and a later step counts each gap against the whole of it, the check compared the first read after that step with the repeat before it, and reported a difference that was not one. It now compares like with like. A real difference is still reported.
0.84.1 2026-11-03
The engine now reads a field that only appears late in a file in four more of its checks
Some files start carrying a field partway through. An earlier fix (0.83.2 and 0.83.3) made most of the engine read every record's fields; four checks still looked only at the opening records. The check that types each column read a late field as having no values and named its kind from its name alone, and the checks for who kept a record, for identifiers left out of a comparison and for the date to grade by could miss such a field entirely. All four now read every field, and a field with no value anywhere is held for a person rather than given a kind.
0.84.0 2026-11-02
The engine now notices when a record starts or stops using a code over time, and says when
A record can change how it is kept without any field emptying and without its most common value moving: a new code can simply start appearing. NCES documents that its school virtual-status field gained a MISSING code in 2018-19, in fewer than one record in four hundred, and the engine's check of how a record keeps itself could not see it. The check now names each code that starts or stops being used between periods, with the period it first appears in and how often, and never says what the code means.
0.83.3 2026-11-02
The engine's check of how a record keeps itself over time no longer gives up when a period is empty
The engine reads whether a record changes how it is kept across time before any count across time is trusted. On three school years of a federal education file, the time cut left its last period empty and the check compared against that empty period, so it said it could not read the history at all. It now compares the first and last periods that hold records, and reads every field, including one only later years carry. On the same three years it now names the fields that stopped being filled and the labels that changed, and still says nothing about why.
0.83.2 2026-11-02
The engine now sees every field in a file, including fields that only some kinds of record carry
When a file mixes kinds of record, some fields belong to one kind only. The engine's check that sets aside a gap a field simply cannot fill looked at the first record's fields alone, so a field the first record lacked was invisible to it, and on a security control catalogue two gaps that were only the file's structure came through as real. The engine now reads the fields of every record, in five places, and its tests hold both ways: the structural gap is set aside, and a real gap between fields every record carries is not.
0.83.1 2026-11-02
The engine now looks for a tool's named fields across every record, so a field that appears only in later records is not missed
The change made earlier today let the engine's seat read run on a security control catalogue. On the real catalogue it still did not run: the engine looked for the named fields in the first 2,000 records only, and one of them appears only on withdrawn controls, which come later in the file. It now looks across every record, and a test holds a field that first appears after record 2,000.
0.83.0 2026-11-02
When one tool reads more than one kind of document, the engine's seat read now runs on each kind whose records can support it
A tool can read more than one kind of document, and the engine's seat read, which looks at the records from the reader's side, used to take one answer for all of them. A security control catalogue's records can support that read where a specification's cannot, and the catalogue never got it. Now the tool's document names the fields for the kind that has them and gives its reason for the kind that does not, and the engine runs the read wherever the records carry those fields. Each new catalogue is still tested on its own before anything ships.
0.82.0 2026-11-01
Every page a build shares now carries LEF's attribution, and the build's own test checks that it does
Every page a build shares now carries LEF's attribution: what generated it, the engine it is built on, and LEF's licence. The tool's own words are never changed, and the build's own test fails any shared page that lacks it.
0.81.0 2026-11-01
Each gap the engine keeps now carries a severity score from 3 to 9, as the traversal filing defines it
Each gap the engine keeps now carries a severity score from 3 to 9 (impact, age and blockage, as LEF's traversal filing defines it), so the kept gaps of a read can be ranked against each other.
0.80.0 2026-11-01
Where two parts of a run disagree, the engine now holds that result back and shows both sides first
When two parts of a run disagree, such as the tool's count and the engine's recount, the engine now holds that result back, shows both sides first, and picks neither.
0.79.0 2026-11-01
The engine's self-read is built into a delivered build only when the licensee asks for it before the build
A delivered build now carries the engine's self-read only when its licensee asks for it before the build; otherwise LEF reads its own kept copy of the build.
0.78.1 2026-11-01
A stated limit with no yes-or-no verdict from the run is now reported as unchecked, not as broken
When a tool states a limit but its run gives no yes-or-no verdict on it, the engine now reports that limit as unchecked, rather than mistaking the wording for a broken limit.
0.78.0 2026-11-01
The spec reader now reads a security control catalogue against itself
The spec reader now reads a security control catalogue such as NIST SP 800-53 against itself: whether each related control names a control the catalogue still holds, where each withdrawn control went, and whether the summary tables say the same as the control text.
0.77.2 2026-10-29
When the gap search cannot run, the front page now says so instead of reporting no gaps
When no value is common enough to search, the read now says the search could not run, rather than reporting that it found no gaps.
0.77.1 2026-10-29
A dollar amount that happens to repeat is no longer read as a record's identity
Records whose amounts happen to match are no longer read as one record told two ways, and the column library no longer learns an amount or a product code as an identifier.
0.77.0 2026-10-29
Every read now learns what each column is, and remembers it
Each read now types every column (an identifier, a date, a place, a count) from a library that learns across runs at the same place, holds the columns it cannot type for a person, and says where the library is kept.
0.76.1 2026-10-29
The front page of each run now masks personal identifiers too
The front page each run writes now masks email addresses and ORCID iDs, as the run's other readable pages already did.
0.76.0 2026-10-29
Each gap now says what holds it apart and whether it can close
For each gap it reports, the engine's page now says which values keep the two sides apart and whether any record consistent with the file could hold both.
0.75.1 2026-10-28
Each run now records the size of the file it read
Each run now records the size of the file it read, beside the time it took and the records it held.
0.75.0 2026-10-28
A build's document can now say the engine's seat read does not fit its records, and the engine checks that reason
A build's document can now say why the engine's seat read does not fit its records; the engine checks the reason against the records before accepting it.
0.74.0 2026-10-28
A build's check now fails when a run breaks one of its stated limits, or when its counts disagree with the engine's
A build's own test now fails when a run breaks a limit the build states, or when a count the build reports disagrees with the engine's recount of the same records.
0.73.0 2026-10-28
Where no existing record links a gap's two sides, the engine now says it cannot picture the record that would fill it
For a gap whose two sides share no linking value, the engine's read now says plainly that it cannot picture the record that would fill it, and shows what it looked at.
0.72.1 2026-10-28
The engine's own read now reports the movement it measured across a file's periods
The engine's own read of a dated file now says how many pairs of values stopped or started meeting across the file's periods, instead of saying that movement was not read.
0.72.0 2026-10-28
Each run now records how long it took, and how well its records cover the places they name
Each run now states how long it took and, for the fields a build names as places, how many records hold a place, how many places there are, and how concentrated they are. It never guesses which fields are places.
0.71.0 2026-10-28
A build's document can now name exactly which fields its work speaks of
A build's document can now list exactly the fields its work acts on, and the engine's read for that work uses those fields, saying plainly if any is not in the records.
0.70.1 2026-10-28
The engine reads the fields a build's document names more exactly, and says whether it asked the live source
When a build's document names the fields its work speaks of, the engine now finds them even where a name breaks across a line, and never matches a name inside another word. Its challenge report says whether the live source was asked, from the run itself.
0.70.0 2026-10-28
The engine now reads where the money runs, not only where the records run
The engine now reads where a product's money runs as well as where its records run, and says which field it weighed by. A place carrying most of the dollars in a few large awards is named, with its award count, where record counts alone never saw it.
0.69.4 2026-10-28
The engine now says what it set aside, and why, wherever it reads across datasets
Wherever the engine reads across datasets it now names what it set aside and why: pairs it could not test, values too common or too thin to read, lines it could not read, duplicate records, and joins it did not read. Nothing is dropped silently.
0.69.3 2026-10-27
Where the engine could not read or test something, it now says so instead of reporting nothing
Where the engine could not read or test something, it now says it cannot tell, and why, instead of reporting that it found nothing.
0.69.2 2026-10-27
The engine now reads several pulls of one source together, reads every value it can, and looks where the work is done
The engine now reads several pulls of the same source together instead of keeping only the largest, reads every value with enough records to judge, and looks both where suppliers are and where the work is done.
0.69.1 2026-10-27
When there is too little to see a shape, the engine now says so instead of agreeing with its own null
When there are too few records to see how something is spread, the engine now says it cannot tell whether its question fits, instead of agreeing with its own finding of nothing.
0.69.0 2026-10-27
Before the engine says it found nothing, it now checks whether its question fits the evidence
Before the engine says it found nothing, it now looks at the shape of what it was asked about. When the evidence is sharply concentrated and its comparison could not have seen that, it says its question does not fit the evidence, and names the concentration, instead of reporting nothing.
0.68.0 2026-10-27
The engine now finds where a product, an industry or any value runs through a few places
The engine now finds where a product, an industry or any other value of a dataset runs through a few places, compared with everything else in the same dataset, and names those places. It says what its records cover, and that a count of records is not a count of money.
0.67.0 2026-10-27
The engine now drags one datapoint across every dataset it holds, and can ask about a single product or industry
The engine now takes one datapoint, such as a kind of hospital, across every dataset it holds that shares its places, and builds a new dataset in which each place says something, says nothing warranted, or cannot speak. It can also ask about a single product or industry, and never mistakes a place's own name for a pattern.
0.66.0 2026-10-27
The engine now takes what one dataset says and does not say to the other datasets it holds, without being asked
The engine now takes what one dataset says and does not say to the other datasets it holds, without being asked: it tells a gap that is only a sample's blind spot from one the source itself lacks, reads each pattern state by state, and takes the places a pattern singles out to other datasets to see whether they stand out there too.
0.65.0 2026-10-27
Given many datasets and no question, the engine now reads every related pair itself and reports what each shows together
Given many datasets and no question, the engine now reads every related pair itself, chooses where to join them, and reports only what each pair shows together, comparing each place with places like it. It never says why, or who should act.
0.64.0 2026-10-27
Given two related datasets, the engine now reads them together and reports what neither shows alone, with the places to look at
Given two related datasets, the engine now reads them together, place by place, and reports what neither shows alone, with the places a person should look at. A question asked in advance is answered yes or no, either way. It never says why, or who should act.
0.63.0 2026-10-27
Given many datasets, the engine now says which relate to one another, on which fields, and how strongly
Given many datasets, the engine now says which of them relate, on which fields, and how strongly, and names the copies and slices of one source apart. It tells you where two datasets could be joined; it never says why they relate.
0.62.3 2026-10-27
The engine no longer reads a record's id number as a measurement, and says plainly which of its kept rules apply to the file in hand
The engine no longer treats a record's id as a measurement when it looks for values that do not fit or cannot be right, and it names the id fields it read that way. Where it keeps rules learned from many datasets, it now says how many belong to the file in hand.
0.62.2 2026-10-26
A tool can now ask the engine how often a source's documentation and its records disagree, for exactly the records it holds
A tool built on the engine can now ask how often a source's documentation and its records disagree for exactly the records it holds, without disturbing the engine's own read.
0.62.1 2026-10-26
The engine's report names every place a source's documentation and its records disagree, never only the first few
The engine's report now names every place a source's documentation and its records disagree, and any list it shortens says how many it left out.
0.62.0 2026-10-26
The engine names fields a record carries from the record it belongs to, such as an order's details copied from its contract
The engine now names fields a record carries from the record it belongs to, such as an order's details copied from its contract, so a reader knows which values were recorded for the record itself.
0.61.0 2026-10-26
The engine also reads combinations of four values that never occur together, as leads
The engine now also reads combinations of four values that never occur together where three of them do, and reports each as a lead, saying how far it read.
0.60.0 2026-10-26
The engine reads a specification against itself: requirements with no verification, documents cited and not listed, references that land in the wrong place
The engine can now read a specification against itself: it names requirements the specification gives no way to verify, documents it cites without listing or lists without citing, references that land nowhere or in the wrong place, and tests no test table runs.
0.59.0 2026-10-25
The engine names fields that hold the same value in most records, such as two dates that fall on one day
The engine now names fields that hold the same value in most records, such as an order's two dates falling on one day, so a reader knows how the record was kept before reading its gaps.
0.58.0 2026-10-25
Every run now opens with a short page in plain words: what was read, what held, what to look at first, and what could not be checked
Every run now opens with a short page in plain words: what was read, what held and what to look at first, what could not be checked and why, and where the detail is.
0.57.1 2026-10-25
The engine reads a date written out in words as a date wherever it appears, not only where a field is named like one
A field of dates written out in words, such as an amendment's effective date, is now read as a date and never as a category to compare against others.
0.57.0 2026-10-23
The engine now sets aside a gap that rests on a word only one of two record systems uses
When two record systems are read together and one of them uses a word the other never does, the engine now treats any gap resting on that word as a lead about how the records were kept, not as a finding.
0.56.1 2026-10-21
When a record answers for a place the outside source does not count, the engine names those records as leads
When a record answers for a place the outside source does not count, the engine now names those records as leads for a person to check, and never counts them as confirmed.
0.56.0 2026-10-21
The engine no longer names a cause for a gap it has not read the cause of
Where a record has room for both values of a gap, the engine now says only that the record's layout is not what keeps them apart, rather than calling the gap a feature of the world, a cause it had not tested.
0.55.0 2026-10-21
The engine holds a quote only when it is whole in its source, and never reads silence through a filtered record
The engine now holds a quote only when it begins and ends where the source's words do, and never reads a record's silence as meaningful when the record was pulled through a filter.
0.54.1 2026-10-21
The absence-or-missed reading now states first the figure it rests on, and the years the site was visited
The engine's reading of whether an absence is true or a missed detection now states first the figure it rests on, and the years the site was visited, so a reader never takes a stricter-sounding number as the answer.
0.54.0 2026-10-20
The engine also recognises a field of people's names, written the way records list who kept them
The engine also recognises a field of people's names written the way records list who kept them, and reads absences through it as how the records were kept.
0.53.0 2026-10-20
The engine reads whether an absence at a site is a true absence or a missed detection, recounts every count a tool reports, and judges absences among three values
The engine can say whether an absence at a surveyed site is likely a true absence or a missed detection, estimate how complete a record is where an independent source exists, count again every number a tool reports, and judge absences among three values the way it judges pairs.
0.52.0 2026-10-20
The engine reads day-first and month-first dates by what each field shows, and refuses to guess where a field mixes them
The engine reads slashed dates the way each field writes them, day first or month first, and refuses to guess where one field mixes the two.
0.51.0 2026-10-19
The engine tells a field naming who kept a record from a field about the world, and reads absences through it as record-keeping
The engine tells a field that names who made or kept a record from a field about the world, and reads an absence through it as how the records were kept, not what they describe.
0.50.1 2026-10-19
The engine's record test can check, month by month, that a dataset holds every period its provider published
The engine can check, period by period, that a dataset holds every period its provider published and nothing in a period it did not, and how far back that check can reach.
0.50.0 2026-10-19
The engine reads dates written out in words and with slashes, and reads each date one way throughout
The engine reads dates written out in words and with slashes, so records dated that way can be read over time, and it reads each date the same way in every check.
0.49.0 2026-10-19
Before reading what a record lacks, the engine tests whether the record would show it
Before reading what a record lacks, the engine can test the record against known answers: whether it shows what is known to be there, stays quiet where something is known to be absent, and how far back an absence can be read.
0.48.1 2026-10-17
The engine no longer reads a whole corpus a second time when there is nothing to fetch
When a build declares no source to fetch from, the engine no longer reads the whole corpus a second time, with the same answers.
0.48.0 2026-10-17
The engine's recorder-or-world reading counts across large record sets part by part, with the same answers
On large record sets the engine's reading of whether the record or the world keeps a gap's two sides apart is counted part by part, with the same answers, using less memory.
0.47.0 2026-10-17
The engine counts across large record sets part by part, checks that the parts add up to the whole, and gives the same answers
On large record sets the engine counts part by part and checks that the parts add up to the whole, with the same answers, using less memory.
0.46.0 2026-10-17
The engine holds large record sets compactly, writes every working file completely before reading it, and gives the same answers
On large record sets the engine holds records compactly and writes every working file completely before reading it back, with the same answers.
0.45.0 2026-10-17
The engine reads large record sets in less memory, with the same answers
On large record sets the engine now needs about a fifth less memory for the same read and the same answers.
0.44.1 2026-10-17
The engine no longer pairs two different documented values as one spelled two ways because they start with the same word
Two documented values that start with the same word are never read as one value spelled two ways.
0.44.0 2026-10-16
The engine now checks a test plan's matrix for planned combinations with too few runs or none, and runs its plan check in every read
Given a test plan, the engine names each planned combination of conditions with fewer runs than the plan requires, none included, and every read says whether a plan was checked.
0.43.1 2026-10-16
The plan check now lists every test lacking a required channel, never only the first ten
The plan check lists every test lacking a required channel and counts them.
0.43.0 2026-10-16
The engine can now read a test's records against the test procedure it followed, and name each test or dummy lacking a channel the procedure requires
Given a test procedure, the engine checks each test, and each instrumented dummy, for every channel the procedure requires, and names any that lack one; a requirement read from a procedure's prose says it rests on LEF's reading.
0.42.2 2026-10-16
When the engine checks a source's documentation against its records, it now always reports the whole file, never only its earlier records
When a source's documentation is checked against its records, the counts reported are always the whole file's.
0.42.1 2026-10-16
The engine no longer reads a day as a month when a date's month is missing, and it now names dates that cannot exist
When a date's month is missing, the engine now places it by its year instead of reading the day as a month, and it names any value written as a date that cannot exist.
0.42.0 2026-10-14
The engine reads three more things the way the documentation means them: a blank documented as missing, a missing code as documented, and a list it could only partly quote
A blank that the documentation names as missing is now counted, a documented missing code is never reported as undocumented, and a value outside a list the engine could only partly quote is said to be just that, not 'documented nowhere'.
0.41.2 2026-10-14
The engine's main search now applies the same rule as 0.41.1: a field that only ever holds one code is never paired with itself
The fix of 0.41.1 now reaches the engine's main search too, so a field holding one code per record never yields an absence that is true by construction.
0.41.1 2026-10-14
The engine no longer reports two codes of a field as never meeting when the field only ever holds one code
Where a field only ever holds one code per record, the engine no longer counts its codes as never appearing together, an absence that was true by construction and said nothing.
0.41.0 2026-10-14
The engine reads each code in a field that lists several, instead of reading the whole list as one value
Where a source writes several codes in one entry, the engine can now read each code on its own, so codes that appear together in one report are counted, and the same codes in a different order are no longer a different value.
0.40.0 2026-10-11
The engine prepares a source's records for reading without changing a single value, and writes down every decision it made
The engine can now prepare a source's records for reading from a written plan, without changing a single value, and it tests that promise on every run.
0.39.0 2026-10-11
Each gap now says whether the source's documentation, the records, or both explain it
Each gap now says whether the source's own documentation, the records, or both explain it, and names a rule the records keep that the documentation never states.
0.38.0 2026-10-11
The engine reports a source's documentation against its records, rule by rule, and changes nothing until the dataset's steward accepts it
The engine now reports a source's documentation against its records rule by rule: what agrees, what the records contradict, what is documented but never used, and what is written differently, with counts. A documented missing code changes nothing until the dataset's steward accepts it.
0.37.3 2026-10-11
Each read's documentation checks now start fresh, and the shape check states its statistics exactly
Each read's documentation checks now start fresh, and the shape check states exactly what its chance correction covers. What the engine finds is unchanged.
0.37.2 2026-10-10
The engine's default Claude model is now Claude Opus 5.5
The engine's default Claude model is now Claude Opus 5.5; what the engine itself reads and computes is unchanged.
0.37.1 2026-10-09
Three corrections: rules checked against the records as written, too few years never mistaken for enough, and a record's edit date never mistaken for its subject's date
Rules about a source are now checked against its records as written, a few stray dates no longer make a short file look long enough to judge over time, and the date a record was last edited is never mistaken for the date of what it describes.
0.37.0 2026-10-09
The engine now takes a source's own definitions of its categories, and checks every record against them
The engine now takes a source's own definitions of its categories, quoted from the source's documentation, and checks every record against them; and each finding's page shows whose rule set it aside or explains it.
0.36.0 2026-10-09
A rule the engine is given now says who it rests on, and only a source, an authority or a named person can set a finding aside
A rule the engine is given about a source now says who it rests on: the source itself, another authority, or a named person can set a finding aside, and the page says which; a rule only LEF believes can explain a finding but never remove it; and where a source's own documentation and its records disagree, the engine says so.
0.35.0 2026-10-08
The engine now finds a stretch of a measurement that holds far fewer records than its surroundings, not only one that holds none
The engine now finds a stretch of a measurement that holds far fewer records than the records on both sides predict, not only a stretch that holds none, and a few extreme values no longer hide one.
0.34.1 2026-10-07
A measurement is no longer read as a date because of its column's name, and pages no longer show a person's email or ORCID iD
A measurement is no longer read as a date because of its column's name, several reads at one place no longer overwrite each other's records, a dataset's history is compared only with its own earlier runs, and the pages a person reads no longer show anyone's email address or ORCID iD.
0.34.0 2026-10-07
A rule the engine confirms now says whether a second source keeps it
A rule the engine confirms now says whether a second, different source keeps it, or only files from the same source, since files from one source can share how that source keeps its records.
0.33.1 2026-10-06
A record filed twice under one identifier, told differently, can no longer hide a gap
A record filed twice under one identifier, told differently the second time, can no longer hide a gap the rest of the records show, while records that only share a name are still read as distinct.
0.33.0 2026-10-06
A licensed build can now tell its licensee which published revisions may answer what its runs keep hitting
A licensed build can now tell its licensee, from its own runs and without contacting LEF, which published revisions may answer what its runs keep hitting, and which of its needs are its own.
0.32.0 2026-10-06
Rules the records keep can now be confirmed across files of the same source, and only by files that are genuinely separate
Rules the records keep can now be confirmed across files of the same source, and only by files whose records are genuinely separate, so a sample of a file never confirms that file's own rules.
0.31.1 2026-10-06
A date written as a number is read as a date everywhere in the report
A date written as a number is now read as a date in every part of the report, so the report no longer says a file has no dates while reading it by date.
0.31.0 2026-10-05
A source's own codebook can now tell the engine which values never go together
A codebook supplied for a source can now state which values it never writes together, each rule cited to the source; a gap such a rule covers is set aside on the source's word, and the report says how many.
0.30.6 2026-10-05
No record is left out of the read because it shares a name or number with another
No record is left out of the read because it shares a name or a number with another record; each one is read.
0.30.5 2026-10-05
A build can no longer present a gap as standing when its engine ruled it out
A build's findings are now checked against its engine's own read, and a gap the engine ruled out cannot be presented as standing.
0.30.4 2026-10-05
The report names the model behind every piece of prose, and says when a piece names none
Each run's report now names the model behind every piece of prose it checked, and says when a piece names none.
0.30.3 2026-10-03
A single stray value no longer makes a gap in a measurement
A single stray value far from the rest no longer makes the engine report an empty range in a measurement.
0.30.2 2026-10-03
Codes and identifiers are no longer read as measurements
A field that holds codes or identifiers written as numbers, such as a ZIP code or an award ID, is now kept as written and is never read as a measurement, so a missing region can no longer show up as a gap in one.
0.30.1 2026-10-03
A file too short in time to cut by date says so
When a file covers too short a time to be cut by date, the engine's report now says that, and which field it read, instead of saying the file has no dates.
0.30.0 2026-10-03
Gaps in numeric measurements are read
The engine now reads numeric measurements for gaps, not only categories, and tells a gap from the edge of the data.
0.29.0 2026-10-03
A real gap is no longer dismissed because two fields are strongly associated
The engine no longer dismisses a real gap because two fields are strongly associated; it keeps the gap and names the pattern it rests on.
0.28.3 2026-10-02
With no record IDs, no conflicting IDs reported
With no record IDs, the engine no longer reports conflicting IDs between sources.
0.28.2 2026-10-02
Copies across sources, read more carefully
When records name their source in more than one field the engine checks each for copies, and with no record IDs it no longer mistakes look-alike records for copies.
0.28.1 2026-10-02
A refused date field gives the true reason
When the engine cannot cut a body of records into periods, it now gives the true reason.
0.28.0 2026-10-02
How the record keeps itself across periods
The engine now reads how a body of records keeps itself over time, which fields stopped or started being filled and which recording channels changed, so a reader knows when a count across years rests on a record that changed.
0.27.0 2026-10-02
A ranking or classification checked against an outcome
A person can now state that a ranking or classification should separate an outcome, and the engine checks it step by step, saying where it separates, where it reverses and where it does not.
0.26.1 2026-10-01
Tracing each gap forward is about ninety times faster
Tracing each gap forward is now about ninety times faster on wide corpora, with exactly the same results.
0.26.0 2026-10-01
Gaps among three values
The engine now finds gaps among three values, where every pair meets but the three never do together; in this version each is reported as a lead.
0.25.0 2026-10-01
A change between periods read for the same holders re-coded
When a pairing appears or disappears between periods, the engine now says when the same holders are still there with a code switched: a change in how records are coded, not in who holds them.
0.24.0 2026-10-01
A gap told through two fields that carry the same information is counted once
When two fields carry the same information, such as a country code and a country name, a gap found through both is now counted once.
0.23.1 2026-10-01
A word in a number column is read as written unless it names absence
A word in a column of numbers is no longer read as missing unless it says so: in a rule table, 'None' can be the rule.
0.23.0 2026-10-01
What counts as not collected belongs to the source
The engine no longer treats words like 'NA', 'None' or 'Unknown' as missing by default: what a code means belongs to the source that wrote it, and a codebook for that source can say so, field by field.
0.22.0 2026-10-01
Claims a person states about the records are checked
The engine now checks the claims a person states about a body of records, saying for each whether the records support it, contradict it or cannot tell, and how far each is from flipping.
0.21.1 2026-10-01
Every report states what no check on the records can see
Every run's report now says plainly what no check on its records can see: a gap hidden without any trace takes a second source to find.
0.21.0 2026-10-01
A change between periods is called only where the records can tell
When the engine says a pairing opened or closed between periods, it now holds that to the same standard as its gaps; one or two records are reported as too thin to tell.
0.20.0 2026-10-01
Every run checks the same records give the same result
Every run now checks that the same records and settings give the same result, and compares a later run on the same file with earlier ones.
0.19.3 2026-10-01
Two runs started in the same second each keep their record
Two runs of one build started within the same second each keep their own record; the second no longer fails at its end.
0.19.2 2026-10-01
Widening the read is answered in every report
Every report now answers whether the read was widened, and a build with no source to widen through says so.
0.19.1 2026-10-01
Each fill proposal says where its gap stood
On the engine's own page, each fill proposal now says whether its gap held, became a lead, or was refuted.
0.19.0 2026-09-30
A read can be handed a library of signals
A read can now be handed a library of patterns that went with gaps closing or staying empty, and names which each gap carries, withholding a pattern's strength where the records are unlike those it was tested on. A signal says more often, never this one will.
0.18.1 2026-09-30
Every count from a whole source carries the time it was asked
When the engine checks a gap against a whole index, each count now carries the date and time it was asked, so a figure says which reading of a changing index it came from.
0.18.0 2026-09-30
Whether each gap is weakly or firmly held apart
For each gap it holds, the engine now also says whether the gap is weakly or firmly held apart right now.
0.17.0 2026-09-29
Fields with very long lists are read, and say how much was read
The engine now reads fields that hold long lists of labels and says how much of each it read, where before it read none, and it no longer draws a conclusion from too few gaps.
0.16.0 2026-09-29
What keeps a gap's two sides apart: the record or the content
The engine now says, for each gap, what keeps the two sides apart: the way the records are kept, or the content itself.
0.15.0 2026-09-29
The engine widens its own read and says what changed
The engine can now widen its own read through the source a build declares, read again, and say which gaps ended, opened or held.
0.14.0 2026-09-29
Several sources read together, and several reads composed
The engine can now read several sources together, joining what they share, and compose several reads into one picture, saying plainly when those reads draw on the same corpus and so are not independent confirmations.
0.13.0 2026-09-29
Each gap's history across runs
The engine now remembers its findings between runs: each gap says whether it is new, recurring or shifted, and each run lists what the last one reported and it no longer does. The memory is context for the reader, never evidence.
0.12.0 2026-09-29
Values that travel together are checked before anyone reads them
The engine now checks the associations it reports as it checks its gaps: one resting on a handful of records, two blanks travelling together, or one association counted twice is marked as such.
0.11.0 2026-09-29
How thinly a combination is held, not only whether it is empty
A combination the records should hold plenty of, held by only one, two or three holders, is now listed for a person, which is where a supply or coverage risk sits. In a sample, each is counted in the whole source first.
0.10.0 2026-09-29
Every gap carries its pursuit: bridge it, fill it, or neither
Every gap now carries a pursuit a person can weigh: whether it can be bridged, whether it can be filled, or neither, with the case for and against, what would refute it, and the next step that would settle the most. The engine does not decide what to pursue; the person does.
0.9.2 2026-09-29
A column of codes is read as codes
The engine no longer mistakes a column of codes, such as supplier codes, for a column of numbers, and still flags a real number column that holds a stray word.
0.9.1 2026-09-29
A trace offers only directions its records support
A gap's trace now offers only directions its records can support, and never offers a date as a direction.
0.9.0 2026-09-29
Every gap carries its parts
Every gap now carries its parts, so a reader can check it rather than take it on trust: what it is, how it was counted, why it is there where the records show a reason, what would change it, and a trace to follow.
0.8.3 2026-09-29
Records a person should read are listed for them
The engine now lists two more kinds of record for a person to read: one that breaks a pattern the records around it keep, and one record carried under two identifiers. Both are listed, never used to doubt a finding.
0.8.2 2026-09-29
A source that stops answering is asked no more, and the report says so
When a source the engine counts in stops answering, the engine stops asking it, and the report says how many gaps went unasked and why.
0.8.1 2026-09-29
A corpus can be declared a sample of something larger
A corpus can now be declared a sample of something larger. A gap found only in the sample is then read as a lead, and where a build can count in the whole source, each gap is counted there and the report says what the whole said.
0.8.0 2026-09-29
Every gap names its cause, or says the records cannot tell
Where a corpus carries dates, the engine now asks whether each gap's two values ever existed in the same period, and lists pairs that met earlier and stopped meeting. Every gap now names its cause where the records show one, and says the records cannot tell where they do not.
0.7.3 2026-09-29
The engine profiles a corpus with its own code
The engine now profiles a corpus itself, and the check a build goes through before it meets a partner's records is the engine's own read of a corpus shaped like theirs, saying which checks that shape lets it answer.
0.7.2 2026-09-29
The look back over time reports by pair of fields
The check of the engine's earlier gaps against what came after now reports by the pair of fields each gap lies between, because what a later fill means depends on what those fields record.
0.7.1 2026-09-28
Repairs: the answering model is named, and no date is invented
Every run's report now names the model that answered, as the provider named it. A date that cannot exist on a calendar is kept as written instead of being turned into one that looks valid. The engine's own test runs to its end again.
0.7.0 2026-09-28
Fields that hold lists are read as lists
Every check now reads a field that holds a list, such as a work's topics, as the values in it, and two values of one list field can now form a gap. Files with no list field read as before. A field that mixes numbers and words no longer stops the read.
0.6.0 2026-09-28
Every run grades its own method against the records' past
Where the records carry dates, every run now checks its own method against their past, grading the gaps it would have named earlier by what came after. It grades the method on the corpus's own history; it is not a forecast.
0.5.2 2026-09-28
Clearer wording for a gap too rare to tell
When a gap is too rare to tell from coincidence, the report now says so and calls it a lead, without overstating it.
0.5.1 2026-09-26
Wider fields read, and a gap that restates a regularity says so
Fields with thousands of values are now read instead of skipped. A gap that restates a stronger regularity in the same records now says so, and is never thrown out on its account.
0.5.0 2026-09-26
Each gap traced to what holds it apart, and to whether it can be filled
The engine now traces each gap it holds: what keeps the two sides apart, what a record filling it would have to carry, and whether any record consistent with the file could fill it at all. A gap that rests on another gap says so.
0.4.0 2026-09-26
Corrections found by testing the engine on deliberately noisy files
One value written several ways is now read as one value where one spelling clearly dominates, and the correction is stated. A 'not collected' phrase in any spelling is read as missing in a number or date column, and a few stray records no longer become a finding. On clean records the results are unchanged.
0.3.0 2026-09-25
Four corrections found by testing the engine on builds of different shapes
The engine now judges every candidate gap on a wide file and says whenever a limit still applies. It no longer takes a row number for a record's identity, it reads a copy filed under a second source as one record carried twice, and padding a file with copies no longer changes its answer.
0.2.1 2026-09-24
Three corrections found by testing the engine on known answers
Values that only look alike in writing are no longer merged, look-alike identifiers no longer drop records, the same records now give the same findings in the same order on every run, and one count no longer stalls on very large files.
0.2.0 2026-09-24
Every run checks its own work, and says so
Every run now carries a report of its own checks: each says it found something, found nothing, corrected something (and what), or could not run (and why). A check that stays silent is a gap in the report, never a pass. Each finding states its standing in plain words, with what would change it, and what a model writes is checked against what it was shown.
Verification's change-log
What changed in Verification, the build that checks whether a specification, dataset or claim is fit to rely on, and why. It is made from the core engine, so a core change reaches it when its tools are regenerated, and its own known answers are re-checked each time.
Verification 1.3.0 2026-11-02
Verification now checks a second standard's releases and a second dataset, so no check is tuned to one document
Two of Verification's checks each had one known answer. The release check now also follows every requirement of NIST SP 800-171 from its second revision into its third, against NIST's own transition analysis: it agrees on every withdrawn and new requirement but one row, where the analysis gives the security-plan requirement a number the earlier revision does not have, and NIST's own catalogue and the analysis's next row place it correctly. The dataset readiness check now also runs every day on a federal education file, whose published counts all match its records, with one value spelled two ways.
Verification 1.2.0 2026-11-02
Verification now checks a standard's findings against its next release, and reads a security plan against the records it rests on
Two reads were added, each with answers worked out by hand before its code was written. The first takes what Verification found in one release of a control catalogue and says, for each place, whether a newer release still has it, has resolved it, or no longer carries the part of the document it sat in, which is never counted as resolved. The second reads an organization's security plan against its own scored assessment, its policies and its earlier records: whether the score it states is the scored one, whether documents it calls unwritten exist, and whether two records of the same assessment agree. On the plan it was built on, it found every place the hand check found, and on the corrected plan it found none still open.
Verification 1.1.0 2026-11-02
Verification's claim ledger can now catch its own mistakes, and names any claim the engine stops practising
The claim ledger maps each element of LEF's filings to the code that practises it. It had no way to catch itself going wrong, because the code it reads changes with every engine revision. It now runs twice on every check. Once on a frozen copy of the engine's code, against answers checked by hand in advance (among them that a person's ruling is never overturned by a re-read, and that a match on shared words is never treated as confirmed). And once on the engine's code as it stands, which names any claim the engine practised before and no longer does, and holds that as a failure until a person accepts it with a reason.
Verification 1.0.1 2026-11-02
Two of Verification's own checks were corrected after its new known-answer run caught them marking right answers wrong
The first run of Verification's known answers found two of its dataset checks marking a correct result as wrong: one matched each figure to the wrong field when several shared a line, and one read a plain statement of what was left unread as a claim to have read everything. Both checks are corrected and tested both ways, and every known answer now holds.
Verification 1.0.0 2026-11-01
Verification now has its own versions, and its known answers are re-checked whenever it or the core engine changes
Verification, the check of whether a specification, dataset or claim is fit to rely on, now carries its own versions and change-log. Its known answers are re-checked whenever it or the core engine changes, and any change in what it finds is named for a person to accept or reject.