2026-08-24 - What observed actually meant, and the ceiling that was not one (D213)

Done. The name-provenance vocabulary split by what was observed, three harvesters added, one checked and refused, and symbols/unaccounted-ceiling.txt emptied.

The finding that started it

Method::Observed documented itself as "a name worked out by watching something run". 137 of the 154 names carrying it had never run anything - they were literal strings read out of a file at rest. The value had been written for one mechanism and was being used by another.

Raised from outside: a reading of the term rather than a bug report, and the code agreed with the reading the moment anyone counted.

It was hiding a capability, not just a label

The interesting part is not that the name was wrong. It is that the static tier was checkable the whole time and nothing checked it, because a bucket holding both "read out of a file" and "concluded from a running guest" has no check that applies to both, so it got none and both were reported as documented, not verified.

A string in a module is there deterministically. audit --verify-harvest re-reads every module a static record names and confirms it contains the string: 200 of 200 hold. CI cannot run it - there is no corpus and never will be - and that is the point of the tier existing separately.

The ceiling was measuring the wrong thing entirely

symbols/unaccounted-ceiling.txt held 202 names, and its own header explained them as vendor symbols the grammar could not spell: a real gap, slowly shrinking.

Wrong, and wrong in a way nobody would have caught by reading it. A generated record is a pattern plus an index, and an index is a position in a mixed-radix enumeration over the vocabularies - so adding a word renumbers every candidate built from it. Adding words is the loop (D195). Every successful search was quietly knocking already-recorded names off the verified list onto a file whose whole rule is that it may only shrink.

audit --repair hashes the stale names and hands them to the ordinary pattern search as targets, so one sweep repairs all of them regardless of how many went stale. All 202 came back, plus 20 more that a single 37-word learning pass had knocked off while this was being written. Names re-derived from this repository alone went 290 -> 512 in that one pass, without a single new name being found.

The number had been sitting there for weeks being read as a fact about the vocabulary.

And the guards - two holes, and the second is the interesting one

audit returned early on "every name is accounted for", before the ceiling comparison. So the half of the ceiling's rule that says an entry which stopped applying must leave was unenforceable in the only state that can trigger it. An empty unaccounted set with a stale 202-name ceiling passed, silently.

Then the knowledge base. FunctionKnowledge::found_by is a second, hand-written copy of a fact the symbol database already audits, and eleven entries contradicted it - six libc names sold short as observed, three C++ ABI names claiming a list they were never in, and sceKernelWrite marked supplied: that we did not derive a name the generator produces. Every correction came from the audited record or from an audit --deep walk; none by hand.

A gate was running on that the whole time and passing. the_shipped_files_account_for_everything_they_claim asserts provenance_faults is empty on every cargo test. It was green on all eleven, because the function checked known_by and its citation and had never looked at found_by. Not a missing gate - a gate reporting success on a field it was not examining.

Fourth instance of the shape (D191, D199, the ceiling above). Promoted from coincidence to rule: a guard is not finished until somebody has made it fail. crates/orbistoun-cli/tests/provenance.rs holds the new ones to it - four of its six tests assert a failure.

Left open and named: an implemented function's name never enters the unnamed set, so no derivation is recorded for it: 57 of the 95 declared functions have none. The 38 that do have one only by luck of ordering - a search confirmed them before anything implemented them. A hole in the audit's coverage, not only in this field.

The corpus is one search now

names takes a directory: every module read, unnamed imports unioned, one sweep. It was a loop over four hand-written globs in orbistoun.sh running the full 2.6-billion-candidate sweep once per module - forty-two times, for a search whose cost is one hash-set lookup per candidate whatever the target set holds. An hour became 85 seconds.

The globs also omitted .sprx. Eleven modules had never been searched once, and nothing said so, because a glob matching nothing is not an error. One of the first names the fixed walk found came out of fakelib/libSceAmpr.sprx.

What the new harvesters actually found

Total: 669 -> 737 names, nothing unaccounted for.

Everything then ran again, and found nothing - which is the useful part

A second full pass over all 53 modules with every mechanism live: 2,609,721,996 generated candidates named 0. 550,450 corpus strings named 0. The runtime harvester named 0. The published list named 0. 3,698 imports remain unnamed.

Do not re-run this expecting a different answer. The mechanisms are at their plateau against the current inputs, and the next name has to come from a word the vocabulary does not have or a source not yet read - not from another sweep. Worth knowing before somebody spends an afternoon on it.

Incidentally it also confirmed the causal chain behind the ceiling: no names found means no words learned, which means no indices moved, which means --repair had nothing to do. The 202 entries really were a by-product of success, not of failure.

Two smaller things worth keeping

crates/orbistoun-names/src/strings.rs opened by claiming symbol tables as a source. They are not one here, and that sentence had been sitting in the file long enough to be believed.

The prose guard catches a new line-continued literal - the cause. It cannot see one a formatter already collapsed - the consequence - and one of those was printing a garbled message out of the name search on every run. Three fixed; six more are on the backlog with the reason they were not fixed in passing.

Not touched, deliberately

Oracle in orbistoun-hle grades behavioural claims and carries the same confusion in Measured, which means "on real hardware" and has no slot for measured-somewhere-else. obSCEne mirrors that vocabulary in its own grading, so changing it one-sided is the drift shared grading exists to prevent. It goes on the bridge instead.