The loop
One turn of orbistoun's work, start to finish: what each step does and who performs it. WORKFLOW.md is the command reference - what to type, with which flags.
Every design choice in this repository exists to make one turn cheap, or to make its output worth reading.
Overview
flowchart TD
A["a title's eboot.bin, in the title library"] --> B["./bin/orbistoun run TITLE"]
B --> C["build the link plan, or reuse the stored one;<br/>list what the module imports<br/>- by 64-bit hash, not by name"]
C --> D{"does the hash<br/>have a name?"}
D -- yes --> G
D -- no --> E["generate candidates, and read<br/>identifier-shaped strings out<br/>of the module's own bytes"]
E --> F{"does a candidate<br/>hash to it?"}
F -- yes --> N["record the name, and add its<br/>words to the vocabulary"]
N --> G
F -- no --> G["build a stub for everything<br/>not implemented"]
G --> H["execute the guest natively"]
H --> I["every system call lands in orbistoun"]
I --> J{"implemented?"}
J -- yes --> K["do the real thing"]
J -- no --> L["record the call, dump the arguments,<br/>answer 'unimplemented'"]
K --> M
L --> M["the guest faults, gives up,<br/>or hits the time limit"]
M --> O["write the trace;<br/>compare it with last time"]
O --> P["print FURTHER / same / BACK,<br/>then the ranked findings"]
P --> Q{"orbistoun-turn runs the<br/>mechanical steps, then stops"}
Q -- "a thread waits<br/>on one call" --> W["the wait sub-loop:<br/>wait, word, writer, cause"]
W --> P
Q -- "a policy patch moved it<br/>and no title went BACK" --> Z["staged as guest-observed;<br/>its measurement filed"]
Z --> B
Q -- "wall hit<br/>(architectural / regression)" --> X["a person reads the findings<br/>and decides what next"]
Q -- "enough is known already" --> R["a person writes the Rust<br/>implementation (known_by: published)"]
Q -- "not enough is known" --> S["a person writes and runs an<br/>obSCEne probe on real hardware"]
S --> T["a person reads the transcript<br/>orbistoun-cli probe reports on"]
T --> R
R --> U{"trace verdict"}
U -- FURTHER --> B
U -- "same / BACK" --> X
classDef human fill:#7a2f2f,stroke:#d08a8a,color:#fff
classDef agent fill:#2f4f7a,stroke:#8aafd0,color:#fff
class X,R,S,T human
class Q,U,W,Z agent
Naming, stub-building, execution, tracing, the progress verdict, the
mechanical sweeps of orbistoun-turn, resolving a waiting
thread to the call it waits on, and staging a policy patch that moved a
wall run unattended. Deciding what a finding means and writing the
implementation are a person's job. Nothing in this repository dispatches
a hardware probe, drives obSCEne or Prosperous, or writes Rust from a
measurement: orbistoun-probe only
reads a transcript, and orbistoun-propose has
no implementation proposer.
The first rule: the title is not the bug
Every title the operator provides runs on real hardware, so every
wall is orbistoun's (D708). "Debug build", "devkit path", "faithful
ENOENT" and "the title's own assertion" are restatements of
a symptom orbistoun has not explained, never reasons to stop.
Before instrumenting a fault, check the upstream fact it rests on. A
guest that faults after a failed open failed because
orbistoun misrouted the path or did not serve the mount, until the file
is shown absent from the place the run reads: the resolved data
directory, which orbistoun-cli paths prints.
Steps
Once
- A title's directory goes into the title library - the one shared
titles/under the data directory that every OOPS tool reads, outside this repository.
Every turn
./bin/orbistoun run <title-id>rebuilds, refreshes names if they are stale, runs the guest under a time limit, and reports.- orbistoun parses the container, links it, and checks the link plan against the one stored for the title; a plan that differs under the same executable, loader and host CPU is a loader defect and heads the findings (D724). It lists every system function the module imports.
- The imports are 64-bit hashes rather than names, because that is how the guest links, so each is looked up in the symbol database.
- For hashes nothing names, the name search generates candidates from a grammar and reads identifier-shaped strings out of the module's own bytes.
- A candidate is accepted only when it hashes to the import. The hash is the proof, so a reported name is never a guess (see PROVENANCE.md).
- A confirmed name is written to
symbols/generated.jsonand its words join the vocabulary, so the next module needs less searching. - orbistoun builds a stub for every declared function it does not implement, from the stub policy. The policy is data: changing an answer costs a relaunch, not a rebuild.
- The ELF loader reserves the address space and applies the plan: it places the module, writes the relocations and any instruction rewrites (D725), sets up TLS, attaches the current handlers and stubs to the thunks, and jumps to the entry point. The title's recorded shaders are translated into its cache before that jump (D113), so a shader that will not translate is a finding before a guest instruction runs.
- The guest's machine code executes natively - same architecture, no translation - until it calls out.
- Every call to a system function lands in orbistoun instead of the platform's operating system.
- Implemented functions do the real work. Unimplemented ones record the call, dump the arguments and answer "unimplemented".
- The guest faults, exits, or reaches the time limit or call budget. All of these are results, and each writes a trace.
- The trace is written to disk keyed by module, so a sweep leaves one per title.
- The trace is compared with the previous one for the same module,
giving
FURTHER,sameorBACK. When the two runs applied different link plans, the verdict says so, so a loader change is never read as the effect of an implementation. - The findings are printed, ranked worst first: what went wrong, the evidence, and what to do about it. After them, under "on the host", come the gaps no guest call shows: audio no device played, a flipped buffer the window could not show, pad ports set to a gamepad nothing reads. They rank below every wall, since a silent title still runs, and are always printed, since nothing else names them.
- A person reads the top finding. For an unimplemented function,
orbistoun-turnreads the structure it was handed and runs the title again with it answering zero: a run that gets further says the answer is what holds the guest back, and the console's answer is the measurement to request (D832).orbistoun-turnhas already run the mechanical sweeps against it, and a thread waiting on one call has already been resolved to the call it waits on (see the wait sub-loop). If what is left is an unmeasured interface or structure, the next step is a hardware probe question rather than a guess, filed as a census row batched with the other unmeasured facts of its area (see the capability sub-loop). - A person writes the implementation - from a published source, or
from what an obSCEne probe measured on the hardware - and tags it with
its
known_by. A policy patch the loop proposed needs no person: one that moves its title and no other title back is staged (see staging what the loop proves). - Go to step 2.
FURTHERkeeps the change;sameorBACKdoes not.
A question answered once by hand becomes a command or a report section the next run answers by itself. The loop has no scratch scripts: a diagnostic worth running twice is orbistoun's code, tested against the wall it first found.
Who does what
| Step | Who | Automatic |
|---|---|---|
| 2 - run | a person types one command | yes |
| 3-4 - imports, name lookup | orbistoun | yes |
| 5-7 - name search, vocabulary widening | orbistoun | yes |
| 8 - stubs | orbistoun | yes |
| 9-12 - load, execute, intercept, dump | orbistoun | yes |
| 13-14 - a trace on every outcome, including a spinning guest | orbistoun | yes |
| 15 - progress verdict | orbistoun | yes |
| 16 - ranked findings | orbistoun | yes |
17 - mechanical sweeps (orbistoun-turn) |
orbistoun | yes |
| 17 - resolve a waiting thread to the call it waits on | orbistoun | yes |
| 18 - stage a policy patch that moved a wall and no title back | orbistoun | yes |
| 17 - interpret a finding, design a probe | a person | no |
| 17 - write and run an obSCEne probe on the hardware | a person, via pros |
no; orbistoun-cli probe reads the transcript
afterwards |
| 18 - write the implementation | a person | no |
| record what a function must answer | orbistoun, into learned.toml |
yes |
| record what was learned by hand | a person, via learn |
no, deliberately |
| rank what no measurement covers, corpus-wide | orbistoun, via census |
yes |
| file a census batch to obSCEne, with predictions | a person | no |
| check a resolution against the rows it cites | orbistoun, via resolutions |
yes |
| record what the title reached | compat record, prompted by the run |
prompted |
Step 17: the dispatcher
orbistoun-turn maps each kind of finding the report
names to a fixed next step and runs the ones that are mechanical: the
argument sweep, the other diagnostic axes, a watchpoint, a naming
attempt, a region handed to the guest when a sweep shows one missing. It
stops at the steps that are a person's, each with a sentence saying
why.
It is a dispatcher, not a chooser. A boot against a wall costs a fraction of a second and a model's answer costs several seconds, so running every candidate experiment is cheaper than choosing between them (D231).
The argument sweep is two-dimensional. It crosses a planted sentinel with what the call is forced to return, because a guest may check the return before it reads the out-parameter, and then neither intervention alone changes anything (D286). It hands back a slot, an offset and the condition it holds under.
A fault on a computed address composes two diagnostics, neither of which reads the guest's code (D276):
fault at an address the guest computed
-> snapshot the structure it was computed from (which words are still zero?)
-> arm up to four of those words (who reads them, and from where?)
-> a named instruction offset, in a named region
The result is an instruction offset, which is a finding; what should have filled the slot is step 18. The variables behind both are in WORKFLOW.md. A waiting thread composes the same two diagnostics another way, in the wait sub-loop.
Step 18: the implementation
Nothing here writes Rust. Each implementation carries a decision - what to leave in the caller's buffer, whether to trust a number the guest supplied, whether refusing beats guessing. A policy entry is different: it is one line of data, and one that earned its place is staged by the loop (D832).
A generated implementation is admissible only as a proposal a person reads, gates and merges. It arrives as an inert patch in a submission, carries an oracle like every other fact, and is merged only by somebody willing to say where the behaviour came from (D322). See TESTING.md.
Walls
There is no separate escape mechanism. A wall is handled by the same verdict and findings:
- A guest that never calls out and never faults is bounded by the time limit and the call budget, and the exit status says which one stopped it (D238).
- A regression prints
verdict: BACK. Nothing reverts a change automatically; keeping or discarding it is the author's decision. - An architectural gap - an undecoded GPU packet, a shader instruction the translator does not handle - appears as a stub or a refusal in the trace and is worked like any other finding.
Reading a turn's output
orbistoun: guest fault: write to 0xfffe0 while executing at 0x400000afc959 (image+0xafc959)
reached ContainerParsed
reached ImportsResolved
reached Mapped
reached Linked
reached Entered
outcome Crashed { signal: "access violation - the guest dereferenced unmapped memory" }
progress
imports 23 distinct (+0), 222 calls (+0)
standing 213 of 222 calls answered by an implementation (4% on stubs)
fault image+0xafc959
verdict same nothing moved
abi 222 calls, all on a conforming stack
faulted write to 0xfffe0
rax=0x0 rcx=0xfffe0 rdx=0x100000 rdi=0x4000019e9ca0
called from 0x400000f5778a <- 0x400000000064 <- 0x4000000000a2
what to do about it
! the guest faulted at image+0xafc959, write to 0xfffe0
write to 0xfffe0 is an address in no region this run mapped
rax=0x0 rcx=0xfffe0 rdx=0x100000 rdi=0x4000019e9ca0
just before: libkernel::0x6abac2f3dc6f8cee(0x600000800d38) from 0x400001595d8b
-> read the calls just before it and the arguments they were given - the value
that became this address was answered by one of them
! libkernel::0xd652cde431670c7e was called 2 times and has no name
arg0 = 0x7
arg3 = 0x400001aa8d28 -> image+0x1aa8d28 = 00 00 00 00 00 00 00 00 ...
-> extend the candidate vocabulary and re-run the name search
verdict-FURTHERmeans the guest executed code it could not reach before; it is the measure of progress.BACKmeans a regression.sameon an unchanged tree is expected, and that stability is what makes any movement attributable. A run with no fault is placed by where its GPU queue stopped, which thegpuline prints beside the run before's (D849).standing- the share of calls answered by a real implementation. A raw call count rises when stubs answer wrongly, so it rewards the wrong thing (D181).faulted- the operation, address, registers and call path of the fault.- Argument dumps under an unnamed import carry scalars as well as pointees, because a value passed in a register points at nothing (D179).
Every finding ends in an arrow saying what to do. A finding without
one is a defect in orbistoun-report::diagnose.
| What you see | What it means | What to do |
|---|---|---|
| A name at the top of the worklist with an enormous count | A guest spinning on it | Implement it; this is the wall |
| A yield, sleep or poll at the top, from one call site | A thread waiting for something that never comes | Read its "waits on" finding: the word it reads, who writes it, and the call that was to complete it |
library::0x... at the top |
The same, not yet named | Extend crates/orbistoun-names/data/vendor.toml,
re-run |
| A fault instead of a time-out | The guest got somewhere and died | Read the faulted block and the calls just before
it |
| Many calls spread thinly | The guest is progressing | Implement the frequent ones and go again |
standing fell while calls rose |
A stub started answering wrongly | Check what the new answers unlocked before believing the progress |
The wait sub-loop
A run whose time goes to one waiting call - a yield, a sleep, a poll, a timed wait retried - is not asking that call a question. Its answer is not the wall; something the thread waits for is. The wait sub-loop finds it without reading the guest's code (D832, D276):
flowchart LR
A["one call dominates,<br/>from one call site"] --> B["the wait: the thread, the site,<br/>and the objects its callee-saved<br/>registers hold there"]
B --> C["the word: snapshot those objects<br/>across iterations; read-watch<br/>the words that never change"]
C --> D["the writer: write-watch<br/>the word the loop reads"]
D --> E{"written?"}
E -- "never" --> F["the cause: the call handed<br/>that object, or a callback in it"]
E -- "by a thread that<br/>itself waits" --> B
F --> G["a 'waits on' finding,<br/>ranked with the rest"]
B --> H{"moves under the<br/>host clock only?"}
H -- yes --> I["a clock finding:<br/>the thread's time stands still"]
- The wait. The run names the thread, the call site and the call, and what the thread's callee-saved registers held: the objects the waiting loop reads.
- The word. Snapshots of those objects at successive
iterations name the words that never change; read watchpoints on them
name the one the loop reads. After the objects, the words the stopped
GPU queue never wrote are watched: each value-storing
RELEASE_MEMand memoryWRITE_DATAfrom where the queue stopped on, and those of every submission held back behind it. A loop that reads one waits on GPU work that never ran, and its cause is the queue's wall. - The writer. A write watchpoint on that word says whether anything writes it, and which thread. A writer that is itself waiting moves the question to that thread.
- The cause. The word's object is joined to the run's calls: the import handed it, a callback in it, a pointer into it. An unimplemented, placeholder or refused call ranks first.
A wait that moves under ORBISTOUN_CLOCK=host and not
under the logical clock is a clock finding, whatever it waits on: the
thread's logical time does not advance.
The writer step also serves a frame that samples a texture nothing tracked filled - no frame drawn into it, no file read landed on it, no compute program stored over it. While no thread waits, the first such texture's first word is write-watched the same way, and the run names the instructions that wrote it, or says nothing did while it was watched.
The decision sub-loop
A run that reaches a screen and draws the wrong thing there - a black world under a working HUD, a feature whose work is never submitted - is not stopped. The title decided to skip something, and the wall is the input to that decision. Tracing it back one link per run costs a run per link, so the sub-loop answers with interventions and with what the title tells its own scripts:
- Read the decision before running anything.
orbistoun-cli callers <eboot> <global>lists every instruction that reads or writes a global, andorbistoun-cli disasm <eboot> <offset>shows the condition around one, both in under a second. Most of a gate - which flags it combines, which functions set them, which script natives touch them - is answered here; a run is spent only on the values static reading cannot know, tallied with step 3 at the gate's own instructions. - What never runs. Execute breakpoints
(
ORBISTOUN_WATCHPOINT=<addr>:x) on the work the frame lacks say which of its entry points run; the summary names each, hit or not. - Who calls it. The first execute hit reports the top of the stack, so an indirect call - a virtual method, a job, a script VM's native dispatch - names its caller from the return address the static caller scan cannot see.
- What the scripts asked.
<addr>:trace@<reg>on a dispatch site stays armed and tallies a register at every hit; on a script VM'scall <reg>that is every native the scripts called, with counts. A native that should run and does not is the decision, in the title's own words. A tally over a whole run is mostly boot and loading frames: count the phase's own frames first (the report's last-minute line) and open the window at its first flip withORBISTOUN_WATCH_FROM=<flip>, so the values describe the phase the question is about. - Whether it is the cause.
ORBISTOUN_HOLD=<addr>:<value>/<width>keeps a value for the whole run;?<addr>=<value>writes it only while a guard word holds (an object's vtable), so memory the guest has not built yet is left alone. One run says whether a gate is the cause - the frame changes - before any link is traced. - What the title built.
ORBISTOUN_FIND=<text>searches all readable guest memory when the run ends andORBISTOUN_SAVE=<addr>+<len>writes regions out: tables and scripts a title decrypts or builds only in memory are read there, not from its files.
A cause found this way becomes a fix in the layer that answered wrongly, and the hold that proved it is dropped; a hold is never the fix.
Staging what the loop proves
A policy patch (D296) is data, and one that has earned its place does not wait for a person:
flowchart LR
A["a proposed policy patch"] --> B["trial on its title"]
B -- "FURTHER" --> C["run across the corpus"]
B -- "same / BACK" --> X["stays a candidate<br/>in learned.toml, unread"]
C -- "no title BACK" --> D["staged in the tracked knowledge,<br/>known_by: guest-observed,<br/>with the run as evidence"]
C -- "a title BACK" --> X
D --> E["census row filed:<br/>the hardware asked the same question"]
E --> F{"measured"}
F -- agrees --> G["known_by: measured"]
F -- contradicts --> H["retired; the measurement<br/>replaces it"]
FURTHER on one title is not enough, because a stub
answering success moves walls too; the corpus run catches a patch that
helps one title by breaking another. A staged patch is labelled for what
it is - the guest accepted it - and its measurement is requested in the
same step. A patch that writes guest memory still needs a conformance
check first (D296). Rust is never staged this way.
The naming sub-loop
Naming is the part of the loop that gets cheaper as it runs.
flowchart LR
A["every unnamed import hash<br/>in the whole corpus"] --> B["candidates from<br/>the grammar"]
A --> C["identifier-shaped strings<br/>in every module's own bytes"]
A --> R["strings in what a guest<br/>passed to an import, as it ran"]
B --> D["hash each candidate"]
C --> D
R --> D
D --> E{"does it collide<br/>with a wanted import?"}
E -- yes --> F["proved - the name is right,<br/>and nothing was consulted"]
E -- no --> G["proves only that the name<br/>was not among those tried"]
F --> H["split the name into words<br/>and add them to the vocabulary"]
F --> I["record what proposed it:<br/>derived, static or runtime"]
H --> B
I --> J["re-derive records whose<br/>coordinates the new words moved"]
J --> B
A hash is one-way, so the only method is to propose a name and let the hash accept or refuse it. A hit is proof rather than a lookup, which keeps the symbol database clean-room. Every source is confirmed the same way; the record says which source proposed the name, and the audit tiers sources by what somebody else needs to repeat them (D213).
The search runs over the whole corpus, not one module at a time: one module's strings name another module's imports, and the vendor C library module carries names that titles import without ever spelling them.
Two edges feed back into the grammar:
- Vocabulary: a name learned from one title teaches the generator words that reach hashes in unrelated titles.
- Repair: a generated record cites a pattern and an index into an
enumeration over the vocabularies, so every learned word renumbers the
candidates built from it.
audit --repairre-derives the records the new words moved.
A model as a vocabulary source
A miss proves only "not in what was tried", so naming more imports
needs more words. Words come from the modules, from published standards,
and from orbistoun-propose::vocabulary, which asks a local
model for words one grammar position at a time.
Nothing a model says is trusted: it proposes words and the hash
decides. A wrong suggestion costs a sweep and vanishes, which is why a
model may guess here and nowhere else in this project. Words are banked
only when a confirmed name was built from them, and promoting a banked
word into vendor.toml is a separate, deliberate act. The
yield sits in the first round of each position; ask once per
position.
The questions sub-loop
Some facts cannot be settled by watching a guest: what a function returns on the hardware when nothing observes the return, or what an argument means when every observed call passes the same value. These are measurements to be taken.
flowchart LR
A["writing a behaviour down"] --> B["known_by:<br/>published / measured /<br/>guest-observed / assumed"]
B --> C["everything unsettled listed<br/>as an assumption on that function"]
C --> D["orbistoun-cli questions --json<br/>- ranked by how often guests call it"]
D --> E["a conformance probe runs them<br/>on the hardware"]
E --> F["orbistoun-cli probe TRANSCRIPT"]
F --> G["known_by becomes 'measured'"]
G --> C
known_by has no value meaning "already known": every
option names something that could contradict it. assumed is
a normal state. A written-down assumption can be counted, ranked, probed
and retired.
Probing on the hardware
Three components share step E:
obSCEne is the instrument. It runs on the hardware and answers a question over a command protocol, so a new question costs a round trip rather than a rebuild.
Prosperous delivers and supervises it. A probe calling functions of unknown arity faults as its normal case, so
pros supervisere-sends it when it stops answering:pros send obscene.module.elf # onto the hardware, through the loader pros supervise obscene.elf # re-send it whenever it stops answering pros logs # the report, as it comes out over the kernel logsuperviserefuses to send while the probe answers, and gives up after three consecutive dead starts. Every session carries an identifier, so a restart is visible and nothing is resumed across it.A person starts the loader on the hardware after a power cycle, and decides the hardware is free: a faulting call takes down whatever was running.
The capability sub-loop
The questions sub-loop retires assumptions orbistoun has already written down. The capability sub-loop finds the ones nobody has written down yet: an import no knowledge entry covers, a register field the pipeline refuses, an instruction the translator does not know. It turns each into a measurement, and the measurement into a test.
flowchart LR
A["orbistoun-cli census<br/>imports with no measured entry,<br/>refusals by reason,<br/>ranked by titles reached"] --> B["group by area:<br/>one library, one GPU layer"]
B --> C["one obSCEne request per area,<br/>many arms; predictions attached<br/>where a reference has them"]
C --> D["obSCEne sweep rows"]
D --> E{"rows settle<br/>every arm?<br/>(resolutions)"}
E -- no --> F["re-file the arms<br/>the rows missed"]
F --> C
E -- yes --> G["knowledge entry,<br/>known_by: measured"]
D --> L["refuted predictions<br/>into the oracle ledger"]
G --> H["a fixture test asserting<br/>the measured value"]
H --> I["the implementation,<br/>step 18"]
I --> A
orbistoun-cli censuslists every import in the corpus with no measured knowledge entry, and every translator and backend refusal by reason, each ranked by how many titles reach it. It is the worklist across titles, asworklistis within one.- Rows are grouped by area - one library, one GPU layer - and each area becomes one request with many arms. A probe that loads a library once and calls twenty functions costs one round trip; twenty requests cost twenty.
- Where a reference emulator has an answer, it travels with the
request as a prediction (D818): a first arm for the probe and nothing
more. The request resolves only on obSCEne's own rows, and an arm the
rows miss is re-filed, never assumed.
orbistoun-cli resolutions <worklog> --reports <obSCEne repository>checks each resolution against the rows of the logs it cites. A status code no row holds, or a function whose rows say it never bound, sends the request back with those rows quoted (D840). - A resolved row becomes a knowledge entry with
known_by: measured, and a fixture test that asserts the value before any implementation uses it (TESTING.md). - Every refuted prediction goes into
crates/orbistoun-hle/data/oracle-ledger.toml, so the next census knows which areas' predictions are worth sending.
Conformance titles grade whole layers
Two kinds of first-party guest turn the census from a list into a graded test:
- GCTS00001, the GL conformance suite, runs on the hardware through oops-mesa. Run on both, its per-case results diff into findings: every case that passes on the hardware and fails here is a GPU fact with its answer attached.
- A first-party title's frames, captured on the hardware by flip index, diff against orbistoun's own. A title chosen because it uses a layer - tessellation, multisampling, compute atomics - grades that layer by picture.
Checkout and binary
The loop does not need this repository. Somebody running a release binary against a title nobody here owns turns the same oracle - the guest itself - and what they produce is worth collecting (D297).
| Artifact | Where it lands | Needs a checkout | Sendable |
|---|---|---|---|
learned.toml measurements |
data directory | no | yes |
| compat entries | --dir, default ./compat |
no | yes |
| traces, run reports | data directory | no | no - they are inputs |
symbols/generated.json |
the repository | yes | via the name, not the file |
| an implementation | the repository | yes | as a patch |
Everything sendable is the same kind of claim: derived from running a
binary the submitter owns, reproducible by anyone with the same title,
and falsifiable by a command. A maintainer without the title cannot
check a diff, but can accept a measurement as assumed and
promote it when somebody who owns the title confirms it.
submit export and submit check gather and
receive these; see WORKFLOW.md.
Properties of the loop
- Step 7 compounds: naming is not per-title work, and every learned name is vocabulary for every later title.
- Step 16 removes diagnosis, not fixing: the run states the wall, with evidence, ranked.
- The loop never keeps unverified code: Rust is a person's, and a
change is kept only when the re-run says
FURTHER. A policy patch is staged only when no title in the corpus wentBACK, and only asguest-observed. - Every diagnosis is a command: a question answered once by hand is answered by the next run.
- Step 18 never invalidates step 3: the plan names thunk indices, not implementations, so a turn that adds an implementation reuses the stored plan and pays only for the run.
- The capability sub-loop makes catching up a ranking problem, not a research problem: the census says what is missing and how many titles it costs, a reference emulator says what the answer probably is, and the hardware says what it is.
- The loop runs in the worker, because the mechanical sweeps of step 17 need it. A native executable (D724) writes the same trace as a run played from the window and is compared and recorded like one, so playing a title that way still feeds steps 14 to 16.