Skip to content

Measure production multiformat reachability, fix launcher credential identity, publish HTTP contract - #157

Merged
DTALEX66 merged 460 commits into
mainfrom
codex/dsh-aaos-real-multiformat-loop-20261001
Oct 6, 2026
Merged

DTALEX66 merged 460 commits into
mainfrom
codex/dsh-aaos-real-multiformat-loop-20261001

Conversation

@DTALEX66

@DTALEX66 DTALEX66 commented Oct 1, 2026 •

Copy link
Copy Markdown
Owner

What this is

The AAOS backend real-multiformat closed loop (P0–P6), plus the versioned production HTTP contract
the UI branch binds to. Based on 1a981a44 — the same base as the UI branch, so the two
diverged rather than one containing the other.

Base codex/Audit is 18 commits ahead of main and 0 behind (this branch's own reading, after
correcting an earlier reversed count): the September consolidation and backend integration are on
codex/Audit and have not yet reached main. Merging here advances that line; it does not resurrect
superseded commits.

Recommended merge: merge commit, so each round's regression tests and evidence stay in their own
commit and remain independently revertable.

Draft on purpose: the objective requires ending at a Draft PR. Release stays FROZEN.

Read these, in this order

Document What it gives you
docs/current/AAOS-BACKEND-UI-HANDOFF-SUMMARY-20261001.md one page: the five things a UI gets wrong, and what is blocked
docs/current/AAOS-PRODUCTION-HTTP-CONTRACT-20261001.md the contract: 30 route addresses, auth, constant fields, error shapes, request bodies
docs/current/AAOS-BACKEND-ACCEPTANCE-RUNBOOK-20261001.md how to reproduce every claim, one command per side
docs/current/AAOS-BACKEND-LOOP-EVIDENCE-20261001.md the P0–P6 measurements
docs/current/AAOS-ERRORS-BLOCKERS-20261001.md this branch's own nine corrections, and the remaining blockers

The five things a UI must not get wrong

  1. schedule_authority has three values and a review produces two of them. POST /learning/reviews answers fsrs or unavailable (next_review: null, next_review_days: -2);
    placeholder_ladder belongs only to POST /learning/events with no schedule_state.
  2. Error bodies are not uniform JSON. Auth middleware and the two job routes answer JSON; the
    quality, members, v3, machine-task and validation errors answer plain text.
  3. Unknown request fields are silently ignored. status, not review_state; new_body, not
    body. The contract lists every field for all thirteen routes.
  4. GET /search has no paging. Only q and active_only; the limit is a hardcoded 20. A
    review is ~6× a projection read and holds the single writer while waiting for the scheduler.
  5. /research*, /plugins*, /models*, /embeddings/search, /graph/search do not exist and
    must render as "not connected".

Verification

Level State Evidence
Structural PASS architecture guard; ledger JSON valid; cargo fmt --check clean
Local execution PASS Rust workspace 100/100 targets, 0 failed; Python 3679 passed, 0 failed
Exact-SHA CI PASS 0b563db0…: CI (a0-gates, test (3.12), lint, gateplan) and vnext-ci
Contract claims PASS each section names its checking test; tests/maintenance/test_contract_verification_map.py fails if a link breaks
Legacy migration / in-place replacement / release NOT_EXECUTED frozen boundary
A02, A16, P0-H01, DP-F01, Research DTO, image.caption, video decode, webpage fetch BLOCKED Owner decision or absent environment

Two CI runs in this window had test (3.12) cancelled inside "Install and verify local OCR
engine" (not failed); both succeeded on re-run at the same exact SHA. A cancelled job is not
reported as a pass.

Development output stayed under .project-local/; the root checkout was not touched.

DSH added 29 commits October 4, 2026 17:28
… a proxy over the core

The previous round found the router itself opens no database connection, and read that as
promising. Its imports show why that search was misleading: the connection lives in the modules it
imports, along with the database path. Those modules contain inserts into evidence anchors, index
revisions and evidence bundles, so the surface that serves the frontend writes the same database.

Three things follow. The boundary is not a proxy over the core, so it cannot be re-pointed, and a
compatibility layer has to be written against the core's HTTP - the contract document is reusable,
the implementation is not. Second, and more importantly, the present wiring holds a single-writer
conflict: running the core alongside this surface puts two writers on one database, which the
package forbids. That rather than style is why the re-pointing has to happen. Third, a table name
worth checking was noticed and deliberately not concluded: the python side inserts into
evidence_anchors while the core selects from anchors.

This is the fifth revision of my cost estimate, and the reason is constant - I estimated before the
survey was finished. The discipline worth recording is not to put a number on migration cost until
the data source's ownership is established. Nothing was changed, built or run, the table-name
question is unexamined, and the runtime client test is unread for a fourth round running.
The anchor concept exists under three different tables: one the Rust core creates, one the python
boundary creates, and a third from a shared migration. The frontend's requirements match the python
one exactly, since that table stores the raw hash and a structured locator json that the frontend
validates, while the core's table stores a hash and an opaque position.

So the layer cannot be a transport projection alone. The columns differ in name and in meaning, and
an opaque offset is not obviously expressible as the structured locator the frontend expects. That
is a capability question rather than a mapping table, and it is the kind of thing this round exists
to surface before anyone writes code.

I also narrowed a claim from the previous round rather than repeating it. Python maintains its own
anchor tables and the core maintains another, so this is not two writers racing on one row but two
parallel data models - and whether they even share a database file is unverified, since the core
takes its path as an argument while python resolves a configured path. That is more accurate and no
less serious: two models is a problem for the idea of one canonical store regardless.

On the runtime client test I am changing my own reporting. It has gone unread for five rounds while
I kept promising it, so I am no longer listing it as a standing debt each round and will read it when
it actually gates a decision. Nothing was changed, built or run.
…of them written

The configured database path and the path the host exports to the backend are the same string, and
the python side resolves its default to that same value. The three converge on one sqlite file.

That answers the fork left open last round, and the answer is the harder branch. It is not two
independent datasets but one file carrying several models at once: the core's anchors, a shared
migration's anchors_v2, and the python surface's evidence_anchors, alongside other tables. The python
surface writes that file, so the writer conflict is real rather than hypothetical, and the migration
is required by ownership and data model rather than by style.

What I did not establish is recorded too, and one item is a correction in the making: a search of the
Avalonia supervisor for its database argument returned nothing, which is not the same as the file
having no argument - the wording may simply differ. The table names come from create statements in
source and not from opening the real database, and two other checks remain undone.

Diagnosis has reached the point where more reading adds little, so the next round turns to delivery:
a one-page decision set naming the canonical model and its costs, a first runnable slice of the
compatibility layer limited to the handshake and one route, and an explicit list of what will not be
touched. That is worth more than a nineteenth comparison table.
…ake composer

Diagnosis is complete enough to act on, and the handshake is the right first slice because it is the
one exchange that depends on no data model at all. The frontend refuses every projection until it
receives product identity, contract, versions, runtime mode, workspace, capabilities and migration
state; the core answers with runtime, contract and schema version, and calls its own contract an
outline.

So the composer takes the core's answer plus the identity facts the host owns and returns the
document the shell validates. It opens nothing and writes nothing, which is why the sqlite owner
count is unchanged at fifty-nine, and it keeps the core's outline self-description alongside the
projected contract so that saying outline is not lost in translation.

The tests restate the frontend's predicate field by field rather than trusting a paraphrase, and
check the composer fails closed on an unusable schema version, a missing runtime, a blank identity
fact, a non-ready migration state and blank capability names. One case failed first time and it was
the test at fault, not the code: passing an empty override merged nothing and left a valid payload
in place, so the case that was meant to remove a field now actually removes it.

This is the first implementation change under the new package. It is additive and reverts with one
commit, and nothing is wired to it yet - the transport and the canonical data model decision both
remain open.
…o narrow

A system module already serves the handshake route, documented in the execution log as RUN-203. It
is not just present but better than what I wrote: it reads the backend version from the project
metadata, runs git for the commit, reads the schema version from the database in read-only mode,
derives a stable workspace id and reports the supervisor's real migration state, behind a
local-request guard. My composer took all of those as caller-supplied arguments.

The error is in the search, not the reasoning that followed it. I looked for the field names inside
the Rust core, found none, and generalised that to the repository having no handshake - without ever
searching the python side for the route. Searching one stack for a shape cannot establish the absence
of an endpoint elsewhere. It is the second time in this work that my own search scope produced the
wrong answer, and the sixth time measurement has corrected a judgement.

So the module and its tests are removed in a new commit rather than rewriting history. Keeping them
would have created a second handshake surface, which is precisely what the boundary contract warns
against, and it would have contradicted the instruction to reuse what already exists and fix only
gaps.

It does narrow the question usefully. The handshake is not the missing piece: the host launches the
python backend that serves it, while the core that should become the only writer serves a different
and thinner exchange and calls its own contract an outline. The problem is that the frontend's
current backend and the intended canonical one are not the same backend - and that needs no new code
from me to state.
…ing data

The app was started against a temporary copy of the database rather than the worktree's own, and it
refused to start: the schema has not been migrated. That is the guard behaving correctly, since it
fails closed instead of running against an unfinished store, and it stopped the probe before it could
report a handshake.

Looking at why the copy was empty produced the round's real finding. The worktree's data directory
holds one file, cognitive_os.sqlite, and no archeaxis.sqlite at all, while the configuration names
archeaxis.sqlite. That qualifies what I concluded three rounds ago. I verified that three places
agree on the configured path, and they do, but I did not check that the file they name is the one
actually carrying data - and it is not the file that exists. So the claim narrows to agreement at the
level of configuration, with the relationship between the legacy-named file present on disk and the
name in the configuration still unexamined.

This is the cost of concluding from source alone, and finding it only when the thing was run is
evidence that running it was the right move this round. The migration entry points were located -
several of them - but which combination migrates a store to usable was not determined, and no
official data or installation was touched.
… as SUP-022

The owner asked for the latest package to be archived properly, describing it as another change and
calling out the UI frontend in particular. The package is now stored under docs/authority following
the repository's existing taskpack convention, copied byte for byte, with its own checksum file
verifying all ten entries against the archive.

The frontend is the focus because the formal product host changes: from the C# Avalonia application to
Tauri 2 with React, TypeScript and Vite. The package's startup prompt states that choice and forbids
raising the Avalonia or Tauri question again, and its joint-architecture document instructs that the
answer be registered as a traceable delta rather than by rewriting the immutable packs.

That delta is registered as SUP-022, superseding the earlier decision that made Avalonia the formal
shell, and the configuration authority index now points at it. Every boundary the earlier decision
carried is retained rather than relaxed: the Rust core stays the only canonical writer, python stays
isolated workers, one writer per file is unchanged, the old python backend must not be re-wired as
authoritative, there is still exactly one default shell, and the release freeze and owner gate are
untouched. The Avalonia application becomes a frozen reference only once the Tauri shell has actually
taken over.

The index also says no parallel task pack should be created, so the note states plainly what this is:
an owner-delivered update that the owner asked to archive, not a plan the executor authored for
itself. The executor does not sign off audits or the owner gate.
…y the Rust core

The file present in the worktree is named as the legacy database by setup status, and the workspace
migration module documents moving data out of it into the four-asset-domain layout, with a backup
prefix, never deleting the legacy file and being idempotent on its recorded source hash. So the
relationship I called unexamined last round is in fact documented and tooled - the worktree simply has
not been migrated yet, which is an unperformed step rather than a defect.

The more useful find is who owns the schema. Nothing anywhere in the repository writes the sqlite
user version, while the knowledge table definition comes from the Rust store crate. So the canonical
database's schema is established by the Rust core and the python side only reads it, which explains
why the system module reads that pragma and no python module sets it. That is concrete evidence for
the core being the canonical writer - it holds the right to create the schema, not just to write rows.

It also names the precondition I was missing when I tried to run the app, and the probe that can
reach that state. The handshake is still uncalled, I have still not run the migration, and nothing
official was touched; the next round is to get a temporary store into a migrated state and make that
one real call.
…a receipt

Twenty-three rounds of this package have been almost entirely reading, so this round ran a real
capability. The probe refused the first attempt because no authorised copy was named, and the legacy
database's hash was identical before and after - it did not touch the original, as its documentation
promises.

Given a copy, the migration ran to completion. It reports the copy's hash matching the original, a
rollback candidate backup, a produced ledger of sixty-five tables and fifty rows, and the original
untouched. The legacy database's hash after the run is the same as before it. So the migration path
is genuinely runnable on this machine, it is rollback eligible, and it left the source alone - the
first executed product capability under this package, with a receipt to cite.

It is not the same as the application starting, and the record says so. The migration produces a
workspace layout, not the database file whose schema the app validates, so the precondition for
calling the handshake is still unmet.

The next step uses an already-built core binary to create that schema in a temporary directory. I am
noting in advance that the binary dates from before the current commit and may not match its schema,
so either it will be rebuilt first or the staleness will be stated with any result - a stale binary's
behaviour will not be reported as the behaviour of this commit.
…locks python outright

The core was rebuilt with an explicit target directory so the binary is current for this commit,
which removes the staleness caveat I raised last round. Started against a temporary database it
created the schema - twenty-six tables - and then the python application refused to start, for a
specific and newly informative reason.

Python's read-only research path requires a checkpointed database and rejects one that still carries
the write-ahead log and shared-memory sidecars, naming both files in the error. The core leaves those
sidecars behind, as a single writer in WAL mode does.

So the practical consequence is stronger than what I had read out of the sources three rounds ago.
Then I described two parallel data models sharing a file; now it is reproducible that while the core
holds the database open, the python side cannot read it at all. Coexistence is not a policy question
here - under the current implementations the two stacks cannot work on one store at the same time.
That is the technical reason the migration has to happen, and it is firmer than the wording I had.

One thing is deliberately left open rather than guessed: the core created twenty-six tables but left
the user version at zero, and I did not establish whether that is intended. Nothing was changed, no
official data was touched, and the handshake is still uncalled.
…rator that guards itself

Getting the application to start turns out to need a chain of conditions, each of which was
observed rather than assumed. The core creates its schema, which it does - twenty-six tables. Live
write-ahead sidecars then block python's read-only access, and checkpointing removes them so that
error disappears. Behind it sits a third condition: a phase four research schema migration must have
been applied, and without it startup fails with that message.

That third step is not freely callable. Invoked with the correct arguments it refuses, saying the
migration must be driven by a MigrationOperator. That is a guard expressing that this operation needs
a proper driver, and I am not going around it - the package says not to fake permission, and this is
exactly what that looks like in code. Two earlier attempts failed on my own misreading of the
signature; the third produced the real constraint.

The conclusion is that the canonical store is not any single stack's product. The Rust side builds
its schema and the Python side must additionally apply a research migration that is itself governed.
That extends what the last two rounds established: after two parallel data models sharing a file, and
then a hard failure when the core holds it open, there is now a third dependency - and it sits behind
an authority boundary rather than a technical one.

The handshake remains uncalled and I will not dress that up. Locating and properly driving the
operator is next; if it needs human authorisation that is not present on this machine, that becomes a
recorded blocker while independent work continues.
…rlier overclaim

The sanctioned driver was the runtime entrypoint, whose migration command applies each migration
using the owner registered for it rather than an owner I invented. Run that way it exits zero, takes
a backup first, and records the workspace owner applying its target.

With the database migrated that way, the application starts and the handshake answers 200 with all
ten fields the shell requires: the pinned product id and contract, a version, the real commit of this
tip, an integer schema version, a runtime mode, a workspace id, an array of capabilities and a ready
migration state. Every one of the frontend's conditions is satisfiable, and it is the python boundary
satisfying them today.

This also narrows what I wrote two rounds ago. I said the two stacks cannot coexist on one database,
which was too strong. What was measured then was that while the core holds the file open, python
cannot even read it; what is measured now is that when the core is not holding it and the governed
migration has run, python works completely. The accurate statement is that only one stack may hold
the store at a time - a lease question rather than irreconcilable data models, which makes the
canonical decision easier than I had made it sound.

Two things are flagged rather than glossed. The handshake reports an empty capability list, so the
catalogue is not yet wired through. And this is still a single manual observation: by my own standard
manual evidence should become a gate, so making it a repeatable probe is next.
The call succeeded once by hand last round, and manual evidence goes stale, so it is now a probe
that anyone can rerun. It drives the sanctioned migration entrypoint, starts the real application
against a temporary database, asks the real endpoint and checks the answer against the conditions
the shell applies, then reports a receipt and an exit code.

It is deliberately unhurried about honesty. It opens nothing of the worktree's, touches no official
installation or library, and says of itself that it signs no product qualification - it verifies one
exchange on one machine at one commit. Its temporary directory lives under the project's ignored
development root rather than the system temporary directory, which the project treats as ambiguous
ownership, and it removes that directory when it finishes.

The test keeps it from rotting. It asserts the migration exited zero and produced a database, that
the endpoint answered 200, that the document satisfies every condition the frontend applies, that the
pinned values are the ones the shell pins, that the cited commit really is a commit in this
repository, and that no failure step was recorded. Seven tests, six seconds, run against a fresh
temporary store each time.

Nothing in the product changed: this adds a probe and a test and touches no existing implementation.
…ing what it launches

Before re-pointing the host's launch target I checked whether the host compiles, and it does not.
The root workspace excludes both Tauri crates on purpose, saying each keeps its own lockfile and
build boundary, but neither manifest declares a workspace root of its own. Cargo therefore refuses
them as being in a workspace while not being a member - so the host was neither part of the
workspace nor buildable on its own, and any change to it would have been unverifiable. That explains
why the re-pointing has not been done in the rounds since it was scoped.

The fix is the one cargo itself suggests and the one the workspace comment already implies: give each
crate an empty workspace root. I deliberately did not add them to the main workspace, which would
pull Tauri's dependencies into the workspace build and could disturb CI; each crate now stands alone,
so the workspace build is untouched.

It works. The workspace error is gone and the build proceeds into Tauri's own build script, which is
how far it had never previously reached. It then fails on a resource path the manifest declares - a
staged runtime under the project's development root that is not present - so the host needs one to
build.

The re-pointing is still not done, but the reason has changed from nothing to a named missing input.
The change itself remains held back until the host can actually be checked, because a change I cannot
verify is not a change I should make. No official installation or data was touched.
…ng conflicts with a gate

Checking the host regenerated four files under the Tauri schemas directory. The diff is one line in
each and says the same thing every time: the regenerated document has no final newline where the
committed one does. The repository convention check exists to catch exactly that, so any build of
the host leaves four modified files that would fail the gate.

That is a real unhandled conflict between building the host and the repository's own conventions,
and it is nobody's error - the tool's normalised output simply disagrees with the convention. I
reverted the files rather than committing them: they are generated artefacts, committing them would
make the gate fail, and adding a workspace root to a manifest should not change a schema.

Three ways to handle it are written down and none is chosen, because that belongs to whoever owns
the convention rather than to me in this round. The re-pointing remains undone for the reason
already recorded - the host still needs a staged runtime before it can build. No official
installation or data was touched.
…cker is a space in the path

The host bundles a runtime from the project's development root, and that directory did not exist, so
the staging tool was run with the built core, an interpreter from the shared tool library, the workers
and the real commit and tree. It produced the directory the manifest names - twenty-seven hundred odd
files - and with it present the resource error disappears.

The build then gets further than it ever has here and fails in the windows resource compiler. The path
in the error is telling: it begins at projects rather than at All projects, so the leading part was
lost at the space. That is the GNU toolchain failing on a path containing a space, not a defect in the
product, and CI would not see it because its checkout path has no space. This machine could not build
the host even before any change of mine.

That matters for the rule set two rounds ago: do not change what the host launches until the host can
be checked. On this machine that rule now meets an obstacle no source change can fix, and three ways
out are recorded - switch toolchain, move the checkout to a space-free path, or accept that neither
this machine nor CI builds the Tauri host and find somewhere that does. I have chosen none of them,
because that is an environment decision rather than mine, and I will not make an unverifiable change
to the launch path in the meantime.

The build also rewrote the same four generated schemas, stripping their final newline again. They have
been reverted a second time. No official installation or data was touched.
…says about each

With the Tauri host blocked locally by a space in the checkout path, this round used the scene that
does run - a temporary store, the sanctioned migration, the application - and posted three real
fixtures to the intake endpoint.

The results are more useful than a support list because they separate three different states. Markdown
is carried through by an engine actually named passthrough, so it is transported and not structured,
and by the package's own standard that does not count as passing. Canvas reports itself as custody
only, saying in its own content that no ingest route claims the format yet - the product describing
its own gap, which is worth more than my inference. The image fails with the missing optional engines
named, Tesseract and pytesseract, which is an uninstalled optional dependency rather than a defect.

The original hash is checkable for each: both successful items report a sha256 identical to the
source file's. Nothing has been called supported that is not, which is the discipline the package
emphasises most, and the next step is to turn these three states into a probe and a test so that the
two non-passes are remembered as non-passes instead of drifting into being described as support.

Only intake was exercised, not the other dimensions the format task names; no optional engine was
installed to make a number look better; no implementation file changed; and neither the official
installation nor the material library was touched.
…passes

Three formats were measured last round and the results are now reproducible. The probe drives the
sanctioned migration, starts the application, posts each real fixture to intake and classifies what
comes back without flattering it. Its outcomes are deliberately separate values - carried through,
custody only, engine missing, structured or refused - because collapsing them is exactly how
transported quietly becomes supported.

The tests assert rules rather than today's answers, with one deliberate exception. They check that
every attempt carries an outcome and its evidence, that a successful intake preserves the original
hash and reports the expected format, and - the rule that matters most - that nothing is called
structured unless the evidence names structure. The exception pins the three outcomes measured this
week, so that carried and refused cannot later be described as supported: if a format genuinely
improves, that test fails and the improvement has to be recorded on purpose.

Eight tests, under eight seconds, against a fresh temporary store each run, and the probe removes its
own working directory. No product implementation changed; this adds evidence and the means to keep it
honest. Neither the official installation nor the material library was touched.
…oute as it really is

CI caught what my own local run had not: the architecture guard rejects a runtime string beginning
with a slash, reading it as a hardcoded external absolute path, and the probe contained the intake
route written that way. The pull request workflow passed and the push workflow failed, on the lint
job and the architecture test together.

The fix is not a trick to satisfy the checker. The route is a path relative to the origin, so it is
now written that way, with the base ending in a slash and the route naming only the segments. The
handshake route was moved to the same form for consistency, and both are named constants rather than
literals buried in a call.

The gap on my side is worth naming: I ran the repository convention check before pushing but not the
architecture guard, and the guard is exactly what this change needed. Rerunning both locally now
passes, as do the eight format tests.

No behaviour changed - the same routes are called, spelled as relative paths.
…survive the read

Against the running product, a real file was ingested and then anchored at the exact characters of a
phrase it really contains. The character range was right - the offset lands on that phrase - and the
create response echoed the whole locator back, including the character region and the block name.

Reading the anchor back loses both. Only the page and the source format return, which is what the
projection function selects; the source shows it reading exactly those two fields. So the system
accepts a precise, explainable position and does not hand it back, and the format task requires
exactly that kind of position.

It is worth noting against the project's own words: its loss receipt contract says unknown fields
must never be silently dropped, and here what is dropped is not unknown but accepted.

I am careful about what this does and does not establish. Only the projected read route was read;
whether the stored record still holds the full locator was not checked, so this is a projection
dropping fields rather than data being lost, and those are different claims. It is also unchecked
whether the character region is a supported field of that route or simply outside its contract.

Nothing was changed this round - evidence was taken, not a fix - and the loss receipt itself, with
its engine, version, parameters, note and coverage, is still to be measured.
…nest

Two things the format task asks for were still unmeasured. A probe now ingests a real file, anchors
the exact character range of a phrase it really contains, reads the anchor back, and asks the
library for the conversion run of that file.

What it finds is recorded rather than smoothed. The offset genuinely lands on the phrase and the
create response returns the locator it was given. The read returns only the page and the source
format, so the probe reports that no precision field came back and the test enforces the rule that
a precise position may only be called returned when a precision field is present. The conversion run
answers and does expose a loss-notes channel and a format execution receipt; for this markdown file
the notes list is empty.

The one pinned assertion is that pair of measured outcomes, so an improvement cannot arrive
unnoticed. Eight tests in six seconds against a fresh temporary store, and the probe removes its own
working directory. No product implementation changed - this is measurement, and the finding that a
precise readback is not returned is now recorded in a gate rather than in my notes.
…precision is lost

The exchange export writes an open directory and its own verification passes with one item
verified. While taking that evidence I wrote a check comparing a freshly computed hash of the
manifest file against the manifest's own manifest_sha256 field, and it disagreed. That is almost
certainly my expectation being wrong rather than the product: that field hashes what the manifest
describes, not the file that carries it, and the product's own verify already says the export is
valid. I have removed the misleading comparison and renamed the value to say plainly that it is the
file's hash, with a note that it must not be compared to the manifest field - so nobody repeats the
mistake and reads a defect out of it.

The more useful result is what the exported evidence item contains. Its locator carries six block
identifiers, a conversion run and a derived document, which means the precise structure exists and
is exported. Three rounds ago I deliberately wrote that I had only read the projected read route and
that whether the stored record retains the full locator was unchecked - so the accurate claim was
that the projection drops fields rather than data being lost. This is positive evidence for that
boundary: the export layer has the structure, the anchor read route returns only the page and the
source format. The careful wording was not wasted.

Nothing was changed in the product, no test for this probe exists yet, and what manifest_sha256
actually hashes was not established - only that it is not the hash of its own file.
…rast cannot drift

The export probe now anchors an exact character range on the same file it exports, so a single
receipt carries both observations. That turns something I had been describing into something
asserted: the anchor read route returns only the page and the source format, while the exported
record carries block identifiers. Seven tests hold the export status, the item count, the manifest
hash, the directory's contents and the product's own verification, and then assert that contrast
directly.

One test exists purely to stop a mistake from returning. Last round I compared a hash of the
manifest file against the manifest's own manifest_sha256 field, got a mismatch, and nearly read a
defect out of my own wrong expectation; the product's verify had already said the export was valid.
The value is now recorded under a name that says it is the file's hash, and a test asserts the
misleading comparison is absent.

No product implementation changed. This is measurement and the gate that keeps it true, and the
official installation and material library were not touched.
… on one store

The last dimension the format task names is cold start. A probe takes a real file in during a first
boot, stops the application, starts it again against the same database without re-ingesting anything,
and reports what it finds.

What it finds is reassuring and now asserted: the library answers before and after and holds the
same thing, the conversion run still answers and still names the same file hash, and the schema
version is unchanged. Eight tests hold that.

One of them exists to keep a weak result from looking strong. Both boots report an empty capability
list, so of course the lists are identical; the test asserts the emptiness explicitly rather than
letting identity stand as evidence that capabilities survived a restart. When the catalogue is wired
through, that test fails and the comparison begins to mean something.

I made the same authoring slip twice in two rounds - a module docstring closed on its first line and
then reopened, which Python reports as an unterminated triple-quoted string. Both times the test run
caught it before anything was committed, and it is worth naming as a pattern of mine rather than
treating it as bad luck. No product implementation changed.
… two wrong guesses at search

The system module builds the handshake response with a literal empty list for capabilities, and the
running product returns exactly that. So the frontend does not receive an unwired catalogue - it
receives one that is empty by construction, whatever the Rust core's capability registry knows. That
is the gap the capability-catalogue task names, and it now has both a source line and a measured
value behind it.

Search did not get measured, and the reason is mine. The workspace search route takes a request body
whose shape I guessed twice and got 422 both times: an object with a query field was told the root
field was missing, and a bare value was told it wanted an object. The errors are informative and
probably name the answer, but I did not work it out this round, so search is neither reported as
working nor as broken.

It is the same pattern as earlier in this work - guessing a shape instead of reading its definition
first, and paying for it in round trips. The next round reads the request model at that route, and
also pins the hardcoded emptiness in a test so that wiring it up cannot pass unnoticed. Nothing was
changed in the product.
… it working

Reading the search route's model - which I should have done before guessing twice - showed the body
is a root and a query, so my earlier object-with-a-query failure was a missing required field rather
than a nested model. With the right shape the route still did not answer: one attempt returned a
server error and the other timed out. I am not calling that broken, because the root I passed may
not be one the route accepts, but I am also not calling search working.

Two things are asserted instead. The capability list the handshake returns is empty and now pinned,
with a comment naming it as the catalogue gap: the handshake builds its response with a literal empty
list while the core has a real registry, so wiring them together must fail this test rather than pass
unnoticed. And every search attempt must have recorded an outcome, with an explicit test that a
successful status is not among them today - so neither a server error nor a timeout can drift into
being described as a passing search.

Two fixes came out of running it honestly. My first error handler hung while reading an error body
and crashed the probe, so reading that body is now guarded. And the search call waited a minute per
attempt, which cost the suite two minutes for an observation that does not change; a short timeout
gives the same answer in twenty-five seconds.
…CI rejected it

The last commit pinned that search had not answered, because locally one attempt returned a server
error and the other timed out. CI rejected that assertion: both attempts returned 200 there. So
search works in CI and did not answer on this machine, which makes the failure a property of my
environment rather than of the product, and I have not found out why this machine differs.

The same commit contained two pins with opposite fates, which is the clearest illustration I have
had. Pinning that the capability list is empty held, because it comes from a literal in the source
and is therefore true anywhere. Pinning that search does not work failed, because it came from one
run on one machine. Facts from source can be asserted; behaviour from a single run can only be
recorded.

The assertion is replaced by a rule that every attempt recorded an outcome and no claim about
success, with the story written into the docstring so the next person knows why it does not pin one.
Running it also let me cut the search timeout, since waiting a minute per attempt bought the same
observation for five times the cost.

My own note is that writing measured on a date in a docstring looked like qualification but the
assertion was still a requirement. Careful wording is not a substitute for designing the assertion
around what actually varies.
…rt it positively

I suspected the space in the workspace path was breaking vault search, the same cause as the
resource compiler failure earlier. A controlled experiment refuted it: a vault under the system
temporary directory and the fixture vault, whose path does contain a space, both answered 200.

Reading the vault module shows why the earlier attempts failed. The root must be an existing
directory, and I had pointed it at my own run directory, which is full of the database and its
sidecars - a store, not a vault. The second attempt timed out at the time and does not reproduce
now, and I have not established why; what I can say is that it was not the space.

With a purpose-built vault the route answers here as it already did in CI, so the assertion can now
be positive rather than withheld. That completes a sequence worth keeping: first I pinned that search
did not work, which CI rejected because it answered there; then I asserted only that an outcome was
recorded; now the claim is that it works, because it has reproduced in two environments. The rule is
plain - a fact from source, or something reproduced across environments, can be asserted; a single
run's behaviour can only be recorded.

One incidental gain: once search actually answers, the test fell from two minutes to five seconds,
because the earlier cost was almost entirely one misdirected call waiting to time out. No product
implementation changed.
The sync manifest recorded b69c42a as base_commit, but the two 20261006
documents it hashes were only published by the following commit, so the
SHA-256 list could not be reproduced from the stated commit. Bind the
mirror to the commit that contains the hashed content and keep the earlier
commit as an explicit prior baseline.
The ledger was the only current-state authority but carried no pointer to the
dated Green mirror or its SHA-256 manifest, so a reader could not tell that the
mirror exists or what it does and does not prove. The manifest's ledger entry is
refreshed to the hashed content of this commit.
Binding alone was not enough: the hashed AGENTS.md bytes came from the local
worktree copy, which carries CRLF that Git normalizes away, so no checkout of
any commit reproduced them. Take every hashed file from the bound commit's own
content, state how to materialize it, and rebind to the commit that holds the
current ledger text.
The read-only history view reported through the Inspector only the current
document identity, so a historical read could not be inspected without risking
a late response overwriting a newer document's Inspector or a dirty draft.
Bind the request to generation, request id and the requested document's
id/version/content hash, and report the historical target with its own body
fingerprint, using the original CAS hash only when the source revision matches.
job_execute inherited the host's 30-second default client timeout while the reader
asks for a 300-second deadline and real media jobs exceed 30 seconds, so the host
aborted requests whose jobs were still going to persist and the interface reported
failure over a durable success; the timeout table is now a function and asserted.

Also: a superseded document read or restore could stamp its failure over the newly
opened document; a content digest and a knowledge type were each displayed under a
label for something else; the backend badge was never announced, the current-space
name was dropped by assistive tech, the browse button was named only by a glyph,
and closing the Inspector from inside it stranded focus on the body; the Inspector
body had no styling at all, the selected rail item had no keyboard focus ring, a
used token was never declared, and the only library section switcher was deleted
below 900px instead of narrowing.
Draft creation, note creation, version restore, export and page citation each
persisted a new document, version, anchor or export per click, so a double click
during an in-flight write silently produced duplicates. Serialise those writes and
disable the controls while one is outstanding.
Adds the measured results that were previously unrecorded: the canonical 21-step
native pass and the isolated Green deployment, the three installed-state increment
runs with their failure receipts kept, the durable video proof at the deployed
candidate, the 300-second job ceiling that structurally blocks long-audio ASR, the
interface audit findings and their fixes, and the vnext-ci worker-environment root
cause plus the SQLite runtime-version evidence AQ27 never had.
A durable check record was announced as unconfirmed when only its follow-up
readback failed, because the write and the readback shared one catch. A latest
job that ended failed was captured in state that nothing rendered, so the source
looked idle. Every non-409 core status collapsed into one sentence that named
neither the operation nor the kind of failure.
Making the context subnav always visible at narrow widths broke the A0 geometry
contract, which requires a single column with no context rail on a phone
viewport. Narrow the relief to the band between the phone layout and the
desktop layout, where the switcher was previously deleted even though there was
room for it.
…proved audit claims

The narrow-layout change broke the A0 browser geometry contract, which is recorded
as a self-inflicted regression together with the scoped fix and the local real-browser
re-run; audit items that measured false on re-check are recorded as disproved rather
than silently dropped.
The canvas node cards and viewport had no rules at all, so they rendered as bare
positioned text, and the expanded activity dock ran its rows together. Every
statically applied class name must now resolve to a rule, which the previous
stylesheet failed for nine of the canvas classes. The quaternary foreground also
failed the 4.5:1 body-text floor against the surfaces it is used on.
The rail, palette and subnav advertised URL and batch intake, note-taking with a
canvas board, open exchange-package validation and system settings, while the
desktop shell routes those ids to the library, knowledge and capability surfaces.
Browser development mode keeps its own wording.
…ardrail

Seventeen class names used in shipped components resolved to nothing: the whole
recovery workbench (card, heading, kicker, message, diagnostic, actions, field,
confirm, progress, feedback, logs), the command palette trigger and its option
rows, the space container and the import block. With the global reset removing
every default margin, those screens rendered as one undivided run of text, and the
palette trigger looked deliberate only because it inherited the bare button rule.
The guardrail now scans every component and space instead of four files.
…ow-window overflow

Eleven reading surfaces printed untouched backend payloads next to the content: the
learning space rendered its own JSON as the page body, and capability, receipt,
revision-basis, export, pipeline and machine-answer payloads were dumped inline. They
now publish to one diagnostic console in the activity dock (and to the developer
console), so the reading surface keeps only human-readable summaries while the exact
receipt stays reachable. Verbatim model output on a failed check is deliberately kept
inline: paraphrasing it would let a failure read as a judgement.

Measured with a stubbed desktop bridge at 1024x900, three fixed panes plus the reading
column collapsed the centre to 304px and overflowed it by up to 58px; the chrome now
narrows before the content and the subnav may wrap, giving 496px and no overflow. The
style-coverage guardrail matched class names as substrings, so `.space-card > h3` hid a
missing `.space-card` rule; it now requires a real selector boundary.
@DTALEX66
DTALEX66 changed the base branch from codex/Audit to main October 6, 2026 06:18
@DTALEX66
DTALEX66 marked this pull request as ready for review October 6, 2026 06:18
… test

The workspace tests exercise real workers, and the xlsx member format needs the
adapter engines; this job built its worker venv from the ci group alone, so the run
failed with AAK-WORKER-003 "engine missing" for an engine that is declared and that
ci.yml already installs. The same test passes locally and in ci.yml with that group.
@DTALEX66
DTALEX66 merged commit 9a7f338 into main Oct 6, 2026
40 checks passed
DTALEX66 added a commit that referenced this pull request Oct 6, 2026
… no longer verifiable

Both sentences read as present-tense truth. Re-measuring them today produced 650/14/10-shared by
one method and 0 by another, because #157 is merged and #158 was closed: the honest correction is
that the claim can no longer be reproduced, not that a new number replaces it. Nothing is
overwritten - the originals stay above the dated correction.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant