Breadcrumb controller host preparation — 2026-10-03
This implements the host portion of mainline task 5g.4. No new kernel, initrd, DTB or matching bundle was built or staged, and no board/serial action occurred. Positive qualification of the new realized bundle/source/config and physical breadcrumb output remain UNVERIFIED. Tasks 5g.4, 5g.5 and 5b.5 stay open.
Worktree /home/jadams/tmp/k230-mainline-uart-progress-breadcrumbs-controller,
branch mainline-uart-progress-breadcrumbs-controller, base 8e66e299.
Owned paths: existing minimal controller, new focused test file, this host note
and only the 5g.4 preparation note. No board or build slot is reserved.
Selected variant proof before UART
Typed --uart-progress-breadcrumbs requires --mode minimal,
--same-image-shell-pid1 and --uart-progress. Original selectors/defaults,
numeric record parsing and protected normal checks retain their paths. It
preserves the original progress qualification:
manifest/count/hash/CRC, exact ordinary artifact arguments, archived RISC-V
programs/common loader, matching selected-system kernel and the same kernel
derivation’s already-realized dev config. Registration absence, including a
dangling marker, is asserted in both protected normal helpers.
CONFIG_K230_UART_PROGRESS=y alone does not qualify the new variant. An
additional bounded read-only host query uses the same verified kernel drv:
nix --offline --extra-experimental-features nix-command derivation show SELECTED_KERNEL_DRV
It accepts the observed Nix JSON v4 wrapper with basename-keyed derivations
and structuredAttrs.src, or the legacy exact-drv map with env.src.
Unknown schemas, missing source or a different derivation fail closed. The
actual immutable source’s drivers/soc/canaan/k230-uart-progress.c must match
the frozen reviewed applied worker SHA256:
7207dcae9462694a07bd4f7d37d1d9ea43a536496f1b96dd94fed3dfa78c6a22
The selected Image, already manifest/hash-bound to that system, must contain
each exact compiled marker string once (including leading/trailing LF and
terminating NUL), and the unique k230.uart_progress_breadcrumbs= setup key.
The result preserves source, worker/Image hashes and literal byte offsets.
This is combined source/config/compiled-byte qualification; strings alone do
not prove configuration, placement, ABI execution or hardware output. Full
build/exact-object lifetime/alignment/DT evidence belongs to 5g.2–3.
No guessed dev source symlink is used: the actual old dev output’s source tree contains headers rather than the full patched worker. A missing source or dev output is never built/fetched by the controller. Host dependencies are Nix, Python with native Zstd archive support (operator Python 3.14), and the existing pyserial environment for eventual operation.
The full literal volatile U-Boot command differs from the existing qualified
progress value by exactly one token: k230.uart_progress_breadcrumbs=1.
Immutable init, sole serial console, marker suppression, initramfs_async=0,
rdinit=/bin/sh, existing reporter flag and the three qualified controls remain.
Unsafe/duplicate/alternate values or oversized input fail before UART; printed
U-Boot arguments and exactly one fresh matching kernel-received command line
still gate the sole receipt. No saveenv, profile/card changes or candidate
reboot are added.
Fixed bytes and interpretation
The only accepted complete breadcrumb lines are:
K230_UPB1 point=worker-entry
K230_UPB1 point=first-post-sleep
Their producer adds literal leading and trailing newlines. The parser accepts one of each at most, in order, before numeric samples. Unknown versions/points, extra fields, echo, duplicates, reordered points, post-sample points, partial or interleaved text are incomplete/unknown. Split transport chunks may combine into the original exact bytes; arbitrary console text is not removed or repaired.
The bounded capture starts at bootm and ignores the pre-existing rolling
session buffer. It retains direct markers that arrive before the printed Linux
banner, but trusts them only after the fresh selected banner and exact received
arguments qualify that same attempt. Stale/unqualified output never authorizes
input. Missing banner/arguments, byte overflow or transport failure keep facts
unknown; independent fresh normal-return recognition remains available.
Breadcrumb presence/completeness, numeric records and receipt are separate fields. Neither breadcrumb authorizes input. Only fresh init entry and primary prompt, after received-argument qualification, permit one fresh builtin receipt. Qualified complete breadcrumb/numeric lines may follow that prompt in the same read. There is no retry, proc/identity probe, exit, or candidate reboot afterward. Capture retains the existing 90-second readiness and 180-second passive observation deadlines, actual elapsed time and independent protected normal postflight. Missing/malformed breadcrumbs remain diagnostic-incomplete even when all numeric samples or normal recovery appear.
With the selected source and gates qualified, worker-entry establishes reaching
its output call, not that the call returned or sleep began. First-post-sleep
establishes that the first sleep and existing stop checks passed and the earlier
entry call returned; earlier output may still have been partial/zero/error.
A later numeric sample establishes progress beyond the post-sleep call and
snapshot/formatting, not the firmware return count or healthy UART/TTY delivery.
Missing any point may reflect scheduling, sleep, output or later work; absence
alone diagnoses none of them. A complete UART record still does not prove that
its own firmware call returned. observed_after_stimulus is host arrival order,
not causal sampling time or per-byte RX timing. The existing counter limits,
manual recovery distinction and open ordinary-root/glass gate remain unchanged.
Host proof
Checks completed 2026-10-04 01:11 UTC (2026-10-03 local):
python3 tests/test_mainline_uart_progress_breadcrumbs_controller.py # 17 passed, 0.065s
python3 tests/test_mainline_uart_progress_controller.py # 20 passed, 0.572s
python3 -m unittest discover -s tests -p 'test_mainline_drm*trial.py' # 214 passed, 31.007s
python3 tests/test_mainline_shell_pid1_comparison.py # 14 passed, 1.406s
The new tests exercise actual parser/transport functions and the real capped pump with isolated fixtures: early/split/late markers, prompt-plus-marker in one read, fresh args, strict failures, one/no stimulus, source/compiled-byte gates, pre-serial rejection and a full mocked five-load/CRC/preflight path. Fixtures do not open UART or build. Existing progress tests retain transport-failure, rolling/overflow and protected return guards.
Two additional read-only checks passed locally: the author’s applied worker
file SHA matches the pin; and the actual cached old reporter kernel derivation
resolves to original 4av3w0… source and is rejected as the wrong worker despite
its enabled reporter config. The query used the observed JSON v4 schema.
This is an actual negative host artifact gate, not new-bundle positive proof.
Strict OpenSpec validation/diff checks are recorded at commit handoff.
After reviewed source/full-build/config/exact-object proof and actual positive host preparation, the sole board operator may use fresh private output paths:
python3 tools/mainline-drm-initrd-shell-trial.py --mode minimal \
--same-image-shell-pid1 --uart-progress --uart-progress-breadcrumbs \
--bundle BUNDLE --manifest PRIVATE_MANIFEST --normal-report PRIVATE_NORMAL \
--log PRIVATE_LOG --result PRIVATE_RESULT
No operator action was performed here. Root retains the separate board reservation, physical result, protected recovery and deployment responsibilities.