kxbox: the bridge API on both backends, checked by signature - #65
Merged
Conversation
The five calls a lesson writes are boot, sh, read, trace and insmod. All five existed. Two of them did not work the same way on both backends and nothing was checking. insmod was a branch inside Box rather than a call on a backend. On a recording it turned a module load into a shell line and looked it up under a recipe named `insmod abba.ko`, a naming convention invented at that call site and written down nowhere. No recipe has ever been named that way, so the recorded path had never once worked. Corpus has an insmod now, matched on a `module` field, and Box is a straight delegation like the other four. max_depth was on the live backend from the day it was written, was on nothing else, and Box.trace could not forward it. The bridge docstring calls it the thing to reach for when the guest would otherwise hang, and no lesson could reach it. Corpus.tape takes it, Box.trace forwards it, and a test now compares the two backends' signatures argument by argument so the next one shows up as a failure rather than as a reader's TypeError. Corpus.read used to take the first recipe that recorded a path. Two readings of /proc/lockdep_stats either side of an insmod is the ordinary case and not a strange one, and a lesson asking without saying which would have been handed the before or the after depending on nothing it could see. It raises now and lists the recipes. Corpus.evidence looked at a recipe's trace and nothing else, so a recipe whose evidence is a /proc snapshot came out marked handwritten however its metadata was written. Both new recipes are that shape. It looks at every file a recipe points at now, and the test fixture grew the .meta.toml it should always have had. Two new recipes, both real captures already in the corpus from the C09 work, and the first for any profile other than teaching. Until now a lesson asking for the lockdep kernel got a session that knew how to do nothing at all. V86 validates its profile name the same way boot() does, since it is the other way in. kxbox/web/first-tape.py was passing a build profile name where a boot profile goes, which profiles.for_build now translates, and the build name still goes out in the report.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The M1 row is "The bridge API:
boot,sh,read,trace,insmod". All five already existed. Two of them did not work the same way on both backends, and nothing was checking, which is the part this PR fixes properly rather than case by case.The five calls
kxbox.boot(profile)box.sh(line, recipe=)box.read(path, recipe=)box.trace(name, do, ...)box.insmod(path)insmodhad never worked on a recordingIt was a branch inside
Boxrather than a call on a backend:The recorded side turned a module load into a shell line and looked it up under a recipe named
insmod abba.ko. That naming convention was invented at that one call site and written down nowhere. No recipe has ever been named that way and none ever would be, so on the branch most readers are on,box.insmodraisedNotRecordedevery single time.Corpushas aninsmodnow. It matches on amodulefield on the recipe rather than on the path, because the path a lesson writes is wherever the rootfs build happened to put the file and only the last part of it means the same thing on both sides.Box.insmodis a straight delegation like the other four, so the difference between the backends lives in the backend that has it.max_depthcould not be reached from a lessonV86.tapehas had it since it was written, and its docstring says what it is for:Corpus.tapedid not take it andBox.tracedid not forward it, so the documented fix for a guest that appears to hang was unreachable from any lesson. Both take it now.The check that keeps this true
Two tests, and they are the point of the PR more than any individual fix above.
and one asserting that every backend argument is forwarded by
Box, sinceBoxis the only way in and a parameter it does not pass on is a parameter that exists in two places and nowhere a reader can type it.An argument one backend has and the other does not raises
TypeErroron whichever machine the reader is on rather than on the machine the lesson was written on, which is the worst place to find out. Both of the problems above are that shape and both would have failed these tests on the day they were introduced.writeis excluded on purpose and there is a test saying so. The live backend has one and drives the tracer with it. A recording can say what a file contained and can do nothing at all about a lesson writing to that file, so a cell that wrote would take effect for the few readers with an emulator and quietly do nothing for everybody else. That is worse than a cell that cannot be written.An ambiguous read now refuses to guess
Corpus.readtook the first recipe in file order that had recorded the path. Two readings of/proc/lockdep_statseither side of aninsmodis the ordinary case rather than a strange one, and a lesson asking without saying which would have been handed the before or the after depending on nothing it could see. Both are plausible readings of the same file, so it would have looked right about half the time.Naming a recipe that did not record the path you asked for now says what it did record, instead of falling through to the generic message.
Two new recipes, and the first for a profile other than teaching
Both are real captures that were already in the corpus from the C09 work, taken off one boot of
D-lockdepwith the module load between them:Until now,
boot("lockdep")gave a session that knew how to do nothing at all, because every recipe in the list wasteaching. The banner said so honestly and that was the whole of it.Adding them turned up one more thing.
Corpus.evidencelooked at a recipe's trace and nothing else, so a recipe whose evidence is a/procsnapshot rather than a tape came out marked handwritten however its metadata was written, and both of these are that shape:That would have put "nothing here is evidence" in the banner of every lesson using a snapshot backed session. It looks at every file a recipe points at now. The test fixture grew the
.meta.tomlbeside its/procsnapshot that it should always have had, which is the same gap in miniature.One name collision, resolved rather than documented
kxbox/web/first-tape.pydid this:KXBOX_PROFILEnames a build, which is what the headless harness picks an image by.V86(profile=...)wants a boot profile. They are different namespaces for good reasons, set out in #63, and this was quietly mixing them.profiles.for_build()turns one into the other, and it can answer None, because three of the six builds have nobody standing on them:A-gzip,B-btf-externalandC-longtermexist to be measured againstA-fullrather than to be booted by a lesson. The build name still goes out in the report, so nothing is lost.V86also validates its profile name now, for the same reasonboot()does. It is the other way in.Checks
Every gate, locally: ruff check and format, 1487 pytest tests with 7 skipped, 63 node tests, lintprose across 37 files, and the check runs of diagrams, nbbuild, sitebuild, kxbox, vendor, baseline, claimledger, coverage, bpc, kconfig, refcheck, lintnb and kxmanim.
kxbox --checkreports 5 recipes clean.