- Python 47.3%
- Rust 28.2%
- Shell 24.5%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
Merge the selected feature/native-cli history with an explicit two-parent commit so main retains the development lineage and the validated source snapshot. The resulting tree is identical to the selected feature commit; no dependency pins or runtime behavior are changed by this merge. Previous main: |
||
| .github | ||
| lib/rootd-integration-orchestration | ||
| scripts | ||
| tests | ||
| .editorconfig | ||
| .gitignore | ||
| .markdownlint-cli2.yaml | ||
| ARCHITECTURE.md | ||
| cargo-repos.toml | ||
| CODE_OF_CONDUCT.md | ||
| components.toml | ||
| CONTRIBUTING.md | ||
| dynlink-acceptance-closure.toml | ||
| dynlink-artifact-abi.toml | ||
| dynlink-dependency-records.toml | ||
| dynlink-executable-migration.toml | ||
| LICENSE | ||
| README.md | ||
| ROADMAP.md | ||
| runtime.dev.toml | ||
| runtime.release.toml | ||
| runtime.sample.toml | ||
| rustfmt.toml | ||
| SECURITY.md | ||
| SOURCE-PINS.md | ||
EriX Integration Repository
integration is the cross-repository system integration and VM validation
repository for EriX.
EriX is a clean-room, capability-based microkernel operating system written entirely in Rust.
Technical requirements are tracked in the EriX requirements, conventions, and project documentation.
See:
- docs for design documents, specifications, and development plans.
- Related architecture repositories for kernel, services, libraries, drivers, and integration tooling.
Purpose of This Repository
This repository implements the EriX integration harness. Its purpose in EriX is to prove cross-repository system behavior in deterministic appliance and VM scenarios.
Functionally, it builds component sets, generates test media, runs scenarios, and checks expected markers and artifacts. The repository keeps the implementation, interface contracts, tests, and documentation for that behavior in one reviewable ownership boundary.
The maintained responsibilities are:
- assemble component revisions into runnable system images
- generate deterministic test media and VM scenarios
- provide the
no_std, authority-free in-guest scenario policy linked into build-gated rootd integration images - verify cross-component behavior, authority failures, and persistence checks
- publish release artifacts only from push/manual CI runs; pull requests validate without mutation and scheduled CI runs are not defined
Canonical dev and release profiles share the same mount graph: writable ext4
/, read-only FAT /boot, and volatile writable ramfs /tmp. A writable mount
does not pregrant write authority to a shell or command. Utilities still request
exact operations through the running-job broker and trusted review as needed.
Read-only scenario media retain explicit read-only test profiles.
The kernel pin now traverses private read-only mapping chunks directly, with pending updates spanning storage boundaries and no effects from empty chunks. Four independent regressions and the strict 584/608-test kernel matrix pass; live checks, error order and hardware batch behavior remain unchanged. Prior NonNull images complete the commands but miss prompt (1.109–1.111 seconds) and four-command (2.898–2.938 seconds) acceptance. CI 1548 passes 486/486 scenarios and all post-image probes; CI 1549 validates its successor separately. The new pin still needs its own private images and unchanged-limit observations.
The compact mapping-preparation refinement keeps complete leaf entries and exact PTE keys, with GLOBAL invalidation encoded only in a validated target address bit. Hardware keys use checked non-null conversion on target-span resolution. Independent untagged-oracle regressions and the strict kernel 580/604-test suites pass; live preparation and all authority/flush boundaries remain unchanged. Smaller emitted code, stack and temporary results are not startup acceptance: both origin-image observations still fail the unchanged strict limits. Matching private-image validation remains required, and the main dev/release images are not replaced by this checkpoint.
The selected mapping-lookup refinement retains a table-owned last-full-search
index, not a pointer or authorization result. Repeated explicit user-buffer
validation and copying still check live bounds, exact page identity, rights,
kind and backing under the existing VSpace lock. Mutable exposure, removal and
clearing invalidate the hint; the original first-match search remains the
fallback. CI 1546 at c306711a passes all 486 scenarios and post-image gates,
but both later 21850e67 staging-image observations still miss the one-second
READY-to-caret and two-second four-command limits (1.020/1.025 and 2.716/2.634
seconds). Matching new-image acceptance remains required. No main image is
replaced, no limit is relaxed and no debugger overhead is subtracted.
CI 1545 at 411bc181 completes all 486 scenarios and post-image gates, closing
the earlier CI repair described below. The stricter isolated startup limits
remain open: both exact published-image baseline observations and both private
c306711a candidate observations fail. The next kernel pin 21850e67 removes
redundant mapping-batch empty tags by initializing only the exact used prefix.
Every preparation succeeds before reading any staged leaf; errors read no
prefix and retain the existing flush. Eight trace-equivalence regressions and
the strict 555/579-test matrix pass. Earlier first-preflight index reuse still
reacquires the copy lock and authorizes each live page again. Neither emitted
work reductions nor host-cost measurements establish candidate image speedup.
The main dev and release images are not replaced by this work.
Run 1542 completes all 486 scenarios and its post-image gates. The corrected
7f7e6cfd graph subsequently passes eight private terminal/time/interrupt
probes, but run 1543 finishes with 473 passes and thirteen storage watchdog
failures after VFS_MOUNT; its post-image gates are skipped. Two unchanged
isolated migration-closure runs pass; neither the page-fault tail nor the
sampled blocked calls alone establish a deadlock. The baseline storage
pipeline previously hid fourteen proof phases behind end-of-pipeline
markers. Integration now reports completed proof phases through rootd's
existing build-gated logging adapter. These are success-only observations,
not heartbeats or early final markers; 120-second total and 45-second silence
bounds remain unchanged. Complete replacement CI is still required.
The migration-closure VM requires all fourteen new records exactly once and
in order between VFS_MOUNT and VFS_IO, retaining every older assertion.
The pinned VFSD also removes an independent oversized owned read-reply
temporary. Its runtime and smoke PIC selected-frame estimate falls from
267,072 to 169,008 bytes within the unchanged 262,144-byte allocation. The
new component CI gate checks emitted frames without claiming whole-program
stack safety. This defect is proven separately, not attributed as the cause
of all thirteen watchdog failures; matching guest validation remains pending.
CI run 1540 passes all 486 catalog scenarios but fails its later development
native-time probe while still selecting the old shell. Integration e7f4fa71
selects exsh b99d6da4; both matching private dev/release native-time probes
now pass. Complete replacement CI remains required. Run 1541 separately exposes
an accounting-fixture precision assumption: raw shell CPU time increases across
exec while both separately truncated centisecond fields remain unchanged.
The successor now performs 64 bounded writes with the existing times builtin,
scratch file and authority before its sole visible snapshot. The original
32-iteration child and strict accounting assertions remain unchanged; this is
deliberate fixture work, not a CPU-speed guarantee or a runtime-accounting fix.
At the same e7f4fa71 image checkpoint, framebuffer-only, serial-only and
disabled-terminal probes pass. Independent terminals exhaust the old observer's
160-frame budget. Pacing only ordinary independent command-result captures at
800 ms preserves every fresh-frame predicate, edit, consent and foreign-Enter
proof, with unchanged 160-frame and 120/15/10-second bounds. The unchanged image
then passes all twenty commands and exact approve/deny/readback checks in
99.816 seconds using 132 captures. This is functional observer evidence, not
a startup-performance result. The intermittent post-interrupt launch failure
and full remote CI remain open.
The final 776e3407 runtime images pass all eight focused feature probes:
dev/release editing and mount/time policy, plus framebuffer-only, serial-only,
no-console and independent-console modes. Host oracle cf59e661 completes the
independent test's twenty commands in 74.491 seconds using 144 of 160 captures,
including both exact consent decisions, processed wrong-seat Enter rejection
and approved-only readback. Earlier failed attempts remain retained. The real
managed-frame hardware test also passes; stricter startup performance does not.
The subsequent empty-file utility report is a separate regression: those eight
probes did not cover named-file cat or copying to an absent destination.
tests/native-utility-vm.sh serial|physical image now checks sixteen commands
and twenty exact trusted reviews. Source READ, missing-entry CREATE and file
WRITE require independent grants; denial is never permission to create.
The probe checks empty/nonempty readback, denied creation, denied post-create
write, explicit truncation and a usable later shell with unchanged 120/15/10
bounds. Host checks and both matching-image 7f57bb8b utility probes pass:
development serial and release physical each complete sixteen commands and
twenty exact reviews, including nonempty copy/readback, both denial outcomes,
empty-source overwrite truncation and the final shell sentinel. The local
artifacts are out/appliance/erix-utility-poll-dev.img and
out/appliance/erix-utility-poll-release.img; canonical open images are untouched.
The first fixed-image checkpoint c9a78901 builds separate
erix-utility-dev and erix-utility-release images without overwriting an open
canonical dev disk. Its new utility probes are 0 PASS / 2 FAIL: dev proves
named-file cat and reaches all three separate copy reviews before the command
deadline; release reaches the silence watchdog before its banner. Both ran
with a separate four-vCPU VM active, but that does not establish the sole
cause of failure. Original bounds and failed evidence remain intact. These
images are diagnostic builds, not accepted replacements. The complete host
matrix passes 300/301 Rust tests and all 472 Python tests across 45 suites.
The release rerun completes its first eight commands, including empty copy and
readback, nonempty cat and denied creation. It then times out waiting for the
status marker after correctly denying post-create WRITE. That c9 checkpoint's
dev/release results remain 0 PASS / 2 FAIL, with three attempts retained.
Kernel b54082bd separately removes a repeated nonblocking receive lookup by
observing dequeue backpressure and live transfer-waiter state under one lock.
Blocking receive, capability validation and generation checks are unchanged;
537/561 host tests and strict checks pass. The matching 7f57bb8b utility
probes pass in 102.569s and 98.375s under the original bounds. A separate
four-vCPU VM remained active, so these are functional results, not an isolated
speedup comparison. The stricter 5/1/1/2-second startup gate remains open.
The explicit [features] switches rtc_cmos, tty_fbcon, tty_serial, and
tty_mirror replace the private-provider presence table and describe console
deployment. TTY switches do not change logd stamps or provider logging routes.
Both paths with mirroring select one session; without mirroring they select two
independent shells. One enabled path selects one shell; neither selects none.
The generator encodes the three TTY bits in a strict 96-byte TTY1 version-2
startup record. The product orchestration entry starts both independent shell
transactions before waiting on either one, with distinct realms and exact
lifecycle/status receipts. Temporary cancellation handles exist only during
dual-start rollback; all launch and control aliases are retired before normal
round-robin status observation. Malformed replies retire all framed receipts
and never invoke unvalidated lifecycle/control endpoints. Uncertain cleanup or
job disposition fail-stops. Console-mode acceptance remains separate from
source/host checks and the accepted mirrored editor probes.
Canonical interactive dev launches now select the same console-count runner as product builds, instead of the authored single-shell fixture path. Zero paths create no TTY session; independent paths start two. Authored scripts and negative fixtures retain their existing protocol. Successful runtime-console completion retires bootstrap and host-report authority, then exits rootd normally without the test-only terminal READY host report that would terminate the VM. Failure reporting is unchanged; surviving services need no retained rootd idle loop.
The focused native-editor-vm.sh probe submits ten separate commands through
physical keys or fragmented COM1 sequences. It checks history, saved drafts,
insertion, Backspace/Delete, boundaries and wrapped recall, retains raw output
and screenshots, and requires fresh results and prompts. The separate
native-image-policy-vm.sh probe binds packaged metadata to the chosen image's
source epoch and live creation/touch to a deterministic 2030 RTC. It authorizes
only named test objects, verifies root writes and /boot denial, and preserves
the source image. Both keep the 120-second total, 15-second silence and
10-second command bounds; screenshots alone are not text/caret acceptance.
tests/native-console-mode-vm.sh fbcon|serial|none|independent image checks
dedicated feature images with separate serial and exact gray framebuffer
evidence. Independent seats must retain distinct cwd, history, input and
consent; wrong-seat answers cannot decide a pending review. Disabled paths
must show no shell, without suppressing independent service logs.
The foreign-seat check requires fresh builtin output and a new prompt while
the original review remains pending; merely injecting Enter and waiting is
not acceptance of input isolation.
Before final READY the observer checks serial order without spending bitmap
captures; afterwards it requires fresh exact frames while continuously draining
COM1. For this probe only, the unchanged 15-second stall watchdog also accepts
finite, ordered verified guest milestones from its private observer log.
Screenshots, input injection, file activity, replayed events and malformed
records cannot keep a stalled guest alive. Other profiles retain their existing
serial progress policy; all command and total deadlines remain unchanged.
tests/native-command-timing-vm.sh [dev-image] records eight separate commands:
builtin : and true controls plus six external launch observations. It arms
the bounded fresh-log startup observer before VM creation and records every
READY interval independently of Enter-to-output/prompt latency. A new exact
caret-show is required after each command. Builtins have no first-output
measurement; native time must report real nonzero elapsed time in its exact
format. These observations are not a waiver of the tighter startup gate.
The ca6f1346 image checkpoint passes dev-serial and release-physical mount/time
probes, including source-derived packaged mtimes, live RTC object creation,
explicit touch timestamps, dot entries and read-only /boot denial. Earlier
failed attempts remain recorded in out/console-editor/ACCEPTANCE.md. The a02f5797
checkpoint additionally passes both 14-command directory probes and exact-pixel
editor probes, including wrapped text and the sole insertion caret. Release
screenshots confirm that the initial firmware artwork is cleared. Console-mode
checks remain separate: they exposed whole-line semicolon history truncation
and a framebuffer-only serial-silence watchdog mismatch. Signed exsh 2ad98e0c
offers original accepted bytes once before execution-plan segmentation or
asynchronous rewriting, staging them in its inactive draft arena until the
complete entered line ends. Invalid or oversized aggregates cannot publish a
truncated suffix or evict old history. All 928 tests pass in both selections;
the 392b6c18 framebuffer-only and serial-only images now pass complete-line
recall with a fresh appended execution result. Exact framebuffer
consent remains mandatory: mirrored serial text merely wakes the bitmap observer
after launch, avoiding redundant screenshots without raising the 128-capture or
time bounds.
Block reads reserve only their checked response header plus the current
fragment's bytes. Lib-block df03ec77 reduces a 512-byte metadata read to
592 total IPC bytes instead of 32,768 without changing fragmentation, returned
length checks or device/request identity. E2fsd 3e564fc3 validates inline
xattrs from the same request's checksum-verified inode bytes, removing one
duplicate inode read without a cross-request cache or altered external-xattr
checks; 249 tests pass in both feature selections. These request-local
optimizations and the sparse kernel refinement require end-to-end timing evidence.
The 9dc9cf6b no-console image passes its complete five-second quiet check:
disabled physical and serial input produce no shell, service logs remain
available, and services survive normal rootd exit. The 392b6c18 checkpoint
also passes exact-pixel editor and mount/time probes on canonical dev/release,
and the no-console quiet check. Independent-console testing completes fifteen
ordinary cwd/history commands but exhausts its unchanged capture bound before
the first review; it is not accepted. Single-seat probes now add their own
approve/deny decisions and exact object readback within the existing bounds.
Kernel 6d642d95 selects a managed extent's lowest free page with one current
mapping-table scan for aligned extents of at most 64 pages. Object identity,
holes, aliases, locking and error order remain exact; other geometries keep
the original path. The new kernel-managed-frame-occupancy-positive scenario
requires real backing readback and private-object cleanup before its success
marker. Loaderd 6761638 drops size-only manifest/object queries while retaining
live metadata checks, digests and pinned-root authority; verified read lengths
split the existing bounded workspace, with full erasure on every result.
Both strict component matrices pass. The dd7ed015 managed-frame hardware probe
passes real backing readback and complete private-object cleanup. Its isolated
date observations are 0.825/0.893 seconds versus an adjacent 392b6c18 control's
1.073 seconds; nested time date is 1.423/1.480 versus 1.985 seconds. These paired
command improvements do not close the tighter service-startup gate.
The dd7ed015 framebuffer-only and serial-only probes each pass eleven commands,
including their own approve/deny decisions and exact approved-only readback;
no-console quiet also passes. Independent mode proves both decisions, rejection
of processed foreign-seat Enter, and approved-only readback, but reaches the
unchanged 160-capture bound before final completion and remains unaccepted.
Its observer now omits eighteen unused command-preamble screenshots while
retaining fresh edit/result frames, all consent checks and original bounds.
Exsh 700e41d6 limits borrowed observation reply buffers to 128 bytes for TTY
events and 112 for job status, retaining the existing two-receipt audit allowance.
Only the borrowed prefix is erased; the unused caller tail is never transmitted
or parsed. Cadence, signal ordering, receipt cleanup and authority are unchanged.
All 936 tests pass in both feature selections with strict target checks; fresh
matching-image and latency acceptance remains separate.
The 547f67b6 checkpoint passes both ten-command editor probes, both twelve-command
mount/time probes, both eleven-command single-terminal consent/history probes,
and no-console quiet. Independent mode passes nineteen commands and submits the
twentieth before its unchanged 160-capture bound: seven feature passes and one
failure, not full acceptance. Two isolated timing runs and an adjacent dd7ed015
control show no clear additional whole-command gain from polling buffers alone.
Kernel 48cc425c combines the remaining exact-address and managed-page scans
under the same VSpace lock. First-address matches and the original overlap,
fallible reservation, page-selection and rights order remain unchanged; device
and noncanonical paths keep their original behavior. Nine new tests prove
equivalence and one traversal instead of two; 527/551 tests pass with one
pre-existing ignored benchmark each. Fresh hardware and timing proof is separate.
On the 776e3407 images, the real managed-frame hardware scenario and all seven
non-independent feature probes pass. Independent mode still reaches its capture
bound after nineteen commands. Its result observer now carries the same 400-ms
interval across Enter instead of taking a closely spaced phase-entry snapshot;
every result predicate still requires a fresh frame, and serial isolation,
consent paths, deadlines and capture limits are unchanged. Fifty focused host
tests and independent review pass. The final .QgXj4d rerun now completes every
milestone and preserves source image hashes under the original 120/15/10 bounds.
The corrected strict startup probe completes all guest commands but fails all four thresholds: root readiness 6.195 seconds (limit 5), complete editor caret after readiness 1.805 (limit 1), RTC-to-TTYD alone 2.981 (gap limit 1), and four native commands 4.166 (limit 2). Its observer requires the complete caret and charges execution during Enter acknowledgment without millisecond rounding. Isolated adjacent-image timings do not establish a uniform whole-command gain.
RTC is encoded as a deviced-driver BootConfig node with explicit deviced,
loaderd, and timed dependencies; it has no filesystem-launch row. Rootd images
receive a build-time version derived from the Integration repository's sorted
tag at HEAD, or the full Integration commit when no tag exists. Initial-shell
development scenarios require the observable order READY:LAUNCHD, final
ERIX_ROOTD:READY, a blank line, the light-gray
EriX <tag-or-commit> banner and its blank line, then shell evidence. Release
images cross the same internal complete-service barrier but deliberately omit
the development-only final READY record before printing the banner. Physical
input injection waits for the real dollar-space shell prompt; the former rootd
PHYSICAL_INPUT:SESSION_READY coordination stamp is absent. The shell is
therefore post-readiness user policy rather than a service-readiness condition.
The interactive transcript explicitly exports PATH=/bin:/usr/bin, so command
lookup is inherited process state rather than an ambient fallback inside exsh.
The tty session carries a bounded native-command operation ceiling. Requests
already admitted by the session and executable/script ceilings use routine
powerbox authorization; exceptional selectors require trusted prompt mediation.
No filesystem or process authority is ambient. Both canonical images execute
an external echo through that path in
their focused VM gates. The release gate waits for that guest output and then
ends only the host QEMU process through its private QMP socket. Rootd observes
all selected shells until terminal, retires their exact remaining authority,
then exits normally; surviving services do not depend on an idle rootd.
Native command launch is program-agnostic: exsh sends the unchanged executable
selector, arguments, cwd, and stdio, with no operand authority records. The
running utility requests exact operations through a job-bound broker; provider
or consent denial is a utility error, not an executable-admission error.
Build-time manifests independently declare CPU accounting, inherited script
launch, timed query, session inspection, cwd, and redirection-resolver ABI bits.
The three-column exsh/extop catalogs receive explicit inventory declarations
49 and 9 respectively; coreutils flags pass through its own catalog unchanged.
tests/launch_manifest_flags_test.py covers all 64 flag combinations, relabelled
catalog entries, exact command identity, and rejection of index/sidecar drift.
Matching-image broker acceptance is recorded separately from these host checks.
Live-image regression checks also keep the shell's own receiver distinct from its launch sender and require each ABI flag to select only its declared authority. Executable inspection borrows the current cwd through the existing launch sender; inherited script launch must not implicitly install a resolver. Strict startup inventory and fail-closed authority checks remain mandatory.
tests/native-runtime-errors-vm.sh physical|serial [dev-image] uses only a
private copy of the dev image. It requires a real dev READY
record, root cwd, generic command -v mkdir, utility-owned permission errors
and status 1 for touch boot/a/mkdir boot/a, utility argument errors and
status 2 for operand-free calls, and a fresh final echo. No prompt is approved
or retried.
The existing powerbox probe supplies the release-safe counterpart: explicit
allow/deny under writable /tmp, a utility-owned denial diagnostic/status 1,
and separately authorized readback proving exact creation and absence. Both
paths keep the 120-second total, 15-second stall, and 10-second command bounds;
host socket fixtures exercise transport and teardown but are not VM evidence.
tests/native-time-vm.sh [source-image] runs six separate COM1 command lines on
a private dev or release image. Native time -p must complete an inherited
pipeline, preserve redirected child stdout, and write its own portable
real/user/sys report after the child's argument-error diagnostic into the
same redirected stderr file. Exact redirected-stdin readback proves child EOF
did not close the parent's description. The probe uses existing shell
redirection authority, never an extra file grant or consent bypass; separate
powerbox probes cover runtime requests. It requires exact output/status and
later prompts with the unchanged 120/15/10-second limits, retaining logs,
per-command timings, and source identity under out/native-time/. Host socket
and private-wrapper regressions are CI gates. Integration d8e83d3d passes all
ten focused matching-image cases: dev root utility errors on both transports,
dev/release directory operations on both transports, and dev/release serial
native-time and powerbox consent. Every wrapper exits zero under unchanged
120/15/10-second limits with unchanged canonical images. Exact source hashes,
timings, and the earlier 090e7156 two-pass/two-fail attempt are retained in
out/runtime-authority/ACCEPTANCE.md. This closes running-program authority
acceptance, not the separate tighter startup-performance gate.
COM1 receive is an alternative ordinary input transport for that same focused
PTY. drv-serial keeps RX bytes separate from transmitted log history,
seriald consumes them only through its private provider route, and ttyd
feeds ordinary bytes through its existing line discipline. During an exact
focused trusted prompt, ttyd instead captures serial answers after complete
private review delivery and an empty post-visibility RX read. No public serial
writer gains input-injection authority. Ttyd advances RX one nonblocking step
per turn, retaining request identity and bytes without blocking rendering or
PTY cleanup. Empty or unavailable reads skip seven focused turns before the
next attempt; accepted replies and buffered bytes keep progressing every turn.
The focused development-image gate proves both
PS/2 and COM1 command input against independent copies of the canonical image.
Interactive reuse is checked separately by
tests/interactive-shell-lines-vm.sh physical|serial [source-image].
Each private VM submits ls, waits for directory output and a fresh later
prompt, submits another ls, and finally submits an external echo sentinel
on its own line. Every command must produce new output and return a new prompt;
one semicolon-separated batch is not equivalent evidence. CI covers both
transports on both dev and release images. Each command has a ten-second
monotonic budget including input injection, inside the 120-second VM deadline.
Logs, milestones, image identity, and source checksum are retained under
out/interactive-shell-lines, including on failure.
This catches terminal focus being redirected to a command's unused lifecycle
PTY even though that command inherits the shell's actual stdin. Ttyd changes
automatic focus only when provisioning really exports a new stdin sender;
lifecycle-only and output-only requests preserve the current focus.
The paired tests/interactive-shell-interrupt-vm.sh [source-image] requires
both canonical input echo and /bin/cat output before one physical Ctrl+C,
then status 130, a new prompt, and a separately entered successful command.
Exsh observes the inherited shell PTY through its existing persistent event
cursor while forwarding only through its held exact child-control route.
CI runs this cancellation check on both image profiles without using repeated
interrupts that could spill into the following command.
The additive tests/interactive-interrupt-reuse-vm.sh [source-image] repeats
nine independently gated cycles on development and release images. Every cycle
requires fresh real-cat output before its single Ctrl+C, then CONTROL130, a
new prompt, AFTERINT and another new prompt. The same absolute 120-second
deadline, 15-second stall bound and ten-second command budgets apply throughout;
there is no retry of a failed interrupt. This is sustained-use coverage, while
launchd's host regression proves exact job-row reuse regardless of deployment
capacity. A cancelled inherited-stream caller must not terminate the parent
TTY. Exsh must consume completion through its already-held status route before
dropping the handles; delivery on a control-only signal route cannot consume
another holder's separate status observation or bypass authority cleanup.
tests/powerbox-prompt-vm.sh [source-image] [physical|serial] checks automatic
trusted attention on each canonical image. No Ctrl+Alt+Delete is injected.
The host decodes exact amber ASCII glyphs using the checksum-verified packaged
PF2 font, then requires a fresh complete prompt with the exact program,
scope-relative object selector, operation, lifetime, and Enter instructions.
Physical y alone must leave the prompt pending; one Enter approves the first
request. A second request is denied with n followed by Enter. Both selectors,
tmp/promptallow and tmp/promptdeny, use writable /tmp on dev and release.
A third complete review for /bin/ls tmp explicitly requests directory
enumeration for this invocation and needs its own y followed by Enter.
Only then does readback verify that the approved object exists and the denied
object does not,
then a separately entered echo proves prompt input did not spill into exsh.
An independent bounded serial audit rejects fresh command-not-found diagnostics
or standalone echoed y/n lines, even when a later echo succeeds; its matching
context survives read splits and discarded command-evidence buffers. Expected
authority-denial diagnostics remain permitted.
The optional COM1 probe requires the same fresh complete framebuffer review
and its entire byte-identical CRLF-normalized serial mirror, then a bounded
200-ms unchanged-review observation before one serial choice. It sends no
physical keys. Separate serial and physical selection state prevents mixed
transport confirmation. Accepted serial decisions drain their input batch and
queued CRLF before ordinary shell input resumes. The private seriald modal
writer excludes ordinary output and bypasses retained public logs; it adds no
capabilities. Raw serial still requires a safe operator terminal emulator and
does not provide the framebuffer's reserved-color display guarantee.
CI checks approval, denial, explicit enumeration, and no answer spill on both
transports and image profiles; matching-image evidence remains separate from
host fixture results.
Every stage is bounded by ten seconds inside the 120-second VM deadline.
Source disk and firmware are privately copied and removed after the run;
raw serial/QMP diagnostics, hashes, and fresh PPM screenshots remain under
out/powerbox-prompt, including on failure. Each run uses only its selected
physical or COM1 transport for commands and consent.
Cells without trusted amber are background, including untouched firmware
artwork; any amber cell must still match an exact black/amber PF2 glyph.
Missing field text, mixed colors, and damaged amber glyphs fail closed.
tests/native-directory-vm.sh physical|serial [source-image] covers the
reported directory command failures on separate shell lines. It requires
nonempty ls bin output, real ls -la metadata, and both enumeration and
metadata reviews for ls -la bin; ls tmp is separately denied. Long rows
must contain a real file type, permission bits, link count, numeric ownership,
size, and UTC timestamp or the explicit provider-unknown marker. Status zero
without the required entries is a failure. The same private VM then checks
cd bin, /bin from pwd, relative ./ls, a failed change preserving cwd,
cd .., / from pwd, and a fresh external sentinel. No directory-navigation
authority is manufactured by the host or inferred from a displayed path.
Repeated selector reviews must have an exact job/generation/session/realm/
request identity absent from matching pre-command reviews; changed pixels or
an old matching review alone cannot satisfy the input gate. Physical and
COM1 profiles preserve the existing single-choice, separate-Enter and no-spill
gates. CI covers both transports and canonical images with ten-second command
and 120-second VM bounds. Private disks/firmware are removed; raw diagnostics,
identity hashes, and screenshots remain under out/native-directory.
Loaderd now transfers authenticated executable and dependency bytes in 32-KiB
chunks directly into their final caller-provided storage. Its authentication
pass reuses one bounded scratch buffer, eliminating the former per-chunk payload
copy and reducing VFS round trips without caching mutable authority or changing
ELF, manifest, relocation, or launch admission. Relocations travel to procd in
bounded batches; procd coalesces adjacent writes and allocates up to 64 pages
per frame extent while preserving page permissions and exact cleanup. VFS
overlay cursors terminate after the last synthetic mount entry. The native
ls VM gate requires directory output, status zero, and at most ten seconds
for four external commands after input injection, measured separately from boot.
Both input probes retain their shells and stop only their private host QEMU
after exact result evidence, avoiding a race with guest teardown. QMP cleanup
has a separate one-second bound and preserves the original command failure.
Kernel address-space switching batches up to 64 tracked page mappings,
including early-service anonymous shadow aliases. Dependent aliases and
duplicate targets split into ordered groups; each group flushes before the
next translation, lock release, or interrupt restoration. Global entries
retain explicit invalidation. Mapping rights,
ownership checks, and the current BSP-only userspace dispatch remain unchanged.
IPC range/copy walks use operation-local index hints to avoid repeated full
mapping scans. Every use rechecks the live page identity, rights, and ownership;
no pointer, backing, or permission is cached between operations.
The new kernel-mapping-batch-isolation-positive VM scenario exercises real
physical and anonymous translation replacement, ordered alias dependencies,
flag preservation, restoration, and scratch cleanup
through a feature-gated early kernel probe; normal images omit that probe.
The separate kernel-mapping-batch-sparse-positive scenario requires a new
sparse-group marker followed by the complete mapping-suite marker. It checks
real gapped targets and exact backing dependencies, unselected holes, mixed
permissions and complete private scratch restoration. Host policy tests ensure
the probe remains early-kernel-only and bounded; matching-kernel VM validation
is recorded separately from the model tests.
Generated freestanding memcpy, memset, and memmove use exact-range
eight-byte integer operations followed by byte tails. They need no SIMD state
or optional CPU extension and never change the direction flag. Backward
overlapping moves preserve source bytes; comparison still returns the first
unsigned-byte difference. Native assembly tests cover unaligned buffers,
overlap, zero length, read-only sources, and inaccessible guard pages. This
reduces a measured secondary copy/fill cost; it is not a substitute for the
address-space switching improvements or fresh VM timing evidence.
The separate tests/dev-image-startup-vm.sh gate measures the earliest
services as well as the disk-resident shell and native tools. Its host-only
observer records complete READY lines with monotonic timestamps, rejects
stale/replaced/truncated logs, and preserves partial evidence on VM failure.
Each event also records its earliest possible arrival from the previous read's
start; unread buffered chunks retain that original bound until drained.
Observation windows exceeding 100 ms fail, even when accumulated records would
otherwise have identical timestamps. Acceptance intervals conservatively use
the later event's observed time minus the earlier event's earliest bound;
raw point timestamps remain available for analysis. VM completion drains the
bounded log to EOF before declaring a missing result.
READY gaps include loading, scheduling, service initialization, publication,
and display delivery; they are not pure loader times. No guest clock or
additional logging capability is introduced. Private-copy runs preserve the
canonical image and use run-private firmware variables. JSON, serial, input,
observer, and QEMU stderr logs remain under out/startup-performance/check.*.
The wrapper accepts at most one optional source-image path; omitting it keeps
the canonical development-image default. It requires readable regular image
and existing identity-sidecar files before starting any observer or VM, preserves
the selected sidecar, and verifies the selected source hash after private-copy
execution. No additional identity schema or image-feature policy is inferred.
The command injector allows up to ten seconds to retain completed slow-run
evidence; the separate performance assertion still rejects any command
sequence exceeding two seconds. The VM's 120/15-second hard/silence bounds
remain unchanged.
While supervising the initial shell, rootd's shared READ_JOB adapter clears
and advertises only 112 bytes: the canonical 72-byte reply plus a bounded
40-byte reserve for auditing unexpected receipts. Delivered capabilities
are retired before typed status parsing. The poll/yield cadence and session
lifetime are unchanged; this optimization does not introduce a timeout or
change the accepted-call completion contract.
New launchd-owned job/script/accounting/stream and ttyd-owned session endpoints record their exact retained receive alias before exporting any sender. One zero-capacity, nonblocking RECV must report empty RETRY; failure follows the existing publication rollback. Delegated foreign receivers are excluded. The kernel preserves this live-validated auxiliary receiver preference when additional callers queue behind an outstanding call, under the same bounded handoff budget. Neither path creates a pending receive buffer or new authority.
This stricter startup target requires all canonical service READY records in order: root launch to final READY within five seconds, each canonical service READY gap within one second, final READY to shell prompt within one second, and the four external commands within two seconds from the start of final Enter emission, including its QMP acknowledgement. Baseline measurements before the new optimization were 14.0, 1.88, 2.38, and 6.60 seconds respectively. The independent 120-second hard and 15-second silence watchdogs still apply. Run the timing gate without concurrent builds or VMs; register-sampling profiles are separate diagnostics, not acceptance timings.
The isolated 186c7c1 comparison records root launch to final READY at
3.324/3.291 seconds, the largest service gap at 0.808/0.806 seconds, the first
shell prompt after another 1.390/1.393 seconds, and four commands at
3.861/3.884 seconds. Evidence is retained in
out/startup-performance/check.kA39Vl and check.UfhWJj. Both runs still fail
the shell and command targets; completed boot barriers are not proof that
native-command latency is acceptable. Repeated whole-address-space mapping
work during ordinary runnable-service tours remains a measured bottleneck.
The mandatory CI performance step remains pending rather than being enabled
with a known-failing result or relaxed limits.
The subsequent isolated continuation retains three completed strict-gate failures across two immutable images. Conservative observation bounds, not point timestamps, give the following seconds; every run meets the first two limits and misses the latter two. The recorder's successful evidence status does not imply performance acceptance; all three wrappers exit 1.
| Image / evidence | Boot (5 s) | Gap (1 s) | Caret (1 s) | Commands (2 s) |
|---|---|---|---|---|
776e3407 / check.Ijhmow |
3.331945 | 0.860476 | 1.236359 | 2.455439 |
7f57bb8b / check.dq8Jql |
3.186823 | 0.847521 | 1.266006 | 3.118697 |
7f57bb8b / check.oypESc |
3.227462 | 0.845896 | 1.213853 | 3.239898 |
These are 0 PASS / 3 FAIL measurements, not four failed thresholds per run. RTC-provider READY to ttyd READY is the largest service interval in each. The same full-caret oracle and Enter-before-ACK, unrounded command timing apply to both images. The mixed results do not establish an overall speedup. Exact source hashes and complete evidence remain in each run directory; the strict 5/1/1/2-second gate remains open without changing the 120/15/10-second bounds.
The final loader-bounds checkpoint is
ad6da25e2ffb1aad8539cee2330867f4d10c982a, source epoch 1788893085.
Loaderd b26f906d includes 75e32c0b's fixed 32-byte dynlink status/commit
replies and active-prefix-only peer framing, plus reuse of the same verified
immutable root's digest at handoff. Every first full live hash, fresh selected
object check, pinned root identity, request/variable-plan capacity, receipt
cleanup and terminal erasure remains required. No digest cache crosses a
launch. Both 90-test matrices and strict component gates pass. The rejected
local-PDE bitmap experiment is absent: fair host benchmarks regressed common
restore-heavy cases roughly 36–40% for only about 6% shuffled-alias improvement.
Kernel b54082bd and the existing hardware scenarios remain unchanged.
The adjacent isolated strict comparison retains these conservative seconds:
| Image / evidence | Boot (5 s) | Gap (1 s) | Caret (1 s) | Commands (2 s) |
|---|---|---|---|---|
7f57bb8b / check.UKNhOl |
3.105823 | 0.817050 | 1.164035 | 3.239686 |
ad6da25e / check.2RwvLL |
3.074977 | 0.793675 | 1.138679 | 3.038390 |
ad6da25e / check.r7CgVn |
3.130488 | 0.820912 | 1.173104 | 3.079151 |
Each wrapper exits 1: first two thresholds pass and the latter two fail. This is 0 PASS / 3 FAIL in the latest comparison, including two failed new-image measurements, or 0 PASS / 6 FAIL across both continuation batches. New command intervals are about 6.2% and 5.0% below the adjacent control, but boot and prompt values straddle it. This limited paired sample neither isolates the two loader changes nor establishes overall startup improvement.
Matching utility functionality does pass: development serial .YYG3LA in
53.095723 seconds and release physical .2ftR8b in 59.918327 seconds both
exit 0 with all sixteen commands and twenty trusted reviews. Original
120/15/10 bounds, fresh review identities, exact output/status/caret checks,
separate source/create/write approvals, denied-effect readbacks, truncation
and final shell reuse all pass. No other VM, compiler or manual overlapped
the sequential runs. Historical contended utility durations are not isolated
comparison baselines. Exact images under out/appliance/ are:
erix-startup-bounds-dev.img, SHA-256:354c6db83572b66874fb2699e736cfe6b334f8bb215f85af9a7529f4232f8703.erix-startup-bounds-release.img, SHA-256:08d8394079edadaa7f8e6bd6c0ce397fc81407cdd6ff8d31bf23b4408469736e.
The latest utility pair is 2 PASS / 0 FAIL; the strict startup gate stays OPEN.
Raw, sidecar and compressed identities, signed boot/closure contents and all
72 component revisions verify. Sources and six protected earlier images are
unchanged. Evidence is retained in out/startup-performance/ and the named
out/native-utility/ directories. Later documentation publication does not
relabel the tested runtime revision or replace retained failures.
The separate rust job in ci.yml runs formatting, strict Clippy, default and
all-feature unit tests, a bare-metal build, and warning-denied rustdoc for the
in-guest crate without coupling those fast gates to the complete VM job.
Direct image PIC and global-assembly compilers, plus the Cargo fallback,
explicitly deny warnings: RUSTFLAGS alone does not cover direct rustc.
A host regression compiles actual warning and clean-object fixtures to check
that this policy rejects diagnostics without rejecting valid artifacts.
Build-gated rootd images consume that crate as
erix-rootd-integration-orchestration.so. The checked rootd dependency record
includes the object explicitly, so the prebuilt registry, early executable
manifest, and final image closure all fail before packaging if the library is
missing or stale. Integration images select the complete effect adapter;
canonical release packaging selects only rootd's product post-readiness hook
and the authority-free interactive transaction. The product adapter admits no
scenario verifier effect or Integration evidence marker and retires its one
launch source after the shell.
Late service-readiness evidence is inherent in this authenticated Integration
policy boundary. It has no independent Cargo feature or false-valued production
selector. The library extends lib-bootstrap's closed product seriald/fbcond
marker and disposition contract rather than duplicating either lifecycle rule.
Framebuffer probe-square behavior likewise adds no rootd Cargo selector; its
authenticated scenario profile and explicit fbcond/kernel fixtures fully
define the evidence path.
Readiness-only input and multi-provider storage now use separate signed
BootConfig profiles instead of crate or rootd features. Their numeric values
remain descriptive and grant no input or storage authority.
The multiline interrupt fixture likewise uses the existing signed interrupt
profile: only the kernel selftest remains build-selected, while rootd runs its
normal profile-owned endpoint-authority verifier. COM1 admission additionally
requires the exact authenticated deviced-driver/drv-serial BootConfig node;
the signed profile name alone cannot select the serial row.
The interrupt policy exposes process launch and terminal observation as
distinct effects. It passes the exact returned process identity into the wait
effect and rejects a substituted terminal identity before emitting readiness;
neither descriptive value grants process authority.
Dynamic bootstrap-helper and extension policy use the same split. Their
authority-free plans supply only request identity, semantic role, launch flags,
and expected terminal result; rootd retains the module graph, procd endpoint,
staging authority, cleanup, child-endpoint mapping, and exact lifecycle
transport.
The initial-shell catalog contains 45 focused scenarios. Its cumulative POSIX
workloads are partitioned into independently bounded mixed-list rejection,
second-command lookup, pipeline state, EXIT action, caught-signal, wait
isolation, and exit-teardown transcripts. Each split transcript retains zero
session operations and an empty script-authority table. The manifests require
both tty and rootd evidence but order markers only within their originating
stream, because ttyd may drain accepted output after rootd observes process
exit. All scenarios retain the repository-wide 45-second no-progress and
120-second absolute QEMU limits.
After MountRoot retires Rootd's final direct kernel process-control source,
the five-helper completion proof consumes only those exact lifecycle
transcripts. It never requests a global kernel-resource snapshot or causes the
retired source to be retained or reacquired. Resource-count comparison remains
limited to pre-procd negative tests, where the required source is still owned.
The component manifest pins signed rootd revision 1092330 for that runtime
effect implementation, its required evidence transport through Rootd's
retained send-only logd route, and exact 1,000-lifecycle execution in 250
bounded batches of at most four process/generation selectors. Rootd
authenticates the complete signed helper dependency graph once and receives no
per-helper capability authority. Procd invokes the kernel's closed
map/relocate/seal graph operation before each start. Rootd reports one fixed
progress marker after
each drained batch and completion only after all exact observations.
The manifest also pins signed lib-ipc revision 0dd36b4 and procd revision
1f105a0. Their Integration-only launch/observe contract returns only bounded
process identities. Procd deletes the broad staging grant immediately after
deriving the exact powerbox grant and deletes that narrow grant before start;
it retains only the local process endpoint through successful start and drops
that final alias before replying. Queued-event reclamation obligations remain
bound to exact process generations. A queued event for an earlier occupant of
a reused kernel PID therefore cannot destroy an unstarted helper or exhaust the
bounded process arena during those lifecycle batches.
Transport failure, malformed or mismatched success, and every standard
non-success procd result select distinct fixed retained-logd evidence; the
diagnostic carries no process identity or capability authority.
Rootd's unconsumed per-role launch debug catalog is deleted rather than moved:
the checked inventory now accepts only terminal and production-warning
evidence that still has a consumer.
The same rule removes direct module, staging, envelope, capability-transfer,
and provider-metadata traces; the cleanup-negative logd-start marker remains.
Rootd's procd startup-call and foundation-update adapters now receive only the
endpoint authority required by their typed IPC transaction. Their 60
unconsumed status, envelope, capability, transfer, and failure markers are
deleted instead of being moved into the library; exact result and response
validation remains product-owned and fail-closed.
Named seeding, sealing, activation, and dynamic staging retain the same exact
typed validation and production warnings, but their fifteen unconsumed debug
markers and telemetry-only capability queries are deleted rather than moved.
Serial verification and seriald writes no longer receive kernel-log authority;
their twelve unconsumed debug markers and production-dead value formatter are
removed while typed peer, response, retry, and final-ready semantics remain.
Kernel-root handoff parsing likewise receives only the immutable handoff bytes;
thirteen unconsumed parse-detail markers are removed while all structural
validation and phase-level terminal reporting remain product-owned.
Runtime PCI discovery likewise receives only its exact probed endpoint. Six
unconsumed transport, result, and counter markers and the kernel-log endpoint
argument are removed while its fixed request identity, typed retry, yield, and
terminal-result validation remain product-owned.
Pre-procd graph construction, mapping, relocation, and sealing likewise receive
no logging endpoint. Eleven unconsumed detail/failure markers are removed; the
library-selected role-completion proof remains a separate best-effort transport
after mapping succeeds, and every kernel mutation remains product-owned.
Dynamic-extension and kernel-staging adapters also omit twenty-one unconsumed
stage/drop/start/wait/result and mapping-detail markers. The shared exact
process-completion wait receives only the procd endpoint and expected identities,
not a logging endpoint; consumed procd-map and cleanup-fault evidence remains.
Framebuffer verification emits each consumed event once through the reviewed
debug transport; the obsolete smoke-only forwarding wrapper and its duplicate
privileged write are absent without changing marker selection or order.
Startup-boundary evidence now crosses the same authority-free boundary as a
typed request-ID/marker value. The library owns peer, primary-control, explicit
endpoint, and pager-retirement evidence selection; rootd retains capability
transfer, mandatory pager source retirement, absence proof, and the explicit
best-effort log transport.
The library also owns the exact release-image admission policy for
Integration-only evidence strings. Rootd passes only the borrowed message to
that pure predicate and retains the logd or kernel-log endpoint and the entire
transport effect; near-matches and product messages fail closed.
The library also owns the complete dynamic/procd negative-spawn transcript:
profile and role selection, exact request fields, unsupported-map acceptance,
resource-count equality, cleanup order, and evidence markers. Rootd supplies
only explicit slot values and mechanical kernel/procd effects. Cleanup invokes
one exact procd abort effect and three independent per-slot exact-retirement
effects, retaining the first cleanup error while attempting every revocation.
The trait cannot expose DROP separately from same-slot absence proof. Any
failure after staged creation is cleaned up before the typed runner returns.
The abort adapter already yields after its acknowledged procd reply, so the
authority-free policy requests no second scheduler yield after cleanup.
Evidence transport is best effort and cannot turn a proven cleanup into a
runtime failure; the host marker contract still fails closed if evidence is
missing.
Signed Integration revision 69d08a5 defines this closed effect surface, and
rootd revision 33f299d supplies its exact-disposition implementation. The
component manifest now pins descendant rootd revision 249d860, which retains
the phase-transition and service-effect closures introduced at 62f8f55,
delegates timed's private RTC receive route, reconciles a state-matched exit
that wins the procd STOP race, and records the current compiler-qualified
source budget exactly. Its production
boundary check emits and scans one unique object for the current invocation, so
cached compiler objects can neither contaminate nor satisfy that evidence.
It also selects the exact dynlinkd self-bootstrap-denial, dynamic-start, and
dynamic-ready request/marker tuples for the focused profile. Rootd retains
manifest parsing and unconditional rejection and only transports the selected
evidence through explicit logging routes.
The post-map success marker is selected there too; rootd retains graph mapping,
success acceptance, failure diagnostics, and the explicit kernel-log effect.
The same authority-free evidence module owns all four cumulative procd-spawn
service-group START/READY plans: exact role membership, first-role selection,
request identifiers, marker strings, completion order, and the descriptive
dynlinkd-versus-runtime logging route choice. Rootd iterates the returned rows
and performs only the named logging effect.
The follow-on checkpoint module owns the ordered core lookup/time,
hardware/console, and storage/VFS/loader success rows and their request IDs.
For storage it accepts one descriptive proof that rootd retired its
bootstrap-only blockd client plus six downstream service-presence booleans. It
refuses residual blockd authority separately from any missing downstream
service; no slot number, endpoint, handle, or capability enters the library.
The module-requirement policy likewise accepts only closed module-presence and
BootConfig-role bitsets. It owns every scenario-specific required-module set,
the legacy role-to-profile priority, and exhaustive omission checks. Rootd
retains authenticated module descriptors and product boot-artifact validation;
the library cannot observe an address, mapping, descriptor, slot, or
capability.
Scenario-profile selection is now exclusively descriptive input from the
authenticated BootConfig validation profile. The orchestration crate has no
per-profile Cargo features and exposes no build-selected profile fallback;
host-only callers use the explicit runtime profile. Loader filesystem
discovery, materialized-launch isolation, and cleanup-authority confinement use
distinct signed values 27, 28, and 29; their policy selectors carry no
endpoint, process, or loader authority.
The same library now maps every profile to a fixed-capacity ordered final
execution plan. Each row carries the complete helper or extension contract,
bounded stress/concurrency range, or exact dynlink/interrupt verifier profile;
profiles whose proof completed earlier receive an empty plan. The plan contains
no endpoint or capability, so the rootd adapter can iterate explicit effects
without retaining a profile match or reconstructing request ranges.
The rootd fixture builder likewise enables one rootd-integration-policy
boundary for runtime test images. Initial-shell and physical-input selection
are dependency features of the authority-free orchestration library;
physical-input implies initial-exsh. Rootd therefore needs no matching
scenario Cargo gates and reads only the library's compile-selected booleans
inside its Integration-only adapter. Changing ROOTD_TEST_MODE alone cannot
change rootd's Cargo feature set.
scripts/check-rootd-integration-surface.py enforces the migration boundary.
Its checked inventory classifies every rootd scenario feature, profile/type,
verifier or fixture function, marker string, and scenario-gated source site as
move, production-validation, or delete. The helper suite proves that a
new unclassified verifier fails the check. Inventory changes therefore require
an explicit audit instead of silently expanding rootd's integration surface.
Pinned rootd 2603439 retains six temporary RTC, storage-layout, and VFS-mount
diagnostic selectors and their six rootd probe sites, while admitting their
source and calls only for the exact Integration probe features. The refreshed
inventory classifies the six call sites, sixteen gated definitions, their
shared source gate, the six selectors, and the product adapter's fixture-named
false hook as delete; the Integration adapter's private-driver selector and
its focused test and the library's explicit full-runtime-transition selector
are move. The authority-free scenario-completion stage mapper and its focused
mapping test are also move: both consume only library-selected success
evidence and are called exclusively by the Integration adapter. The seven
feature-gated fully-backed pre-procd stack-policy sites are likewise move:
rootd still owns every frame, mapping, pager-registration, and retirement
effect, while the gated choices carry no authority. The exact current ledger
is therefore 52 items: twelve move, ten production-validation, and thirty
delete. These diagnostic branches
select only an exit observation and receive no endpoint, object, or capability;
classification restores fail-closed CI coverage without accepting them as
permanent product surface.
The complete runtime-transition selector additionally requires an actual
KERNEL_ROOTD_TEST=runtime image, ext4 runtime storage, and the authenticated
Runtime validation profile. Every other profile retains its verification-only
or loader-pair transition even when compiled into the same image; legacy smoke
and profile fixtures cannot acquire the complete runtime suffix from a media
name. Host and library tests prove both sides of this boundary.
This descendant also consumes the Integration-owned pre-memd negative-spawn
schedule, so named and deviced snapshots precede Foundation process-source
retirement without adding a new classified rootd surface.
The pinned rootd now also owns exact-capacity, move-only lifecycle ledgers for
foundation, core, and hardware children. Those product cleanup dispositions,
authenticated kernel/procd teardown effects, and source-retirement funnels do
not cross into the authority-free orchestration library. The exhaustive check
therefore contains exactly 268 items: 255 move, 13 production-validation, and
zero delete. The pinned cleanup path uses confirmed STOP terminal evidence
directly and validates an exact terminal QUERY only after a lost STOP reply
before consuming WAIT. It retries only empty typed transient WAIT replies with
the same process/generation selector and independently proves
endpoint-slot absence after every DROP attempt. Integration receives neither
observation nor authority from that reconciliation; focused rootd unit tests
remain its exact proof. A raw pre-acceptance NOT_FOUND on STOP, QUERY, or WAIT
permits one additional identical call only after rootd proves that the selected
local slot still contains exactly its canonical SEND|GRANT generic procd
endpoint. Missing, weaker, substituted, or stronger authority and a repeated
absence remain terminal. A
later partial startup-transfer failure now aborts the staged child, then drops
and proves absence of every local install grant,
endpoint source, service endpoint, and published source. A source already
retired at its final successful transfer is accepted only after the same proof;
an uncertain proof cannot skip the remaining cleanup. The pinned rootd path
also reconciles a lost procd START reply through one exact query validator
shared by boot-module and ext4 launches. Only authenticated STAGED state
selects abort and only authenticated RUNNING state continues startup;
substituted or terminal evidence fail-stops. Started ext4 cleanup independently
proves its optional published source absent after the drop attempt. Foundation,
core, and hardware also follow every fixed phase-boundary source DROP with an
exact local-slot absence query; lost replies are accepted only after proof, and
one uncertain proof cannot skip later sources. RetireAuthority applies the same
proof contract to named-resolution sources, authenticated service sources,
ordinary root clients, and the private RTC routes. The attenuated query alias
remains live until every queryable client is resolved and is then retired
directly through the synchronous local-capability syscall. Rootd passes 308/308
default and all-feature tests with a reviewed 15,849-line, 4,616-byte production
baseline. This product lifecycle logic and every authority-bearing route remain
outside the Integration library; the exhaustive surface remains 298/286/12/0.
MountRoot's namespace and loader-materialization source cleanup now uses the
same exact contract through a transition-local injected boundary. Its focused
tests prove that exact absence resolves a lost DROP reply and that proof
failure cannot skip a later source. Rootd passes 310/310 test matrices with a
reviewed 15,859-line, 4,616-byte baseline; the Integration surface remains
unchanged.
The nested one-shot RTC completion path now retires only the exact role-derived
local service endpoint and requires absence proof after DROP. A lost reply is
accepted only after that proof, while a substituted slot is rejected before an
effect. After semantic kernel-report authority has retired, successful RTC
completion is observed through rootd's already retained send-only logd route as
ERIX_ROOTD:READY:RTC_PROVIDER; no kernel host-report route is reacquired.
That marker is emitted only when the signed ext4 runtime suffix contains the
private RTC provider. Boot-image-only authority-retirement profiles omit the
entire ext4-only suffix, including the RTC provider, ttyd, powerboxd, and
launchd, and therefore prove their declared cleanup sequence without inventing
filesystem-runtime completion evidence. Disk-image scenarios retain coverage
of the complete suffix.
Rootd passes 311/311 test matrices with a reviewed 15,882-line, 4,616-byte
baseline; the Integration surface remains unchanged.
The StartRuntime failure funnel now has one deterministic exact-order proof over
plain cleanup dispositions. Pending leases abort in reverse order, followed by
started-service cleanup, authenticated-source retirement, and private-RTC
retirement; an earlier failure cannot skip a later family and the first cleanup
error remains authoritative. Rootd passes 312/312 test matrices with a reviewed
15,903-line, 4,616-byte baseline. No endpoint, process, source, or cleanup
observation enters Integration, so the surface remains 298/286/12/0.
RetireAuthority now exposes the full terminal sequence through a rootd-local
descriptive injection seam: five pre-report source families, terminal status
emission, and final root-client retirement. Cleanup continues after failures
and retains the first error. Exit separately proves that report failure cannot
skip host-report endpoint retirement. Rootd passes 314/314 test matrices with
a reviewed 15,938-line, 4,616-byte baseline. No authority or cleanup
observation enters Integration, so the surface remains 298/286/12/0.
The pinned terminal follow-up requires each kernel-control reply to agree across
syscall status, message-header result, typed response result, and operation.
Final host-report responses also require zero value fields. Rootd passes
315/315 test matrices with a reviewed 15,966-line, 4,616-byte baseline. The
next pinned test-only proof drives an actually malformed handoff through every
terminal retirement family and Exit, and passes a rejected delegated-driver
receipt directly into reverse prior-child and phase-source cleanup with
first-error precedence. Rootd passes 316/316 test matrices; the production
baseline and Integration surface remain 15,966/4,616/8 and 298/286/12/0.
The signed selector follow-up removes rootd's last two scenario Cargo features
and maps every initial-shell and physical-input fixture directly to the
authority-free dependency features. The exact inventory drops those two
features and six obsolete cfg sites, then adds six mechanical policy-boundary
sites for a reviewed 290/278/12/0 surface. Rootd remains at 316/316 tests with a
15,968-line, 4,616-byte, eight-unsafe-block production baseline.
The next dynamic-catalog slice moves all eleven Integration-only executable
names, the helper/core/interrupt role family, and pre-procd launch selection;
fourteen obsolete cfg surfaces disappear for an exact 276/264/12/0 ledger.
Rootd's production measures and 316/316 test matrices remain unchanged.
The timed-verifier adapter is then isolated behind one crate-level Integration
gate instead of five item gates interleaved with production named publication.
The exact inventory falls to 272/260/12/0, while rootd's production surface
falls to 15,918 lines and excludes both timed response decoder types.
The VFS verifier transport is subsequently isolated behind one crate-level
gate. Twelve item gates become one include gate for an exact 261/249/12/0
surface. Rootd production retains only path encoding and signed-mount
transport, measures 15,691 lines, and excludes seven verifier-only VFS response
types without changing its binary or authority inventory.
The pinned deviced final-use follow-up exhaustively retires and proves absent
all four child-only public endpoint sources after their final transfers. A
lost DROP reply cannot leave an ambiguous source, and one failed proof cannot
skip the other independent sources. The checked Integration surface remains
261/249/12/0; rootd measures 15,703 production lines with the same 4,616-byte
binary, eight unsafe blocks, and authority inventory.
The downstream-consumer follow-up gives all seven retained deviced sources an
immediate exact absence proof after final transfer and exhaustively disposes
sources for absent optional consumers after registry sealing. The Integration
surface remains 261/249/12/0; rootd measures 15,742 production lines with the
same binary, unsafe count, and authority inventory.
The root device-control follow-up retires the canonical one-slot
SLOT_IRQ_CONTROL catalog after deviced startup with DROP plus exact absence
proof. Integration remains 261/249/12/0; rootd measures 15,754 production lines
with unchanged binary, unsafe count, and authority inventory.
The pager fault-delivery follow-up uses the same shared disposition after its
final pagerd transfer, so a lost DROP reply cannot skip exact absence proof.
This removes a bespoke validator and classifies its injected product-validation
seam explicitly, producing a 262/249/13/0 surface without changing rootd
production measures.
The dynamic staging follow-up centralizes the install-grant, endpoint-source,
and service-endpoint scratch disposition across kernel and procd paths before
creation and during staged-failure cleanup. Exact proof and continued cleanup
remain product-owned; the 262/249/13/0 surface is unchanged while rootd
measures 15,784 production lines.
The loaderd filesystem-staging follow-up gives the root-local install-grant and
staged-process endpoint receipts one exhaustive DROP/query disposition after
installation and during preparation cleanup. No receipt authority enters the
orchestration library; the surface remains 262/249/13/0 while rootd measures
15,802 production lines.
The legacy procd-spawn negative fixture now applies exact DROP/query disposition
to its three staging slots both before process creation and after staged abort.
The library owns only the fixed order and first-error rule; its effect API names
one exact retirement per slot and cannot split DROP from proof. Rootd retains
every slot, capability operation, process identity, and absence query. The
checked surface remains 262/249/13/0.
The library now owns time, serial, framebuffer, probe, hotplug, ACPI,
driver-lifecycle, normalized-input, input-authority, physical-input, interrupt,
crash-reporting, and logging evidence policy. It also owns the complete generic
initial-exsh transport: launch transcript submission, TTY lifecycle and
multi-PTY independence, staged exec sequencing, reply-authority auditing,
bounded status polling, cleanup, outcome classification, and evidence-marker
selection. Its hardware/console runner selects and orders hotplug, ACPI,
serial, framebuffer, input-authority, and active-input verification, owns their
boundary markers and framebuffer mirror requirement, and returns an ordered
descriptive readiness result. Rootd supplies only explicit syscall, IPC,
logging, and readiness-transport effects. The time verifier owns its
deterministic host-only synthetic evidence source and validates exact request
and operation correlation. That source is one descriptive counter with no
endpoint, clock, timer, or capability; only the freestanding rootd adapter
performs timed IPC. The probe verifier also owns its stateless host PCI scan
and known-device evidence and rejects mismatched response request, operation,
device, and policy identities before accepting it; only the freestanding rootd
adapter performs probed or deviced IPC. The driver-lifecycle verifier similarly
owns a two-state host model, rejects invalid transitions, and validates every
start/read/stop correlation field without owning a process or endpoint.
The serial-console verifier likewise owns a two-transition host model and
rejects reordered readiness, peer-query, request, or payload evidence. That
model performs no endpoint lookup or write; only the freestanding rootd adapter
uses seriald authority, and its ordinary host path fails closed.
Hardware effect methods require every
endpoint, request identifier, bounded event count,
and device selector explicitly, including the private ACPI endpoint returned by
deviced. Rootd's
adapter performs only the requested typed call and emits the library-owned
diagnostic event; neither descriptive device identities nor diagnostics confer
authority.
Signed BootConfig generation keeps selected hardware services in one canonical
ordered block: drv-acpi, drv-serial, seriald, fbcond, drv-i8042,
drv-ps2-kbd, drv-ps2-mouse, inputd, drv-virtio-block, then blockd.
Provider drivers precede their consumers, consumer dependencies name the
selected providers explicitly, and Integration-only driver fixtures cannot
enter the phase graph. Generation rejects duplicate, reordered, omitted, or
interrupted hardware blocks instead of emitting a compatibility topology.
Every accepted validation profile consumes an explicit runtime config and
emits the same signed native-CLI substrate: an ext root mount whose authority
does not exceed the attached medium, the canonical storage sequence,
dynlinkd then loaderd, and the ext4 suffix of optional drv-rtc-cmos
followed by mandatory ttyd, powerboxd, and launchd. Default and other
read-only-media profiles sign every block-backed mount read-only; writable
fixture profiles must select qemu_block_readonly=false. The profile changes
verifier policy only. Mode-only generation, a FAT root, missing hardware, or
omitted suffix policy fails before image construction.
Focused configs may select the explicit standard-v1 service policy instead
of duplicating its fixed bounded values; unknown or implicit selection fails.
Rootd fixture commands enable Integration policy through direct checked
rootd_integration_orchestration/<feature> dependency features; scenario-only
forwarding aliases are not part of rootd's product feature table.
Input effects likewise name each deviced, inputd, seriald, fbcond, ttyd, logd,
and returned driver endpoint. The library owns normalized producer-identity and
console-projection decisions, diagnostic-route denial, physical counter
baselines, and exact trusted-control deltas; the rootd adapter retains no input
producer capability and performs only those explicit observations.
Interrupt effects receive only the explicit procd and logd endpoints. The
library owns the exact client request, role, child-local endpoint slot, accepted
terminal status, and profile-specific marker; the rootd adapter can neither
discover an endpoint nor retain child authority.
Crash effects likewise receive explicit procd, crashd, and optional logd
endpoints. The library owns the fault-client contract, child-local endpoint
slot, terminal reason,
cursor/correlation checks, cooperative retry, and dynamic marker. Launch and
exact terminal wait are distinct effects; the returned process identity is
passed into wait and checked again before crashd scanning. Rootd returns only
descriptive observations after retiring its child endpoint.
The same closed catalog selects request identifiers, semantic roles, flags,
child-local endpoint slots, and expected results for every bootstrap helper and
lookup/time extension. Request-ID override constructors change correlation only;
all other launch fields remain immutable orchestration policy.
One shared bounded transcript now owns pure graph preparation followed by exact
staging-slot retirement, one procd create, dependency-before-executable map
steps, one relocation and seal per reported item, map evidence, install-grant
retirement, start, optional probe start, and endpoint-source retirement. The
effect adapter retains every graph cursor, module byte, endpoint, capability,
and process-control route; returned counts and receipts are descriptive only.
Its thematic cleanup policy issues one STOP at a time with a 1,024-reply bound,
then validates exact QUERY and WAIT receipts before requesting endpoint drop
and absence proof. Failed starts are first queried and select only exact staged
abort or the same running cleanup; transport, identity, state, or revocation
uncertainty invokes an explicit rootd fail-stop effect.
Logging effects name separate authenticated submit and query routes, and both
the kernel-log and submit routes for the optional dynamic marker. The library
owns append content, required roles, response validity, cursor and timestamp
monotonicity, stress sequencing, and marker selection; the adapter retains no endpoint.
Trusted-terminal policy is one immutable plan covering secondary-session
creation, status-route independence, session-control retirement, the exact
trusted-delivery delta, and the completion marker. Rootd retains only the
typed session-lifecycle adapter. Signed BootConfig driver discovery remains a
production rootd validation invariant and is deliberately excluded from the
scenario library.
Block-storage selector translation remains production logic, while media
validation does not. Rootd now admits only typed namespace enumeration,
matches the signed ESP and data selectors, rejects malformed, duplicate, or
aliased partition identities, and drops plus proves absence of its blockd
client before mounting. Raw block reads, MBR and filesystem signatures,
journal geometry, sentinel policy, and 28 storage diagnostics are gone.
Blockd and the authenticated filesystem providers own those semantics. The
library receives only the authority-free multiple-whole-disk observation and
validates it against the signed scenario profile; rootd's product selector no
longer receives a scenario expectation.
The same signed profile selects one total final-verifier timing in the
authority-free library. Module-backed proofs run before boot-module retirement,
the storage-services proof runs only after runtime startup, and the
hardware/console proof is recorded as already complete. Rootd retains all
module and runtime authority and performs only the selected execution step.
Pinned rootd revision 52dec12 consumes that typed result and removes its
unreachable local deferral predicate. The storage-services proof now runs after
runtime startup with its complete stage sequence, while the checked rootd
surface contracts to 261/248/13/0 without moving authority into this crate.
Pinned rootd revision fb2fd48 then deletes the separate constant-false
framebuffer-deferral and runtime-serial-only readiness branches, their unused
stage buffer, and duplicate assertions. Pre-logd evidence remains uniquely
queued and direct framebuffer fallback writes only terminal READY. The reviewed
production surface falls to 15,802 lines without changing the 4,616-byte image
or any authority measure; the Integration ledger remains 261/248/13/0.
Pinned rootd revision 1729fba then routes both sides of MountRoot through the
same readiness dispatcher. A descriptive phase bit preserves the former trace
and failure-fixture distinctions while the duplicate post-mount context and
transport implementation disappear. Production falls to 15,737 active lines,
and deleting three superseded cfg adapters reduces the checked ledger to
258/245/13/0 without changing authority.
Pinned rootd revision 5cec30f deletes the permanently disabled eager
framebuffer-cursor scan and capture path. Deferred verification continues from
cursor zero in this crate, while rootd retains only the live framebuffer effect
adapter. The reviewed rootd surface falls to 15,724 active lines and removal of
four stale cfg surfaces reduces the ledger to 254/241/13/0; image and authority
measures remain unchanged.
Pinned rootd revision 6ff326c consumes the library-owned readiness
disposition through a mechanical adapter and retains only the closed
seriald/fbcond product policy plus all stateful transport effects. The reviewed
production surface falls to 15,578 lines, and replacing six older cfg surfaces
with five exact boundaries reduces the ledger to 253/240/13/0. The 4,616-byte
image, eight unsafe blocks, and authority inventory are unchanged.
Pinned rootd revision 3f9cfcf also deletes its obsolete test-only
driver-readiness catalog. Integration scenario manifests remain the
authoritative positive and negative marker contracts. The cleanup removes 296
rootd Rust source lines, including one otherwise empty production include, so
the reviewed production baseline is 15,577 lines; the 253/240/13/0 ledger,
4,616-byte image, eight unsafe blocks, runtime behavior, and authority are
unchanged.
The orchestration library owns the exact observable ERIX_ROOTD:TRACE:VFS:*
strings emitted by its VFS verifier plans. Rootd receives those strings as
authority-free data and performs only the explicit kernel-log effect; it no
longer rewrites an Integration-only debug namespace into the observable trace
namespace.
Pinned rootd revision 554b471 deletes the unconsumed pre-mount
READY_APPEND_CURRENT_* trace branches and that namespace rewrite. The
reviewed production baseline falls from 15,577 to 15,500 Rust lines while the
release image remains 4,616 bytes and the unsafe count remains eight. Replacing
two deleted trace-adapter rows with four exact mechanical cfg boundaries makes
the checked ledger 255/242/13/0; authority and runtime behavior are unchanged.
The library also classifies its exact TRACE, READYTRACE, and DBG
diagnostic namespaces from borrowed text only. Rootd retains the enable flags
and every kernel-log/logd effect; no endpoint, capability, or buffer crosses
the classification boundary.
Pinned rootd revision 3adb9b3 consumes that classification mechanically and
removes the broad diagnostic-prefix parsers from production. The reviewed
baseline falls from 15,500 to 15,479 Rust lines while the 4,616-byte image,
eight unsafe blocks, runtime behavior, and authority remain unchanged. Three
exact mechanical cfg boundaries replace two stale marker-prefix rows, yielding
the checked 256/243/13/0 ledger.
Canonical named-publication names are product capability policy, not scenario
policy. Lib-capabi now binds names to its closed pagerd/timed/irqd target set,
so this library deletes its wider eight-role duplicate catalog. Signed rootd
revision bd57279 consumes that mapping while retaining explicit named seed,
response-validation, sealing, and endpoint effects. Its reviewed production
baseline falls from 15,479 to 15,441 Rust lines; the image and unsafe count stay
unchanged. Removing three obsolete scenario-policy cfg rows yields the checked
253/240/13/0 ledger.
Signed rootd revision 7aed97d next removes validation-profile control over
named seeding/activation and deviced registry seeding. Those product paths now
follow only signed BootConfig publication flags, canonical target scopes, and
driver-policy rows. Its reviewed baseline falls from 15,441 to 15,435 lines;
three stale cfg rows leave the checked ledger at 250/237/13/0 while image,
unsafe, runtime, and authority measures remain unchanged.
Probe verification can consume an already product-triggered, exactly
correlated discovery response. The library then performs only its explicit
read-last-scan and per-device evidence effects; it neither repeats discovery
nor receives the probed endpoint used by rootd for the product trigger.
The complete IRQD fixture plan is selected here as descriptive admission,
request-correlation, timer, and optional serial data. Rootd supplies only the
descriptive fact that its authenticated BootConfig contains the exact
deviced-driver/drv-serial node; this library combines that fact with the IRQ
profile gate. Rootd retains the IRQD endpoint and performs each exact seed,
seal, and unmask IPC with fail-closed reply validation. Signed rootd revision
2ad27f2 introduces this binding and keeps the 4,616-byte product image, eight
unsafe blocks, and every authority inventory unchanged.
Signed rootd revision d930064 now performs that product trigger solely from
signed delegated-driver rows in every runtime validation profile and forwards
only the correlated descriptive receipt. Exchanging two obsolete profile
selectors for two mechanical forwarding sites keeps the checked ledger at
250/237/13/0 and leaves rootd's 15,435-line production baseline, 4,616-byte
image, unsafe count, runtime authority, and syscall set unchanged.
Signed rootd revision 3c5c0eb consumes the library-owned complete IRQ row
slice for both seeding and unmasking, deleting its serial-profile selector and
duplicate optional-row branches. The checked ledger falls to 249/236/13/0 and
the reviewed source surface to 15,413 lines; the 4,616-byte image, eight unsafe
blocks, authority, and syscall inventories remain unchanged.
Signed Integration revisions 04f4219 and c972697 complete that plan with
fixture admission and checked per-row request correlations. Signed rootd
revision a7d0eb7 removes all three local IRQ fixture request constants and
consumes only the typed plan. The exact ledger falls to 246/233/13/0 and the
reviewed surface to 15,412 lines; rootd passes 316 default and 315 all-feature
tests while the orchestration crate remains at 248 and 249.
Signed Integration revision 2f9c639 next owns the exact descriptive full and
legacy StartFoundation retirement slices. Signed rootd revision aec42c2
consumes the selected slice mechanically while retaining every capability
DROP, absence proof, and failure disposition. Exchanging two obsolete local
policy sites for three mechanical cfg sites yields an exact 247/234/13/0
ledger; rootd's reviewed surface is 15,411 lines, its image remains 4,616 bytes,
and the orchestration crate passes 249 default and 250 all-feature tests.
Signed Integration revision 64b8ecf then constructs every exact loader
discover/launch request and intentionally malformed discovery body. Signed
rootd revision b00d3e3 consumes those values mechanically and deletes its
three request builders plus duplicate tests. Rootd's loader adapter files total
249 lines, down by 110 source lines; it passes 313 default and 312 all-feature
tests, while the orchestration crate passes 250 and 251. The exact ledger stays
247/234/13/0 and all production measures remain unchanged.
Signed rootd revision 211247b next deletes the unconsumed target-only hardware
debug, numeric, and lifecycle-marker mirrors. Probe, hotplug, ACPI, and driver
adapters no longer receive a kernel-log endpoint; every authenticated service
effect and evidence check remains intact. Rootd removes 102 Rust lines and
passes 313 default and 312 all-feature tests. Replacing four obsolete transport
cfg rows with two mechanical enable-state rows reconciles the ledger to
245/232/13/0; every production measure remains unchanged.
Signed Integration revision a5508d9 then owns the total final-execution
action plan for every profile, including complete helper/extension contracts,
bounded stress and lookup ranges, dynamic-bootstrap helper order, and exact
dynlink/crash/interrupt profiles. Signed rootd revision 8ada277 replaces its
complete per-profile match with a mechanical explicit-effect dispatcher and
admits only the planned storage action after module retirement. Rootd removes
41 Rust lines and passes 313 default and 312 all-feature tests; the
orchestration crate passes 253 and 254. The exact ledger is 246/233/13/0 and
the 15,411-line, 4,616-byte, eight-unsafe production baseline is unchanged.
Host-only service launch ordering is likewise authority-free policy. The
orchestration crate owns a total profile-to-order mapping whose rows contain
only signed service roles and rootd report-stage codes. Its bounded 4--23-row
plans preserve foundation order, console adjacency, and storage/dynlink tails;
rootd must still validate and execute every row through its own BootConfig and
service authority.
Signed Integration revision 558aba1 and signed rootd revision de54855
complete that split. Rootd deletes 811 net Rust lines, passes 313 default and
312 all-feature tests, and leaves its 15,411-line, 4,616-byte, eight-unsafe
production baseline unchanged. The orchestration crate passes 256 and 257
tests, and the reconciled surface ledger remains 246/233/13/0.
Signed Integration revision e850a65 then makes the legacy
DynlinkPreProcd exception explicit in the authority-free Foundation plan as
one optional process-source number beside the immediately retired slots.
Signed rootd revision e9e1d1a accepts only the canonical process-control
slot, carries it through move-only Core, Hardware, and MountRoot authority
states, and drops and proves it absent immediately after the final direct
storage launch and before named resolution or runtime staging. Every earlier
phase failure independently attempts the same retirement; a lost DROP reply is
accepted only after exact absence proof, while failed proof preserves the
state for retry and prevents the success transition. Rootd passes 318 default
and 317 all-feature tests at a reviewed 15,402 production lines, 4,616 bytes,
and eight unsafe blocks. Classifying the 22 newly explicit adapters produces
the exact 268/255/13/0 ledger; the orchestration crate remains at 256 and 257
tests.
Signed lib-capabi revision d41f0c9 next completes the shared final-use
catalog at 30 source-to-final-consumer entries, including the four
deviced-final and seven later deviced-consumer sources, without granting
transfer authority. Signed rootd revision e95326b consumes the catalog only
after exact route validation and installation, retains its local DROP and
absence-proof effects, and uses the same rows for absent optional consumers,
including blockd. Rootd passes 317/316 tests and its production baseline falls
to 15,280 lines while the 4,616-byte image, eight unsafe blocks, and all other
measured inventories remain unchanged. No cfg site changes, so the audited
Integration ledger remains exactly 268/255/13/0.
Signed rootd revision c93b402 then admits all 21 wholly Integration-only
effect-adapter files through one guarded integration_adapters.rs include.
This replaces 20 scattered crate-level cfg sites and excludes
scenario_policy.rs from release compiler inputs without moving any endpoint
or capability effect out of rootd. The checked surface contracts to
248/235/13/0, and the release baseline falls one non-effectful include line to
15,279. Rootd retains 317/316 tests, a 4,616-byte image, eight unsafe blocks,
and unchanged dependency, syscall, decoder, stage, and authority inventories.
Signed rootd follow-up f6785f3 folds eight nested hardware, console,
dynamic-launch, monitoring, negative-spawn, and VFS-marker adapter includes into
that same boundary. All 29 wholly Integration-only adapter files now have one
admission point, the exact checked surface contracts again to 240/227/13/0,
and the reviewed release baseline falls to 15,269 lines. Rootd retains the same
317/316 tests, image size, unsafe count, and authority measures.
Signed rootd follow-up 2d26e5c moves integration_policy.rs behind the same
gate as the thirtieth wholly Integration-only adapter file. Only its
compile-time initial-shell source-retention result remains in the common mode
adapter; production fixes it to false and retires the launchd source
immediately. The exact surface contracts to 238/225/13/0 and the reviewed
release baseline falls to 15,268 lines without changing any authority measure.
Signed rootd follow-up b19b348 adds the thirty-first wholly
Integration-only adapter by consolidating the legacy retained process-control
exception's Foundation, Core, Hardware, failed-phase, and MountRoot effect
implementations. The adapter is absent from production compiler inputs, and
production retains no exception state or authority. Eight superseded cfg rows
leave the exact surface at 230/217/13/0 while the 15,268-line baseline and every
authority measure remain unchanged.
Signed lib-bootstrap revision b1dbeaf then becomes the sole product owner
of the exact 29-role signed boot-store executable-name mapping. Signed rootd
revision a6e531c consumes it after the Integration-only extension overlay and
rejects post-mount and unassigned extension roles. This changes no cfg surface,
so the exact ledger remains 230/217/13/0; removing rootd's duplicate table
lowers its reviewed baseline to 15,237 lines while its 4,616-byte image and all
authority measures remain unchanged.
Signed lib-bootstrap revision 5da8002 next becomes the sole owner of six
disjoint ordered Phase 5 service catalogs covering exactly 33 bootstrap roles.
Signed rootd revision d92d41b aliases its Foundation, Core, Hardware,
MountRoot storage, and StartRuntime ext4 arrays to that shared contract while
retaining every sequencing and authority effect. The exact surface remains
230/217/13/0; rootd's reviewed baseline falls to 15,203 lines without changing
its image or authority inventories.
Signed rootd revision f6fb701 next centralizes every rootd-owned asynchronous
DROP-plus-local-absence disposition in one generic primitive. Exhaustive unit
coverage binds all 30 shared final-use rows to their declared consumer, admits
a lost DROP reply only after exact proof, rejects uncertain proof, and confirms
non-final consumers do not select retirement. The private RTC path removes one
redundant query; the 230/217/13/0 surface, production baseline, image, and
authority inventories remain unchanged.
Signed lib-bootstrap revision c5256a2 next binds all 22 Foundation, Core,
and Hardware roles to their canonical readiness report and rootd-versus-deviced
launch kind. Signed rootd revision c158bb7 consumes those rows while retaining
every signed dependency/subsequence check and authenticated effect. The exact
surface is 228/215/13/0; rootd's reviewed baseline falls to 15,170 lines
while its 4,616-byte image, eight unsafe blocks, and authority inventories stay
unchanged.
Signed lib-bootstrap revision 81917f9 completes that contract with the five
MountRoot and six StartRuntime rows and one exact row matcher. Signed rootd
revision 59558ea consumes all 33 role/readiness/launch-owner rows, proving the
direct storage sequence, adjacent direct dynlinkd/loaderd pair, and selected
filesystem suffix before effects. The exact surface remains 228/215/13/0;
rootd passes 321/320 tests at a reviewed 15,176 lines and unchanged 4,616-byte,
eight-unsafe-block, and authority measures.
Signed lib-bootstrap revisions 2b4824a and a1011d6 then own exact product
seriald/fbcond marker selection, borrowed-text membership, and readiness
disposition. This library reuses that type, deletes its lifecycle duplication,
and proves every product mode and endpoint combination remains exact; signed
rootd revisions bf722de and 43ada27 delete the local record, field-copy
adapter, product matrix, marker match, release-filter literals, and four cfg
sites while retaining every effect. The surface falls to 222/211/11/0 and
rootd's reviewed baseline to 15,147 lines; image, unsafe, and authority measures
remain unchanged.
Signed rootd revision 3c22778 then centralizes Integration-smoke selection in
one mode helper. Product builds receive a compile-time false result, while
Integration builds read the authenticated scenario fact. Entry, logging, and
readiness modules remove three positive/complement cfg pairs. The surface falls
to 218/207/11/0 and rootd's reviewed baseline to 15,141 lines; all other
measures remain fixed.
Signed rootd revision b51c0d4 next moves the hardware-console runtime-mode
and framebuffer-cursor state, readiness observation, and verifier invocation
into one typed context inside the existing Integration-only adapter boundary.
Release-active bootstrap and hardware-phase code retain only one opaque guarded
crossing, and product compilation admits no context type or Integration effect.
The exact surface contracts to 215/204/11/0 while rootd's 15,141-line,
4,616-byte, eight-unsafe-block, and authority baselines remain fixed.
Signed rootd revision a9fbd8f next consolidates build-specific bootstrap
policy behind two complementary compile boundaries. Integration mode facts,
module/profile projection, endpoint requirements, and terminal override live
in the existing Integration adapter; product Foundation, Core, and Hardware
retirement implementations live in one product adapter. Semantic phases call
uniform methods without scattered positive/complement branches. The exact
surface contracts to 197/186/11/0 and rootd's reviewed baseline to 15,139
lines; its 4,616-byte image, eight unsafe blocks, and authority measures remain
fixed.
Signed rootd revision 8aa37ab next removes Integration-only module-name
parsing from the common handoff path. Its build-gated adapter owns the ten exact
fixture names, two aliases, type/required-flag checks, duplicate rejection, and
descriptor-free presence projection. Product rootd recognizes none of that
catalog and stores no fixture state; the release-object gate rejects seven
distinctive literals. The exhaustive surface contracts to 196/185/11/0 and the
reviewed rootd baseline falls to 15,097 lines with binary and authority
measures fixed.
Signed rootd revision 00c8d04 then places the remaining product mode
identity, constants, module and endpoint validation, and host launch selection
inside the product adapter, while the complementary aliases and launch order
remain inside the Integration adapter. Common handoff, required-module, and
type modules contain no Integration feature branch, the obsolete mode.rs is
deleted, and the product presence value is zero-sized. The source regression
gate rejects restoration. Thirteen stale cfg rows disappear, contracting the
exhaustive surface to 183/172/11/0 and the reviewed rootd baseline to 15,095
lines without changing runtime effects or authority.
Signed rootd revision c903739 next moves validation-profile decoding, host
profile encoding, target terminal override selection, and the last
Integration-only pre-module failure code behind the same adapters. Product
accepts only the signed runtime profile and its terminal hook is a no-op;
Integration owns its closed profile and override mappings. The four newly
cleaned common modules are source-gated, and six stale cfg rows disappear,
contracting the exhaustive surface to 177/166/11/0 and the reviewed rootd
baseline to 15,082 lines without changing runtime effects or authority.
Signed rootd revision 9e628bf then moves release-message admission, boot-log
suppression, stage-marker lookup, ready-stamp disposition, and final-route
choice behind the same complementary adapters. Endpoint-bearing logging and
ready-stamp transports remain explicit in rootd but choose no product-versus-
scenario policy. The source gate preserves that boundary. Eight stale cfg rows
disappear, contracting the exhaustive surface to 169/158/11/0 and the reviewed
rootd baseline to 15,061 lines without changing runtime effects or authority.
Signed rootd revision a80ac51 next moves the remaining Integration live-marker,
routed-evidence, marker-flag, and debug/trace logging effects into a dedicated
103-line adapter. Every endpoint and request identifier remains explicit; the
shared request-ID hash used by product terminal status carries no build branch.
Common logging is now Integration feature-free and source-gated. Eight stale
cfg rows disappear, contracting the exhaustive surface to 161/150/11/0 and the
compiler-qualified rootd baseline to 15,006 lines without changing runtime
effects or authority.
Signed rootd revision db4fef8 then moves console reads, discovery-history
reads, ACPI/hotplug discovery, and driver lifecycle effects into the existing
explicit Integration adapters. Product console writes, canonical probe
discovery, and device reads remain with their semantic owners. Four common
transport files are Integration feature-free and source-gated, and every moved
effect retains explicit endpoint and request identity. Ten stale cfg rows
disappear, contracting the exhaustive surface to 151/140/11/0, the
compiler-qualified rootd baseline to 14,736 lines, and accepted external typed
messages from 39 to 29 without changing runtime effects or authority.
Signed rootd revision f54da1a removes the redundant nested Integration feature
gates from initial-shell, physical-input, and loader-verification adapters that
are already admitted only by integration_adapters.rs. Target/host selection,
explicit endpoint inputs, and fail-closed host behavior remain unchanged. Eight
stale cfg rows disappear, contracting the exhaustive surface to 143/132/11/0;
the 14,736-line product baseline, 29 accepted typed messages, image size, and
all authority and runtime-effect measures remain fixed.
Signed rootd revision fab1395 next moves IRQ fixture seed, seal, and mask
effects into a dedicated 203-line Integration adapter behind the same boundary.
The 183-line common hardware-seed module retains only product named/deviced
registry behavior and is feature-free and source-gated. Explicit IRQD endpoints,
request correlations, reply checks, and seed/seal/unmask order stay fixed. Nine
stale cfg rows disappear, yielding 134/123/11/0, a 14,577-line product baseline,
and 26 rather than 29 accepted typed messages; image, runtime-effect, and
authority measures remain fixed.
Signed rootd revision ead5b85 then isolates Integration-specific
process-completion retry, terminal-state, and host-fixture policy in a 70-line
adapter. The 156-line common procd host module remains feature-free and retains
the shared WAIT transport required by product cleanup and explicit dynamic
effects. Endpoint/request correlation, yielding, and failure behavior remain
unchanged. Two stale cfg rows disappear, yielding 132/121/11/0 and a
14,517-line product baseline while accepted messages and all other measures stay
fixed.
Signed rootd revision b26e576 then moves the target-only hexadecimal formatter
and kernel boot-log effect used by VFS evidence into the 148-line Integration
logging adapter. Product capability operations remain in the 737-line
feature-free common kernel-control IPC module. The explicit endpoint, prefix
checks, rendering, and best-effort disposition stay fixed. One stale cfg row
disappears, yielding 131/120/11/0 and a 14,478-line product baseline while
accepted messages and all other measures remain fixed.
Signed rootd revision cb78a72 next moves forced service-start failure
selection into the Integration adapter's authority-free postcheck. The common
procd transport remains responsible for its explicit endpoint, authenticated
request, correlated reply, role/status validation, and host fixture behavior,
and is now feature-free and source-gated. One stale cfg row disappears, yielding
130/119/11/0; the explicit product postcheck raises the reviewed baseline to
14,481 lines while the 4,616-byte image, 26 accepted messages, eight unsafe
blocks, runtime effects, and authority remain fixed.
Signed rootd revision 2d27e87 then moves post-start cleanup evidence into the
155-line Integration logging adapter. The 986-line feature-free, source-gated
common cleanup module retains process kill, terminal wait, destruction,
endpoint retirement, and fail-stop cleanup. Product builds compile a
capability-free no-op disposition; Integration builds preserve the explicit
kernel-log endpoint, marker, and best-effort behavior. One stale cfg row
disappears, yielding 129/118/11/0 and a 14,480-line product baseline while the
image, accepted messages, unsafe blocks, runtime effects, and authority remain
fixed.
Signed rootd revision 398987b next replaces three common conditional retained
process-source fields with a build-selected phase state. Product state is
zero-sized; only rootd's Integration adapter owns and disposes the retained
pre-procd process source, and no endpoint or capability enters this library.
Foundation and core token definitions are feature-free and source-gated; the
hardware token loses this authority branch while retaining unrelated scenario
validation. Three stale cfg rows disappear, yielding 126/115/11/0 and a
14,481-line product source baseline while the 4,616-byte image, 26 accepted
messages, eight unsafe blocks, ten dependencies, five syscalls, runtime effects,
and authority inventory remain fixed.
Signed rootd revision 7c07380 then routes the retained process source's final
MountRoot use, failure cleanup, and success proof through rootd-local
build-selected adapters. Its launchd-source disposition moves into the
Integration-only StartRuntime adapter; product state is zero-sized, and no
capability, source token, retirement effect, or authority enters this library.
The common MountRoot phase is feature-free and source-gated. Five audited cfg
rows disappear, yielding 121/110/11/0 and a 14,500-line product source baseline
while the 4,616-byte image and every other runtime and authority measure remain
fixed.
Pinned rootd revision 673564e carries that source with the prepared
dynlinkd/loaderd pair only for the signed DynlinkPreProcd fixture. Its
verification transition aborts the pair before exact retirement, while
runtime-starting transitions reject and clean up unexpected retention. Runtime
authority cannot contain the source, and no capability enters this library.
Signed rootd revision 221b80a then replaces ValidateHandoff's conditional CPU
count and intake-marker branch with build-selected rootd policy state. Product
state is zero-sized and capability-free; only rootd's Integration adapter
retains the descriptive count required by its multicore scenario and emits the
conditional marker through the explicit kernel-log route. The common validation
phase remains structurally authoritative but is feature-free and source-gated;
no state, endpoint, or effect enters this library. Four audited cfg rows
disappear, yielding 117/106/11/0 and a 14,515-line product source baseline while
the 4,616-byte image and every other runtime and authority measure remain fixed.
Signed rootd revision b9dd2bd then replaces StartHardware's conditional
context, construction, readiness observation, and verifier call with one
build-selected policy state. Product state is zero-sized and capability-free;
only rootd's Integration adapter retains the framebuffer evidence cursor,
performs hardware-console verification through explicit service routes, and
borrows the live pre-retirement hardware authority token. The common hardware
phase is feature-free and source-gated; no state, endpoint, token, or effect
enters this library. Six audited cfg rows disappear, yielding 111/100/11/0 and
a 14,550-line product source baseline while the 4,616-byte image and every other
runtime and authority measure remain fixed.
Signed rootd revision d6616fd then replaces MountRoot block-storage
completion's conditional mode parameter and provider-evidence branches with one
build-selected policy state. Product state is zero-sized and capability-free;
only rootd's Integration adapter retains the signed scenario profile and
validates the descriptive multiple-whole-disk observation. Device endpoints,
namespace selection, blockd-source retirement, filesystem mounting, and all
authority effects remain in rootd; no endpoint, device identity, or authority
enters this library. The common storage module is feature-free and source-gated.
Four audited cfg rows disappear, yielding 107/96/11/0 and a 14,566-line product
source baseline while the 4,616-byte image and every other runtime and authority
measure remain fixed.
Signed rootd revisions b4fac9f and cbd2ec2 then replace BootConfig post-node
finalization's conditional scenario state and IRQ fixture branch with one
build-selected policy state. Product state is zero-sized and capability-free;
only rootd's Integration adapter retains the signed scenario profile and
selects this library's authority-free IRQ fixture plan. The IRQD endpoint,
ordered seed/seal/unmask effects, request correlation, reply validation, and
failure mapping remain in rootd; no endpoint or authority enters this library.
The common finalizer is feature-free and source-gated. Two audited cfg rows
disappear, yielding 105/94/11/0 and a 14,581-line product source baseline while
the 4,616-byte image and every other runtime and authority measure remain fixed.
The pinned rootd now routes startup-cap installation and direct-launch
observations through one build-selected policy state. Product state is
zero-sized and endpoint-free; only the Integration adapter retains explicit
kernel-log and logd slots, consumes this library's authority-free route and
evidence selections, rejects substituted routes before delegation, and emits
startup-peer, logd-begin, pager-drop, and control-route evidence. Capability
installation, retirement, exact absence proof, and cleanup remain in rootd.
Seventeen audited cfg rows disappear, yielding 88/77/11/0 and a 14,579-line
product source baseline while the 4,616-byte image and every other runtime and
authority measure remain fixed.
Signed rootd revision 6c96849 next replaces signed-BootConfig VFS smoke
execution's two conditional common branches with a build-selected compile
adapter. Product expansion evaluates and retains no endpoint arguments. Only
rootd's Integration adapter selects this library's authority-free storage or
memory plan and invokes explicit rootd-local VFS and logging effects;
filesystem mounting, the live VFS endpoint, and readiness emission remain in
rootd. Common vfs_bootcfg.rs is Integration feature-free and source-gated.
The two stale cfg rows disappear, yielding 86/75/11/0 and a reviewed 14,581-line
product source baseline. The 4,616-byte image and every other runtime and
authority measure remain fixed.
Signed rootd revision 738afec next moves pre-procd target naming, legacy
kernel-launch selection, readiness and role evidence, deliberate cleanup-fault
hooks, and probe-start transport behind the build-selected adapter boundary.
Product expansion admits only signed product executable names and the procd
kernel path; its evidence and fault macros do not evaluate or retain endpoint
arguments. Only rootd's Integration adapter consumes this library's
authority-free selections, while dynamic mapping, cleanup, endpoint effects,
and capability retirement remain rootd-local. Common dynlink_pre_procd.rs
and launch_runtime.rs are Integration feature-free and source-gated. Eleven
stale cfg rows disappear, yielding 75/64/11/0 and a reviewed 14,524-line
product source baseline. The 4,616-byte image and every other runtime and
authority measure remain fixed.
Signed rootd revision ab91a71 then moves dynlinkd denial, negative-spawn, map,
START, READY, log-routing, and singleton-marker evidence behind a dedicated
build-selected adapter. Product macros do not evaluate endpoint arguments;
only the Integration adapter consumes this library's descriptive evidence and
invokes explicit rootd log effects. Common dynlink_support.rs is Integration
feature-free, and common dynlink_procd_spawn.rs has no orchestration-library
reference or evidence transport. Its four remaining classified sites are
granular probe and relocation effects. Nineteen stale cfg rows disappear,
yielding 56/45/11/0 and a reviewed 14,476-line product baseline. The 4,616-byte
image and every other runtime and authority measure remain fixed.
Signed rootd revision 36dc133 next moves the last four per-step fixture
helpers into its 769-line Integration-only dynamic-launch effect adapter: lazy
probe-page derivation, relocation counting, one exact relocation call, and one
exact object-seal call. Authority-bearing effects still require the explicit
procd endpoint and correlated request/process/generation identity; this library
receives only descriptive observations. Common dynlink_procd_spawn.rs is
Integration feature-free and source-gated while retaining the product
whole-graph path. Four stale cfg rows disappear, yielding 52/41/11/0 and a
reviewed 14,358-line product baseline. The 4,616-byte image and every other
runtime and authority measure remain fixed.
Dynamic cleanup now carries that same exact process/generation identity into
its terminal-wait effect. This prevents a root-visible event for another
process from being consumed during reconciliation without giving the
authority-free policy library an endpoint or capability.
Signed rootd revision d3500f6 then moves startup peer-fault selection and
undeclared-peer injection into its Integration-only startup-capability adapter.
Common startup-transfer and authenticated route-plan code retains explicit
transfer-table effects behind build-selected macros; product expansion neither
evaluates fixture inputs nor constructs undeclared transfers. Both common files
are feature-free and source-gated. Twenty stale cfg rows disappear, yielding
32/21/11/0 and a reviewed 14,352-line product baseline. The 4,616-byte image and
every other runtime and authority measure remain fixed.
Signed rootd revision 7785d28 next moves whole-bootstrap readiness routing,
pre/post-runtime verification, scenario timing, initial-shell/loader
verification, and final debug-authority retirement into a 320-line
Integration-only adapter. The 506-line common bootstrap.rs is feature-free,
library-free, and source-gated; its build-selected product state is zero-sized
and performs no scenario effects. Explicit endpoint and capability effects
remain invocation-scoped in rootd. Seventeen stale cfg rows disappear, yielding
15/4/11/0. The explicit product compile interfaces add 98 reviewed active lines
for a 14,450-line baseline; the 4,616-byte image and every other runtime and
authority measure remain fixed.
Signed Integration revision 1d1895a now owns the exhaustive final-execution
action dispatcher and the deferred storage-only admission rule. Signed rootd
revision fbf3514 implements the library effect trait with a 585-line,
invocation-scoped adapter carrying only the explicit module view, service
endpoints, kernel-log route, and concrete launch, wait, checkpoint, and verifier
effects. No capability enters the library. Removing the stale dispatcher row
yields 14/3/11/0; because rootd's execution.rs was already Integration-only,
the 14,450-line product baseline, 4,616-byte image, and every authority measure
remain fixed.
The final audit confirms that the only remaining feature and two cfg sites are
the intentional product-exclusion boundary: rootd-integration-policy links
this library and selects rootd's Integration effect adapters only in explicit
Integration builds, while product rootd selects its complementary authority
adapter and has no orchestration dependency. Signed rootd revision 64d6912
records that invariant. Reclassification yields an exact 14/0/14/0 ledger with
no remaining migration row and changes no product measure.
Pinned rootd revision 117b6d6 closes its product kernel-control operation
selector. Five unreferenced operations are rejected and resource snapshots are
admitted only through the build-selected Integration adapter. The semantic
baseline now checks exactly 42 release-active protocol operation identifiers;
the rootd Integration surface remains 14/0/14/0.
Pinned rootd revision bc85135 binds that compiler-derived inventory to 14
closed semantic groups. Every release operation has exactly one authenticated
transport owner, semantic owner, bounded rootd sequencing role, and retirement
postcondition. Assigned service routes remain distinct from scoped kernel
capability plumbing and dedicated root-only effects; direct kernel process
operations are temporary foundation transport for procd, not permanent
rootd authority. The checker rejects additions, omissions, duplicates, owner
or family drift, rootd ownership, and promotion of the temporary route while
the Integration surface remains 14/0/14/0.
Pinned rootd revision 66cb1c7 additionally records all 72
operation-to-source-file bindings from sanitized release compiler inputs.
Moving an operation into another product module, deleting its last source
site, or adding a new site is reviewed semantic drift even if the 42-operation
inventory remains unchanged. Tests, comments, literals, and Integration-only
adapters cannot satisfy a product source binding; the rootd Integration
surface remains 14/0/14/0.
Pinned rootd revision 62f8f55 upgrades that ownership contract to schema 3.
Seven release-family evidence rows bind process, image, publication, driver,
time, namespace, and terminal policy to their exact targeted groups. Time and
terminal policy remain capability-transfer-only; image work admits only
loaderd preparation plus graph-declared dynlinkd route transfer. Missing,
reassigned, or widened family evidence fails rootd's product audit. Combined
with Integration's exact 14/0/14/0 ledger, rootd retains no functional verifier
or provider-policy row awaiting migration or deletion.
Pinned rootd revision 4d90264 carries the selected process-control transport
from staging through start and rollback and hides its route tag behind an
opaque module boundary. Product chooses temporary kernel control only for
procd; Integration may still select its declared pre-procd fixture roles
behind the build-selected policy. Consumers cannot construct temporary-kernel
transport, inject an unchecked delegated endpoint, re-evaluate mode/role after
staging, or replace the selected procd endpoint during cleanup. Both generic
kernel-control routes reject all ten temporary process operations; only the
private process-transport entry point accepts them, and then only with the
carried temporary route and fixed kernel endpoint. The opaque value is now
move-only: effect boundaries borrow it, while lifecycle states transfer its
sole ownership. Rootd's reviewed source count falls to 14,609 lines; its 42
operations, 72 source bindings, 4,616-byte image, eight unsafe blocks, and the
14/0/14/0 Integration surface remain fixed.
Filesystem launch failure handling follows the same narrow boundary. The
pinned rootd deletes 15 unconsumed launchd phase and loader-rejection warnings,
their stable request-ID hash, and the logging inputs used only for those
messages. Exact loader transport, receipt, response, process,
authority-retirement, and reverse-cleanup validation remain product-owned. The
reviewed production baseline is 16,230 active Rust lines, a 4,616-byte image,
ten normal dependencies, eight unsafe blocks, and five direct syscall
operations.
The final eight specific bootstrap warning families are unconsumed as well.
The pinned rootd removes their formatter, stable request IDs, and warning-only
transport while preserving typed failures, terminal status, mandatory cleanup,
and authority disposition. Its current baseline is 16,051 active lines with
every other recorded measure unchanged.
Forced-terminal fixture selection and precedence now reside in the
authority-free orchestration crate as one closed enum. Signed rootd commit
d3a608b retains a single mechanical success-only status mapping and removes
the two per-feature branches, reducing the reviewed production baseline to
16,045 lines without changing the 4,616-byte image or any authority measure.
The crate also owns the exact logd-start and post-start-cleanup evidence
strings; they contain no endpoint or process identity and grant no authority.
Signed rootd commit e69e330 uses them only from tests or explicit Integration
builds and converges kernel- and procd-managed cleanup on one post-success
effect. The production baseline is 16,039 lines; the image and authority
measures are unchanged.
The authority-free logging policy also owns the dynlink-procd direct-kernel
suppression family used by non-smoke fixture builds; rootd supplies only the
borrowed message after its own runtime/smoke decision. Signed rootd commit
bfea4d3 removes the product prefix table and lowers the reviewed baseline to
16,030 lines without changing the image or authority measures.
The library readiness catalog maps descriptive rootd report-stage codes to the
exact 29 Integration evidence strings. It receives no bootstrap token or log
route; seriald/fbcond lifecycle-control ownership remains in rootd. Signed
rootd commit 1412a01 removes the other 27 product strings and lowers the
reviewed baseline to 16,007 lines without changing the image or authority
measures.
The catalog now also returns the complete authority-free Integration readiness
disposition: whether to emit, retain internally, route through logd, echo on
the early kernel sink before or after append, and treat append failure as
fatal. Its inputs contain only a report-stage code, runtime/release facts, and
endpoint-presence booleans. Rootd remains the sole owner of endpoint slots,
request identifiers, buffers, retries, ordering state, and capability effects.
The same authority-free logging module selects the two post-shell verification
strings from only a build-feature fact and the presence of an authenticated
physical-input baseline. Rootd retains the baseline object, launch-source
retirement, logging endpoint, failure handling, and marker transport. Signed
library commit 2f4fd5d and rootd commit 8d52aad remove both literals from
product source. The exact ledger is now 392 items: 380 move, 12
production-validation, and zero delete; the 16,007-line production baseline is
unchanged because the adapter was already excluded from release builds.
Signed rootd commit f133c47 then converts ten validated fixture descriptors
to the same closed eight-byte presence value before handoff discovery returns.
No scenario mapping address, size, or hash remains in retained rootd state. The
inventory is now 390 items: 378 move, 12 production-validation, and zero delete;
production measurements remain unchanged.
Signed library commits 3e30ba6 and 47ff31d next replace the former
multiple-provider requirement boolean with a closed descriptive evidence type
and authority-free validator. Signed rootd commit 3a8345c performs identical
signed-topology selection for every profile and supplies the observation only
after namespace and partition selection. The ledger remains 390/378/12/0; the
reviewed production baseline falls to 16,002 active lines while the 4,616-byte
image and every authority measure remain unchanged.
Signed orchestration commit db5cdff then moves the deterministic host-only
time evidence source into the library and requires exact request/operation
correlation. Signed rootd commit 1c0268c removes its duplicate synthetic
clock state while retaining the real timed IPC adapter. Three stale cfg rows
leave an exact 387/375/12/0 ledger; rootd falls to 15,976 active lines, while
the 4,616-byte image and all authority measures remain unchanged.
Signed orchestration commit 0dcae00 next owns the deterministic host hotplug
insert/remove model and exact correlation checks. Signed rootd commit 5c30072
removes the atomic host state and duplicate test while preserving the real
freestanding hotplug IPC adapter. Four stale cfg rows leave an exact
383/371/12/0 ledger; rootd falls to 15,873 active lines, while the image and
authority inventory remain unchanged.
Signed orchestration commit e810f16 then owns the fixed host ACPI scan and
device evidence and checks exact request, operation, device, and policy-identity
correlation. Signed rootd commit 06d9e94 removes the duplicate host replies
while preserving the freestanding drv-acpi and deviced IPC adapter. Two stale
cfg rows leave an exact 381/369/12/0 ledger; rootd falls to 15,835 active lines,
while the image and authority inventory remain unchanged.
Signed orchestration commit 6e1d223 next owns the stateless host PCI scan and
known-device evidence plus exact response correlation. Signed rootd commit
a85905f removes successful host probed replies, preserves target typed IPC,
and makes the non-target product stub fail closed. One stale cfg row leaves an
exact 380/368/12/0 ledger; rootd falls to 15,809 active lines, while the image
and authority inventory remain unchanged.
Signed orchestration commit 3a784bf then owns the two-state host driver
lifecycle, invalid-transition rules, and exact start/read/stop correlation.
Signed rootd commit 0eff7b0 removes fabricated host start/stop replies and
makes the deviced lifecycle adapter, hardware observer, and debug transport
target-only. Two stale cfg rows leave an exact 378/366/12/0 ledger; rootd falls
to 15,779 active lines. Signed orchestration commit b2cba27 then owns the
two-transition host serial-console model, and signed rootd commit a20e035
removes its fabricated successful write. The ledger remains 378/366/12/0 and
rootd falls to 15,772 active lines, while the image and authority inventory
remain unchanged.
Signed orchestration commit 078e4fd next owns deterministic host framebuffer
and normalized-input evidence as authority-free descriptive state with exact
request, operation, role, payload, cursor, and marker correlation. Signed rootd
commit ff65920 removes the fabricated framebuffer, serial-mirror, and input
replies while retaining real target IPC and a fail-closed host framebuffer
product path. Exchanging three stale transport rows for two mechanical adapters
leaves an exact 377/365/12/0 ledger; rootd falls to 15,696 active lines, while
the image and authority inventory remain unchanged. The library passes 209
default and 210 all-feature tests; rootd passes 281 tests in each matrix.
Signed orchestration commit 9ac7403 then lowers the top-level hotplug step to
the existing exact discovery and last-event verifier effects. Signed rootd
commit 2e2ab6c removes the coarse verify_hotplug callback and duplicate
runner while retaining one typed IPC per target effect and authority-free host
delegation. Removing that final stale function row produces the exact
376/364/12/0 ledger; the production baseline remains 15,696 lines and 4,616
bytes because the adapter is Integration-only.
Signed orchestration commit d90f65e next lowers the ACPI step to exact
deviced lookup, driver-capability query, discovery, last-scan, and device-read
effects. Signed rootd commit 368562d removes the coarse verify_acpi callback
and duplicate runner; the target performs one typed operation per effect, the
host delegates to the authority-free model, and unconsumed per-operation ACPI
debug observations are absent. Removing the stale function row produces the
exact 375/363/12/0 ledger. Production remains 15,696 lines and 4,616 bytes.
Signed orchestration commit 62f2593 then lowers serial verification to exact
driver-lookup, capability-query, and typed-write effects with explicit deviced
and seriald routes. Signed rootd commit 7267d79 removes the coarse callback,
duplicate runner, and unused IRQ-route guard; it rejects route substitution and
performs one operation per effect. Removing the stale row produces the exact
374/362/12/0 ledger, with production measures unchanged. Integration passes
210 default and 211 all-feature tests; rootd passes 281 in both matrices.
Signed orchestration commit c1d4345 then lowers framebuffer verification to
exact peer-query, status-read, fixed-route write, optional mirror,
retained-stream read, and progress-yield effects with explicit fbcond and logd
routes. Signed rootd commit 27bcc1a removes the coarse callback and duplicate
runner, rejects route substitution, and retains only one existing transport
operation per effect. Removing the stale row produces the exact 373/361/12/0
ledger, with production measures unchanged. Integration passes 211 default and
212 all-feature tests; rootd passes 282 in both matrices.
Signed orchestration commit c65279e then lowers input-authority verification
to exact inputd status, three deviced lookup, denied i8042 diagnostic, and logd
marker effects through a dedicated narrow trait. Signed rootd commit 7e0f9cb
removes the coarse callback and duplicate partition runner, validates fixed
routes, and binds the diagnostic route to the exact lookup result. Removing the
stale row produces the exact 372/360/12/0 ledger, with production measures
unchanged. Integration passes 212 default and 213 all-feature tests; rootd
passes 283 in both matrices.
Signed orchestration commit 69e4f52 then lowers active-input verification to
exact deviced lookup, i8042 injection, progress, inputd status/event, and
serial/fbcond projection effects through another narrow trait. Signed rootd
commit ebd949e removes the coarse callback and duplicate input runner,
validates every fixed route, and reuses only the i8042 route proven by the
authority partition. Removing the stale row produces the exact 371/359/12/0
ledger, with production measures unchanged. Integration passes 213 default and
214 all-feature tests; rootd passes 283 in both matrices.
Signed orchestration commit 1a9b0ce then makes every monotonic and wall effect
receive the descriptive timed route explicitly and rejects an absent route
before any effect. Signed rootd commit 9793c87 replaces the coarse time
wrapper with a stateless exact-effect adapter and removes unrelated kernel-log
and procd preconditions. Exchanging the stale wrapper row for the mechanical
adapter row preserves the exact 371/359/12/0 ledger. The reviewed production
baseline falls to 15,674 active lines while the 4,616-byte image and authority
inventory remain unchanged. Integration passes 214 default and 215 all-feature
tests; rootd passes 284 in both matrices.
Signed orchestration commit 827f3d4 next splits interrupt-client launch from
its exact terminal wait and rejects a substituted returned process identity
before success evidence. Signed rootd commit 561c5e5 implements the two
effects while retaining the existing dynamic launch and wait transports. The
surface ledger remains 371/359/12/0 and production remains 15,674 active lines
and 4,616 bytes. Integration passes 215 default and 216 all-feature tests;
rootd remains at 284 tests in both matrices.
The checked ledger classifies seriald/fbcond readiness, framebuffer context
handoff, and the four terminal failure strings as retained product validation.
They drive product lifecycle or terminal reporting and are not movable fixture
policy merely because scenarios also observe them.
The dynamic catalog additionally owns the eleven Integration-only executable
names, the closed helper/core/interrupt launch family, and the pre-procd
kernel-launch selector. These APIs consume only role numbers, the signed
validation profile, and a product-supplied manifest-recognition boolean; they
receive no module bytes, endpoint, process, or capability authority.
The pinned production rootd also carries its own semantic-bootstrap baseline:
release-active source, unsafe blocks, accepted external typed messages, direct
syscalls, normal dependencies, binary size, and one reviewed authority row for
each bootstrap stage. Integration does not own or weaken that product gate; its
component pin makes image and VM evidence resolve the reviewed rootd surface.
The same pin now carries rootd's checked bootstrap threat model. Its closed
catalog covers malicious boot bytes, malformed replies, forged descriptive
identities, transferred-capability confusion, partial launches, and accidental
Integration inclusion; all release decoders and authority families must remain
classified. Integration may supply build-gated policy to a fixture image, but
it cannot add an exception to the production boundary or its failure rules.
Rootd's target semantic phase contract is pinned with the same rule. Only its
eight reviewed phases may exist; each authority-lineage output is a strict
subset of the preceding input, and all 33 bootstrap service roles have one
start phase. Integration orchestration remains outside that service catalog,
so a fixture cannot insert exsh, coreutils, extop, or another ordinary program
into production rootd's phase graph.
The pinned schema-2 contract binds every phase to a real repository-local Rust
unit test through twelve checked anchors. Its evidence classes are exactly
malformed handoff, rejected delegate, lost reply, partial capability transfer,
child-start failure, and cleanup failure; missing coverage, invented classes,
path escape, and stale test names fail the product audit. Integration supplies
no exception to the strict authority contraction or empty Exit result.
The pinned StartFoundation implementation now consumes a non-copy authority
token while starting exactly procd, memd, vspaced, and pagerd. Once pagerd is
ready, rootd attempts every inherited RAM-allocation and root-object authority
drop plus the consumed memd, vspaced, and pagerd primary-control endpoint
source drop and the production process-control source drop before entering the
residual bootstrap. Post-start managed cleanup retains the exact staged
generation and uses only rootd's authenticated procd route; numeric process
identities remain descriptive. Query effects receive both identity scalars and
never a PID alone, preventing a recycled process number from redirecting test
cleanup or loader visibility checks. The authority-free orchestration library
owns
the one descriptive legacy exception as an exact seven-slot retirement slice
plus the sole retained process-source number. Rootd receives no capability
object and must represent that retention in its consuming phase state, perform
its final DROP, and prove exact absence itself. A lost STOP reply is accepted
only after an
exact role/process/generation/terminal QUERY, which must validate before the
matching event is consumed. A lost endpoint DROP reply still requires an exact
absence proof. Partial startup-transfer cleanup applies that same proof to every
local staged-launch slot after abort, without passing those slots or outcomes
to Integration. The legacy Integration-only DynlinkPreProcd fixture is the
only plan that retains direct process control, while the runtime profile is
test-locked against that exception. The next typed transition requires the
exact selected core prefix named -> logd -> crashd -> timed -> irqd -> deviced -> probed -> hotplugd; Integration profiles may select only a leading prefix,
and driver fixtures follow the complete selected core set. Rootd derives a
send-only query client, then exhaustively retires its inherited time, IRQ,
hotplug, platform-discovery, and transferable query sources after StartCore.
StartHardware then consumes only the ten canonical hardware roles and retires
their inherited discovery and device sources. MountRoot executes the signed
mount, pre-stages owned dynlinkd and loaderd leases, and invokes the root-only
one-shot operation that unmaps every recorded boot blob. StartRuntime starts
those leases and the exact ext4 suffix while retiring each final-use endpoint
source before START. The terminal transition runs exhaustive root-client
cleanup, attempts one final typed status report, retires the report endpoint,
and invokes process_exit instead of entering a receive loop. Kernel process
exit then retires rootd's recorded receiver and clears its complete CSpace.
Reverse procd cleanup and terminal fail-stop rules remain product invariants;
Integration supplies no bypass or alternate mount path.
If startup-envelope construction fails after a process is staged, rootd aborts
that exact staged generation and independently retires its install grant,
endpoint source, and service endpoint. An abort failure cannot skip another
capability drop; rootd unit tests preserve this fail-closed property without
making those capabilities observable to Integration.
The focused
subsystem-rootd-foundation-authority-retirement-positive scenario requires
pagerd readiness followed in order by residual service readiness, probe
completion, and final readiness. It also forbids both the retired deviced-timed
and discarded best-effort foundation debug names. This proves that moving the
drop point does not strand the later bootstrap without treating a diagnostic
marker as proof of the individual capability removals, which remain covered by
rootd's exhaustive unit tests.
The focused
subsystem-rootd-procd-managed-cleanup-negative scenario reaches named after
the foundation boundary, starts logd, makes that service reject its startup
request, and requires the correlated post-start cleanup marker before the
service-failure exit. It therefore covers the live procd-managed stop path
without granting the fixture a process-control endpoint or treating the
PID/generation pair as authority.
The focused
subsystem-rootd-core-authority-retirement-positive scenario requires the
canonical core readiness order, then requires device discovery, hotplug, and
final readiness after the consuming transition. It composes that live
post-retirement continuation proof with rootd's unit-level assertions for the
exact five-slot retirement set and exhaustive cleanup; it does not expose a
capability-probing route to the fixture.
The phase5-semantic-bootstrap scenario group fixes those three authority
transition scenarios together with the inserted-foundation contract negative
as the complete focused semantic-bootstrap VM set. CI locks its exact four-file
membership and dry-runs every entry. Run it with
scripts/run-scenario-group.sh phase5-semantic-bootstrap; the separate complete
catalog remains mandatory before Phase 5 closure.
Because orchestration is an independently linked shared library, the image
builder resolves the selected rootd feature closure before constructing the
shared-object registry, propagates only the named dependency features into
erix-rootd-integration-orchestration.so, and includes that exact set in the
registry cache identity. Unknown rootd or library features fail the build
instead of silently producing a default-policy fixture. The fixture builder
publishes the selected registry path and manifest digest as a checked build
receipt; scenario and appliance packaging reload that exact receipt only after
feature selection, so an earlier default registry cannot be reused as ambient
build state. Rootd smoke/runtime fixtures load the receipt even when their
scenario-level prebuilt option began as disabled, because fixture construction
promotes those images to required dynamic consumption internally.
Loader policy owns the ABI self-check and the complete filesystem-discovery,
ELF rejection, materialized-child isolation, and five-boundary cleanup
sequences. Every effect names its loaderd, procd, kernel-log, and logd route,
request identifier, and path explicitly. Rootd only encodes or submits that
request and returns a typed response; the library alone chooses the final
continue or expected fail-stop disposition.
Core VFS I/O policy owns five disjoint plans for the memory root, ESP, data
root, indexed-directory proof, and volatile /tmp proof. Each plan fixes its
paths, request range, payload, operation order, response expectations, cleanup
order, and trace evidence. Effects name the exact vfsd namespace session and
kernel-log route on every call; the library cannot discover or retain either
capability. For signed BootConfig storage mounts, the library also inspects the
validated descriptive mount table and selects the volatile /tmp plan only
when that exact path is backed by the memory provider; rootd supplies the table
and executes the selected plan without retaining scenario expectations. The
complete memory pipeline is instantiated from matching core-I/O and
extended-API plans, including a /tmp/api namespace, so signed read-only /
plus writable memory-backed /tmp topology cannot accidentally issue mutating
smoke operations against the root filesystem.
FAT and ext truncate verification uses a shared 22-operation policy with two
immutable plans. The library fixes each file path, disjoint request range, fill
byte, shrink and growth sizes, zero-filled read evidence, and trace behavior;
rootd supplies only explicit open, write, truncate, stat, read, close, and
kernel-log effects.
The ext sparse policy reuses that bounded effect surface while owning both
paths, the write-past-end offset and tail, zero-hole and tail reads, sparse
truncation evidence, its disjoint request range, and its trace.
FAT, exFAT, and ext metadata verification adds only explicitly addressed
set-metadata and path-status effects to the same file boundary. The library
owns host and created-file expectations, timestamp normalization, mode and
ownership changes, filesystem flags, immutable denial, exact request order,
and traces; rootd selects one immutable plan and retains no route for the
library.
FAT namespace verification owns the optional lowercase host fixture, bounded
directory enumeration, persistent payloads, file and directory replacement,
and nonempty-directory, type-mismatch, and descendant-cycle denials. Its
effects name the VFS route explicitly for every raw stat, directory read,
path-status, and two-path operation.
The extended VFS policy owns its fourteen-operation cross-API transcript,
including root and signed /tmp path plans, payload, request identifiers,
truncate size, link denial, metadata/stat values, cleanup order, and traces.
Effects receive the VFS and kernel-log routes explicitly and retain neither.
The ext rename policy owns overwrite and cross-directory moves, symlink and
device identity, tree and HTree moves, cycle and nonempty-directory denials,
prefix evidence, and the complete request sequence. Its effects receive the
VFS route explicitly and return only typed observations.
The encrypted ext casefold policy owns its optional fixture, lowercase lookup,
payload, case-preserving directory entry, end-of-stream evidence, and exact
request sequence behind explicitly supplied raw-stat and directory-read effects.
The ext link policy owns fast/slow symlink evidence, hard-link counts, special
inode modes, denial cases, created-link and persistent-file sequencing,
cleanup, and diagnostics. Every typed effect receives the VFS or kernel-log
route explicitly.
Persistent-media plans own FAT/ext host markers, read-only and ext-only
profiles, created markers, indexed-directory evidence, large-file samples and
sizes, payloads, diagnostics, and request sequencing. The typed dispatcher
invokes those immutable plans over the shared explicit file effects; rootd has
no dedicated persistent-plan adapter.
VFS completion-marker policy is library-owned as one ordered transcript: a
focused profile emits only its selected evidence, while the baseline emits FAT
truncate, ext-link, and ext-rename evidence followed by encrypted-casefold
evidence only when that optional proof ran. Rootd's adapter iterates the plan
over the explicit logd route and chooses no marker or ordering.
The encompassing memory, read-only, FAT/ext, and verity pipeline order is
library-owned as typed VfsPipelineStep slices too. The baseline fixes all
fifteen nested plans and completion placement; each focused profile fixes one
proof followed by its completion transcript. These steps contain descriptive
plans and markers only, so rootd remains the sole holder of the explicitly
supplied VFS, kernel-log, and logd routes. Its 253-line dispatcher makes no
scenario-selection or expected-value decision and centralizes verifier-error
mapping. Ten redundant high-level verifier/plan wrapper families and the
dedicated persistent adapter are gone. Together with the nine prior selector
files and four duplicated entries, the VFS split removes 387 rootd source
lines.
Dynamic-link fixture constants are library-owned too: the exact dynamically
materialized rootd-intake marker, six named-service negative-selftest
diagnostics, and the zero optional-spawn-flags policy. Rootd still performs
every kernel-log and procd effect explicitly. Its two dedicated policy files
are deleted and the mixed marker adapter contains production diagnostics only,
removing another 31 rootd Rust lines.
Clean-Room Policy
EriX follows a strict clean-room philosophy:
- No external source code may be copied.
- No external Rust crates are allowed.
- No code generation tools that embed third-party code.
- All code must be authored within the project.
Violations will result in rejection of the contribution.
License
All EriX repositories are licensed under the ISC License.
Development Model
EriX development is modular, deterministic, reproducible, authority-explicit, security-first, and self-hosting oriented.
This repository follows the project roadmap and the validation rules documented in its own roadmap.
Deterministic VM Test Contract (Current)
Scenario-driven VM tests are grouped as:
- full-system normal run
- subsystem positive run
- subsystem negative run
- targeted scenario groups under
tests/scenario-groups, includingexact-entry-grantsfor one-shot receiver-retirement replay and retained- parent selector-race proofs,multi-block-providerfor two independently discovered virtio-block PCI functions, location-derived physical identities, cursor-driven provider traversal, and successful GPT-backed storage through the second provider,ram-allocator-domainfor one exact manage-only capability spanning every authenticated usable extent, atomic RAM-frame backing, non-power-of-two page alignment, alias lifetime, exact final-cap reclamation, and range reuse,host-report-authorityfor the root-only endpoint and rejected ambient syscall proof,fs-compliance-matrixfor the cross-filesystem compliance matrix smoke gate,fs-cross-apifor the expanded VFS rename/truncate/symlink/readlink, hard-link denial, and metadata-update verifier andfat-metadatafor focused FAT32 timestamp/attribute stat and mutation checks andexfat-metadatafor focused exFAT primary-entry timestamp/attribute stat and mutation checks andexfat-entry-typesfor focused exFAT Volume Label/GUID, benign vendor, TexFAT padding, and malformed entry-type checks andexfat-renamefor focused exFAT file and empty-directory replacement checks with hostfsck.exfatandfat-truncatefor FAT12/FAT16/FAT32 truncate shrink/grow media checks andext-linksfor ext2/ext3/ext4 symlink, hard-link, and special-inode metadata verification andext-renamefor ext2/ext3/ext4 rename, overwrite, directory-move, and HTree rename verification andext-truncatefor ext2/ext3/ext4 regular-file truncate shrink/grow media checks andext-sparsefor ext4 write-past-EOF sparse-hole and truncate-hole media checks andext-metadatafor ext2/ext3/ext4 inode metadata stat and mutation media checks andext-geometry-boundariesfor inconsistent ext2/ext3 block geometry plus format-valid 1,024-byte ext4 inode coverage andext-advanced-corpus-maintenancefor advanced ext corpus maintenance across fast-commit indexed directories, sparse/unwritten extents, metadata mutation checks, legacy fscrypt v1, fsverity built-in signature policy, and large-inode metadata preservation andext-xattr-policyfor ext2/ext4 xattr and POSIX ACL preservation plus malformed xattr fail-closed checks with mandatory hostdebugfs/e2fsck -fnand optionalgetfattr/getfaclprojection when FUSE is available. The FUSE projection retries a normal unmount and then lazy-detaches so a transient busy mount cannot poison scenario cleanup.vfs-memory-provider-renamecovers the memory-provider ABI and startup-peer rename path.
Runtime and appliance scenarios also forbid the direct
ERIX_DRV_SERIAL:PROVIDER_REGISTERED driver debug marker; the public serial
readiness surface in dev/runtime fixture boots is
ERIX_DEVICED:READY:DRV_SERIAL, and dev runtime framebuffer output receives the
configured ERIX_DEVICED:READY:* driver startup set through logd's fbcond-only
mirror path. Release runtime images suppress every ready stamp, including the
development-only final ERIX_ROOTD:READY. Committed dev/release runtime TOML
mounts /boot from the
ESP as read-only FAT, and the dynlink image closure check rejects every
non-bootloader executable that is not a dynamic artifact. The fixture policy
keeps that production authority boundary intact: only positive FAT-mutation
scenarios select a signed writable test policy, with distinct
runtime.dev.storage-writable-fat.toml and
runtime.dev.storage-writable-exfat.toml provider kinds. Host validation
rejects an omitted or mismatched selection and an unrelated scenario that
retains either writable mount. Verity, read-only, and ext-only scenarios
therefore receive no FAT-family mutation authority. It also
rechecks every staged VM service fixture as a PIE
ET_DYN artifact after it is copied into the bootloader fixture directory.
The pinned rootd requires serial and direct framebuffer READY writes to report
a byte count exactly equal to the requested length; partial and over-reported
completion cannot satisfy the visibility barrier. The authority-free
Integration verifier applies the same exact-count rule, so host-side scenario
evidence cannot bless a response that the product runtime rejects.
Pinned logd applies the same exact nonempty count rule to its seriald and
fbcond mirror transports, preserving replay work on short or over-reported
success evidence.
The encrypted/casefold VFS proof likewise rejects a read length larger than its
exact bounded request, binds EOF and next offset, and closes the opened file or
directory handle after completed or failed reads. Cleanup failure takes
precedence over the earlier evidence or transport disposition.
The ext-rename proof applies exact length and next-offset framing to its fixed
prefix reads and closes the opened handle after either a completed read or a
transport error; cleanup failure takes precedence.
The fixture builder compiles the kernel, rootd, services, drivers, and test
helpers directly as dynamic artifacts; it does not create fixed-address or
static precursor executables. Bootloader remains the sole static exception.
Host-side filesystem
evidence checks capture debugfs/dumpe2fs output before marker matching so
pipefail/SIGPIPE behavior cannot hide or invent runtime-image evidence.
scripts/run-ci-vm-scenarios.sh executes a committed scenario list and shards
it across private worker workspaces. Blank lines and lines whose first
non-whitespace character is # are list metadata and are never scheduled as
scenario paths. Each worker is extracted from the exact
HEAD^{commit} archive and verifies every tracked blob against that commit's
Git tree before any scenario can run. Before copying prepared components, the
runner also verifies every manifest-pinned checkout against its exact commit;
stale prepared state fails with a clone-components.sh recovery instruction
instead of silently testing an older runtime. Each private worker also exposes
its verified archived repository as the sibling Integration component selected
by nested rootd dependency and dynamic-closure resolution. A stale prepared
Integration self-checkout therefore cannot shadow the exact worker commit. A
source mismatch reports the commit, path, and expected and observed blob
identities. The worker root is normalized against the Integration checkout
before sharding, so
a relative override remains stable after workers enter their private checkout.
The current
native-shell checkpoint
selects the complete committed scenario catalog, including forty-one focused
initial-exsh scenarios, both focused extop scenarios, the physical-input disk
scenario, two trusted powerbox decision scenarios, and every historical
native-CLI scenario. The script
accepts ERIX_CI_VM_WORKERS as either a
positive integer or auto, and auto is the default. auto resolves to the
host's online CPU thread count. The aggregate workflow selects auto; run 706
proved that one serialized worker reaches Forgejo's 24-hour job limit after
only 207 completed scenarios and therefore cannot supply a complete-catalog
gate.
Each worker defaults CARGO_BUILD_JOBS to 1 through
ERIX_CI_VM_WORKER_CARGO_JOBS, so worker-level parallelism does not multiply
into nested Cargo/rustc process fan-out.
Disk-image residency and launch intent are independent. A scenario may package
the ext4-resident exsh program without starting it; only the explicit
initial_exsh_launch = true field selects the Integration launch transaction.
Schema validation requires that field for every scripted-shell or physical-input
case and couples it to a runtime-rootd disk image. The runner defaults it to
false, and rootd fixture selection treats auto as false, so an unrelated
runtime program inventory cannot retain the Integration-only initial-shell
state machine or silently acquire one shell launch transaction.
ERIX_CI_VM_BOOTIMG_TIMEOUT_SECS controls each worker's boot image packaging
timeout and defaults to 600 seconds;
ERIX_CI_VM_QEMU_DEFAULT_TIMEOUT_SECS supplies the ordinary VM deadline and
defaults to 120 seconds, including bootloader negative-case VM probes.
ERIX_CI_VM_QEMU_TIMEOUT_SECS retains its role as the global cap and defaults
to the same 120-second absolute ceiling. A legacy caller that tightens only this
cap also clamps the implicit default to the same value.
ERIX_CI_VM_QEMU_STALL_TIMEOUT_SECS
defaults to 45 seconds and terminates a QEMU process group when its serial log
does not change for that interval, even when the hard deadline has not elapsed.
The two closed quiet-release contracts, appliance-full-system-release and
subsystem-runtime-release-positive, intentionally disable both early consoles
and permit no product serial record before terminal readiness. Their watchdog
therefore ignores OVMF chatter and arms the same 45-second deadline only after
the first ERIX_ product record. A release warning followed by silence still
stalls in 45 seconds; a boot with no observable product record remains bounded
by the unchanged 120-second absolute deadline. The selector rejects either
named contract if its release profile, console flags, launch/input policy, sole
final-READY requirement, or forbidden early-marker set drifts.
Scenario definitions also reject deadlines above the repository-wide
120-second maximum, so local and CI runs bound both total execution and an
observably stalled guest. Every committed scenario now fits the common ceiling;
CI may tighten either bound without weakening any
exit, marker, warning, or authority assertion. The ceilings are calibrated
against a healthy main-branch result of 422 scenarios in 40 minutes on 12
workers: 68.2 occupied worker-seconds per scenario on average makes the
absolute limit about 1.76 times that mean, while the independent progress limit
releases a worker after 45 seconds of observable product silence;
bootloader marker-mode probes also enforce that window in the harness so a
QEMU process terminated on timeout cannot be reported as a clean exit;
the runner logs QEMU KVM availability near startup, sends a sole active worker's
native output directly to CI, streams each parallel worker through an
unbuffered shell prefixer, and emits an aggregate progress heartbeat every 60
seconds while workers remain. ERIX_CI_VM_HEARTBEAT_SECS accepts a positive
integer override for diagnostics. Each heartbeat reports pending workers and
completed, passed, and failed scenario counts from the worker result files, so
an 80-minute failed-scenario timeout cannot make an advancing job appear
silent. Parallel pipelines remain pipefail protected, and the runner prints a
final passed/failed/total scenario summary with failed scenario names;
scripts/run-scenarios.sh remains the serialized single-workspace runner for
local focused runs and prints the same per-run summary. In monorepo mode it
defaults Cargo and independent dynamic-artifact work to every online hardware
thread; CARGO_BUILD_JOBS or ERIX_DYNAMIC_BUILD_JOBS can set an explicit
diagnostic limit.
Complete-catalog run 1316 at Integration e3cbf4f finished all 461 scenarios
in 55 minutes 23 seconds of worker execution: 365 passed and 96 failed. Exact
serial classification separated 86 legacy profiles that inherited a
Runtime-only full transition, one vm-appliance runtime-media mismatch, and
nine independent regressions. The authenticated profile now selects the
transition, not the compiled feature alone. A vm-appliance scenario requiring
runtime-fs or loader-fs derives its attached disk from the packaged
self-contained image and replaces only the boot partition with an empty valid
FAT filesystem; the ext4 runtime graph and executables remain byte-identical.
The strengthened appliance-full-system-dev scenario locally reaches loaderd,
ttyd, powerboxd, launchd, and final READY through that separate-ESP topology.
The independent failures are covered by bounded deadline selections, canonical
powerbox marker order, exact procd retry authority, retained asynchronous
here-document bodies, and a times workload that exceeds the POSIX centisecond
display quantum without adding authority. Signed complete-catalog run 1468 at
Integration 1838b7b closes that acceptance gate with all 483 scenarios
passing in 40 minutes 11 seconds.
Complete-catalog run 1318 at Integration dcfb181 finished all 461 scenarios
in about 52 minutes of worker execution: 369 passed and 92 failed. This restores
bounded full-catalog throughput to 8.9 scenarios per minute and proves the
then-current 120/180-second hard ceilings plus 45-second progress watchdog no
longer hide a multi-hour stall. Its exact failure classes are 16 status-37
protection exits,
47 status-41 service exits, 13 forbidden-marker reports, 12 missing-marker
reports, three no-progress stalls, and one accounting assertion. Pinned kernel
8a8b8ab separates executing VSpace lifetime from userspace map/manage
authority: dropping rootd's final VSpace capability no longer destroys the
still-running dynamic address space. The focused dynamic-bootstrap replay
therefore removes its protection fault and reaches the separate service-failure
terminal report. Pinned rootd 8571227 also gives terminal log submission one
exact SEND-only receiver-rebind retry. Focused dynamic-bootstrap diagnosis then
found that the positive memd graph retained rootd's singleton deployment arena
while the Integration-only policy attempted to construct the named and deviced
negative graphs. Pinned rootd 4211ac1 constructs and releases every negative
graph before acquiring the positive graph; the replay passes all three
negative roles and advances through positive memd, vspaced, pagerd, and the
core service sequence. Its later storage-path status-41 exit was a separate
regression, not evidence that the graph-lifetime repair failed. Signed
complete-catalog run 1468 supersedes that failing checkpoint and passes all
483 scenarios.
VM runners default QEMU_ACCEL/scenario qemu_accel to auto: they select
KVM when /dev/kvm is usable and the selected QEMU binary advertises KVM
support, and otherwise fall back to TCG. Set qemu_accel = "tcg" or
QEMU_ACCEL=tcg only for tests that must force emulation.
Monorepo scenario builds reuse immutable local git-source mirrors under
out/git-source-overrides-monorepo and content-addressed dynamic build caches
under out/dynlink-build-cache. Cache identity includes source trees, feature
sets, linker inputs, the selected target dependency record, the authenticated
identity of every shared object in that target's transitive closure, and the
toolchain. Unrelated registry rows and cache-local paths therefore do not force
identical services to rebuild in separate scenario workers. Relevant artifact,
compiler-metadata, dependency, or target-record changes still produce a new
cache key. Fixture construction hashes its immutable builder/toolchain input
set once and resolves every target-scoped dynamic-link closure in one validated
registry pass. Each executable key still combines that prepared context with
its own component tree, feature set, linker inputs, deployment policy, and
authenticated closure; factoring the common context changes neither cache
equivalence nor invalidation behavior. When a worker's exact commit archive has
no Git metadata, source-tree
identity traversal prunes .git, .ci, out, target, and __pycache__
directories before descent. Generated component trees and caches therefore
cannot inflate provenance hashing or influence its result; every remaining
source path and byte remains part of the deterministic digest. Shared-object
compilation also remaps worker-local source and scratch roots to package-scoped
canonical paths. Equivalent registries therefore retain byte-identical object
and compiler-metadata hashes across isolated workers, while a real source,
feature, dependency, or toolchain change still invalidates consumers. The
registry builder caches each shared object and its complete compiler-metadata
closure under that exact authenticated build identity and expected artifact-
metadata digest. Artifact metadata names each manifest by its stable component-
relative coordinate, never by a host or worker checkout prefix. A scenario-
specific orchestration feature therefore rebuilds only its changed object;
unchanged objects are restored under a per-toolchain/source namespace after
every cached file passes its recorded SHA-256 check. Whole-registry cache keys
still include the complete selected feature set, so composing a new registry
cannot reuse a stale orchestration row. The
capacity and runtime-policy sources for both exsh and extop are
explicit inputs, so changing a packaged workspace or authority ceiling cannot
reuse a stale dynamic artifact. CI workers preserve those caches and component
Cargo targets across runner invocations, and each private worker begins with a
reflinked copy of the main workspace's immutable dynamic cache.
ERIX_MONOREPO_GIT_SOURCE_OVERRIDES_ROOT,
ERIX_DYNLINK_ARTIFACT_CACHE_ROOT, ERIX_DYNLINK_REGISTRY_CACHE_ROOT, and
ERIX_DYNLINK_OBJECT_CACHE_ROOT can move the caches;
ERIX_DYNLINK_DISABLE_BUILD_CACHE=1 forces a clean diagnostic build. Reuse
never changes canonical Cargo URLs or grants fallback authority.
The aggregate workflow clones the configured component snapshot before running
host helper tests. Catalog-bound coreutils and extop tests resolve their exact
inputs from out/components/<repo> in component-checkout CI and retain the
existing sibling-repository fallback for monorepo development. Explicit
COREUTILS_CATALOG and EXTOP_CATALOG inputs remain available for isolated
fixtures; resolution does not infer an executable path or grant runtime
authority. tests/ci-component-source-layout.sh locks the clone-before-helper
ordering and both workspace-first and explicit monorepo resolution modes.
The loader contract scenario is
subsystem-loader-contract-positive. It runs only the new memory-VFS
based contract proof, requires ERIX_ROOTD:READY:LOADER_CONTRACT, and does not
replace older storage and loader filesystem scenarios.
The loader ELF-plan scenario is
subsystem-loader-elf-plan-positive. It runs only the focused
block-backed loader path, requires ERIX_ROOTD:READY:LOADER_ELF_PLAN, and
keeps older VM scenario groups out of the local validation path.
The loader filesystem-preflight scenario is
subsystem-loader-filesystem-preflight-positive. It runs only the focused
block-backed loader path and proves authenticated discovery plus malformed ELF
and overlapping load-plan rejection. It forbids successful materialization so
pre-mount validation cannot claim launch-child lifecycle authority.
The authority-free loader verifier constructs every exact typed discover and
launch request plus the intentionally malformed discovery bytes before calling
an effect adapter. Endpoint slots remain separate explicit effect inputs, so a
planned request body cannot carry or select loader authority.
The loader root-lifecycle-isolation scenario is
subsystem-loader-root-lifecycle-isolation-negative. It permits rootd to ask
loaderd to materialize one authenticated fixture, then requires procd to deny
root's query with no managed state disclosed. Rootd records
ERIX_ROOTD:LOADER_LIFECYCLE:LAUNCHD_ONLY and fails closed instead of waiting
on launchd's private event route.
The procd endpoint-partition scenario is
subsystem-procd-root-launch-child-visibility-negative. It focuses the same
negative transaction on procd's endpoint policy: loader materialization, root
orchestration, and launchd lifecycle remain distinct, and only launchd may
query or consume the resulting child's lifecycle.
The loader cleanup-authority scenario is
subsystem-loader-cleanup-authority-positive. It runs only the focused
pre-start cleanup and authority regression path, requires cleanup-failure
markers for each procd-owned partial state, authority-denial
markers for unwanted provider/block/key/journal/peer/scratch/caller authority,
and ERIX_ROOTD:READY:LOADER_CLEANUP_AUTHORITY. Fault injection begins only
after procd creates materialization state; no loader request identifier is
reserved for a synthetic pre-procd failure.
The loader closure group is loader-closure. It runs only the focused
filesystem-discovery, ELF-plan, root-lifecycle-isolation, and cleanup-authority
scenarios needed to prove loader AC11 through AC13 without running older broad
VM groups.
The loader boot/image integration group is
loader-boot-image-integration. It covers the runtime
features.program_loader toggle, optional omission with the same VFS/storage
stack, and the appliance disk-image path that installs a disk-loadable native
loader fixture under /bin.
The dynamic-linking complete-graph group is dynlink-complete-graph. It runs
the current storage-services profile, authenticates the packaged runtime graph,
starts dynlinkd before loaderd, streams two selected executables and their
full dependency closures, and requires distinct child exit codes plus
stale-source authority rejection. Partial model, library-only, linker-only, and
loader-only profiles are intentionally absent: the integration contract is the
complete product path.
The dynamic-linking final migration closure scenario group is
dynlink-final-migration-closure. It runs only the focused positive VM
path after dynlink_final_migration_mode=required regenerates executable
inventory and requires check-dynlink-acceptance-closure.py with
--require-final-migration, proving that all kernel and service executables in
runtime/appliance images are migrated dynamic artifacts before the boot starts.
The ext4-only drv-rtc-cmos, exsh, and coreutils rows are included because
their inspected dynamic artifacts, runtime graphs, and post-mount launch paths
are complete. The RTC executable is a private one-shot provider rather than a
named service or general client route. The multicall coreutils artifact expands
into twenty exact /bin/<applet> graph roots rather than one generic
executable selector, while its bytes remain stored once;
host-tool and not-yet-created rows remain tracked outside the native runtime
image closure.
The dynamic-linking focused boot-image dynamic scenario group is
bootimg-dynamic-focused. It covers kernel entry, bootstrap helpers, core
services, device/console/input services, storage/loader services, the complete
runtime graph, final closure, and negative failure classes.
scripts/list-ci-scenarios.py emits the full committed VM scenario set by
default and accepts --group-file for an explicit focused set. The aggregate
workflow validates and boots the complete scenario catalog, including the
initial-exsh start/exit, missing-program, PATH-search, exact-not-found,
provider-backed redirection-script, local here-document, exact nested/outer
exit-status, POSIX for snapshot/one-time-expansion, parenthesized-subshell
state-isolation, function-scope, eval, dot, successor-exec, external-pipeline,
CPU-times, and persistent-trap scenarios, plus
the historical powerboxd, ttyd, and launchd ext4 lifecycle scenarios in
tests/scenario-groups/native-cli-runtime.txt. The six-entry
native-cli-time group adds three bounded fixed-RTC positives, an
authority-free utility positive, an otherwise identical runtime whose
authenticated private RTC provider is absent, and a provider build that
submits one semantically malformed private sample. The clock positive alone
enables an RTC startup classifier that substitutes
distinct process-exit values for receive, framing, inventory, and reply
failures. It selects signed rootd revision ba9cc5c, which retains the
generation-bound cleanup repair from b414de6, uses only ordinary procd/kernel
scheduling, and isolates complete Integration runtime-transition policy in the
authority-free orchestration library. Kernel revision 9e27303 removes the
completed call-first scheduling fixture, extends the retained narrow RTC trace
across reply-copy, wake, and exit-switch boundaries, and retains the prior
production scheduler quantum after a controlled one-tick experiment showed no
measurable change. A separate tenfold-shorter BSP LAPIC experiment also left
the approximately 74-second RTC and 217-second TTYD milestones unchanged, so
the exact revert retains the established bounded interval. Authoritative
retained serial evidence
records queued CALL admission (RTC_CALL_RC=6, the kernel's internal blocked
CALL result), a clean provider exit, and subsequent rootd TTYD and POWERBOXD
readiness. The positive scenario keeps the narrow kernel RTC startup trace to
classify ordinary direct-versus-queued delivery; it cannot select a receiver or
change scheduling and does not enable broader IPC-block trace families.
The current ordinary-scheduling replay also exposed a separate storage
throughput regression after the clean RTC exit: each partition block request
rescanned the complete GPT entry array twice, amplifying one loaderd VFS read
into thousands of provider calls. The cache introduced by signed blockd
revision 0b33df0, with warning-denied bare-metal build correction ff9b461,
retains only the last partition geometry inside the current provider namespace,
clears it with provider state, and still performs an unbounded complete scan on
a cache miss. The focused native-time group is the regression gate for both the
RTC handoff and this post-RTC ext4 executable-loading path.
With blockd ff9b461, the exact focused guest reached storage, dynlinkd,
loaderd, the clean RTC reply, and TTYD readiness before the global 300-second
watchdog expired. A controlled one-tick scheduler rerun reached TTYD at the
same time and returned the same timeout, disproving that hypothesis. An exact
experiment then restored a bounded 256-observation local used-ring window in
the physical provider. It reached TTYD at the same approximately 216-second
point and exhausted the same watchdog, proving local guest polling cannot
advance QEMU device emulation without a VM exit. Signed drv-virtio-block
revision 0022a09 therefore restores the validated one-observation cooperative
design, including exact completion checks, periodic idempotent notification,
and indefinite outstanding DMA ownership. The timer experiment likewise timed
out at 300 seconds with identical milestones. Artifact inspection then
identified the remaining deterministic amplifier: loaderd authenticates every
byte while filesystem executables still carry build-only debug and
static-symbol sections. Image finalization now strips that metadata from every
packaged executable and shared-object copy only after deployment-capacity
patching and before final hashes and manifests are generated. It preserves
.erix_dynlink, dynamic symbols, relocations, load segments, and all
authority-bearing metadata. Early canonical executables are finalized before
their identical signed-store mirrors are refreshed; shared-object source
registry artifacts remain unchanged while their zone-assigned image copies are
finalized. The focused rerun therefore measures the corrected authenticated
byte path without changing the watchdog, scheduling policy, or endpoint
authority.
The obsolete rootd RTC phase selectors are removed. RTC lifecycle failures are
now observed at deviced's exact loader, child-start, sample-acknowledgement, and
clean-exit boundaries instead of injecting control flow into rootd.
The same pinned rootd revision closes runtime terminal-report ordering. Rootd
first resolves reverse cleanup, exact source retirement, and every ordinary
authenticated client disposition without an output effect. Exit then sends
the sole typed status through rootd's dedicated kernel host-report endpoint,
retires that endpoint, and exits. Runtime images deliberately suppress the
kernel smoke-marker text, so Integration observes the kernel-owned QEMU exit
0x14 rather than requiring a second rootd logd/seriald publication. The
missing-program and exact command-not-found scenarios bind that exit to their
unique reconciled shell marker and complete before either watchdog. Removing
the four obsolete rootd terminal marker rows reduces the audited
product-validation surface without changing the operation, source-binding,
capability, or authority-family inventories.
Its pre-acceptance cleanup retry now proves the retained procd route has exactly
its canonical SEND|GRANT rights before yielding once; missing, weaker,
stronger, substituted, or repeatedly absent authority remains terminal.
The initial-shell runner now separates a fully reconciled expected negative
from an unexpected service or transport failure. Rootd retires its retained
launchd source in both cases, but only unexpected failures invoke broad runtime
teardown; expected command-not-found and clean rejection outcomes preserve the
already-procd-owned service graph until the one-shot kernel host report ends the
focused VM.
That provider serializes a canonical private request before changing only the
encoded nanosecond field, so timed observes the invalid semantic value and can
return the exact typed, correlated rejection without accepting time state.
The QEMU runner validates the civil timestamp before emitting
-rtc base=...,clock=vm; scenario data cannot inject additional options.
Setting SCENARIO_BUILD_ONLY=1 on a disk-image scenario builds its exact
scenario-selected appliance and raw GPT image, reports the image path, and
stops before disk-case mutation, QEMU startup, marker assertions, or post-VM
media inspection. The selector is rejected for every other run mode and for
values other than 0 or 1; dry-run output records the effective value.
The native-time component snapshot pins lib-ipc 0dd36b4, launchd 0b22de9,
loaderd caf5aa7, procd 1f105a0, rootd eef3c3a, and ttyd c09775a
together. The packaged tty session admits the same exact-entry metadata-read
and touch operation set
exercised by the exact-source host tests, while successful loader launches and
all procd queries preserve the exact process generation. The focused scenario
policy test rejects any of these pins drifting back to an earlier contract.
The pinned ttyd submits an accepted framebuffer or serial renderer call once,
retains its original private request buffer, and polls exact correlated
completion between bounded service-loop turns. It therefore continues
authenticated lifecycle intake without resubmission, timeout, discovery, or
additional authority while rendering is pending. The closed
native-cli-ttyd-renderer-liveness group names exactly the nine native-CLI
scenarios that stalled behind the old synchronous wait. Complete-catalog run
1468 passes all nine together with the other 474 catalog members.
At signed Integration revision 7fe1979, SCENARIO_BUILD_ONLY=1 produces all
three focused images without entering QEMU. Each is 156,237,824 bytes; the
positive, unavailable, and malformed SHA-256 values are respectively
c26f9fa62708db210628529373fcf584328f77f04e181d6f3b17b3e0a741127f,
520e9ddd052c7828158be176724c332eebf0335b0cbf26af99d78722ae889e77,
and e03268dacd0ee445d75d68d4d178b441f6b2af5a063f404876cdc7f39b6c7280.
All checksum sidecars, identity sidecars, GPT verification, read-only FAT
checks, and read-only ext checks pass. The positive and malformed graphs carry
38 executables and four filesystem launches; the unavailable graph carries 37
and three because drv-rtc-cmos is absent. These are construction results only,
not VM or post-mutation timestamp evidence.
At signed Integration revision a5f6570, the unavailable-provider and
malformed-sample VMs pass and the positive VM reaches final readiness after
proving the trusted date, persisted writes, utility-denial status 1, timed statuses
0 and 1, missing-command status 127, and self-signal status 143. Its marker
assertion then exposes a Coreutils defect: one printf '%s\\n' invocation with
four proof operands emits only the first. Coreutils c808279 repairs both
buffered and target execution by reusing the format until all operands are
consumed without changing authority; pinned successor bbd8a14 retains that
repair and records its completed VM acceptance.
The current fixture separates RTC/filesystem persistence from time process
semantics. Both scripts emit distinct bounded shell-builtin milestones after
their ext4, FAT, denial, status, lookup, and signal phases. Each record advances
the 45-second progress watchdog only after real work completes, cannot be
divided by an unrelated kernel diagnostic, and adds no launch or object
authority. The utility script has an empty filesystem authority table. Both
positive VMs now pass end to end at Integration 2d784a7: the filesystem path
also passes its read-only media verifier, and the utility path proves all four
timing triplets and statuses 0, 1, 127, and 143. Only the complete catalog
requires a fresh rerun with that bounded contract.
The two exact bounded trap-script VMs jointly prove every trap state,
EXIT-status, direct self-TERM, timed self-TERM, shell-exit, and root-readiness
boundary, while their
contiguous-marker assertion exposes token-by-token trap -p output interleaved
with kernel child-exit diagnostics. Exsh descendant aaf2d11 retains the
bounded listing repair and additionally keeps asynchronous here-document bodies
with their isolated child when a same-line parent command captures $!. It
also stages bounded listings for one logical selected-stdout write, preserves
the complete oversized-output fallback, clears its already-owned scratch, and
adds no authority. This
snapshot pins that repair; the exact trap VM and complete catalog require a
fresh rerun.
The focused physical-input group contains the baseline pointer/SAS/exit proof
plus approval and denial profiles. The latter type an authority-bearing
coreutils command into interactive ext4 exsh, require its complete fresh trusted
framebuffer review, select physical y or n, and commit once with Enter.
Distinct shell status markers establish approval and denial results.
Rootd requests prompt-default policy only for this fixture and separately marks
that exsh startup admitted no direct loaderd or procd endpoint.
The signal-contract checkpoint pins exsh, lib-ipc, and lib-tty as one coherent
catalog set. Its ttyd successor also pins the exact compiler-described
OrdinaryEventSlot layout that shares authenticated TTY1 ordinary capacity
between input and descriptive per-session PTY events. The capacity patcher
derives the changed arena size from the packaged target ELF; it does not add a
bootstrap field, boot-store executable, endpoint, or authority.
The trusted-grant successor pins lib-ipc, lib-bootstrap, ttyd, and powerboxd as
one coherent contract. TTY1 uses its previously reserved word for a caller-sized
grant-view table, and runtime configuration requires that table to cover the
entire powerboxd grant table. Ttyd receives exact receipt-free ACTIVE and REMOVE
reconciliation over its existing private powerbox endpoint; the mirror carries
descriptions only and grants no lookup, revocation, or process-control route.
The current coordinated successor pins exsh 296f5364, launchd 6166eed7,
lib-ipc 6959c644, and procd 2209b088. It carries only validated ignored
dispositions across ordinary, pipeline-child, utility-bearing exec, and
ENOEXEC process boundaries. The existing endpoint-selected job-control route
derives one exact process generation before launchd forwards a receipt-free
delivery request on its private procd endpoint. Explicit and default ignore are
mutation-free, terminate-class defaults use a tagged reason distinct from
managed cancellation, and unsupported stop/continue requests fail without
mutation. This pin adds no executable to boot.img and does not claim a new
end-to-end VM until exsh consumes authenticated terminal events.
Same-branch pushes retain an active complete-catalog run and queue the newer
revision in the same concurrency group. This preserves partial and terminal
regression evidence from every started sweep while still preventing two branch
sweeps from intentionally running together. Local iteration may select
tests/scenario-groups/authority-capacity-provenance.txt, which contains the
newly added named-receipt, log-state, RAM allocator-domain, kernel
hardware-deadline, semantic VFS path-body, and IRQD endpoint-authority
regressions. Positive cases set
dynlink_filesystem_mirror_check=required, which runs
scripts/check-dynlink-filesystem-mirrors.py against closure-report.json
before boot. It requires identity for every declared filesystem mirror and for
the boot-store half of each early/boot-image row, while rejecting residual
boot-store paths on filesystem-only rows. The complete-graph and final-closure
cases emit dynamic artifacts
for every executable in the selected boot graph before strict executable
metadata checks run. The filesystem mirror mismatch negative uses
dynlink_filesystem_mirror_check=expected-failure plus an injected rootd mirror
hash divergence so host validation rejects a stale mirror before boot.
Negatives keep serial markers separate for bootloader kernel-link failure,
kernel service-link failure, and normal service failure.
dynamic-linking operator evidence reuses that focused group and documents the
manual inspection path. boot-tool inspect must show dynlink-img,
dynlink-early, dynlink-objs, and dynlink-store in boot.img; extracted
manifests plus closure-report.json compare the signed boot-image dynamic
object store with the /lib/erix/dynlink filesystem mirror. The report keeps
bootloader as the only static executable exception and leaves host-tool
inventory rows outside the native runtime image closure.
The subsystem-stress-1k-positive scenario is part of the dynamic-only
runtime validation surface. It runs the procd-mediated 1k spawn/exit stress
loop in policy-selected batches of at most four simultaneously live helpers
with exact generation-bound terminal draining. The stress fixture alone adds
procd-integration-stress-batch: Rootd authenticates the complete signed
exit(42) dependency graph once, while each launch response returns only distinct
process/generation identities and transfers no child endpoint or installation
grant. Procd uses the kernel's full-graph map/relocate/seal operation, holds its
local process endpoint through successful start, but retires broad grant
authority before graph mapping and narrow grant authority before start. It
drops the endpoint before returning that identity-only response. Exact prefix
observation reclaims each terminal generation before the next batch. The
four-helper ceiling is the focused VM-proven bound: eight and 32 simultaneous
signed helper graphs exhausted the fragmented kernel heap, while four completed
all 1,000 lifecycles under the unchanged 120-second absolute and 45-second
no-progress watchdogs.
Production procd builds deny both operation IDs. Signed lib-ipc 0dd36b4,
procd 1f105a0, and rootd eef3c3a define and consume this closed test
contract; signed kernel b3ebbd4 suppresses only repetitive successful
Integration traces. The scenario retains the exact 1,000-lifecycle requirement
under the repository-wide 120-second deadline, requires batch progress, exact
completion, and final ERIX_ROOTD:READY, and still passes the strict dynamic
image closure gate that rejects non-bootloader static executables before
boot.
Scenario validation now rejects an earlier exit_on_serial_marker whenever
final READY is also required. The five affected dynamic-bootstrap scenarios
therefore terminate on final READY, after every earlier lifecycle marker can be
observed, instead of stopping QEMU before satisfying their own contracts.
Dynamic-link host fixture builders assemble their small metadata, import, and
runtime support objects through scripts/dynlink_assembler.py and link dynamic
artifacts through scripts/dynlink_linker.py. The helpers prefer standalone
LLVM tools when present, then fall back to Rust-bundled global_asm and
rust-lld, so isolated runners still build the same ET_DYN artifacts and run
the same metadata and closure checks. CI installs the Debian llvm and lld
packages so the standalone tool path is available in the canonical container.
Runtime packaging derives loaderd and dynlinkd private storage from the
explicit filesystem-loadable graph rather than a product cap or the larger boot
closure. It derives rootd's reusable early-link graph arena from the largest
packaged executable dependency closure and patches both the exact graph-record
count and its page-rounded backing extent. It also derives vfsd mount-record
storage from the selected mount rows and handle-record storage from explicit
deployment policy.
One [service_state.procd].managed_process_records value, bounded by procd's
canonical 128-slot pagerd partition, sizes procd lifecycle and event slices,
procd's capability scratch ranges, and its pagerd binding-record contribution.
Pagerd's binding arena adds rootd's disjoint 64-slot temporary-launch
contribution, so the canonical deployment patches 192 binding records. The
pagerd CSpace window remains fixed at canonical slots 320..512; deployment
count does not resize it. Packaging validates the record contributions and
fixed partition bounds against embedded target layouts and the shared
capability-space ABI before patching exact page-rounded arenas; callers do not
apply parallel limits.
vspaced keeps no deployment-sized mapping state: operation-scoped capability
receipts identify each VSpace and the kernel remains the authoritative mapping
state owner.
[kernel_state].reserved_heap_bytes selects positive page-aligned
kernel-private storage for runtime images. The build discards any inherited
ERIX_KERNEL_RESERVED_HEAP_BYTES, exports only the validated configuration
value, includes it in kernel artifact cache identity, and records it inside the
signed kernel image. The native-CLI profiles select 80 MiB so persistent frame
and VSpace metadata for the complete ext4 executable graph does not inherit the
retired 64-MiB compatibility extent; this setting conveys no usable-RAM or
service authority.
For ramfsd, packaging derives the mount-record count from only the selected
provider = "ramfs" rows and requires explicit nodes-per-mount,
file-bytes-per-node, and provider-handle policy. No service or caller supplies a
hidden compile-time ceiling. For e2fsd, the mount-record count likewise equals
only selected provider = "ext" rows and the provider-handle count is explicit
deployment policy. For fatd, the mount-record count equals only selected
provider = "fat" rows and the provider-handle count is explicit deployment
policy.
For logd, runtime configuration supplies canonical retained-record,
pending-submission, and retained-byte counts. Packaging maps only their exact
typed, page-rounded storage, including one exceptional terminal-delivery
record; logd retains no allocator or duplicate sink-payload queues.
For crashd, runtime configuration supplies one positive retained-report
record count. Packaging patches an exact typed arena, so overwrite policy is
deployment-selected rather than fixed at the retired 256-record crate table;
the daemon receives neither allocator authority nor access to page padding.
For seriald, runtime configuration supplies one positive retained-stream byte
count. Packaging patches an exact byte arena, so readback retention is selected
by deployment rather than fixed at the retired 4-KiB crate ring; seriald
receives neither allocator authority nor access to page padding.
For fbcond, runtime configuration independently supplies one positive
retained-stream byte count. Packaging patches the exact prefix of a dedicated
page-rounded arena, replacing the retired 128-KiB source ring without granting
allocator authority or access to page padding.
For deviced, runtime configuration supplies binding and HAL-registration
record counts. Packaging includes the five per-binding state vectors in one
exact typed arena, so valid deployments are not constrained by the retired
16-record crate tables and the service receives no allocator authority.
For irqd, runtime configuration supplies the handler-record count. Packaging
patches one exact typed registry arena, so neither the service nor its callers
retain the retired 16-handler ceiling or allocator access to page padding.
The focused subsystem-irqd-endpoint-authority-positive VM resolves only the
LAPIC-timer handler object, requires a mask-control request on that object to be
denied, then proves registration, timer delivery, and acknowledgement still
complete. This distinguishes handler authority from root-held IRQD
administration at runtime.
The focused subsystem-irqd-multiline-delivery-positive VM enables the
integration-only kernel_interrupt_multiline_test fixture. It starts the
ordinary LAPIC client after a serial-capable stack registers the COM1 driver
and requires exactly one kernel observation with both lines delivered and still
outstanding, followed by exactly one observation that both captured deliveries
were acknowledged by their independent handlers. The fixture adds no runtime
interrupt-injection operation or caller authority.
scripts/service_deployment_capacity.py reads each component ELF's embedded
target Rust layout, mirrors the real allocation sequence, patches its
deployment arena and containing load segment, and updates authenticated
runtime-read capacity words. When the service has an in-image stack, the arena
must precede the terminal .stack_reserve; patching moves that reserve and its
section-bound symbols with arena growth. An exact symbol at the old capacity-
section end moves to the new end as well, so a runtime linker-extent proof
cannot authenticate stale bounds. Generated dynamic-service import cells use a
.data.* input section so ordinary service linker scripts place them before
deployment arenas and the terminal stack instead of creating a later allocated
orphan section. Packaging then rediscovers the changed
artifacts before emitting the final runtime graph. The image manifest binds the
exact lowercase SHA-256 and canonical VFS path of that final graph as
runtime_graph_hash and runtime_graph_path; strict metadata validation
rejects missing, stale, noncanonical, or post-hash-mutated inputs. Images
without delegated runtime programs receive an authenticated empty deny-all
graph.
The dynamic-linking executable inventory gate is
scripts/check-dynlink-executable-inventory.py. It generates the authoritative
executable target list from configured component Cargo manifests, including
src/main.rs and [[bin]] targets, then joins that generated list with
dynlink-executable-migration.toml. CI fails if a discovered target lacks a
status, if kernel is treated as a static exception, or if any target other
than bootloader is approved for static execution. The generated JSON inventory
is written to out/dynlink-executable-inventory.json during CI.
The discovered exsh target is admitted only as an ext4-resident runtime
program. Rootd's selected initial-shell feature now supplies the explicit
post-mount ttyd and launchd transaction; complete POSIX shell usability remains
blocked on the later CLI work. Its exact dynamic dependency
closure, including lib-sha2 and lib-stdio, is recorded. Canonical dev and
release runtime inventories explicitly select the real exsh-runtime PIE as
an ext4-only runtime-graph root; it has no early-manifest or boot-store entry,
and packaging grants no launch, terminal, namespace, or process authority.
scripts/build-launch-manifests.py cross-checks the dependency records, final
image manifest, executable bytes, parsed runtime-graph root, and exsh-owned
catalog before writing the exact 624-byte exsh.elf.lmf. The sidecar binds the
stable executable
dependency-manifest digest, executable content, complete graph, canonical
/lib/erix/dynlink/executables/exsh.elf command entry, and all nine declared
filesystem/session authority ceilings. Its authenticated header declares CPU
accounting, held cwd, and the job-bound redirection resolver. The ceilings
grant nothing without matching session, script, and
invocation policy, and the manifest never serializes invocation-local VFS
capability identity.
components.toml includes both repositories with empty build commands so
coordinated CI can discover and validate their manifests without treating
either one as a statically built image component.
The discovered coreutils target is likewise an ext4-only runtime program.
Its repository-owned erix-coreutils-applet-catalog-v2 projection is the
single packaging input for all twenty command names, exact /bin paths,
signed launch flags, and maximum authority rows. Image generation aliases one
inspected multicall PIE into twenty independently hashed runtime-graph roots;
disk installation
stores those bytes once and creates exact hard links only for the catalogued
entries. Every entry receives a separately indexed launch sidecar whose command
digest, launch flags, and authority-table digest bind that applet alone. The
current catalog declares timed query for date and touch, held cwd for pwd,
and timed query, cwd, and inherited script launch for time. All six generic
bits are independent, not constrained by utility names. Launchd does not parse
POSIX utility syntax or install a direct timed sender: a running consumer uses
the broker only when its operation needs clock data. There is no
/bin/coreutils, early-manifest entry, BootConfig node, or boot-store copy.
The discovered extop target is a separate ext4-only runtime program. Its
repository-owned EXTOP1 catalog admits only /bin/extop, the exact
job-lifetime INSPECT_PROCESS ceiling for the SHA-256 scope of session, and
an interactive job-control maximum that must be refined to a delegated exact
job. Image generation emits one runtime-graph root and one indexed sidecar,
stores the PIE once, and hard-links that inode at /bin/extop. Its authenticated
header requests the accounting route that authorizes its session snapshots.
Neither the
executable nor its sidecar enters boot.img or BootConfig.
The discovered drv-rtc-cmos target is a private ext4-only provider. Signed
runtime policy either omits it or places one exact role-36 launch immediately
after loaderd with dependencies on loaderd and timed. Rootd installs only
sampling-only CMOS authority—fixed selector writes to port 0x70 and data-port
reads from 0x71—plus one authenticated send-only timed provider route. The
driver has no named publication, general client, restart, CMOS data-write,
index-read, NMI-masking, unrelated-selector, or implicit clock-setting path.
After one bounded sample attempt it reports ready, exits cleanly, and procd
reconciles the exact process generation before rootd reports provider
completion; process teardown retires the final installed authority.
The dynamic-linking manifest dependency closure gate is
scripts/check-dynlink-dependency-closure.py. It maps every normal Cargo
manifest dependency for each non-bootloader executable target to an
erix-<package>.so dynamic object name, compares those generated edges and a
canonical manifest digest against dynlink-dependency-records.toml, and writes
out/dynlink-dependency-closure.json. Dev-dependencies, build-dependencies,
and proc-macro/build tooling are excluded from executable dynamic edges;
renamed dependencies use the package name for the object and retain the alias
in the generated JSON. scripts/verify-dynlink-image-closure.py is the
image-time companion that rejects non-bootloader static executable entries,
missing/stale image dependency records, duplicate image dependency records, and
explicit statically bundled dependency records.
Image conversion first copies post-mount build outputs into private staging,
patches their selected deployment-capacity symbols there, and then removes
non-runtime debug sections and the static symbol table. Early bootstrap
capacities are patched on the canonical module and mirrored into the signed
boot store, so the catalog and boot-module bytes remain identical. The
finalizer explicitly retains .erix_dynlink, allocated program segments,
dynamic symbols, relocations, and dependency records. All executable
hashes, runtime graphs, lookup rows, and launch manifests are derived from
those final bytes, so no authenticated identity is mutated after publication.
The dynamic-linking image-conversion gate is
scripts/build-dynlink-image-manifest.py plus
scripts/verify-dynlink-image-closure.py. Fixture, runtime, and appliance
builds now emit a dynamic image manifest, an early boot-image dependency
manifest, an early object bundle, a binary
erix-dynlink-runtime-graph-v1 source graph, and deterministic erix-*.so
object-store artifacts from dynlink-dependency-records.toml. The runtime
graph binds each exact package/digest identity to one authorized absolute VFS
path and uses direct object indexes for dependency traversal. Boot executables
remain in the signed boot closure but do not automatically become loader
authority. Packaging fails
before boot if a required object is missing, has a stale hash, lacks
relocation/dynamic section metadata, is placed in the wrong
early-versus-filesystem zone, or if bootloader gains dynamic dependency
requirements. Runtime
features.program_loader=true now includes dynlinkd before loaderd with
explicit vfsd authority.
The dynamic-linking object-store contract adds a full boot.img dynamic store and
a filesystem mirror. The generated manifest records
erix-dynlink-boot-store-v1, erix-dynlink-filesystem-store-v1, boot-store
paths, filesystem paths, hashes, executable identities, shared-object
identities, and explicit no-ambient authority flags. Disk-image installation
places manifests, dynamic executable mirrors, and shared objects under
/lib/erix/dynlink; tests/dynlink-object-store-contract.sh covers the host
contract, and bootimg-filesystem-object-store is the focused VM group.
The generated erix-launch-manifest-index-v1 records every admitted sidecar
hash, authenticated header flags, and five policy digests. Installation rejects
a missing, unindexed, stale, executable-mode, malformed, or catalog-divergent
authority sidecar;
indexed .lmf files are installed as non-executable data with mode 0644
beside their 0755 executable. Exsh retains native-command filesystem
delegation maxima plus its exact session-inspection maximum, extop retains that
exact session scope plus an explicitly interactive control maximum. Exsh
declares CPU/cwd/resolver ABI support and extop declares CPU/session inspection;
neither declaration selects rights by argv. Each coreutils entry binds its exact
catalogued launch flags and maximum rows with an all-zero object selector that
must be refined to an exact object by an authorized running-program request.
The boot store contains only executables explicitly marked for early startup
and shared objects assigned to the boot-image zone. Post-mount executables and
filesystem-zone objects still receive authenticated ext4 paths, but packaging
omits their boot-store paths and the closure verifier rejects any residual
boot-store copy.
The fixture builder keeps those inputs in a separate
FILESYSTEM_EXECUTABLE_FIXTURES set. Runtime profiles with complete TTY1 and
PBX1 policies build ttyd and powerboxd with their runtime features, while
the explicit [programs] exsh = true inventory builds exsh with
exsh-runtime, [programs] coreutils = true builds the multicall runtime
artifact, and [programs] extop = true builds the native monitor. Each selected
artifact is marked for the filesystem zone and never
enters the boot-service set. Selecting either program requires the program
loader and launchd policy. Exsh additionally requires complete
[program_state.exsh] caller-resource policy; coreutils requires one positive,
page-aligned [program_state.coreutils].workspace_bytes ceiling. Extop requires
all four [program_state.extop] workspace, processor-row, process-row, and
control-handle capacities; the control count cannot exceed the process count. Inventory
booleans and workspace sizes remain authority-free.
tests/exsh-filesystem-packaging.sh proves the exact five-object dependency
closure, runtime-graph membership, and absence from the early manifest and boot
store. It also parses every LMF1 field, verifies the exsh-owned exact
session-inspection authority digest,
installs the exact sidecar on ext4, and rejects changed graph bytes, dependency
identity, executable content, or indexed sidecar bytes. Dynamic
service packages may expose a package-local library target: the artifact
builder compiles that library and its binary as separate package-owned PIC
objects, then links both against the declared prebuilt shared-object closure.
Every direct rustc PIC compile uses the owning package's declared Rust
edition, including Rust 2024 services loaded from the filesystem partition.
It does not turn the package-local crate into a static cross-repository
dependency.
scripts/powerboxd_state_capacity.py parses the executable's PBX1 target
layout, derives the exact page-rounded arena for every configured request,
grant, selector-byte, retained-record, cleanup-record, and transient
capability-slot pool, and patches the authenticated arena word. Its focused
host test proves exact growth and rejection of missing, partial, or zero
capacity. The canonical runtime profiles supply every PBX1 storage value plus
the transient capability-slot base and count. Configuration rejects a range
outside the native-broker CSpace window, and image packaging rejects a
powerboxd artifact unless the complete storage projection is present.
tests/dynlink-service-local-library.sh covers the package-local library link
path, and tests/powerboxd-filesystem-packaging.sh proves that capacity
patching rebuilds the final artifact identity, includes powerboxd in the
runtime graph, and leaves it out of the early manifest and boot store.
scripts/ttyd_state_capacity.py likewise parses ttyd's target record layouts,
including the PTY stream, opaque shared ordinary input/control, and trusted
grant-view slots, derives and patches its page-rounded session, PTY, event,
cleanup, ordinary output, trusted chrome, PTY input, canonical-line, PTY output,
output-record, and grant-view arena in runtime allocation order, and rejects
partial or absent TTY1 policy whenever ttyd is packaged. Runtime parsing also
rejects a grant-view capacity that differs from powerboxd's grant capacity.
tests/ttyd-filesystem-packaging.sh proves the real binary and package-local
library remain ext4-only.
scripts/launchd_state_capacity.py derives and patches launchd's exact
page-rounded transaction, job, intent, manifest, authority, script, pending,
cleanup, status, reply, launch-stream endpoint, retained logical-stream,
selected-body, and transient-slot arena from the version-5 target layout and
authenticated version-2 LCH1 policy. The target descriptor carries distinct
script-envelope, launch-stream endpoint, and logical-stream record sizes. The
logical-stream count derives from the authenticated endpoint count, while its
disjoint byte arena derives from authenticated intent-byte capacity. Validation
reserves twelve non-aliased slots per job for control, status, script,
and resolver pairs, a job-broker creator/source/receiver triple, and an exact
retained filesystem-scope sender when required, then
two slots per configured stream pair, and requires a disjoint, nonempty tail
for launch-intake receipts. The standard 128-job/64-stream policy reserves 1,920
slots: 1,664 for job and stream routes and 256 for intake receipts. Boundary
tests reject the prior eleven-slot geometry and require a nonempty disjoint
intake tail without enlarging the CSpace budget.
scripts/exsh_workspace_capacity.py parses the pristine version-20 target
layout, expands the thirteen explicit command/syntax/variable/descriptor/local-
body/expansion/launch/search/subshell/function/background-job resource classes
into all 94 authenticated capacity words, reproduces exsh's complete typed
carve order, and patches the page-rounded .exsh_workspace. Stable for
item/byte arenas
derive from the explicit expansion policy. Subshell frame depth is backed by complete
variable-slot/byte, positional-slot/byte, and function-slot/byte/event/here-
document/boundary snapshot arenas for every admitted nested level; checked
products cannot overflow or advertise unbacked state. The same depth also backs
complete trap-slot/action-byte snapshots, so caught dispositions can reset on
entry while ignored dispositions survive and the exact parent table can be
restored and erased on leave.
The syntax-record policy additionally backs one typed pending/completed
pipeline-job slot per admitted command record. A caller-sized background-job
ledger retains only exact status/control routes and descriptive process
identities. Function depth separately backs
persistent definitions, immutable active-call
snapshots, iterative execution frames, parameter checkpoints, and validation
frames. Its retained descriptor layers have a caller-sized local journal, and
a second complete evaluation workspace expands definition-site redirections
after call parameters have been installed without aliasing the invocation
candidate. Authenticated eval source, event, here-document, substitution-
boundary, execution-frame, and parser arenas derive from the same deployment
classes and are carved before both evaluation workspaces. Four additional
capacity words provide the fixed 28-condition live/candidate trap slot sets and
derive both action-byte arenas from the explicit command-byte class, without a
separate private action ceiling. The 96 capacity words and 70 type-layout words
form the exact 166-word EXS21 descriptor. Two new explicit byte classes back
the interactive editor, its saved draft, and volatile command history. The
editor/draft slices share one capacity; history has its own byte budget. Neither
adds filesystem storage or authority. The distinct command-search byte
arena is deployment-sized and cannot become an implicit pathname limit.
Packaging rejects a missing policy, a stale version or type layout, any
non-pristine default word, and an undersized or overlapping NOBITS range.
tests/exsh-workspace-capacity.sh covers the exact word projection, growth,
patch, and stale-layout rejection; the filesystem packaging test proves that
the final patched ELF is rehashed before its image and launch manifests are
emitted.
Initial-exsh VM scenarios select explicit test deployment policies rather than
the product dev profile. The preceding EXS20 layout derived a 4,194,304-byte
workspace, down from 106,061,824 bytes. Current canonical EXS21 builds derive
4,235,264 bytes, including the editor/draft/history slices, while retaining
64 KiB command/search bodies, 128 syntax records,
16 descriptors, four nested subshell/function levels, and 16 background jobs.
The canonical dev, release, sample, writable-FAT, and writable-exFAT profiles,
plus the non-product smoke fallback, use that same bounded tuple. The former
106,061,824-byte product allocation
exceeded both the 64 MiB sample heap and the 80 MiB dev/release heap before any
other service allocation; the bounded allocation fits the smallest canonical
heap and prevents unrelated filesystem launches from failing while merely
packaging exsh. This changes retained storage only and grants no launch,
filesystem, endpoint, or namespace authority.
The subsequent read-only-root regression is repaired at signed vfsd revision
18d1dfa. Vfsd now retains the validated mount flags and omits access-time
evidence for READ_AT, READDIR, and READLINK on read-only mounts, including
provider-pinned exact objects and ordered redirection streams. Loaderd discovery
and POSIX sourced-script input therefore remain non-mutating provider reads even
after timed becomes available; writable mounts still receive trusted atime
updates, and filesystem providers independently retain their read-only
enforcement.
The RTC reconciliation contract now belongs to deviced: it accepts success only
after exact clean process exit and retirement of the materialization receipts
and child aliases, so rootd receives no RTC process-lifecycle authority.
At the pinned rootd and vfsd revisions, the canonical default-profile
appliance-disk-image-dynlink-kernel-artifact-positive VM crosses RTC cleanup,
read-only loader discovery, and final marker validation. The writable
native-time filesystem VM also passes every in-guest and post-VM payload,
timestamp, ctime-order, and read-only-denial check, proving writable atime
propagation remains intact. Both use the unchanged 120/45-second watchdogs.
The scenario contract test rejects an implicit product-profile fallback or a
divergent canonical profile or special RTC policy. It also requires eight TTY
session and PTY records: rootd owns one authenticated bootstrap session before
launchd provisions exsh, and unused records confer no endpoint or session
authority.
scripts/coreutils_workspace_capacity.py parses the pristine ERIXCORCAPLAY001
target layout and patches the exact page-aligned .coreutils_workspace byte
ceiling before the multicall ELF is hashed. tests/coreutils-catalog.sh
enforces the repository-owned command/authority projection,
tests/coreutils-workspace-capacity.sh covers pristine layout and exact
capacity failures, and tests/coreutils-filesystem-packaging.sh proves all
twenty ext4 entries share the one stored inode while retaining distinct,
tamper-evident sidecars, exact date/time/touch flags, and no generic or
boot-image executable path.
tests/launchd-filesystem-packaging.sh proves the rehashed real binary and
package-local library remain ext4-only and absent from the boot store.
scripts/extop_workspace_capacity.py parses the pristine
ERIXTOPCAPLAY001 target layout and patches the caller-owned workspace plus
processor, process, and control record capacities before final hashing.
tests/extop-catalog-capacity.sh covers exact catalog scopes, capacity
validation, and stale-layout rejection; tests/extop-filesystem-packaging.sh
proves the one ext4 entry, exact two-row sidecar, absence from the boot store,
and tamper rejection.
The same validated runtime policies are encoded once into BootConfig's
canonical FSL1 tail. The first filesystem launch node binds private role 36
to /lib/erix/dynlink/executables/drv-rtc-cmos.elf and the fixed 24-byte
RTC1 authority description. The next node binds role 30 to
/lib/erix/dynlink/executables/ttyd.elf and the complete 96-byte TTY1
record. The next binds role 32 to the exact powerboxd selector and complete
64-byte PBX1 record; the final row binds role 31 to
/lib/erix/dynlink/executables/launchd.elf and the complete 68-byte version-2
LCH1 record. This is authenticated configuration only: BootConfig contains no
ELF bytes, boot-store path, namespace capability, or process-control authority.
The RTC, ttyd, powerboxd, and launchd BootConfig tests check complete gap-free
node/row/policy bindings and reject reordering or substitution. The RTC image
test additionally proves that the executable and its five-object closure are
present in the ext4 runtime graph and absent from the early manifest and boot
store.
Production disk construction installs runtime-graph executables with mode
0755, indexed launch-manifest sidecars with mode 0644, and shared objects as
non-executable data. It never overlays the authenticated graph with the retired
loader filesystem fixture. The focused
appliance-disk-image-powerboxd-filesystem-positive scenario boots the real
ext4 executable through loaderd, dynlinkd, and procd, then requires ordered
loader, VFS I/O, powerboxd, and final root readiness while rejecting trace and
service-failure markers. The corresponding ttyd scenario requires the ordered
loader, root-mount, VFS-I/O, typed ttyd, and final readiness sequence. The
launchd scenario requires that same mount and I/O prefix, then ttyd and
powerboxd readiness before unique typed launchd and final readiness. It runs
the real ext4 object through loaderd, dynlinkd, and procd and rejects service
failure or diagnostic trace markers. Reaching both broker readiness markers
also proves that powerboxd's final decision-notification sender and launchd's
paired receiver fit their exact child CSpace windows and survive the complete
rootd-to-procd startup handoff.
Three focused coreutils scenarios start the ext4-only multicall artifact
exclusively through its catalogued /bin/<applet> entries. Bounded POSIX shell
scripts separately cover text pipelines, exact-object copy/rename/unlink
lifetime, and directory mutation plus status/current-directory primitives.
Each uses the repository-wide 120-second absolute deadline and 45-second
silence watchdog. The separate native time-utility scenarios are now
split into bounded filesystem-persistence and process-semantics positives with
independent completion and post-VM contracts.
Rootd selects only each variant's filesystem operation families and puts one or
two exact selector/lifetime/class rows in its script envelope. Expected
cross-applet operations fail, so sequential launches cannot accumulate the
catalog's authority ceilings. The fixture selector is mutually exclusive with
every other initial-exsh command mode and requires the complete post-mount
runtime graph.
The focused
appliance-disk-image-initial-exsh-regular-builtins-script-positive scenario
keeps the same ext4-only exsh launch and empty authority envelope. It requires
fresh, clustered, explicit-operand, silent, and resettable getopts behavior;
octal and symbolic umask state; command -v/-V, function bypass, and
default-path execution; and operand-tolerant true/false. One expected exact
/bin/grep reads the mode-0600 file only through exsh's explicit inherited
stream, proving that mask attenuation does not widen namespace authority.
External probes remain exact catalogued /bin launches, and the warning-free
focused VM completes its serial marker and final readiness contract.
The native-cli-initial-exsh group identifies forty-one focused entry scenarios
within the full CI catalog. The baseline positive case requires the ext4-loaded
shell's typed zero-status exit before final rootd readiness. The missing-program
fixture keeps the complete service and mount graph but excludes exsh from the
runtime program inventory; its clean-rejection marker follows launchd's
correlated abort and temporary-authority cleanup before rootd reports service
failure. The PATH case launches a second ext4 exsh through the first shell's
unchanged bounded route and requires a distinct zero-status marker. The exact-
absence case searches one missing candidate, requires status 127 after clean
abort, and rejects final readiness without adding authority to either launch.
The redirection-script case creates a POSIX script through the job-bound /tmp
provider, reopens it as a nested ext4 exsh child's fd zero, and proves that the
dynamic description replaces rather than supplements inherited fixed stdin.
The here-document case supplies a quoted literal body from exsh's authenticated
local producer as nested ext4 exsh fd zero, then requires terminal cleanup and
final readiness without adding rootd or filesystem authority.
Its fifteen native-time entries run ext4-resident date, touch, and time
through exsh. The clock positive performs exactly two external launches and
has an empty script-authority table: trusted date must succeed and an
ungranted touch must execute and return utility status 1 without creating an
entry. The ext
and FAT persistence proofs are nine separate scenarios with exactly one
filesystem-mutating external command apiece. Create and truncate each receive
only invocation-lifetime write plus one-shot create-entry authority for their
exact target. Current-time and explicit-time touch each receive one one-shot
touch row. The cross-mount reference case receives only one metadata-read row
for its seeded ext4 source and one touch row for its FAT target. This preserves
create, truncation, current-time, explicit-time, and reference-copy semantics
without allowing one expensive provider operation to consume another's VM
budget or authority. The
utility-positive path checks child success and failure status, while a separate
auxiliary positive checks not-found and signal status. Both require POSIX timing
output with zero filesystem session operations and empty script-authority
tables. The signal child installs a TERM action, targets only its
authenticated $$ identity with the regular kill built-in, and exits 143
from the caught action; an unmatched or undelivered signal instead reaches a
distinct failure exit. The unavailable path retains only write, create, and
touch rows, omits the authenticated private RTC provider despite fixed virtual
hardware, and requires date and current-time touch to report unavailable
while an explicit timestamp still succeeds. A separate clockless negative uses
the same provider omission to prove monotonic time remains independent with
zero filesystem authority. Rootd emits the terminal success marker only after
hanging up the session and retiring every temporary launch, lifecycle, and
status capability. The malformed peer selects the same three-row script
authority while compiling only the private provider with its adversarial sample
feature; timed must return the exact rejection and remain unavailable. Each
mutation positive has a closed post-VM verifier mode: denied checks absence on
ext; ext create, truncate, current-touch, and explicit-touch modes verify their
exact payload and timestamp contract; and the five FAT modes verify create,
truncate, current-touch, explicit-touch, or reference-copy state. The reference
mode also verifies its immutable ext4 source.
All fifteen native-time paths use the common 120-second absolute deadline and
retain the 45-second no-serial-progress deadline. A healthy main-branch run
completed 422 scenarios in 40 minutes with 12 workers, or 68.2 occupied
worker-seconds per scenario; multi-hour execution
is therefore a stall failure, not a valid slow path. Timeout selection changes
no guest authority or accepted marker.
The replacement fixed-RTC and clockless workflows are independent disk
scenarios.
Host gates lock their exact selectors, launch counts, authority rows, markers,
catalog membership, and persistence modes before focused VM validation.
The native-cli-physical-input group contains three focused post-mount hardware
paths. After rootd validates ttyd's interactive parent-session receipt, commits
the exsh launch, and validates its status route, the disk VM exposes a private
Unix QMP socket to a bounded host helper. The runner allocates that socket under
a short system temporary path instead of inheriting a potentially deep build
TMPDIR, and removes the private directory on every exit path. The baseline
sends relative mouse motion, Ctrl+Alt+Delete, and exit; two peers type an
exact-object operation one
acknowledged key stroke at a time and answer its trusted prompt with physical
y or n followed by Enter. Bounded inter-group and inter-key settling intervals
prevent the emulated PS/2 queue from dropping a line delimiter or truncating a
longer command while the scenario retains one overall timeout. Since line echo
is earlier than prompt registration, a PF2 glyph matcher requires the complete
fresh amber review, including its exact executable, scope-relative selector,
operation, lifetime, and Enter instructions. Consent is never retried into a
subsequent prompt or resumed shell. Only the approval, denial, replay, and
selector-race profiles
select rootd's powerbox fixture feature, which admits one-shot CREATE_ENTRY
and a prompt default for the primary session; ordinary physical-input and
secondary sessions remain deny-all. Rootd observes inputd's public keyboard,
pointer, and exact trusted-acknowledgement counters in the post-commit callback
while the process session remains live. Rootd then publishes an evidence-ready
marker, and the host sends input that may terminate the shell only after
observing that second barrier. Terminal-status observation and exact hangup
follow. Rootd publishes
success only after exsh reports the expected status and the ext4-loaded shell
exits normally. Scenario data cannot
name the QMP socket, fabricate a target event, or grant target-side input
authority.
The native-cli-trusted-tty group adds three ext4-backed interactive proofs.
The multi-PTY member creates one independently receipted empty session beside
the running exsh session and proves ordinary PTY echo. The host waits for both
the echoed true MULTIPTY builtin and exsh's second prompt before sending
trusted control. Keeping the probe inside exsh prevents an unrelated completed
child-session cleanup from becoming the anchor for focus traversal.
It then paces secure attention, selects the authored secondary with the
previous-session control, and returns to exsh with the next-session control as
separate bounded input groups before exit. The final Return is retried only
until the guest publishes the unique initial-exsh exit marker, so QMP controller
acceptance cannot be mistaken for delivery through the emulated PS/2 queue.
The spoof-negative member
prints CTRLALTDELETE through ordinary PTY output before sending the one real
secure-attention chord; rootd accepts only an exact trusted-delivery delta of
one. The session-control member enters secure attention, focuses the secondary
session, kills that focus with target-free Ctrl+Alt+K, and can type exit only
after ttyd restores primary focus. Its expected delta is exactly three. All
three use QEMU's private input socket and return no input producer, PTY stream,
session selector, or job-control authority to rootd. Their terminating input is
also held behind rootd's evidence-ready marker.
The one-shot local group invocation stopped before image construction because
BOOTIMG_SIGNING_KEY was unset (passed=0 failed=3 total=3). No target build
or runtime result is claimed, and the failure was neither investigated nor
rerun.
The native-cli-launch-handles group contains one focused ext4 client proof.
Rootd launches interactive exsh with only its mandatory status sender. Exsh
then observes /bin/false as status one, launches foreground /bin/cat, and
forwards a physical Ctrl+C only through cat's independent control sender before
observing status 130. The QMP profile retries that selector-free chord until a
new CONTROL130 marker appears, so a slow foreground handoff cannot turn the
test into a timing lottery. The profile names neither a process nor a job;
serial status text plus the target completion marker proves the two route roles
were used without returning either child sender to rootd. The warning-free
focused run passes 1/1, including ordered authority-boundary and final-ready
assertions.
The exact-entry-grants group contains two focused negative disk scenarios.
The replay member builds coreutils with a test-only mode, performs one approved
mkdir, then calls the same child send alias again and succeeds only when the
kernel reports NOT_FOUND after vfsd retires its receiver. The selector-race
member opens an exact ramfs entry and then asks a test-only provider hook to
rename the retained parent through the ordinary API; only BUSY is accepted
before the exact mutation proceeds. Scenario coupling prevents either QMP
profile from selecting a production feature combination, and neither fixture
adds a mount, namespace, parent, path, or control capability.
The required one-shot local group invocation stopped before image construction
because BOOTIMG_KEY_ID was not selected (passed=0 failed=2 total=2). It was
recorded without diagnosis or rerun, so target-build and runtime evidence
remain open.
The native-cli-extop group identifies the two process-monitor scenarios in
that same complete catalog. The positive case boots two processors, launches
the ext4-only /bin/extop through exsh, loaderd, dynlinkd, and procd, and
requires two bounded dashboard samples containing both processor rows, memory
accounting, and the session-scoped process table. Its bootstrap session carries
only INSPECT_PROCESS; no process-control operation is delegated. The negative
case leaves the session deny-all, supplies only a forged numeric job identity,
and requires launch denial before any dashboard row can reveal or mutate an
out-of-session process. The current positive run rejects the initial exsh
commit with an authority-class invalid argument before extop executes. The
negative run reaches the expected command-denied status 126, then exits rootd
status 220 without its completion marker. Both failures are recorded without
debugging.
The exit-status case makes that nested shell return seven, expands the outer
shell's $?, and requires the outer POSIX exit built-in to propagate the
exact status before rootd resumes final readiness. It changes no launch or
authority record.
The for case mutates positionals and an expansion variable inside loop bodies
to prove that omitted in snapshots "$@" and explicit words expand once. It
uses the same ext4 executable, launch transcript, and authority-free command
bytes as the other focused variants.
The parenthesized-subshell case mutates variables, positionals, option flags,
and status inside (...), then proves their restoration and successful
! (exit 9) completion in the outer source. It adds no authority or launch
record and executes the same ext4-only exsh artifact through loaderd, dynlinkd,
and procd.
The function case defines and invokes POSIX functions, proves call-local
arguments, shift, return 7, and caller-parameter restoration, then enters a
parenthesized environment. That environment inherits an outer binding but
confines replacement, definition, and unset -f; leave restores the outer
binding and omits the inner one with ordinary status 127. Final removal also
falls through to status 127. The same fixture applies an invocation-site output
redirection before a definition-site pathname expanded from a call-local
argument, executes the written body through nested ext4 exsh, then retains a
function-body here-document until another nested child exits seven. It accepts
that status only after descriptor/provider cleanup and scope restoration. The
fixture also calls break 3 and continue 3 from functions inside caller
loops, requires both caller bodies to resume, and sends exit 7 through two
nested child-function scopes. The case changes only authority-free -c bytes
and uses the same ext4 executable and fixed launch transcript. Its large
authenticated workspace also crosses the kernel's historical 32,768-frame
registry boundary and switches its large user range after ext4 materialization.
It forbids kernel-heap exhaustion, proving both bounded frame-registry growth
and allocation-free range-permission activation.
The eval case runs nested POSIX eval in the current environment, suspends and
resumes a function around an eval-originated return, transfers continue and
break from eval to the selected caller loop, replays a retained here-document,
and checks exact status and leading negation. It changes only authority-free
command bytes; exsh remains ext4-only and rootd receives no evaluator,
descriptor, stream, namespace, process, or additional launch authority.
The dot case installs two non-executable shell files on the ext4 data partition
only for its focused image. The outer ext4 exsh selects one file through
PATH; that source opens the other by direct path. The pair proves
current-environment mutation, retained here-document parsing, redirection
cleanup, function-local and eval-to-dot return, exact nested statuses, and
noninteractive missing-source termination inside a subshell. Neither file is
placed in boot.img or admitted as a launchable program, and the rootd launch
and authority transcript is unchanged.
The exec case installs two executable-mode POSIX shell files only in ext4, with
no native launch manifests. It first proves exact status 127, then status 126
when an execution-only shell cannot authorize the required successor handoff.
The selected script is read only after exact native-manifest absence, and its
interpreter is the fixed ext4 exsh.elf selector rather than a PATH fallback.
A direct successor returns status 23, a separately authenticated shell then
launches and reaps one nested ext4 shell, and the final PATH-selected script
successor returns zero. Both scripts compare stable $$, the selected pathname
in $0, remaining arguments, prefix export, and an inherited descriptor
persisted by redirection-only exec. Sequential child completion, isolated
nested-shell reuse, and current-environment replay of the provider-backed output
prove predecessor route/provider cleanup. The successor boundary releases
predecessor-local state only after it atomically reparents remaining inherited
descriptions to the exact same-realm candidate resolver through launchd's
receipt-free private vfsd call and migrates the matching cleanup-ledger rows. A
pre-boundary format refusal discards only duplicated candidate aliases, so the
running predecessor can read the selected script through its still-live stream.
The predecessor receiver is retired before the next shell is admitted. This
adds no executable to boot.img and grants rootd no new authority.
The times case invokes the no-operand special built-in four times: before and
after one failed lookup, after one terminal-observed ext4 child, and from an
ext4 successor that replaced the original stable shell job. A host validator
accepts only eight canonical C-locale rows, requires exact child-counter
equality across the failed lookup, strict child growth after the waited child,
unchanged child counters across replacement, strict successor self-time growth,
and non-regressing shell totals. Operand, prefix/redirection, closed-stdout,
and status behavior are checked inside the target first. The serial transcript
transfers no authority. Every snapshot uses the stable job's dedicated
send-only CPU-accounting endpoint, including after exec; neither shell
executable is added to boot.img. The final snapshot also proves that fixed
terminal descriptions use fresh successor-session endpoints rather than
senders owned by the predecessor TTY lifecycle that commit hangs up.
Because that snapshot is immediately followed by orderly exit, it also proves
that ttyd makes the successor routes non-callable while draining accepted bytes
through framebuffer and serial before exact receiver-capability cleanup.
The trap case checks persistent prefix and disposition replacement, canonical
default/ignore/executable listings, invalid-condition continuation, status-two
direct-special-builtin syntax termination in nested ext4 shells, and
closed-stdout status. Nested ext4 invocations prove EXIT action file effects,
pre-action status restoration, explicit and operand-less exit selection,
syntax-error status, caught self-TERM safe-point dispatch with exact status 143
both directly and through time, primary EOF dispatch, and
consume-before-execute recursion prevention. The serial transcript and terminal
status are the only
observations; neither rootd nor exsh receives signal, event, process, or job
authority.
Exact-revision KVM validation applies the same 120-second hard and 45-second
no-progress ceilings to the nested-child trap matrix and trap dispatch. These
bounds do not relax ordered, unique, terminal, failure-marker, or authority
assertions.
Disk-scenario ordering follows the signed semantic topology: VFS mount and I/O
readiness precede loaderd, then ttyd and launchd. The schema rejects a return to
the obsolete loader-before-mount host assertion.
The trap-dispatch case enables a ttyd integration fixture that commits and
consumes one canonical INT on the bootstrap session's first authenticated
event read through its existing bounded queue. The outer ext4 exsh forwards it
only over the bounded, syscall-yielding foreground child's returned exact job
route, observes status 130 before running the caught action, and then executes
the following external list member exactly once. Ordered unique markers prove
action-before-resume and no replay; rootd still owns only its status route, and
ordinary ttyd images do not enable the seeded event.
The asynchronous-wait case selects a distinct build-gated one-shot mode and the
unchanged outer rootd launch transcript. Ttyd preserves the first exact empty
post-asynchronous read and injects only on the same session's next read inside
wait. Launchd now returns a stable POSIX-visible process identity from a
namespace disjoint from recyclable kernel TCB IDs; procd retains that identity
through terminal state and successors while exact routes remain the only
lifecycle authority. The ext4 shell proves immediate asynchronous status zero,
distinct nonzero descriptive $! values, caught INT interruption of wait
at status 130, later status-seven observation, status-127 retirement, all-job
waiting, parent-state isolation, asynchronous here-document status nine, and
teardown cleanup of an unobserved final child. Rootd emits the success evidence
through shell built-ins, avoiding a utility lookup outside its deliberately
restricted PATH. Ordered unique markers and final readiness are observed over
serial; neither the scenario nor rootd gains a child job, process, event,
stream, or control selector. The one-entry
native-cli-asynchronous-wait group permits running only this new VM locally.
The focused VM passes its complete required, forbidden, unique, and ordered
marker contract at signed Integration 48c12c3 with rootd 5de3dee, procd
1f105a0, launchd 0b22de9, ttyd dbe2be2, and exsh f0f44af. It reaches
final readiness under the unchanged 120-second absolute and 45-second
serial-progress watchdogs.
The regular-builtins case uses the unchanged outer launch transcript and an
empty script-authority table. Distinct target-side statuses classify failures
in getopts, umask, command, or default-path execution before rootd emits a
single success marker. Its mask-077 file is read only through the exact stream
opened by exsh, so creation-mode privacy is preserved without granting the child
namespace authority. The one-entry native-cli-regular-builtins group permits
focused local execution while the pushed CI workflow continues to select the
complete scenario catalog.
The extop out-of-session case now completes its full negative contract. The
forged scalar control claim is denied with status 126, launchd publishes the
following authority-free coreutils job without inventing an accounting route,
and coreutils submits the complete completion marker and newline as one logical
write. Exact denial, shell success, rootd script success, and final readiness
markers all pass in the warning-free focused disk VM.
Component selection pins exsh, lib-ipc, and lib-tty as one coherent signal-
vocabulary set. This prevents a newly resolved PTY adapter from compiling
against an older pinned IPC catalog while keeping the catalog descriptive and
adding no event route to the VM.
The first complete replay exposed one kernel scheduler regression after all
438 scenarios reached launchd readiness: sustained pending IPC wake traffic
could starve the already-runnable cooperative block driver while the device had
completed its request. The focused replay pins the round-robin voluntary-yield
repair and passes without a driver reset or widened authority.
The pipeline case first rejects a mixed AND-OR list containing a singleton
compound pipeline with status 126 before any stream allocation and proves that
neither compound mutates parent state. It next commits a finite ext4 exsh child
before the missing second command returns status 127; partial-submission
reconciliation must observe that finite child and retire both job routes and
the provisional stream. The following valid work proves immediate reuse. The
fixture then transports
nondefault IFS, a readonly set variable, and a readonly declared-unset
variable into isolated ext4 children as exact descriptive LCS1 v1.5 state. It
requires zero from the IFS split/shift proof and one from both forbidden
assignments, then confirms the parent state did not change. It next commits one
three-stage ext4 pipeline: a function-definition child, a brace-group child
containing
built-in export, and an
exsh.elf -s reader for its reinput-safe declaration stream. The parent retains
its original variable and no function binding, proven by exact status 127 on
parent invocation. It then launches ext4 exsh as both writer and reader around
one launchd-provisioned stream. An outer built-in first prepares
valid shell input in ext4. The outer shell is required to commit each pair
before waiting;
the writer overrides stdout to a second ext4 file and the reader overrides
stdin from the prepared file. Explicit descriptor-three aliases retain both
logical pipe halves through child exit. The gate requires successful child
statuses to prove the output commit and redirected-input evaluation, retirement
of both exact status/control route pairs, and outer status zero before final
rootd readiness. No executable is added to boot.img, and neither exsh nor
rootd receives stream endpoint authority. Its first focused run reached
launchd readiness but exposed an exact 8-KiB managed-frame metadata allocation
with only 5,280 fragmented heap bytes free while the second 83-MiB exsh was
being staged. The authenticated native-CLI heap policy was raised from 72 MiB
to 80 MiB, and both large-shell scenarios now reject the kernel's exact
allocation-failure marker. The focused replay pins launchd 8ca9977, builds
the complete image without warnings. A superseded multi-pair fixture then timed
out after its first two children exited successfully, before reaching any
redirection, so it did not isolate the new behavior. The bounded single-pair
fixture exposed a pre-child status-126 failure: exsh semantically released a
pathname provider immediately after launchd had accepted cleanup ownership.
Exsh d4805f9 instead drops only its duplicate local aliases after COMMIT and
leaves launchd as the sole provider-lifecycle owner. A generated-checkout-only
binary search proved stream setup, process start, job publication, the
capability-bearing COMMIT reply, and temporary source retirement all complete.
The apparent first-COMMIT stall was an early local stop during the fixture's
normal long-running window, not a launchd/procd or authority regression. After
removing every diagnostic change, the warning-free focused replay passed both
role-preserving precedence cases and exact route retirement. The workload now
runs as separate state, function-isolation, and descriptor-redirection scripts,
each with an empty script-authority table and the common 120-second ceiling.
The later three-stage compound fixture exposed a distinct middle-child COMMIT
rejection. Launchd found an endpoint ordinal only among prepared rows; after
the reader transfer became live, the writer moved from filtered ordinal one to
zero and the requested ordinal became invalid. A diagnostic-only replay encoded
the exact COMMIT / INVALID_ARGUMENT / INTENT result as status 141, then all
instrumentation was removed. Launchd 8d96bc5 now counts every live transaction
row while resolving the stable ordinal and still requires the selected row to
be prepared, without granting exsh or rootd endpoint authority.
The next pristine replay passed all three new children, but exposed an
independent script-route rendezvous error before the final launch. A
behavior-preserving diagnostic encoded 0xE2100006: after non-blocking receive
reported a transfer waiter, the armed blocking receive resumed with retryable
status 6. Launchd 6c1f58e returns that outcome to bounded polling while
retaining fail-stop handling for terminal receive errors. It also reserves
transaction receipt ranges only across inventory-proven empty local slots, so
handed-off cleanup authority cannot become an implicit reusable destination.
The negative prefix then passes before the diagnostic-free positive pipelines,
proving both pre-BEGIN denial and finite-predecessor observation on the same
ext4-only path.
With diagnostics removed, the focused VM passes the three-stage isolation
proof, the prior redirection-precedence pair, exact cleanup, and final readiness.
The exact-state replay pins lib-ipc 96cffcf, launchd 2949549, exsh
6dd0a0a, and rootd e4a1270; with a conservative 1,800-second single-vCPU
host budget, it passes nondefault IFS plus readonly-set and
readonly-declared-unset child-state assertions while keeping exsh on the ext4
runtime partition rather than adding it to the boot image.
Scenario builds request the initial shell only for disk-image modes. The
historical standalone-appliance regression keeps that launch disabled, but its
secondary disk is now derived from the self-contained image so the production
ext4 program store remains available after mount. The derivation replaces the
copied ESP with a valid empty FAT32 filesystem: the packaged ESP tree is the
sole firmware boot source, /boot remains mountable, and loaderd, dynlinkd,
and procd load post-mount services from unchanged ext4 bytes. Boot-image-only
VMs still do not convert textual program configuration into unavailable
filesystem authority. Direct release packaging retains its configured auto
selection for the disk artifact pipeline.
The dynamic-linking shared-object pipeline is
scripts/build-dynlink-shared-objects.py. It scans library package manifests,
compiles each owning library crate to a target-none PIC object plus compiler
metadata sidecar, links one real ELF64 ET_DYN erix-<package>.so per
package/version/target/feature/ABI identity with ld.lld, records normal,
target-specific, optional, build, dev, and proc-macro dependency policy in
erix-dynlink-shared-object-registry-v2, and lets image packaging copy those
prebuilt objects instead of synthesizing per-executable dependency bytes.
Each zone-assigned shared-object image copy is stripped of non-runtime debug
and static-symbol metadata before its image hash is recorded; required
dynamic-linking sections and .erix_dynlink remain intact. Registry source
artifacts remain byte-identical and are never used as mutable packaging
scratch.
Each object identity commits to the exact owning source revision and the
ordered build identities of its dependency closure, so a source or transitive
dependency revision cannot reuse a stale logical object identity.
tests/dynlink-shared-object-pipeline.sh covers deduplication, DT_NEEDED
transitive object inclusion, real library symbols, compiler metadata sidecars,
compiler metadata dependency closures for downstream rustc-only executable
links, stale-hash rejection, and missing-transitive failure;
dynlink-real-shared-objects is the focused VM group.
The dynamic-linking prebuilt-consumption gate is
scripts/check-dynlink-prebuilt-consumption.py. It reads the shared-object
registry before each kernel or service build in
DYNLINK_PREBUILT_MODE=required, rejects missing, stale, wrong-target,
wrong-feature, wrong-ABI, manifest-digest-mismatched, source-fallback, or
static-bundle inputs, and writes
erix-dynlink-prebuilt-link-plan-v2 metadata for every Cargo manifest
dependency consumed as a shared object. Plans carry the source revision and
dependency build identities committed by the registry.
tests/dynlink-prebuilt-consumption.sh covers source-checkout-free link
planning, repeated dependency reuse, source-revision invalidation, transitive
identity invalidation, and negative registry mutations;
dynlink-prebuilt-consumption is the focused VM group.
The dynamic-linking kernel dynamic artifact gate is
scripts/build-dynlink-kernel-artifact.py plus the kernel-specific artifact
inspection path in scripts/check-dynlink-artifact-metadata.py. Dynamic image
packaging consumes kernel-dyn.elf as the kernel executable; VM, appliance,
and disk-image runners fail if that dynamic kernel fixture is absent.
No static kernel comparison fixture is built or staged. With a shared-object
registry, the generated artifact is linked
from kernel-owned PIC objects, the target-none Rust runtime shim, Rust
core/alloc/compiler-builtins archives, and DT_NEEDED edges to the prebuilt
shared objects. The direct rustc PIC path expands the kernel crate's Cargo
feature implications before compiling dynamic objects, so dynamic-kernel cfg
gates match the crate manifest. The shim supplies the current Rust allocator
ABI functions plus one exported copy of the C memory helpers used by early
shared-object relocations. It is an ELF64 ET_DYN PIE with
erix_dynlink_entry, entry ABI erix-kernel-relocated-entry-v2, handoff
pointer register rdi, exact handoff-size register rsi, entry-only exports,
undefined dependency implementation/import symbols, relocation records, and
dependency metadata matching dynlink-dependency-records.toml.
tests/dynlink-kernel-artifact.sh covers missing dependency metadata,
static-artifact rejection, import relocation checks, and accidental
dependency-export definitions inside the executable;
dynlink-kernel-artifact is the focused VM group.
Bootloader negative VM scenarios use the same dynamic kernel fixture before
mutating boot.img. When they exit early on a rejection marker, the VM harness
runs QEMU under its own process group and tears down that group before returning;
it also sweeps any remaining process with the exact scenario serial-log
argument before returning. tests/bootloader-vm-early-marker-cleanup.sh covers
the no-stale-QEMU regression. Serial marker success is token-boundary aware: a
terminal marker such as ERIX_ROOTD:READY does not match staged readiness
markers such as ERIX_ROOTD:READY:PROCD, so final-ready VM exits wait for the
real terminal stamp.
The dynamic-linking dynamic-kernel relocation path is covered by
dynlink-kernel-relocation. The group runs a positive VM that boots
through kernel-dyn.elf from the signed dynlink-store, resolves kernel
dependency imports from validated shared-object exports, and now includes
missing-object, stale-object, missing-export, duplicate-export,
unsupported-relocation, and W^X negatives that exit on bootloader markers before
ERIX_KERNEL:ENTER. The VM harness prepares bootloader exact-revision sources
for its UEFI build while isolating the helper boot-tool build so local override
patches do not create Cargo warning noise. In a monorepo checkout those
dependency checkouts may fetch the selected commit objects from sibling local
repositories, while Cargo resolves canonical URLs through generated mirrors
that preserve the original commit IDs.
The dynamic-linking dynamic boot catalog handoff path is covered by
dynlink-boot-catalog. The group runs only the new positive catalog
handoff scenario and the duplicate logical-name negative. It requires
ERIX_BOOTLOADER:DYNLINK_CATALOG_READY, ERIX_KERNEL:DYNLINK_CATALOG_OK, and
ERIX_ROOTD:READY on the positive path, while the negative exits on
ERIX_BOOTLOADER:DYNLINK_CATALOG_DUPLICATE_NAME before kernel entry.
The kernel entry length contract is covered independently by
kernel-handoff-length. This new focused group boots only the positive
pointer-and-length path and requires ERIX_KERNEL:HANDOFF_SIZE_OK before
dynamic catalog parsing and root readiness. It forbids both the exact-length
failure marker and the general handoff failure marker.
The normalized service-resolution receipt contract is covered independently by
named-resolution-receipt. Its sole new scenario launches the dynamic lookup
and time helpers, requires their successful completion markers, and therefore
proves that callers reserve the full receipt-bearing reply and authenticate the
transferred endpoint before use.
The dynamic-linking dynamic rootd bootstrap path is covered by
dynlink-rootd-bootstrap. The group runs only the new positive scenario
plus focused negatives for missing dependency, relocation failure, W^X
permission rejection, and stale shared-object hash. It selects
rootd_test_mode=dynlink-rootd-bootstrap, requires dynamic boot catalog
markers, kernel ROOTD_DYNBOOT markers, and
ERIX_ROOTD:DYNLINK_ROOTD:INTAKE_OK on success. The relocation negative
retargets a counted R_X86_64_RELATIVE entry to text and requires kernel
cleanup plus ROOT_SLOT_POLICY_VIOLATION, and the group keeps older VM groups
out of the focused run.
The dynamic-linking pre-procd dynamic launch path is covered by
dynlink-pre-procd. The group runs only the new positive scenario plus
focused negatives for missing dependency, unresolved symbol, dependency cycle,
W^X permission rejection, and cleanup after partial launch. It selects
rootd_test_mode=dynlink-pre-procd, requires dynamic boot catalog and
dynamic rootd intake markers, and on success requires
ERIX_ROOTD:DYNLINK_PRE_PROCD:MEMD_OK,
ERIX_ROOTD:DYNLINK_PRE_PROCD:VSPACED_OK,
ERIX_ROOTD:DYNLINK_PRE_PROCD:PAGERD_OK,
ERIX_ROOTD:DYNLINK_PRE_PROCD:PROCD_OK, and
ERIX_ROOTD:DYNLINK_PRE_PROCD:READY without starting dynlinkd.
The dynamic-linking procd early dynamic spawn path is covered by
dynlink-procd-spawn. The group runs only the new positive scenario,
selects rootd_test_mode=dynlink-procd-spawn, requires dynamic
boot-catalog and dynamic rootd intake markers, reuses the dynamic procd
from the pre-procd path, then requires procd-mediated denied-object,
abort, cleanup, map, start, and ready markers for dynamic memd, vspaced,
and pagerd before dynlinkd is available.
The dynamic-linking bootstrap helper port is covered by
dynlink-bootstrap-helpers. The group runs only the new positive
scenario, selects rootd_test_mode=dynlink-bootstrap-helpers, packages
probe, exit, isolation-a,
isolation-b, and fault-kill as dynamic boot artifacts, then
launches them through the rootd/procd early dynamic path. The verifier requires
the existing lazy-fault, isolation, expected-kill, and exit semantics plus the
ERIX_ROOTD:DYNLINK_BOOTSTRAP_HELPERS:CLEANUP_OK resource cleanup marker.
The dynamic-linking core-service coordination port is covered by
dynlink-core-services. The group runs only the new positive and
missing-dependency scenarios, selects
rootd_test_mode=dynlink-core-services, packages named, logd,
crashd, timed, lookup-client, and time-client as dynamic
boot artifacts, and launches them through the rootd/procd early dynamic path.
The verifier requires denied-object cleanup plus lookup, logging, crash, and
time markers while forbidding dynlinkd startup.
The dynamic-linking hardware, console, and input port is covered by
dynlink-hardware-console-services. The group runs only the new positive
and missing-dependency scenarios, selects
rootd_test_mode=dynlink-hardware-console-services, packages irqd,
deviced, probed, hotplugd, drv-acpi, driver-capcheck,
driver-hold, irq-client, drv-serial, seriald, fbcond,
drv-i8042, drv-ps2-keyboard, drv-ps2-mouse, and inputd as dynamic boot
artifacts, and launches the rootd-managed services through the rootd/procd
early dynamic path. The verifier requires interrupt delivery, driver
registration, serial and framebuffer console continuity, and the i8042
authority-partition marker while active input delivery remains post-mount
behind ext4-only ttyd. Missing dynamic dependencies fail before device or IRQ
authority is retained. The positive scenario enables deviced's integration-only
background-reconcile deferral so discovery reports do not start drivers until
rootd exercises the explicit admin verification path. Dynamic service artifact
builds expand the service crate's Cargo feature graph before the direct rustc
PIC compile, keeping integration feature aliases aligned with their runtime
cfg gates.
The dynamic-linking storage/filesystem/loader port is covered by
dynlink-storage-services. The group runs only the new positive and
missing-dependency scenarios, selects
rootd_test_mode=dynlink-storage-services, uses the loader-fs
media, packages drv-virtio-block, blockd, ramfsd, keyd, e2fsd,
fatd, vfsd, dynlinkd, and loaderd as dynamic artifacts, starts
dynlinkd before loaderd, and keeps loader process handoff explicit. The
fixture mode selection treats this stack as both a loader stack and a
dynlinkd stack, so the generated dynlinkd boot-config node always has a
matching packaged dynamic service artifact before loaderd can start. The
verifier requires storage, VFS, loader, disk-execution, process-handoff, and
fail-closed missing-object markers while preserving the existing explicit
block, filesystem, key, VFS, loader, and procd authority bundles.
The dynamic-linking dynamic materialization fixture extends loader-fs with
/lib/erix/dynlink/objects/filesystem/libdep.so. The disk-backed
/bin/dyn-loader-ok executable relocates a dependency pointer and exits
with the byte loaded from that object. The complete-graph scenario proves those
dependency bytes execute through the same filesystem launch path instead of
boot-image module bytes or a summary-only handoff.
The dynamic-linking artifact metadata gate is
scripts/check-dynlink-artifact-metadata.py plus
dynlink-artifact-abi.toml. The ABI record fixes the supported Rust/no-std
dynamic artifact shape as ELF64 x86_64 ET_DYN, .erix_dynlink metadata,
PIE executable or shared-object kind, erix_dynlink_entry for executables,
panic-abort/no-unwind, and unsupported TLS, init/fini, lazy binding, IFUNC,
text relocations, and unwind features. Generated dynamic dependency objects are
inspectable ELF fixtures with .dynamic, .dynsym, .rela.dyn, SysV hash,
and .erix_dynlink sections. The checker runs before packaging and fails if
metadata is missing, hashes are stale, unsupported features are declared, or
bootloader stops being the only static executable exception. Image manifests
pass --strict-executables before every boot image, runtime appliance, and
disk-image packaging path. Non-bootloader executable artifact bytes are
inspected with the same ET_DYN and metadata rules before any VM boot can use
them, so kernel, rootd, services, and drivers cannot silently fall back to
static artifacts. After coordinated CI artifact builds, CI also runs
scripts/check-dynlink-porting-wave-gates.py over the generated executable
inventory, searching the consolidated component tree and any focused VM worker
component trees that exist. Every artifact actually built must be dynamic and
have dependency metadata matching
dynlink-dependency-records.toml; migrated targets not selected by that
scenario set are reported as unbuilt rather than treated as failed builds.
Ordinary sibling-repository Cargo outputs are not packaging artifacts and are
excluded unless a caller explicitly names them with --artifact-root.
Callers that intentionally build the complete migrated inventory can add
--require-all-artifacts.
Service-state packaging also patches deviced with the configured binding and
HAL-registration record counts. The corresponding exact typed arena replaces
the daemon's former crate-wide 16-record tables without granting allocator
authority or exposing page-rounding padding.
It patches irqd from the configured handler-record count in the same pass;
the focused capacity image carries 256 records in a two-page arena.
It patches crashd from the configured report-record count as well; the new
focused capacity VM packages 512 records, accepts a procd crash report, and
proves typed readback through the authority-partitioned public endpoint.
The final staged VM boot service fixtures are independently checked by
scripts/lib/dynamic-boot-fixtures.sh, which invokes the same metadata checker
on each copied service path before fonts, boot config generation, or boot image
publication.
The dynamic-linking lookup-manifest gate is part of
scripts/build-dynlink-image-manifest.py and
scripts/verify-dynlink-image-closure.py. Generated image manifests now carry
erix-dynlink-lookup-manifest-v1 dependency rows that map every executable
dependency to an object path, object hash, metadata hash, version, object ABI,
object identity, allowed lookup root, and stable load order. The only native
lookup roots are the boot-image early bundle and the runtime filesystem object
store; current-directory lookup, global search paths, service-discovery bypass,
and direct block-device lookup are forbidden. tests/dynlink-lookup-manifests.sh
and dynlink-lookup-manifests cover the focused host and VM gates.
The dynamic-linking acceptance-closure gate is
scripts/check-dynlink-acceptance-closure.py plus
dynlink-acceptance-closure.toml. It maps the six executable porting waves and
every dynamic-linking acceptance criterion to runnable scenario groups or host CI
gates, validates that each non-bootloader migration row is assigned to a wave,
and keeps bootloader as the only approved static executable exception. CI runs
the map with final runtime migration enabled for the closure scenario: kernel
and service rows must be migrated, kernel has no static boot-artifact
exception, and category = "tool" host-tool rows remain tracked without becoming
runtime image exceptions. The focused dynlink-final-migration-closure
group runs --require-final-migration before image build and boot. The
focused bootimg-dynamic-focused group is also mapped as the dynamic boot-image
VM coverage criterion. The migration inventory classifies ext4-only exsh as
migrated; full POSIX shell-language completion is a product milestone, not a
reason to misclassify the executable's already completed dynamic packaging and
launch path.
dynamic-linking documentation additionally requires the generated
closure-report.json and filesystem mirror rows to be usable as operator
evidence for boot.img inspection, mirror comparison, and dynamic failure-class
triage.
All scenario classes execute as VM boots. The default full-system scenario
validates core multi-service bootstrap smoke (bootloader -> kernel -> rootd -> {memd,vspaced,pagerd,procd} contract checks), and runtime appliance/disk-image
scenarios boot their packaged images to the terminal ERIX_ROOTD:READY stamp
unless they are explicit negative media tests. The current packaging workflow
does not boot them. The complete catalog and focused groups remain available
for local or separately requested validation without running older VM
scenarios in the current pushed gate.
Filesystem Compliance and Strict Gate
scripts/fs_compliance_matrix.py is the checked cross-filesystem status matrix.
It records FAT12, FAT16, FAT32, VFAT, exFAT, ext2, ext3, and ext4 rows as
read-write, read-only, rejected, obsolete-rejected, or planned, and links
accepted states to unit tests, deterministic media, host producer tools, host
verification tools, and VM scenarios. Negative media is grouped by malformed
feature bits, metadata checksums, geometry, allocation accounting, directory
entries, journal state, and bitmap state.
Operation probes are checked alongside the status matrix. They record the
current provider result for mount,
open/create, read/write, directory, rename, truncate, symlink/readlink,
hard-link, metadata-update, unlink/rmdir, and xattr surfaces for each
FAT/exFAT/ext format. The matrix checker rejects rows that advertise a mutable
operation while the current provider path is explicitly denied, and it documents
preservation-only or permanent non-goal surfaces without adding new provider
authority.
tests/fs-compliance-matrix.sh remains available as a local matrix-drift
diagnostic without running a VM. In an integration-only checkout, cross-repo
evidence is resolved from out/components/<repo> after
scripts/clone-components.sh; in a monorepo checkout, sibling repos such as
../fatd and ../e2fsd are used directly. CI relies on the focused
fs-compliance-matrix VM scenario group instead of running the standalone
matrix checker as a separate gate.
scripts/fs-strict-validation.sh is the local strict filesystem slice gate: it
runs the ext feature-registry and ext interoperability checkers, then runs
cargo fmt --all -- --check, cargo clippy --all-targets -- -D warnings, and
cargo test --all-targets for the filesystem Rust repos, and finally runs the
focused fs-compliance-matrix VM scenario group unless
ERIX_FS_STRICT_SKIP_VM=1 is set.
Every scenario is parsed once as strict schema-version-1 TOML before fixture
construction. scripts/parse-scenario.py rejects duplicate or unknown keys,
wrong scalar types, unsupported product-independent enum values, invalid
cross-field combinations, non-positive CPU counts, negative timeouts, filename
/ scenario-name mismatches, and duplicate names across the committed scenario
set. Boolean fields such as qemu_block_readonly use native TOML booleans;
qemu_smp_cpus and qemu_timeout_secs use native TOML integers. The shell
runner receives only shell-quoted assignments whose field names come from that
closed schema.
Scenario schema includes rootd bring-up controls:
kernel_rootd_test(none|smoke|runtime)rootd_test_mode(none|smoke|force-fail|bootstrap-*|core-service-*|hardware-*|console-and-input-*|storage-*|input-readiness|multi-block-provider|dynlink-rootd-bootstrap|dynlink-pre-procd|dynlink-procd-spawn|dynlink-bootstrap-helpers|dynlink-core-services|dynlink-hardware-console-services|dynlink-storage-services)- in current implementation this is translated into a generated BootConfig
payload (
out/fixtures/boot-config.bin) instead of selecting rootd launch arrays at compile-time - publication flags are emitted only for the target-scoped
pagerd,timed, andirqdservices and only whennamedis present; bootstrap-only graphs carry no discovery declaration loader-contractselects validation profile26and the same memory-provider/vfsdservice stack asvfs-memoryloader-fs-discovery,loader-materialized-launch, andloader-cleanup-authorityselect distinct validation profiles27,28, and29over the same canonical topology; Cargo features cannot select or override the loader verifier policymulti-block-providerselects validation profile21, the ordinary storage launch graph, and an additional rootd proof that the namespace contains at least two distinct physical whole-disk providersinput-readinessselects the pre-mount input graph and proves the partitioned i8042 diagnostics and translator endpoints without injecting an event that would require ext4-only ttyddynlink-rootd-bootstrapselects validation profile34, the bootstrap foundation service stack only, and the dynamic rootd bootstrap verifierdynlink-pre-procdselects validation profile35, the bootstrap foundation service stack only, and the dynamic pre-procdservice launch verifierdynlink-procd-spawnselects validation profile36, the bootstrap foundation service stack only, and theprocd-mediated early dynamic service spawn verifierdynlink-bootstrap-helpersselects validation profile37, the bootstrap helper dynamic launch verifierdynlink-core-servicesselects validation profile38, the core-service coordination dynamic launch verifierdynlink-hardware-console-servicesselects validation profile39, the hardware, console, and input dynamic launch verifierdynlink-storage-servicesselects validation profile40, the storage, filesystem, VFS, and loader dynamic launch verifier
- in current implementation this is translated into a generated BootConfig
payload (
dynlinkd_test_mode(none|smoke|force-fail)- controls the
dynlinkdservice binary features for complete loader profiles, includingrootd_test_mode=dynlink-storage-services
- controls the
dynlink_final_migration_mode(disabled|required)- when required, regenerates executable inventory, requires acceptance closure before build, and forces every executable in the selected boot graph through dynamic artifact generation
runtime_config_profile(dev|release)- selects
runtime.<profile>.tomlat integration repo root
- selects
runtime_config_path(optional, relative to integration root or absolute)- explicit runtime TOML override for scenario/appliance builds
- if omitted,
runtime.<profile>.tomlis used - local overrides must be selected explicitly, for example
RUNTIME_CONFIG_PATH=runtime.local.toml features.program_loader=trueaddsloaderdbehind the loader runtime toggle, requires VFS plus ext-backed storage, and selectsloader-fsfor automatic block-storage fixture media
require_markersandforbid_markersaccept comma-separated exact markers; a trailing*selects an entire marker prefix for family-wide assertionsunique_markersaccepts the same syntax and requires each selected marker to occur exactly once in the serial logordered_markersaccepts the same syntax and requires the selected markers to occur in the listed serial-log orderblock_storage_image(auto|none|gpt|malformed-gpt|fs|loader-fs|fs-ext2|fs-ext2-indirect|fs-ext2-compat|fs-ext2-xattr|fs-ext2-geometry-512|fs-ext2-links|fs-ext2-rename|fs-ext2-corpus-1k|fs-ext2-corpus-2k|fs-ext2-corpus-4k|fs-ext3|fs-ext3-replay|fs-ext3-external-journal|fs-ext3-jbd2-legacy|fs-ext3-jbd2-csum-v2|fs-ext3-jbd2-csum-v3|fs-ext3-many-journal|fs-ext3-fast-commit|fs-ext3-htree|fs-ext3-htree-depth0|fs-ext3-htree-depth1|fs-ext3-geometry-512|fs-ext3-links|fs-ext3-rename|fs-ext4-metadata|fs-ext4-extent-tree|fs-ext4-bigalloc|fs-ext4-meta-bg|fs-ext4-stable-resize|fs-ext4-xattr|fs-ext4-quota|fs-ext4-orphan-list|fs-ext4-orphan-file|fs-ext4-mmp|fs-ext4-large-dir|fs-ext4-encrypted|fs-ext4-encrypted-casefold|fs-ext4-casefold|fs-ext4-inline|fs-ext4-verity|fs-ext4-verity-salted|fs-ext4-verity-large|fs-ext4-shared-blocks|fs-ext4-geometry-512|fs-ext4-links|fs-ext4-rename|fs-fat12|fs-fat12-metadata|fs-fat16|fs-fat16-metadata|fs-fat32-primary-only|fs-fat32-mirrored|fs-fat32-active-fat|fs-fat32-metadata-clean|fs-fat32-directory-metadata|fs-fat32-metadata-set|fs-fat32-short-name|fs-fat32-rename|fs-fat32-vfat-unicode|fs-fat32-stress|fs-fat32-deep-directory|fs-exfat|fs-exfat-boot-region|fs-exfat-stale-backup|fs-exfat-one-fat|fs-exfat-active-fat|fs-exfat-unicode|fs-exfat-contiguous|fs-exfat-stream-metadata|fs-exfat-metadata|fs-exfat-entry-types|fs-exfat-rename|fs-exfat-corpus|malformed-fat|malformed-exfat|exfat-bad-upcase-table|exfat-bad-name-hash|exfat-duplicate-upcase-name|exfat-malformed-utf16-name|exfat-bad-main-boot|exfat-bad-backup-boot|exfat-bad-extended-boot|exfat-boot-region-mismatch|exfat-dirty-volume|exfat-media-failure|exfat-invalid-active-fat|exfat-reserved-volume-flags|exfat-duplicate-bitmap-entry|exfat-duplicate-upcase-entry|exfat-bad-bitmap-entry|exfat-bad-bitmap-length|exfat-corrupt-directory-set|exfat-bad-entry-type|exfat-bitmap-fat-mismatch|exfat-duplicate-cluster|exfat-no-fat-missing-bitmap|exfat-leaked-cluster|exfat-chain-loop|exfat-out-of-range-chain|exfat-invalid-valid-data|malformed-ext|ext2-inconsistent-block-geometry|ext3-inconsistent-block-geometry|ext4-large-inode|ext2-bad-block-map|ext2-bad-dirent|ext2-bad-inode-size|ext2-bad-bitmap|ext2-reserved-inode-corruption|ext-needs-recovery|fat-mirror-mismatch|fat-cluster-loop|fat-bad-lfn|fat-bad-lfn-ordinal|fat-orphan-lfn|fat-duplicate-alias|fat-short-leading-e5|fat-oem-short-name|fat-invalid-nt-flags|fat-ambiguous-lfn-alias|fat-bad-cluster-chain|fat-file-chain-loop|fat-cross-linked-files|fat-out-of-range-chain|fat32-bad-fsinfo-count|fat32-bad-backup-boot|fat32-dirty-metadata|fat32-hard-error-metadata|fat32-bad-reserved-entry|ext-checksum-failure|ext-unsupported-feature|ext-obsolete-feature-corpus|ext-unknown-feature-corpus|ext-unknown-feature-gap-corpus|ext-readonly-feature|ext-shared-blocks-feature|ext-journal-device-volume|ext-bigalloc-bad-bitmap|ext4-meta-bg-bad-descriptor|ext4-encrypted-missing-key|ext4-encrypted-wrong-key|ext4-encrypted-casefold-missing-key|ext4-encrypted-casefold-wrong-key|ext4-bad-fscrypt-policy|ext4-bad-encrypted-casefold-policy|ext4-bad-encrypted-casefold-name|ext4-bad-casefold-encoding|ext4-bad-casefold-name|ext4-bad-xattr|ext4-bad-quota|ext4-bad-orphan-list|ext4-bad-orphan-file|ext4-bad-mmp-active|ext4-bad-mmp-checksum|ext4-bad-inline-data|ext4-bad-verity-data|ext4-bad-verity-algorithm|ext4-bad-verity-signature|ext4-verity-signature|ext4-verity-encrypted|ext4-bad-verity-merkle|ext-external-journal|ext-jbd2-unknown-feature|ext-jbd2-csum-failure|ext-fast-commit-mutating|ext-fast-commit-htree|ext-fast-commit-linear|ext-fast-commit-bad-tail|ext-external-journal-uuid-mismatch|ext-external-journal-misroute|ext-malformed-extent|ext-malformed-htree|ext-malformed-htree-index|ext-malformed-htree-deep)autoattaches the deterministic GPT disk only whenfeatures.user_storage=trueandfeatures.storage_virtio=true- non-
nonevariants attach a secondary raw modern-only virtio-blk disk to QEMU (virtio-blk-pci,disable-legacy=on) in read-only mode so the deterministic fixture cannot be rewritten during negative-path boots fsbuilds a GPT disk witherix-espFAT32 anderix-dataext4 partitions;loader-fsuses a clean ext2erix-datapartition and adds executable/binELFs with distinct byte fingerprints and exit markers, a dynamic dependency object at/lib/erix/dynlink/objects/filesystem/libdep.so, plus a changed-source ELF used to prove stale materialization fails before process start; host-side scenario verification checks those fingerprints are present only in the filesystem executable/object fixtures and absent from boot image service modules;fs-ext2andfs-ext3use clean ext2/ext3 data partitions for legacy provider coverage;fs-ext2-indirectadds a host-generated ext2 large-file corpus that crosses the direct-block boundary and verifies a VFS-created block-stride probe file after shutdown;fs-ext2-compatcarriesdir_prealloc,imagic_inodes,ext_attr, andresize_inodefor ext2 compatibility safety coverage;fs-ext2-xattradds user xattr and POSIX ACL payloads and verifies hostdebugfspluse2fsck -fnxattr/ACL preservation after VM mutation, withgetfattr/getfaclprojection when FUSE is available;fs-ext2-geometry-512keeps ext2 at the supported 4 KiB block limit while validating 512-byte inode tables and inline xattr preservation;fs-ext2-corpus-1k,fs-ext2-corpus-2k, andfs-ext2-corpus-4kbroaden ext2 coverage with varied block/inode geometry, sparse superblocks, non-default blocks-per-group, grown directories, and sparse triple-indirect host files;ext2-inconsistent-block-geometryadvertises a different block size without changing the encoded layout and therefore fails closed;ext2-bad-block-map,ext2-bad-dirent,ext2-bad-inode-size,ext2-bad-bitmap, andext2-reserved-inode-corruptionprovide fail-closed malformed ext2 media;fs-ext3-replay,fs-ext3-external-journal,fs-ext3-jbd2-legacy,fs-ext3-jbd2-csum-v2,fs-ext3-jbd2-csum-v3,fs-ext3-many-journal,fs-ext3-fast-commit,ext-fast-commit-mutating,ext-fast-commit-htree,ext-fast-commit-linear,ext-fast-commit-bad-tail,fs-ext3-htree,fs-ext3-htree-depth0,fs-ext3-htree-depth1, andfs-ext3-geometry-512exercise recovery-required replay, explicit same-disk external-journal partition selection, legacy and CRC32C checksum-v2/v3 JBD2 dialect validation, device-absolute external JBD2 log addressing independent of the journal-superblock offset, journal-ring replay without a fixed transaction-count cap, split provider-originated journaled writeback, ordered-data large writes, fast-commit no-delta validation, supported multi-segment mutating-delta replay, indexed-directory and multi-block linear dentry replay, and bad-tail fast-commit fail-closed media;ext3-inconsistent-block-geometryapplies the same malformed-layout check to journaled media; indexed-directory ext3 mutation coverage;ext-malformed-htree-indexandext-malformed-htree-deepkeep malformed index layouts and non-large_dirdepth-2 HTree metadata fail-closed; these malformed fixtures keep scenario-local QEMU timeouts because they must prove public mount exposure before the focused malformed-directory operation fails;ext-external-journal,ext-journal-device-volume,ext-external-journal-uuid-mismatch, andext-external-journal-misroutecover fail-closed missing mapping, standalone journal-device, UUID, and BootConfig mapping failures;fs-ext4-metadataadds metadata checksums and a host-built indexed HTree directory;fs-ext4-extent-treefragments free space so VFS-created large files spill into indexed extent leaf blocks and are checked after shutdown; the focused ext sparse scenario reuses that media to prove write-past-EOF gaps stay unmapped with hostdebugfs bmapand cleane2fsck -fn;fs-ext4-bigallocuses e2fsprogs bigalloc media to prove cluster bitmap and free-count accounting, whileext-bigalloc-bad-bitmapflips a free cluster bit without fixing counters so mount validation fails closed;fs-ext4-meta-bguses e2fsprogsmeta_bgdescriptor placement with non-default blocks-per-group, andext4-meta-bg-bad-descriptorcorruptss_first_meta_bgsoe2fsdrejects impossible descriptor layout;fs-ext4-stable-resizecarriesstable_inodesplusresize_inodemedia so VM mutation, hoste2fsck -fn, and generator checks cover stable inode mutation safety and resize-reserved metadata preservation;fs-ext4-xattrcarries metadata-checksummed external xattr blocks, inline inode-body xattr metadata, a large user xattr, and a POSIX ACL, verifies preservation with hostdebugfspluse2fsck -fn, projectsgetfattr/getfaclchecks when FUSE is available, whileext4-bad-xattrcorrupts the external xattr checksum for fail-closed validation;fs-ext4-quotacarries user/group/project quota metadata and aPROJINHERITdirectory, whileext4-bad-quotacorrupts quota metadata for fail-closed validation;fs-ext4-orphan-listandfs-ext4-orphan-filecarry recoverable legacy and orphan-file orphan state, whileext4-bad-orphan-listandext4-bad-orphan-filecover fail-closed corrupt orphan metadata;fs-ext4-mmpcarries clean metadata-checksummed MMP media, whileext4-bad-mmp-activeandext4-bad-mmp-checksumprove active and malformed MMP state fail closed;fs-ext4-large-dircarries ext4large_dirmedia with a depth-2 HTree for VFS marker insertion and hostdebugfs/e2fsck -fnchecks;fs-ext4-encryptedcarries an fscrypt v2 encrypted host marker unlocked only through keyd startup material, whileext4-encrypted-missing-key,ext4-encrypted-wrong-key, andext4-bad-fscrypt-policyprove missing material, mismatched material, and malformed policy modes fail closed;ext4-fscrypt-v1-policy,ext4-fscrypt-hctr2-policy,ext4-fscrypt-direct-key-policy, andext4-fscrypt-data-unit-policyprove explicit non-goal fscrypt policies fail closed before key lookup;fs-ext4-encrypted-casefoldcarries an encrypted case-insensitive directory that is unlocked through keyd and verified by lookup plus readdir, whileext4-encrypted-casefold-missing-key,ext4-encrypted-casefold-wrong-key,ext4-bad-encrypted-casefold-policy, andext4-bad-encrypted-casefold-nameprove missing material, mismatched material, malformed policy metadata, and malformed encrypted names fail closed;fs-ext4-casefoldcarries host-created UTF-8 casefold directories with root-level folded lookup and indexed/htreemutation, whileext4-bad-casefold-encodingandext4-bad-casefold-nameprove unsupported encodings and malformed normalized names fail closed;fs-ext4-inlinecarries ext4 inline-data files and directories, verifies inline host and VFS markers withdebugfspluse2fsck -fn, andext4-bad-inline-dataproves malformed inline payloads fail closed;fs-ext4-veritycarries a read-only Linux-layout fsverity host marker unlocked through a private keyd trust root,fs-ext4-verity-saltedadds descriptor salt coverage, andext4-bad-verity-data,ext4-bad-verity-algorithm,ext4-bad-verity-signature,ext4-verity-signature,ext4-verity-encrypted, andext4-bad-verity-merkleprove fail-closed data, algorithm, malformed PKCS#7, unsupported signature-policy, encrypted verity, and Merkle-tree tamper rejection;fs-ext4-shared-blockscarries shared-block ext4 media with a depth-2 HTree and uses rootd's read-only profile for host-marker traversal, whileext-shared-blocks-featureproves read-write mount denial;fs-ext4-geometry-512carries 4 KiB blocks and 512-byte inodes with metadata checksums, extents, an internal journal, indexed directories, inode-body xattrs, and inline-data payloads;ext4-large-inodeproves 1,024-byte inode records mount and preserve their unknown tails during metadata mutation;fs-ext2-links,fs-ext3-links, andfs-ext4-linkscarry host-created fast and block-backed symlinks, regular-file hard links, and FIFO/character/block special inode metadata; theext-linksgroup verifies readlink/stat/link-count behavior and proves special-file metadata does not imply openable device authority;fs-ext2-rename,fs-ext3-rename, andfs-ext4-renamecarry host-created rename fixtures for same-directory moves, cross-directory moves, compatible overwrite, directory..repair, special metadata entries, and indexed HTree entries; theext-renamegroup verifies the public VFS-visible results and leaves the media clean for hoste2fsck -fn;fs-fat12,fs-fat12-metadata,fs-fat16,fs-fat16-metadata,fs-fat32-primary-only,fs-fat32-mirrored,fs-fat32-active-fat,fs-fat32-metadata-clean,fs-fat32-directory-metadata,fs-fat32-metadata-set,fs-fat32-short-name,fs-fat32-rename,fs-fat32-vfat-unicode,fs-fat32-stress,fs-fat32-deep-directory,fs-exfat,fs-exfat-boot-region,fs-exfat-stale-backup,fs-exfat-one-fat,fs-exfat-active-fat,fs-exfat-unicode,fs-exfat-contiguous,fs-exfat-stream-metadata,fs-exfat-metadata,fs-exfat-entry-types,fs-exfat-rename, andfs-exfat-corpusvary ESP media geometry, FAT32 extended-BPB policy, FAT32 reserved-entry state, FAT directory-entry metadata, VFAT Unicode/dense-alias entries, fragmented FAT allocation, grown directories, sparse-looking payloads, free-slot reuse, exFAT main/backup boot-region checksum policy, exFAT active-FAT/volume-state policy, exFAT upcase-table UnicodeNameHashpolicy, exFAT no-FAT-chain allocation policy, exFATValidDataLengthzero-fill behavior, and fragmented exFAT streams, plus 1 KiB exFAT clusters, two FATs, dual allocation bitmaps, a grown root chain, fragmented host data, deep Unicode-heavy paths, and spare allocation clusters for public VFS mutations while keeping the same clean ext4 data partition and storage marker flow; active-FAT media uses a direct FAT divergence check because dosfstools repairs the intentionally inactive FAT copy even when ExtFlags selects FAT 1;ext-obsolete-feature-corpussets all obsolete ext feature bits rejected bye2fsd,ext-unknown-feature-corpussets high future compat, incompat, and ro-compat bits, andext-unknown-feature-gap-corpussets currently undefined feature-bit gaps so negative VM scenarios prove fail-closed mount behavior before VFS state is exposed;e2fs-fatpositives setqemu_block_readonly=falseto exercise writable mount requests;e2fs-fat-readonlypositives attach writable QEMU media but pass the VFS read-only mount flag for/malformed-gptcorrupts the primary GPT header CRC and entry array after CRCs are written so storage fail-closed negatives stay deterministic- malformed FAT/ext variants derive from the filesystem disk and corrupt
provider-specific media, including FAT mirror mismatch, FAT cluster loops,
bad VFAT LFN entries, duplicate short aliases, bad referenced FAT chains,
cross-linked files, out-of-range FAT links, inconsistent FSInfo counts,
malformed exFAT upcase metadata, bad exFAT
NameHashentries, duplicate exFAT upcase-equivalent names, malformed exFAT UTF-16 names, bitmap/FAT mismatches, duplicate exFAT cluster ownership, missing no-FAT-chain bitmap coverage, leaked clusters, exFAT chain loops, out-of-range exFAT starts, ext checksum- required media, unsupported/obsolete/unknown ext features, external journal metadata, standalone journal-device volumes, external-journal UUID/mapping failures, unknown JBD2 feature bits, JBD2 checksum failures, bad fast-commit tails and mixed/indexed/linear fast-commit replay after full commits, malformed extents, malformed HTree metadata, malformed ext4 casefold metadata, and malformed inline-data metadata
qemu_block_readonly(TOML Boolean)- defaults to
truefor existing block-storage scenarios - set to
falseonly when a scenario intentionally validates writable media
- defaults to
disk_image_case(no-virtio-sata|single-virtio-junk-sata|single-virtio-esp-raw-sata|single-virtio-gpt|two-virtio-disks)- used with
run_mode=vm-disk-imageto boot the packaged.imgthrough QEMU and validate SATA/virtio storage topology behavior - extra virtio disks are read-only unless the scenario adds the
:rwsuffix; the two-virtio case keeps junk media read-only while making the copied GPT storage disk writable for the runtime/mount
- used with
missing_service(none|memd|vspaced|pagerd|procd|probe|named|timed|logd|crashd|irqd|deviced|probed|hotplugd|drv-acpi|drv-serial|drv-virtio-block|seriald|blockd|fbcond|console-font|drv-i8042|drv-ps2-keyboard|drv-ps2-mouse|inputd|ramfsd|keyd|e2fsd|fatd|vfsd|lookup|time|irq|driver-hold|driver-capcheck)- in
e2fs-fat, missing-provider negatives prove the specific absent provider blocks VFS exposure; the missing-FAT-provider case still expectsE2FSDreadiness because rootd starts the ext provider first
- in
service_primary_control_fault(none|probed-omit-primary-control|probed-misroute-primary-control|drv-acpi-omit-primary-control|drv-acpi-misroute-primary-control|drv-serial-omit-primary-control|drv-serial-misroute-primary-control|drv-i8042-omit-primary-control|drv-i8042-misroute-primary-control)- integration-only authority-shape override for staged service startup
- used to prove fail-closed behavior when a narrow primary-control endpoint is omitted or replaced with the wrong endpoint family
- constructor-rejected variants must not require receiver retirement: the child never starts or binds a receiver after route validation fails
service_explicit_endpoint_fault(none|deviced-misroute-pci-config-endpoint|deviced-misroute-pci-device-endpoint)- integration-only wrong-kind auxiliary endpoint override for staged service startup
- used to prove fail-closed validation of explicit endpoint source-slot and endpoint-kind contracts outside the primary control slot
service_startup_peer_fault(none|logd-inject-timed-resolution-scope|probed-omit-deviced-peer|probed-misroute-deviced-peer|probed-inject-undeclared-peer|inputd-omit-deviced-peer|inputd-misroute-deviced-peer|drv-serial-omit-deviced-peer|drv-serial-misroute-deviced-peer|drv-serial-misroute-logd-peer|vfsd-omit-memory-provider-peer|vfsd-misroute-memory-provider-peer|e2fsd-omit-blockd-peer|e2fsd-misroute-blockd-peer|e2fsd-omit-keyd-peer|e2fsd-misroute-keyd-peer|fatd-omit-blockd-peer|fatd-misroute-blockd-peer|vfsd-omit-e2fsd-peer|vfsd-misroute-e2fsd-peer|vfsd-omit-fatd-peer|vfsd-misroute-fatd-peer)- integration-only startup-peer override for split delegated peers
- used to prove fail-closed rejection of omitted, misrouted, or undeclared startup peers for both root-launched and deviced-launched consumers
- source/destination selection is an authority-free library result; rootd supplies both candidate pairs and remains the only component that validates and transfers the selected capability
- project requirements:
logd-inject-timed-resolution-scope -> rootd_test_mode=logging,probed-* -> rootd_test_mode=probe,inputd-* -> rootd_test_mode=input,drv-serial-* -> rootd_test_mode=serial,vfsd-omit-memory-provider-peer|vfsd-misroute-memory-provider-peer -> rootd_test_mode=vfs-memory, ande2fsd-*|fatd-*|vfsd-*-e2fsd-peer|vfsd-*-fatd-peer -> rootd_test_mode=e2fs-fat - the omitted memory-provider peer case may still require
VFSDreadiness as precursor evidence, but it must forbidVFS_MOUNTandVFS_IO
- per-service build modes:
memd_test_mode,vspaced_test_mode,pagerd_test_mode,procd_test_mode,named_test_mode,timed_test_mode,logd_test_mode,crashd_test_mode,irqd_test_mode,deviced_test_mode,probed_test_mode,hotplugd_test_mode,drv_acpi_test_mode,drv_serial_test_mode,drv_virtio_block_test_mode,seriald_test_mode,blockd_test_mode,fbcond_test_mode,drv_i8042_test_mode,drv_ps2_keyboard_test_mode,drv_ps2_mouse_test_mode,inputd_test_mode- values:
none|runtime|smoke|serial-probe|force-fail(serial-probecurrently applies todrv_serial_test_mode)
Runtime policy:
kernel_rootd_test=runtimeis bootstrap-only bring-up driven by generated BootConfig from runtime TOML, withvalidation_profile=none.- BootConfig v1.5 encodes compact timeout-free entries and dependency-role
records in separate count-derived tables. Dependencies must name earlier
entries, so the payload
itself carries a canonical topological launch order without fixed graph or
per-entry dependency ceilings. Every generated graph begins with the exact
required direct-launch chain
procd -> memd -> vspaced -> pagerd; the generator rejects attempts to omit any member, and the rootd ingress rejects insertion, reordering, stage reuse, cycles, undeclared edges, or duplicate roles. PrivateKYD1,EJRN, andMNT1tail tables are likewise sized by their encoded row and path counts. A final optionalFSL1table binds each filesystem-launch entry in order to one exact role, canonical path, and role-private startup policy without embedding the executable. - Kernel-to-root module records carry the exact verified file size in addition to the page-rounded mapping extent, so rootd parses precisely the generated BootConfig bytes rather than mapping padding.
- runtime VM scenarios opt into
RUNTIME_IMAGE_TEST_HARNESS=1so QEMU exits classed success/failure without enabling smoke-only service feature gates. - runtime/appliance kernel builds enable
kernel-runtime-image; packaged dev and release artifacts leaveRUNTIME_IMAGE_TEST_HARNESS=0sokernel-rootd-smoke-testand integration debug-exit code are not included. - runtime/appliance rootd builds keep diagnostic chatter quiet as well:
ERIX_ROOTD:TRACE:*, late VFS verifier probes, and focused test-marker mutation paths are reserved for integration smoke runs and must stay out of ordinary runtime/appliance serial output. - High-volume focused runtime fixtures, including the pipeline, wait, and
native-time workflows, select the kernel's
kernel-integration-runtime-quietrefinement. It removes only repetitive successful demand-fault, process-exit, lifecycle, and rootd/logd-reply debug projection while preserving exact RTC evidence, failure diagnostics, marker contracts, guest behavior, and the explicit host-report terminal. - runtime mode must not rely on synthetic probe/client workflows.
- when
features.user_storage=trueandfeatures.storage_virtio=true, the harness generates a deterministic GPT disk image locally and attaches it as a secondary raw modern-only virtio-blk disk for both subsystem and appliance runs. The disk stays read-only by default; full-system appliance profiles that request writable runtime mounts setqemu_block_readonly=falseso the guest can create the configured namespace without weakening read-only media tests. Host policy validation rejects any block-backed writable mount in a full-system scenario whose QEMU medium remains read-only. - disk-image VM scenarios boot the built GPT appliance image directly and cover no virtio disk, junk virtio media, raw ESP-only virtio media, a single virtio GPT boot image, and a two-virtio-disk topology. Extra disks stay read-only by default, with an explicit writable suffix only for the storage disk that must satisfy a writable runtime mount.
- storage-capable VM runners default to
QEMU_MEMORY=1G, keeping the current DMA window rooted at0x2000_0000inside guest RAM for virtio queue/data buffers; callers can still overrideQEMU_MEMORYexplicitly when needed. - smoke/negative matrices remain unchanged and continue to use integration smoke features.
- smoke/negative matrices keep mode knobs as fixture-generation inputs and feed rootd through BootConfig payloads.
rootd_test_mode=stress-1kstays on the normal narrowed runtime endpoint inventory. Its leak-bound assertions useSNAPSHOT_RESOURCE_COUNTSover the dedicated process endpoint and do not injectkernel-rootd-test-root-endpoint. Only this profile enables procd's receipt-free integration stress batches; ordinary smoke and production builds cannot execute those batch operations.- runtime TOML also controls filesystem composition:
user_vfs=true|falseadds or removes the publicvfsdservice, whilefs_ramfs,fs_e2fs, andfs_fatselect the private filesystem providers that may be delegated to it.fs_e2fsalso includes privatekeyd, which is required for ext fscrypt authority.[[mounts]]rows are encoded into the generated BootConfig mount table and decide the runtime namespace layout independently of provider selection- runtime/appliance validation proves configured filesystem bring-up through
ERIX_ROOTD:READY:VFSD,ERIX_ROOTD:READY:VFS_MOUNT, andERIX_ROOTD:READY:VFS_IO; provider-ready markers appear only for selected providers - persistent runtime mount scenarios intentionally require storage/VFS and
DRV_VIRTIO_BLOCKprovider readiness, leaving serial, framebuffer, and input-provider readiness to the focused console-and-input scenarios - runtime BootConfig mount scenarios use provider-neutral basic VFS I/O, so FAT-root coverage does not require symlink/readlink or POSIX metadata semantics that FAT providers intentionally deny
Current integration checks consume these marker families:
ERIX_BOOTLOADER:*(bootloader startup and failure markers)ERIX_KERNEL:*andERIX_KERNEL_STUB:*(kernel bring-up/test markers)ERIX_KRN:*(kernel library/runtime diagnostics)
Rootd smoke negatives now assert the specific reported failure class when available:
ERIX_KERNEL:ROOTD_SMOKE:CONTRACT_INVALIDERIX_KERNEL:ROOTD_SMOKE:INTERNAL_ERRORERIX_KERNEL:ROOTD_SMOKE:SERVICE_FAIL
The generic ERIX_KERNEL:ROOTD_SMOKE:FAIL marker is reserved for unknown or
legacy rootd failure reports.
The force-service-fail negative path now forces failure from rootd's
real post-START_PROCESS startup handshake and requires
ERIX_ROOTD:DBG:POST_START_CLEANUP_OK so the VM suite proves that the started
child was torn down before exit class 0x14 is reported.
Bootstrap scenarios now assert staged rootd progress markers in order:
ERIX_KERNEL:ROOTD_STAGE:INTAKE_VALIDATEDERIX_KERNEL:ROOTD_STAGE:MODULES_DISCOVEREDERIX_KERNEL:ROOTD_STAGE:MEMD_READYERIX_KERNEL:ROOTD_STAGE:VSPACED_READYERIX_KERNEL:ROOTD_STAGE:PAGERD_READYERIX_KERNEL:ROOTD_STAGE:PROCD_READYERIX_KERNEL:ROOTD_STAGE:SERVICES_READYERIX_KERNEL:ROOTD_STAGE:PROBE_SPAWN_REQUESTEDERIX_KERNEL:ROOTD_STAGE:PROBE_SPAWNEDERIX_KERNEL:ROOTD_STAGE:PROBE_EVENT_RECEIVEDERIX_KERNEL:ROOTD_STAGE:PROBE_COMPLETED
Resolved demand faults are normal runtime behavior and emit no
ERIX_KERNEL:BOOTSTRAP:FAULT_* markers. Positive paging and isolation scenarios
forbid that marker family; the expected-fault-kill scenario requires
FAULT_RESOLVE_FAIL and FAULT_KILLED instead.
The focused subsystem-pager-write-protect-policy-positive scenario registers
the write-protect helper with pagerd, then writes a present read-only page. It
requires the kernel-policy and killed markers while forbidding every pager
notification marker, proving pager registration does not delegate protection
fault policy. The helper name is the complete product name and stays within the
boot image's 15-byte service-name field; no compatibility alias is packaged.
Time scenarios additionally assert:
ERIX_KERNEL:ROOTD_STAGE:TIMED_READYERIX_KERNEL:ROOTD_STAGE:TIME_READY
Framebuffer scenarios additionally assert framebuffer continuity
contracts and enforce fail-closed behavior when the console-font blob is
missing.
Pre-mount input-readiness scenarios assert deterministic input stack staging and authority partitioning:
ERIX_DEVICED:READY:DRV_I8042ERIX_DEVICED:READY:DRV_PS2_KEYBOARDERIX_DEVICED:READY:DRV_PS2_MOUSEERIX_KERNEL:ROOTD_STAGE:INPUTD_READYERIX_ROOTD:READY:I8042_AUTHORITY_PARTITION
The focused pre-mount active-input negative additionally requires
ERIX_ROOTD:INPUT_ROUTING:TTYD_REQUIRED and forbids the input-routing and
console-input stage markers. A future post-mount positive must include the
ext4-loaded ttyd graph before it may claim those end-to-end markers.
Service deployment-capacity VMs use service-specific runtime configurations, but retain the complete signed native-CLI service and mount topology. Every such configuration reserves at least 80 MiB of kernel heap; the parser rejects the former 64-MiB fixtures before image construction. Service-private arena sizes remain the only values varied by each capacity scenario. The host authority test enumerates every scenario-selected runtime-config path and runs the same parser over each unique file, so a focused configuration cannot drift below the floor without failing before CI enters QEMU.
The current dev-runtime positive VMs use the production disk-image path. They must load ttyd, powerboxd, launchd, and exsh from ext4 through the ordinary loaderd/dynlinkd/procd graph. The loader boot-image scenario instead uses a loader-only runtime configuration to isolate its pre-mount contract.
The cumulative dynamic-spawn fixture executes the memd, named, and deviced negative transcripts immediately before memd. This is the last boundary where the explicit Foundation process-control source needed for exact resource snapshots still exists; the ordinary Foundation retirement remains unchanged, and later named/deviced staging receives no residual kernel process authority.
Current unwanted-explicit-authority negatives additionally cover:
- an undeclared
timedresolution scope injected intologd - wrong-kind auxiliary explicit endpoint transfer into
deviced - wrong-kind PCI-device/MMIO explicit endpoint transfer into
deviced - root-launched split startup-peer misroutes such as
inputd -> deviced - deviced-launched split startup-peer misroutes such as
drv-serial -> deviced - drv-serial's authenticated log client misrouted into the generic log slot
- subsystem-scoped startup-peer harness validation so hardware, console, and input delegated-peer negatives run under the matching rootd bring-up mode instead of being misclassified as probe-only
The deviced-evidence-authority-regressions group binds the eight ACPI,
i8042, and pre-serial driver negatives whose fail-closed result must remain
observable without granting deviced authority to select a log sink.
The matching subsystem-logd-scoped-resolution-positive scenario proves that
the declared seriald and fbcond scopes materialize and reach terminal
readiness; subsystem-logd-cross-scope-negative proves the extra timed scope
is rejected before logd readiness.
The authenticated-producer-endpoints group proves the deviced-launched
producer boundary: its positive scenario reaches drv-serial and both PS/2
drivers through fixed clients, while its negative scenario requires drv-serial
to reject a log client installed in the generic service slot. The independent
producer-ready markers are checked for presence and uniqueness rather than a
scheduler-dependent total order; only the logd, inputd,
i8042-authority-partition, and terminal root barriers form an ordered chain.
EXT-CROSS validation is tracked by a repository-local manifest:
scripts/check-ext-cross-corpus.pycompares thee2fsdfeature registry againstscripts/ext_cross_corpus.py, verifies that every accepted feature has focused positive VM coverage, checks malformed-media negatives for fail-closed VFS exposure, recomputes every scenario's fsverity trust material from the fixture payload and salt, pins authority-negative scenarios, and enforces the 1k LoC boundary on near-limit ext media modules.scripts/check-fs-compliance-matrix.pyalso validates the advanced ext corpus rows inscripts/ext_cross_corpus.py, requiring implemented, planned, rejected, obsolete-rejected, and permanent non-goal classes to carry VM scenarios, unit evidence, and documentation links before the matrix can pass.scripts/check-ext-interoperability-corpus.pyvalidates the Linux/e2fsprogs ext interoperability matrix inscripts/ext_interop_corpus.py. The matrix links each ext2/ext3/ext4 corpus image to the feature bits it proves, required host tools, malformed companions, and provider-mutation VM scenarios.tests/ext-cross-corpus.shis the unit-style entrypoint for the manifest check and runs in CI after the selected component commits have been cloned.tests/ext-interoperability-corpus.shis the unit-style entrypoint for the interoperability matrix check.tests/scenario-groups/ext-cross-*.txtgroups the focused VM subsets for feature positives, feature-registry negatives, malformed ext media, and authority regressions;tests/scenario-groups/ext-interoperability-corpus.txtgroups the focused ext2/ext3/ext4 Linux/e2fsprogs corpus VM subset;tests/scenario-groups/host-report-authority.txtcontains only the new root-only reporting-authority VM proof;tests/scenario-groups/vfs-memory-provider-rename.txtgroups the renamed volatile-memory provider VFS scenarios;tests/scenario-groups/fat-01.txtgroups the targeted FAT32 extended-BPB media scenarios, andtests/scenario-groups/fat-02.txtgroups FAT32 reserved-entry, dirty-state, and hard-error-state scenarios.tests/scenario-groups/fat-03.txtgroups FAT12/FAT16/FAT32 directory metadata scenarios.tests/scenario-groups/fat-04.txtgroups the VFAT Unicode/dense-alias positive scenario plus malformed ordinal, orphan-chain, and duplicate-alias fail-closed scenarios.tests/scenario-groups/fat-short-name.txtgroups lowercase short-entry NT-flag positive media plus short-byte, OEM-byte, NT-flag, ambiguous-LFN, and duplicate-alias fail-closed scenarios. Its positive scenario usesrootd_test_mode=e2fs-fat-short-nameto keep the VM path focused on the new verifier while preserving the real block-backed VFS stack.tests/scenario-groups/fat-rename.txtgroups the focused FAT32 rename replacement scenario. It usesrootd_test_mode=e2fs-fat-rename, then verifies file-over-file replacement, empty directory replacement, rejected incompatible replacements, and clean hostfsck.fatmedia.tests/scenario-groups/fat-metadata.txtgroups the focused FAT32 metadata scenario. It usesrootd_test_mode=e2fs-fat-metadata, then verifies host-created timestamp stat fields, explicit VFS atime/mtime/fs_flags mutation, read-only denial, and clean hostfsck.fatmedia.tests/scenario-groups/exfat-metadata.txtgroups the focused exFAT metadata scenario. It usesrootd_test_mode=e2fs-fat-exfat-metadata, then verifies host-created primary-entry timestamps, UTC offsets, attribute stat fields, explicit VFS atime/mtime/fs_flags mutation, read-only denial, and clean hostfsck.exfat/dump.exfatmedia.tests/scenario-groups/ext-truncate.txtgroups the focused ext2/ext3/ext4 regular-file truncate scenarios. It usesrootd_test_mode=e2fs-fat-ext-truncate, then verifies public VFS shrink/grow behavior and clean hostdebugfs/e2fsck -fnmedia.tests/scenario-groups/ext-sparse.txtgroups the focused ext4 sparse-hole scenario. It usesrootd_test_mode=e2fs-fat-ext-sparse, then verifies write-past-EOF holes, sparse truncate tail trimming, hostdebugfs bmapallocation state, and cleane2fsck -fnmedia.tests/scenario-groups/ext-fscrypt-policy.txtgroups focused ext4 fscrypt policy negatives for v1 descriptor access, AES-256-HCTR2, direct-key, and non-default data-unit-size media.tests/scenario-groups/ext-metadata.txtgroups the focused ext2/ext3/ext4 inode metadata scenarios. It usesrootd_test_mode=e2fs-fat-ext-metadata, then verifies public VFS mode, owner, atime, mtime, and filesystem flag updates, immutable denial, and clean hostdebugfs/stat/e2fsck -fnmedia.tests/scenario-groups/exfat-entry-types.txtgroups the exFAT Volume Label/GUID, TexFAT padding, and benign vendor-entry positive media plus an unsupported vendor-allocation entry-set negative.tests/scenario-groups/exfat-rename.txtgroups the focused exFAT rename replacement scenario. It usesrootd_test_mode=e2fs-fat-rename, then verifies file-over-file replacement, empty directory replacement, rejected incompatible replacements, clean hostfsck.exfatmedia, and direct parser checks for removed source names.tests/scenario-groups/exfat-percent.txtgroups primary percent-in-use refresh media and a patched partial-update dirty-volume negative.tests/scenario-groups/fat-05.txtgroups allocation-stress media, andtests/scenario-groups/fat-depth.txtcontains the focused 24-level stackless FAT mount proof.tests/scenario-groups/exfat-03.txtgroups exFAT upcase-table Unicode lookup plus bad-NameHash, duplicate-upcase-name, and malformed-UTF16 fail-closed media, andtests/scenario-groups/exfat-04.txtgroups exFAT allocation reconciliation positive and fail-closed media.tests/scenario-groups/exfat-05.txtgroups sparse-valid-data/fragmented-stream exFAT media and invalid valid-data fail-closed media.tests/scenario-groups/exfat-06.txtgroups the broadened exFAT interoperability corpus and root-metadata fail-closed media.tests/scenario-groups/ext-geometry.txtgroups the targeted ext2/ext3/ext4 512-byte-inode VM media,tests/scenario-groups/ext-geometry-boundaries.txtgroups inconsistent ext2/ext3 block layouts and the format-valid ext4 large-inode positive media,tests/scenario-groups/ext-links.txtgroups the ext2/ext3/ext4 symlink, hard-link, and special-inode metadata VM media, andtests/scenario-groups/ext-rename.txtgroups the ext2/ext3/ext4 rename and directory-move VM media.tests/scenario-groups/ext-truncate.txtgroups focused ext2/ext3/ext4 regular-file truncate VM media, andtests/scenario-groups/ext-sparse.txtgroups focused ext4 sparse-hole VM media.tests/scenario-groups/ext-fscrypt-policy.txtgroups focused ext4 fscrypt policy fail-closed VM media, andtests/scenario-groups/ext-verity-signature-policy.txtgroups focused ext4 fsverity built-in signature, missing/wrong-root, and encrypted-verity fail-closed VM media.tests/scenario-groups/loader-fs-discovery.txtgroups the focused loader filesystem-discovery scenario usingrootd_test_mode=loader-fs-discoveryandloader-fsmedia.tests/scenario-groups/vfs-namespace-session-authority.txtselects the focused proof that loaderd's dedicated VFS session rejects mount control, directory enumeration, and write-open authority before normal read-only discovery succeeds.tests/scenario-groups/loader-elf-plan.txtgroups the focused loader ELF-plan scenario using the same rootd mode and media, but asserts the dedicatedERIX_ROOTD:READY:LOADER_ELF_PLANproof marker.tests/scenario-groups/loader-process-handoff.txtretains its historical group name but now selects the filesystem-preflight scenario. It asserts discovery and malformed-plan rejection while forbidding successful child creation.tests/scenario-groups/loader-materialized-launch.txtgroups the root-lifecycle-isolation negative scenario using the same rootd mode and media. It treats an identity-onlyDENIEDresponse as evidence that rootd cannot observe launchd-owned children.tests/scenario-groups/procd-loader-endpoint-partition.txtgroups the focused negative proof for disjoint root, materialization, and launchd lifecycle endpoints.tests/scenario-groups/loader-cleanup-authority.txtgroups the focused cleanup-authority scenario using the same media while asserting only the new cleanup and authority-denial marker family.tests/scenario-groups/loader-closure.txtgroups the final loader closure evidence set: VFS policy, malformed ELF/load-plan rejection, launchd-only lifecycle visibility, stale-source rejection, cleanup, and authority denial.tests/scenario-groups/loader-boot-image-integration.txtgroups the loader boot/image scenarios for runtime loader enablement, optional omission, and appliance disk-image fixture packaging.tests/scenario-groups/dynlink-complete-graph.txtgroups the focused current product path. It usesrootd_test_mode=dynlink-storage-services, requires bothdynlinkdandloaderd, and proves the authenticated dynamic service graph, VFS I/O, loader discovery, and malformed-plan rejection. Post-mount executable lifecycle is exercised through launchd scenarios instead.tests/scenario-groups/dynlink-artifact-metadata.txtgroups the focused dynamic-linking artifact metadata scenario. It boots only the appliance disk-image path after host-side dynamic artifact ABI, ELF section, metadata, relocation-record, symbol-table, static executable rejection, and static-exception inspection passes.tests/scenario-groups/dynlink-real-shared-objects.txtgroups the focused dynamic-linking real shared-object closure scenario. It boots only the appliance disk-image path after library-owned PIC objects, compiler metadata sidecars,DT_NEEDEDedges, and registry deduplication pass host-side inspection.tests/scenario-groups/dynlink-kernel-artifact.txtgroups the focused dynamic-linking kernel artifact scenario. It boots only the appliance disk-image path after the generatedkernel-dyn.elfartifact, kernel shared objects, boot-image store, and filesystem mirror pass host-side inspection.tests/scenario-groups/dynlink-kernel-relocation.txtgroups the focused dynamic-linking bootloader relocation scenarios. It boots the dynamic kernel fromboot.img, proves missing-object, stale-hash, missing-export, duplicate-export, unsupported-relocation, and W^X failures before kernel entry, and skips older VM groups.tests/scenario-groups/kernel-handoff-length.txtcontains only the new SysV64 pointer-and-exact-length ingress scenario. It requires the kernel's pre-parse length-validation marker and skips older VM groups.tests/scenario-groups/dynlink-rootd-bootstrap.txtgroups the focused dynamic-linking dynamic rootd bootstrap scenarios. It usesrootd_test_mode=dynlink-rootd-bootstrap, boots the dynamicrootdexecutable from the signed boot dynamic store, and covers the new missing-dependency, relocation-failure, W^X, and stale-hash negatives without running older VM groups.tests/scenario-groups/dynlink-pre-procd.txtgroups the focused dynamic-linking dynamic pre-procdservice launch scenarios. It usesrootd_test_mode=dynlink-pre-procd, boots the dynamicrootdexecutable, launchesmemd,vspaced,pagerd, andprocdfrom signed boot-catalog dynamic artifacts, and covers missing-dependency, unresolved-symbol, dependency-cycle, W^X, and cleanup negatives without running older VM groups.tests/scenario-groups/dynlink-procd-spawn.txtgroups the focused dynamic-linkingprocdearly dynamic spawn scenario. It usesrootd_test_mode=dynlink-procd-spawn, reuses the dynamicrootdandprocdcatalog bootstrap, then validatesprocd-mediated denied-object, abort, cleanup, map, start, and ready markers for dynamicmemd,vspaced, andpagerdwithout running older VM groups.tests/scenario-groups/dynlink-bootstrap-helpers.txtgroups the focused dynamic-linking dynamic bootstrap helper scenario. It usesrootd_test_mode=dynlink-bootstrap-helpers, launches all five helper executables from signed dynamic boot artifacts throughprocd, and checks lazy-paging, isolation, expected-fault-kill, exit-code, and cleanup markers without running older VM groups.tests/scenario-groups/dynlink-core-services.txtgroups the focused dynamic-linking dynamic core-service coordination scenarios. It usesrootd_test_mode=dynlink-core-services, launchesnamed,logd,crashd,timed,lookup-client, andtime-clientfrom signed dynamic boot artifacts throughprocd, and checks denied-object, lookup, logging, crash, and time markers without running older VM groups.tests/scenario-groups/dynlink-hardware-console-services.txtgroups the focused dynamic-linking hardware, console, serial, and input scenarios. It usesrootd_test_mode=dynlink-hardware-console-servicesand packages the services, drivers, and helper clients as signed dynamic boot artifacts, checks interrupt, driver, serial, framebuffer, and pre-mount input-authority markers, enables explicit rootd-drivendevicedactivation in the positive case, and includes a missing-dependency fail-closed case without running older VM groups. Active input routing remains a post-mount ttyd contract. The service artifact builder expands Cargo feature implications before invokingrustcdirectly so dynamic artifacts use the same cfg surface as the static fixture build.tests/scenario-groups/dynlink-storage-services.txtgroups the focused dynamic-linking dynamic storage, filesystem, VFS, and loader scenarios. It usesrootd_test_mode=dynlink-storage-services, packages the storage/filesystem/loader targets as signed dynamic boot artifacts, exercises theloader-fsdisk media, checks storage, VFS, loader, disk-execution, and process-handoff markers, and includes a missing shared-object fail-closed case without running older VM groups.tests/scenario-groups/multi-block-provider.txtcontains only the new two-provider VM. Its disk-image case attaches a junk virtio disk followed by a GPT virtio disk, requires two location-derived physical whole-disk identities, and reaches normal storage and terminal readiness through blockd's full-width provider-and-namespace cursor pair without running older VM groups.scripts/run-scenario-group.sh <group>runs only a named scenario group, so cross-cutting work can validate new VM coverage without invoking the older full scenario matrix locally.tests/scenario-groups/irqd-multiline-delivery.txtcontains only the focused simultaneous LAPIC/COM1 delivery scenario.tests/scenario-groups/ipc-transport-framing.txtcontains the focused canonical IPC transport scenario. It boots the integrated runtime with strict contiguous request framing, independently sized writable call buffers, and the shared transport ceiling, then requires startup, device, console, pre-mount input-authority, and VFS readiness without running older VM scenarios.tests/scenario-groups/process-memory-streaming.txtcontains the focused child-population scenario. It loads the dedicated 5,000-byte filesystem fixture through loaderd, dynlinkd, and procd, requires semantic load and launch success across bounded materialization fragments, and then requires root's lifecycle query to fail with the launchd-only identity-denial contract.tests/scenario-groups/phase5-catalog-regressions.txtcontains the eight scenarios classified by the full 483-scenario Phase 5 catalog run. It covers malformed ext casefold mount rejection, signed volatile-memory I/O, post-retirement RTC readiness, and bounded process-memory materialization.
Storage scenarios now additionally cover:
- positive block bring-up through
blockd - positive GPT partition publication through
blockd - missing
drv-virtio-block - missing
blockd - malformed GPT media
- wrong-kind
devicedPCI-device/MMIO authority - runtime disk-image topology coverage for SATA boot without virtio storage, junk virtio media, ESP-only virtio media, a single GPT virtio boot disk, and two virtio disks; the two-disk case leaves junk media read-only and grants write access only to the copied GPT storage disk needed by the runtime root mount
Current exit-code class mapping:
0x10: success0x11: bootloader failure0x12: kernel failure0x13: rootd failure0x14: service bootstrap failure
Repository Layout (Current)
integration/
├── components.toml
├── cargo-repos.toml
├── dynlink-executable-migration.toml
├── dynlink-dependency-records.toml
├── dynlink-artifact-abi.toml
├── scripts/
│ ├── clone-components.sh
│ ├── build-all.sh
│ ├── build-kernel-fixture.sh
│ ├── build-kernel-fixture-main.sh
│ ├── build-dynlink-kernel-artifact.py
│ ├── dynlink_kernel_metadata.py
│ ├── dynlink_closure_policy.py
│ ├── generate-monorepo-cargo-config.py
│ ├── generate-block-test-disk.py
│ ├── disk_image_gpt.py
│ ├── setup-component-ci-overrides.sh
│ ├── setup-component-ci-overrides.py
│ ├── boot_config_codec.py
│ ├── boot_config_hardware.py
│ ├── generate-boot-config.py
│ ├── parse-runtime-config.py
│ ├── build-dynlink-artifact-fixture.py
│ ├── check-dynlink-dependency-closure.py
│ ├── check-dynlink-executable-inventory.py
│ ├── check-dynlink-artifact-metadata.py
│ ├── verify-dynlink-image-closure.py
│ ├── check-dynlink-filesystem-mirrors.py
│ ├── check-ext-cross-corpus.py
│ ├── ext_cross_corpus.py
│ ├── run-scenario.sh
│ ├── prepare-appliance-runtime-disk.sh
│ ├── run-scenario-group.sh
│ ├── run-scenarios.sh
│ ├── run-vm.sh
│ ├── run-bootloader-vm.sh
│ ├── run-bootloader-negative-case.sh
│ ├── run-disk-image-vm.sh
│ ├── run-kernel-exception-negative-tests.sh
│ ├── package-dev-appliance.sh
│ ├── package-appliance.sh
│ ├── build-disk-image.sh
│ ├── publish-release-artifacts.sh
│ ├── assert-markers.sh
│ ├── lib/bootloader-cargo.sh
│ ├── lib/rootd-fixture-features.sh
│ ├── lib/scenario.sh
│ ├── lib/scenario-storage.sh
│ └── lib/components.sh
├── tests/
│ ├── dynlink-dependency-closure.sh
│ ├── dynlink-executable-inventory.sh
│ ├── dynlink-artifact-metadata.sh
│ ├── dynlink-filesystem-mirrors.sh
│ ├── bootloader-vm-marker-timeout-status.sh
│ ├── generate-monorepo-cargo-config.sh
│ ├── ext-cross-corpus.sh
│ ├── scenario-groups/*.txt
│ └── scenarios/*.toml
├── runtime.sample.toml
├── runtime.dev.toml
├── runtime.release.toml
├── .github/workflows/ci.yml
├── README.md
├── ARCHITECTURE.md
└── ROADMAP.md
Large integration helpers are split at thematic boundaries. Kernel artifact metadata, dynamic closure policy, signed hardware-phase validation, GPT image construction, rootd fixture feature selection, and scenario storage preparation live in dedicated modules so every tracked script remains at or below 1,000 lines.
Quick Start
From integration/:
./scripts/clone-components.sh
./scripts/build-all.sh
./scripts/run-scenarios.sh
./scripts/run-scenario.sh tests/scenarios/full-system-normal.toml
./tests/ext-cross-corpus.sh
./scripts/run-scenario-group.sh ext-cross-feature-registry
./scripts/run-scenario-group.sh fat-truncate
./tests/generate-monorepo-cargo-config.sh
export BOOTIMG_SIGNING_KEY=tests/keys/bootimg-test-ed25519.pem
export BOOTIMG_PUBLIC_KEY_HEX_FILE=tests/keys/bootimg-test-ed25519.pub.hex
export BOOTIMG_KEY_ID=0
export BOOTIMG_SIGNING_PROVENANCE="repository test key; not for production trust"
./scripts/package-dev-appliance.sh
./scripts/build-disk-image.sh
APPLIANCE_NAME=erix-release RUNTIME_CONFIG_PROFILE=release ./scripts/package-appliance.sh
RUNTIME_CONFIG_PROFILE=release ./scripts/build-disk-image.sh erix-release
PUBLISH_DRY_RUN=1 ./scripts/publish-release-artifacts.sh
./scripts/setup-component-ci-overrides.sh /path/to/component
Those relative paths are intentionally relative to the checked-out
bootloader repository because its fixture builder owns path resolution. They
select repository fixtures suitable only for tests. The integration caller
must not prefix them with the component checkout path. Production packaging
must inject its own private key, matching public-key file, and key ID.
Publication additionally requires BOOTIMG_SIGNING_PROVENANCE; that
caller-supplied statement is embedded in the pre-release body so test-signed
artifacts cannot be presented without their trust classification.
Appliance archives and raw disk images are byte-reproducible under the same
recorded inputs and host-tool versions. Archive entry order, ownership, and
timestamps are normalized. GPT disk/partition GUIDs, the FAT volume ID, the
ext4 UUID, and the ext4 directory-hash seed are derived from a fingerprint of
the appliance tree, runtime configuration, image parameters, normalized epoch,
and media-tool versions. FAT and ext4 creation/mutation use that epoch in UTC.
The default epoch is the Integration source revision's Git commit timestamp,
not a fixed 1980 date or the current build clock. Explicit SOURCE_DATE_EPOCH
is supported within the unsigned 32-bit seconds range. Packaging records its
decision in source-date-epoch.json; disk construction requires that record
and rejects a conflicting override, so a later checkout cannot retimestamp
an already packaged appliance. Guest mutations use the independently queried
runtime clock, not this build-time value.
Each raw image has a sibling <name>.img.identity.json that records the
fingerprint, derivation contexts, effective identifiers, and epoch. A caller
that intentionally needs distinct media identity may set any of
IMAGE_DISK_GUID, IMAGE_ESP_PARTITION_GUID,
IMAGE_DATA_PARTITION_GUID, IMAGE_DATA_FS_UUID,
IMAGE_DATA_HASH_SEED, or IMAGE_FAT_VOLUME_ID. Overrides are validated and
recorded instead of bypassing the identity manifest.
The identity manifest has its own .sha256 file and is published alongside the
image checksum.
setup-component-ci-overrides.sh resolves the exact commits selected by the
standalone crate's manifests, using the catalog as a repository allowlist.
Sibling repositories may supply those commit objects, but cannot override the
selected revisions. Generated Cargo transport mirrors preserve original Git
commit identities and disable registry sources. Manifest discovery prunes
.git, .ci, out, and target before descent. See
immutable source selection for closure validation, explicit
monorepo mode, and the separate Integration tool/runtime source roles.
To bootstrap the multi-repository checkout into the current directory without
first cloning integration, select a reviewed full commit containing the
immutable bootstrap helper and fetch the script from that exact commit:
revision=YOUR_REVIEWED_40_LOWERCASE_HEX_COMMIT
base="https://git.erikinkinen.fi/erix/integration/raw/commit/$revision"
curl -fsSL "$base/scripts/bootstrap-repos.sh" |
sh -s -- --integration-revision "$revision"
The script verifies that exact Integration tool commit and uses the catalogs
and helper code from it. Component repositories are detached at their selected
commits; dirty targets fail without reset or cleanup. The tool lives at
integration, while its separately pinned runtime-library source lives at
integration/out/components/integration. To use SSH transport, add --ssh:
curl -fsSL "$base/scripts/bootstrap-repos.sh" |
sh -s -- --integration-revision "$revision" --ssh
build-kernel-fixture.sh now generates and injects a required boot-config
section payload for rootd orchestration.
Runtime appliance defaults:
KERNEL_ROOTD_TEST=runtimeRUNTIME_IMAGE_TEST_HARNESS=0RUNTIME_CONFIG_PROFILE=devROOTD_TEST_MODE=none(runtime image composition is config-driven)
Runtime config files:
runtime.dev.toml(default dev profile)runtime.release.toml(default release profile)runtime.sample.toml(schema + documented behavior)runtime.local.toml(gitignored local override selected only throughRUNTIME_CONFIG_PATH)- committed dev/release defaults mount
/from ext onerix-data,/bootfrom FAT onerix-esp, and/tmpfrom ramfs [service_state.logd]explicitly selects canonical retained-record, pending-submission, and retained-byte capacities. These values patch one exact typed arena before the logd artifact is signed; they are deployment policy rather than service ceilings. Retained-byte storage must accommodate at least one complete 192-byte early-kernel-log transfer record.[service_state.procd].managed_process_recordsexplicitly selects one nonzero process-record count no greater than procd's canonical 128-slot pagerd partition. It sizes procd lifecycle/event storage, procd's capability scratch ranges, and its pagerd binding-record contribution. Pagerd adds the disjoint 64-slot rootd temporary-launch contribution to its binding arena; the default 128-record policy therefore patches 192 binding records. Pagerd's CSpace import window remains the fixed canonical slots 320..512; deployment count does not resize that partition. Rootd and procd consume lib-capabi's same versioned per-process multiplier; addressable empty slots convey no authority. Vspaced retains no service-local mapping state or deployment-sized capacity.[service_state.powerboxd]supplies the complete authenticated PBX1 policy: request, grant, selector-byte, trusted-prompt, session-policy, decision, consumption-receipt, cleanup, expiration, resolution, reply, and transient capability-slot storage. Every value is positive, the slot range must remain within the native-broker CSpace window, and the page-rounded arena grants no allocator or namespace authority. Runtime BootConfig generation reuses this exact validated policy for the post-mountpowerboxdlaunch row; it never reconstructs capacities from patched ELF size or local defaults.[service_state.seriald].retained_bytesexplicitly selects the positive serial readback byte count. Packaging authenticates the exact prefix in a dedicated page-rounded arena; the value is deployment policy, not a daemon source ceiling.[service_state.fbcond].retained_bytesexplicitly selects framebuffer-console readback retention. Packaging authenticates only that prefix of a dedicated page-rounded arena; no daemon or caller retains a parallel byte ceiling.[service_state.drv_serial].retained_bytesexplicitly selects the positive serial-driver readback byte count. Packaging authenticates the exact prefix in.drv_serial_state_arena; the page-rounded remainder is not allocator authority and the former 4 KiB source limit no longer exists.[service_state.drv_i8042]independently selects positivekeyboard_retained_bytesandmouse_retained_bytes. Packaging authenticates both exact contiguous slices in.drv_i8042_state_arena; neither stream can consume the other's retention policy, and page-rounded padding is unusable.service_state.vspacedis intentionally absent and rejected. Vspaced keeps no redundant mapping records or service-local capacity; exact per-call capability receipts authorize operations and kernel results report real mapping limits.[service_state.irqd].handler_recordsexplicitly selects the nonzero interrupt-handler registry count. It is authenticated deployment policy, not a crate-wide ceiling, and packaging exposes no allocator over rounded pages.[service_state.inputd].event_recordsexplicitly selects the input-event retention count. Configurations with input enabled require a positive count; configurations without input require zero. Packaging authenticates the exact typed slice in.inputd_state_arena, so inputd has neither a source-coded ring ceiling nor allocator authority over page padding.[service_state.vfsd].handle_recordsexplicitly selects the deployment's VFS handle-record count. The mount-record count is the exact number of[[mounts]]rows; neither value is a compile-time service ceiling. The shared VM profile provisions 128 records so the Phase 5 shell scenarios can retain digest-only lost-reply tombstones across their bounded repeated redirections until each launch resolver is retired.[service_state.ramfsd]explicitly selects nodes per ramfs mount, file bytes per node, and provider-private handle records. Its mount-record count is the exact number of[[mounts]]rows whose provider isramfs; a configuration without ramfs mounts must set all three values to zero.[service_state.e2fsd].handle_recordsexplicitly selects provider-private ext handle records. The mount-record count is the exact number of[[mounts]]rows whose provider isext; a configuration without ext mounts must set the handle count to zero.[service_state.fatd].handle_recordsexplicitly selects provider-private FAT handle records. The mount-record count is the exact number of[[mounts]]rows whose provider isfat; a configuration without FAT mounts must set the handle count to zero.features.program_loaderis the loader toggle. The dev profile enables it and packagesloaderdplus the loader executable fixture path. The current release profile enables the same authenticated loader path.
Storage helpers:
scripts/generate-block-test-disk.pybuilds deterministicgpt,malformed-gpt,fs, FAT12/FAT16/FAT32/exFAT ESP variants, exFAT boot-region, active-state, percent-in-use, and upcase-name positive/negative variants, malformed FAT/exFAT/ext, ext recovery-required, encrypted ext4, casefold ext4, inline-data ext4, and Linux-layout fsverity ext4 raw disks locally. CI installs the hostfsveritypackage alongside e2fsprogs/exfatprogs so fsverity media coverage has the expected host tooling available.tests/generate-block-test-disk.shchecks GPT CRC corruption, FAT12/FAT16 marker readability, deterministic exFAT marker readability viascripts/verify-exfat-image.py, malformed-media variant generation, and hostfsck.fat -n/fsck.exfat -n/e2fsck -fnon the filesystem fixture. FAT32 active-FAT VM verification usesscripts/verify-fat32-active-fat.pyafter mutation so valid inactive-FAT divergence is not normalized away. exFAT active-FAT VM verification usesscripts/verify-exfat-image.pyto check the FAT count, the primaryVolumeFlagsactive selector, and the VFS-created marker after mutation because the installedfsck.exfatrejects two-FAT TexFAT-style images even though the fixture is intentionally exercising the provider's active-selector policy. That scenario carries a local 600-second VM budget so the dynamic-only image can finish the full VFS mount and I/O readiness path before post-VM exFAT validation runs. EXFAT-03 Unicode-name VM verification also usesscripts/verify-exfat-image.pyso upcase-table lookup and streamNameHashsemantics are checked with the same deterministic parser. EXFAT-04 VM verification uses the same parser to reconcile all reachable exFAT stream ownership against the allocation bitmap and uses hostfsck.exfat -non the accepted contiguous no-FAT-chain image. EXFAT-05 VM verification checks sparse valid data,DataLength,ValidDataLength, zero-filled ranges, and fragmented stream chains. Focused exFAT metadata VM verification checks host-created primary-entry attributes, create/modify/access timestamps, 10 ms increments, UTC offsets, VFS-updated metadata, and read-only denial, then verifies the ESP withfsck.exfat,dump.exfat, and direct exFAT entry-set checks. Focused ext metadata VM verification checks VFS-updated mode, owner, atime, mtime, nodump/noatime/immutable flags, immutable mutation denial, and the resulting data partition withdebugfs, hoststat, ande2fsck -fn. Focused ext sparse VM verification checks that a write past EOF reads a zero-filled hole without allocating logical block zero, that the tail block is allocated, that truncating a sparse file keeps the leading hole unmapped, and that the resulting data partition passese2fsck -fn. exFAT entry-type VM verification checks Volume Label/GUID root metadata, TexFAT padding, preserved vendor-extension secondaries, and fail-closed vendor-allocation media with the direct parser and host exFAT tools. exFAT rename VM verification reuses the public rootd rename flow and checks the resulting ESP withfsck.exfatplus direct payload and absence checks. exFAT percent-in-use VM verification starts from unknown primary/backup percent values, requires the accepted image's primary value to match the allocation bitmap after public VFS mutations, keeps backup stale, and rejects patched dirty partial-update media on read-write mount. EXFAT-06 VM verification uses the same parser to assert 1 KiB clusters, two FATs, a grown root chain, fragmented deep Unicode-path payloads, and spare allocation clusters for public VFS mutations; its negative media rejects bad upcase tables, malformed bitmap entries, duplicate critical metadata entries, and corrupt directory-entry sets before VFS readiness. FAT32 dirty and hard-error metadata variants are negative read-write mount tests; malformed reserved-entry variants keep mirrors consistent sofatdfails specifically on FAT[0]/FAT[1] metadata validation. FAT-04 verifies hostmtoolslisting/lookup for accepted VFAT Unicode and dense-alias fixtures after VM execution and patches malformed LFN/alias fixtures for targeted negative mount failures. FAT short-name verification checks host-created lowercase short entries and VFS-created lowercase short entries with direct NT-flag parsing after VM execution. FAT-05 verifies fragmented cluster chains, multi-cluster directories, slot reuse, sparse-looking payloads, and fail-closed malformed referenced-chain media. The focused FAT depth scenario mounts a host-created 24-level directory tree throughfatd, reaches ordinary VFS readiness, and verifies the deepest marker withmtoolsafter the VM. EXFAT-03 verifies upcase-table Unicode lookup and bad-NameHash, duplicate-upcase-name, and malformed-UTF16 fail-closed media. EXFAT-04 verifies no-FAT-chain contiguous streams plus bitmap/FAT mismatch, duplicate ownership, missing bitmap allocation, leaked allocation, loop, and out-of-range fail-closed media. FAT12/FAT16/FAT32 directory-metadata variants usescripts/verify-fat-directory-metadata.pyplusmtoolsto verify timestamps, attributes, volume labels, lowercase short-name flags, and VFS-created archive/timestamp metadata after the VM. FAT metadata mutation usesscripts/verify-fat-metadata.pyplusmtoolsand direct directory-entry parsing to verify host-created timestamps, date-only access time, two-second modification time, stat-only creation time, and read-only attributes after the VM. FAT rename replacement usesscripts/verify-fat-rename.pyplusmtoolsandfsck.fat -nto verify the destination file payload, renamed directory child, rejected non-empty destination, and removed source names after the VM. exFAT rename replacement usesscripts/verify-exfat-image.pyplusfsck.exfat -nto verify the same public VFS mutations on exFAT media. exFAT percent-in-use media uses the direct parser to verify the final primary percent against the active allocation bitmap while preserving stale backupPercentInUse=0xff. FAT truncate variants usescripts/verify-fat-truncate.py, hostmtools, andfsck.fat -nto verify shrink, zero-length shrink, zero-filled growth, released-chain cleanup, and FAT32 FSInfo accounting after the VM. Ext truncate variants usedebugfsande2fsck -fnto verify the focused/EXTTRUNC.BINshrink/grow result after the VM. Ext metadata variants usescripts/verify-ext-metadata.py, hoststat, ande2fsck -fnto verify/EXTMETA.TXTmode, owner, explicit atime/mtime, preserved legacy ctime, flags, payload, and clean media.BLOCK_STORAGE_IMAGE=auto|none|gpt|malformed-gpt|fs|loader-fs|fs-ext2|fs-ext2-indirect|fs-ext2-compat|fs-ext2-xattr|fs-ext2-geometry-512|fs-ext2-links|fs-ext2-rename|fs-ext2-corpus-1k|fs-ext2-corpus-2k|fs-ext2-corpus-4k|fs-ext3|fs-ext3-replay|fs-ext3-external-journal|fs-ext3-jbd2-legacy|fs-ext3-jbd2-csum-v2|fs-ext3-jbd2-csum-v3|fs-ext3-many-journal|fs-ext3-fast-commit|fs-ext3-htree|fs-ext3-htree-depth0|fs-ext3-htree-depth1|fs-ext3-geometry-512|fs-ext3-links|fs-ext3-rename|fs-ext4-metadata|fs-ext4-extent-tree|fs-ext4-bigalloc|fs-ext4-meta-bg|fs-ext4-stable-resize|fs-ext4-xattr|fs-ext4-quota|fs-ext4-orphan-list|fs-ext4-orphan-file|fs-ext4-mmp|fs-ext4-large-dir|fs-ext4-encrypted|fs-ext4-encrypted-casefold|fs-ext4-casefold|fs-ext4-inline|fs-ext4-verity|fs-ext4-verity-salted|fs-ext4-verity-large|fs-ext4-shared-blocks|fs-ext4-geometry-512|fs-ext4-links|fs-ext4-rename|fs-fat12|fs-fat12-metadata|fs-fat16|fs-fat16-metadata|fs-fat32-primary-only|fs-fat32-mirrored|fs-fat32-active-fat|fs-fat32-metadata-clean|fs-fat32-directory-metadata|fs-fat32-metadata-set|fs-fat32-rename|fs-fat32-vfat-unicode|fs-fat32-stress|fs-fat32-deep-directory|fs-exfat|fs-exfat-boot-region|fs-exfat-stale-backup|fs-exfat-one-fat|fs-exfat-active-fat|fs-exfat-unicode|fs-exfat-contiguous|fs-exfat-stream-metadata|fs-exfat-metadata|fs-exfat-entry-types|fs-exfat-rename|fs-exfat-percent|fs-exfat-corpus|malformed-fat|malformed-exfat|exfat-bad-upcase-table|exfat-bad-name-hash|exfat-duplicate-upcase-name|exfat-malformed-utf16-name|exfat-bad-main-boot|exfat-bad-backup-boot|exfat-bad-extended-boot|exfat-boot-region-mismatch|exfat-dirty-volume|exfat-partial-update-dirty|exfat-media-failure|exfat-invalid-active-fat|exfat-reserved-volume-flags|exfat-duplicate-bitmap-entry|exfat-duplicate-upcase-entry|exfat-bad-bitmap-entry|exfat-bad-bitmap-length|exfat-corrupt-directory-set|exfat-bad-entry-type|exfat-bitmap-fat-mismatch|exfat-duplicate-cluster|exfat-no-fat-missing-bitmap|exfat-leaked-cluster|exfat-chain-loop|exfat-out-of-range-chain|exfat-invalid-valid-data|malformed-ext|ext2-inconsistent-block-geometry|ext3-inconsistent-block-geometry|ext4-large-inode|ext2-bad-block-map|ext2-bad-dirent|ext2-bad-inode-size|ext2-bad-bitmap|ext2-reserved-inode-corruption|ext-needs-recovery|fat-mirror-mismatch|fat-cluster-loop|fat-bad-lfn|fat-bad-lfn-ordinal|fat-orphan-lfn|fat-duplicate-alias|fat-bad-cluster-chain|fat-file-chain-loop|fat-cross-linked-files|fat-out-of-range-chain|fat32-bad-fsinfo-count|fat32-bad-backup-boot|fat32-dirty-metadata|fat32-hard-error-metadata|fat32-bad-reserved-entry|ext-checksum-failure|ext-unsupported-feature|ext-obsolete-feature-corpus|ext-unknown-feature-corpus|ext-unknown-feature-gap-corpus|ext-readonly-feature|ext-shared-blocks-feature|ext-journal-device-volume|ext-bigalloc-bad-bitmap|ext4-meta-bg-bad-descriptor|ext4-encrypted-missing-key|ext4-encrypted-wrong-key|ext4-encrypted-casefold-missing-key|ext4-encrypted-casefold-wrong-key|ext4-bad-fscrypt-policy|ext4-bad-encrypted-casefold-policy|ext4-bad-encrypted-casefold-name|ext4-bad-casefold-encoding|ext4-bad-casefold-name|ext4-bad-xattr|ext4-bad-quota|ext4-bad-orphan-list|ext4-bad-orphan-file|ext4-bad-mmp-active|ext4-bad-mmp-checksum|ext4-bad-inline-data|ext4-bad-verity-data|ext4-bad-verity-algorithm|ext4-bad-verity-signature|ext4-verity-signature|ext4-verity-encrypted|ext4-bad-verity-merkle|ext-external-journal|ext-jbd2-unknown-feature|ext-jbd2-csum-failure|ext-fast-commit-mutating|ext-fast-commit-htree|ext-fast-commit-linear|ext-fast-commit-bad-tail|ext-external-journal-uuid-mismatch|ext-external-journal-misroute|ext-malformed-extent|ext-malformed-htree|ext-malformed-htree-index|ext-malformed-htree-deepcontrols whether a secondary read-only virtio-blk disk is attached during fixture, subsystem, and appliance runs.- fscrypt scenarios may set
keyd_fscrypt_material_id_hexandkeyd_fscrypt_material_hex; the harness encodes those bytes in rootd's private keyd startup material tail, not innamedor provider metadata. The encoded row carries no caller role or compatibility padding. - fsverity scenarios may set
keyd_fsverity_root_id_hexandkeyd_fsverity_root_hex; the harness encodes those bytes in the same private keyd startup material tail as trust-root material fore2fsdand selects rootd's targeted fsverity validation profile for positive/tamper media. Linux-layout fsverity coverage is grouped undertests/scenario-groups/ext-verity-linux.txt, while explicit signature and authority-policy negatives are grouped undertests/scenario-groups/ext-verity-signature-policy.txt. scripts/build-disk-image.shbuildserix-dev.imganderix-release.imgas GPT-partitioned raw disks. Partition 1 is a FAT32 ESP namederix-esp; partition 2 is an ext4 filesystem namederix-datacontaining the selected dynamic executable/object mirror and any enabled loader fixtures.scripts/package-dev-appliance.shis the canonical development packaging entry point. It selects the isolated Integration policy, the full ext4 runtime transition, and the product interactive exsh console plan. Its explicitINITIAL_EXSH_INTERACTIVE_ESCALATION=1selector retains the same session capability ceiling and trusted powerbox policy without enabling an authored physical-input test transcript. The closed Boolean selector rejects combinations with authored command or physical-fixture selections. The resulting dev image exposes the complete readiness stream and starts exsh from ext4. Release packaging continues throughpackage-appliance.shwith product rootd and its bounded post-completion shell hook; it does not compile the Integration effect adapters.- CI builds, boots, and publishes runtime appliance images as part of the
committed VM scenario set. Positive development images must reach terminal
ERIX_ROOTD:READY; release images instead prove the later version banner and shell output while forbidding that record. StagedERIX_ROOTD:READY:*markers are evidence only for their owning services. After constructing the publication artifacts, CI boots both exact canonical images and drives each interactive shell through emulated PS/2 input. The dev gate also requires every semantic readiness marker and final READY. Both gates require the independently expected exact version banner and a fresh, complete shell caret. Two separate physical command epochs prove exact typed input, distinct PATH/absolute external-command output, status zero and a new caret; typed echo alone cannot pass. Each gate retains hashed boot and final framebuffer screendumps and retires only QEMU after acknowledged host quit: both product shells intentionally remain live. The focused visual gate requires defaultfbcondforeground across multiple rows and light-gray terminal pixels, so a prompt-only framebuffer cannot pass merely because serial output is complete.tests/canonical-image-vm.sh dev|release [source-image]copies the source disk and both firmware files privately, retains diagnostics, checks source hashes even after VM failure, and uses unchanged 120/15/10-second total/stall/whole- command bounds. An older supplied image requires an independently knownEXPECTED_INTEGRATION_VERSION; accepting its observed banner is not proof. The nine authored physical-input, powerbox and trusted-TTY scenarios still select the Integration fixture runner and require their original guest evidence-ready, exit and authority-cleanup assertions. Product observations do not substitute for those scenario contracts. - EXT-CROSS groups live under
tests/scenario-groups/; usescripts/run-scenario-group.sh ext-cross-feature-registryfor the fail-closed feature-bit subset,ext-cross-feature-positivesfor accepted feature media,ext-cross-malformed-mediafor malformed ext fixtures, andext-cross-authorityfor authority-shape negatives. - Use
scripts/run-scenario-group.sh ext-advanced-corpus-maintenancefor the targeted advanced ext corpus maintenance subset without rerunning older broad VM groups. - Use
scripts/run-scenario-group.sh ext-interoperability-corpusfor the targeted Linux/e2fsprogs ext2/ext3/ext4 interoperability subset without running older VM scenarios.
Set RUNTIME_CONFIG_PROFILE=release (or RUNTIME_CONFIG_PATH=...) to select
runtime image behavior, and APPLIANCE_NAME to select output artifact prefix.
Release builds keep memd, vspaced, and pagerd free of discovery and
logging dependencies; procd receives its release-image feature so its implied
runtime logging chain stays quiet too. Runtime probed also
receives its release-image feature so packaged release images preserve
ERIX_PROBED:WARN:* records while suppressing informational discovery
telemetry. Runtime logd receives its release-image feature as well, retaining
submitted records while suppressing external sink output for non-warning records
and non-final readiness markers.
Source selection requires explicit full lowercase commit IDs in component
catalogs and Cargo manifests. scripts/clone-components.sh fetches and verifies
those exact objects, checks them out detached, and records revision, sha,
and pinned = true in out/resolved-revisions.json. Missing commits and dirty
component worktrees fail closed without resetting or cleaning local changes.
Branch names and ambient CI branch variables never replace a selected revision.
Explicit ERIX_COMPONENT_SOURCE=monorepo validation requires clean sibling
checkouts at the selected catalog and manifest pins. Per-build Cargo patches
include only the active dependency graph; transport mirrors retain the original
commit IDs. The Integration runtime-library row always uses its separately
pinned out/components/integration checkout, not the executing orchestration
tool's HEAD. See immutable source selection.
Acceptance of a declared pin set still requires its source build and applicable runtime checks. Host resolver tests do not establish appliance or VM acceptance; retain resolved source inventories with images and validate the committed set.
Main outputs:
out/resolved-revisions.json- VM serial logs generated by the active harness
out/appliance/erix-dev.tar.gzout/appliance/erix-dev.imgout/appliance/erix-dev.img.sha256out/appliance/erix-dev.img.identity.jsonout/appliance/erix-dev.img.identity.json.sha256out/appliance/erix-dev.img.zstandout/appliance/erix-dev.img.zst.sha256(when compression is enabled)out/appliance/erix-release.tar.gzout/appliance/erix-release.imgout/appliance/erix-release.img.sha256out/appliance/erix-release.img.identity.jsonout/appliance/erix-release.img.identity.json.sha256out/appliance/erix-release.img.zstandout/appliance/erix-release.img.zst.sha256(when compression is enabled)
Governance Principles
integration governance is scoped to assembling, building, and validating
cross-repository EriX systems.
The scoped governance rules are:
- Scenarios must be deterministic and make component revision selection explicit.
- Generated media and VM tests must fail closed on missing tools, warnings, or authority regressions.
- Dependencies use immutable commit IDs; generated local transport configuration must not change those selected revisions.
- New system behavior requires targeted positive and negative scenarios before it is considered validated.
- Cross-cutting ext work must update the EXT-CROSS and ext interoperability corpus manifests plus grouped scenario lists in the same branch as feature-registry, authority, or media boundary changes.
Validation Boundaries
- Host VM-runner fixtures must work without a preexisting
out/applianceand keep firmware sources, writable variables and every log in private temporary paths. Both runners create the selected OVMF variables destination's parent independently of the serial-log path.tests/vm_firmware_fixture_test.pychecks cold-checkout defaults, nested destinations, source preservation, failure before QEMU launch and serial-fixture isolation using fake QEMU. Sibling firmware/input fixtures also preserve guarded ambient output paths. Invalid editor-profile and console-mode cases use private dummy disks rather than assuming an already-built canonical image exists. - Marker-only failures print bounded final serial context (80 lines within 16 KiB) alongside the unchanged failing assertion, so a correct guest exit cannot conceal missing or reordered final output in the CI job log.
integrationmay coordinate component builds but does not own component source policy.- Driver daemons remain managed through
devicedandprocd; tests should assert that ownership boundary. - Hardware verification accepts the exact authenticated RTC seed's zero PCI metadata only with matching typed identity, presence and live generation. It still reads that seed, rejects malformed seed fields, and checks ordinary PCI devices and report counts independently. Seeded RTC presence must not be confused with a PCI discovery report or permission to start a driver.
Contact
Development occurs in EriX organization and discussions happen in issues and design documents.
No decisions are considered valid without documented rationale.
Maintainers can be reached via email: admin@erikinkinen.fi.