ADR 0030 Phase D: Kconfig profiles, committed defconfigs, and a 99-line Makefile - #167
Merged
mcfbytes merged 11 commits intoSep 12, 2026
Merged
Conversation
…hase D)
Each board is now ONE committed Buildroot defconfig, loaded the vanilla way:
make mister_de10nano_defconfig && make
make O=output-de25 mister_de25nano_defconfig && make O=output-de25
The shared package sets are Kconfig PROFILES -- one symbol that `select`s a
documented list -- so two boards share a userspace by enabling the same
symbol and cannot drift apart on it:
- package/mister-firmware (31 selects: the /lib/firmware set, both boards)
- package/mister-drivers (4: the out-of-tree USB WiFi + xone drivers)
- package/mister-userspace (207: the DE10 userspace, with the old fragment's
32 section headings carried as comments)
The DE25 selects only mister-firmware (rule 5: DE10 packages reach it by
owner decision). Two Kconfig facts shaped the profiles and are asserted by
the new checker: a `select` of a kconfig `choice` member is SILENTLY ignored
(BR2_PACKAGE_ZLIB_NG therefore stays in the defconfig), and a `select` of a
symbol that does not exist is ignored too (mister-initramfs's select of
BR2_PACKAGE_HOST_FAKEROOT -- a host package with no Kconfig symbol -- is
removed; the .mk dependency was always what carried it).
Proof: the candidate defconfigs were resolved with `make <name>_defconfig`
and diffed against the fragment stacks' resolved configs -- identical for
both boards except for the profile symbols themselves (set lines AND
`is not set` lines). The committed files are then Buildroot's own
`savedefconfig` form plus a header comment. BR2_PACKAGE_LINUX_RT_VERSION
loses its Kconfig default so the pin is a defconfig line savedefconfig
keeps (a default would have been dropped and the pin left unmanaged).
Retired: configs/fragments/ (every fragment, stacks.mk, golden.sha256),
scripts/check-config-fragments.sh, scripts/hash-sync-golden.sh (case 8),
scripts/lib/config-stacks.sh. New scripts/check-defconfigs.sh replaces
them, the way upstream Buildroot's own CI checks its defconfigs: each
loads, every line survives (support/scripts/check-dotconfig.py -- the
2026.08 headers regression would have failed here instead of moving a
hash), savedefconfig reproduces the file, every profile select lands, and
the boards agree on the old `common` layer's seven symbols.
The wrapper Makefile is rewritten (799 -> 99 lines): pin, fetch + verify +
unpack (scripts/fetch-buildroot.sh), the GNU-install shim
(scripts/hostshim.sh), `all` with a "configure first" hint, `de10nano-defconfig`
/ `de25nano-defconfig` / `de25` aliases for CI and muscle memory, `sdcard`,
clean/distclean, help (ours + Buildroot's), and `%` forwarding with O= and
BR2_EXTERNAL set. Bare `make` builds, as in Buildroot. The DE25 artifact
assertions the old `de25` recipe carried are already made by
board/mister/de25nano/post-image.sh, so nothing moved.
Consumers repointed to configs/mister_de10nano_defconfig: ci-tests.sh,
test-initramfs.sh, test-sdcard-install.sh, lint-kernel-patches.sh,
hash-sync-kernel.sh (both pins), renovate.json (both kernel managers),
export-kernel-tree.sh / check-export-tree.sh, the CI toolchain fingerprint
and dl cache key, renovate-hash-sync.yml's path filter (golden case gone).
README's build section, docs/buildroot-config.md (banner: where each
section's lines now live), docs/ci.md and ADR 0030's status follow.
Verified: check-defconfigs.sh OK (3 defconfigs); `make
mister_de10nano_defconfig && make` on the Phase C tree rebuilt nothing
(target-finalize + images only); ci-tests.sh 366 pass / 0 fail / 6 skip;
shellcheck clean on every touched script and the composite actions.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V21CRKVv5f66XFNbcrteMD
…follow-through) .github/actions/buildroot-build: 545 -> 213 lines, 18 -> 16 steps. The `variant` and `board` inputs and everything hung off them -- the sentinel table (scripts/lib/board-expectations.sh, deleted), the variant-keyed host cache and make targets, the two conditional build steps -- are gone: since ADR 0030 Phases B-D there is one configuration and one tree. Cache key strings are unchanged (buildroot-tarball-*, br-dl-*, br-host-*, ccache <version>) so existing entries keep hitting. The `ccache-max-size` input nobody passed is a literal. The header comment now states the four caches and the two rules that keep them honest; the fingerprint check is one grep for BR2_arm=y instead of a table. Makefile: the de10nano-defconfig / de25nano-defconfig aliases go (their only caller, release.yml's azcopy job, now says `make mister_de10nano_defconfig`); `de25` stays because the DE25 docs use it. scripts/check-kernel-fragment-noop.sh had no caller and is removed (docs/de25-kernel-config.md says so). Docs: a fixed path/target map applied to the 33 live docs (fragment paths -> the defconfig or the profile that now carries the line; `make rt` -> `make linux-rt`; output-rt/ and output-initramfs/ artifacts -> output/images/), with the passages the map could not fix rewritten by hand (docs/renovate.md's kernel-pin rows and its retired golden-hash case; the debug-tooling and RT build blocks). docs/ci.md gains "The pipeline today" at the top -- nine workflows in a table, the action's four caches and two rules -- and the 1,400-line narrative moves under a "Historical design notes" heading with its anchors intact. The dated DE25 planning ledgers get a layout-note banner instead of line edits. ADRs and kernel-recon records are left as written. Verified: every workflow/action parses; composite-action shellcheck and the script sweep clean; check-defconfigs.sh OK; Makefile parses. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V21CRKVv5f66XFNbcrteMD
….yml 1,110 -> ~560 lines) scripts/mk-release.sh owns everything release.yml's build job used to do inline between `make` and the sdcard image: read /MiSTer.version back out of linux.img and check the Downloader contract, stage the image assets and the single legal-info bundle, fetch + verify + extract the pinned stock archive (scripts/verify-stock-payload.sh, unchanged), assemble files/linux with our linux.img/zImage_dtb/7za, pack release_YYYYMMDD.7z, round-trip it under the pinned ARM 7za via qemu-arm, re-verify uboot.img/updateboot and the member list, and write SHA256SUMS. It runs at a terminal with the STOCK_* pins in the environment; proven locally against the worktree build (release_20260904.7z, 84,632,824 B, every check green). release.yml's build job goes from 27 steps to 9 (checkout, derive version, build, verify-image, mk-release.sh, sdcard, summary, report, upload); the two sdcard steps become one with SDCARD_CORES from the dispatch input; the publish job checks a fixed asset list and `sha256sum -c SHA256SUMS` instead of discovering kernel variants; the dependency-graph job extracts the one manifest. The STOCK_* pin block, the build-azcopy job and the release-notes prose are carried over verbatim. docs/ci.md's release row names the script. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V21CRKVv5f66XFNbcrteMD
The golden-case removal in Phase D consumed the COMMITMSG line that closes the `git commit -F -` heredoc (actionlint/shellcheck on PR #167: SC1044). Restored after the last bullet, with the guarded push it precedes; the stale GOLDEN_CHANGED condition on the step is dropped too. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V21CRKVv5f66XFNbcrteMD
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V21CRKVv5f66XFNbcrteMD
…onlint) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V21CRKVv5f66XFNbcrteMD
…s' patch 0031 The rig, still on an RT 7.2.3 kernel built 2026-09-05 (before PR #152's 7.x re-anchor of the exFAT symlink patch shipped there), Oopsed on the first symlink update_all.sh's Arcade Organizer created on /media/fat: PC 0x0 from page_symlink() via exfat_symlink() -- the NULL write_begin that the DE25's aarch64 QEMU leg had found on 2026-09-06. With CONFIG_PANIC_ON_OOPS=y and panic=15 the board rebooted 17 s later. Nothing executed that patch as 32-bit ARM: the DE10 QEMU leg builds at the shipped 6.18 pin with the shared (page_symlink) form, and the only runs of the 7.x rewrite were aarch64. `--kernel rt` (de10nano only) builds the same multi_v7 test kernel at BR2_PACKAGE_LINUX_RT_VERSION with linux-patches-beta/0031 and its own work/test-initramfs-rt* caches. ci-tests.sh runs its three exfat-driver cases after the DE10 leg. Verified locally at 7.2.4: symlink, exfat, fsck-request pass; the 6.18 form of the patch applied to the same 7.2.4 source reproduces the rig's Oops in QEMU (PC is at 0x0, LR is at page_symlink), so the leg catches the bug it exists for. The shipped 6.18.50 leg still passes symlink. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V21CRKVv5f66XFNbcrteMD
test-initramfs: --kernel rt, the 32-bit QEMU leg for the RT series' exFAT symlink patch
release.yml: one script from a built output/ to a verified dist/
mcfbytes
added a commit
that referenced
this pull request
Sep 16, 2026
The golden-case removal in Phase D consumed the COMMITMSG line that closes the `git commit -F -` heredoc (actionlint/shellcheck on PR #167: SC1044). Restored after the last bullet, with the guarded push it precedes; the stale GOLDEN_CHANGED condition on the step is dropped too. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V21CRKVv5f66XFNbcrteMD
mcfbytes
added a commit
that referenced
this pull request
Sep 16, 2026
ADR 0030 Phase D: Kconfig profiles, committed defconfigs, and a 99-line Makefile
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
The third implementation phase of ADR 0030, stacked on #166 (Phases B+C). Merge #166 first; this PR then re-targets to master automatically.
After this, the newcomer's session is plain Buildroot:
The one departure from a plain defconfig (the caveat you asked for): package selection lives in three Kconfig profiles —
package/mister-userspace(207 selects, the old fragment's 32 section headings kept as comments),package/mister-firmware(31, shared by both boards),package/mister-drivers(4). The defconfig enables them with one line each. Pointers: the profiles' own Kconfig help, the rootConfig.inmenu comment, the Makefile header, README "Building it yourself", and a banner at the top ofdocs/buildroot-config.mdsaying where each section's lines now live.Proof the artifacts are unchanged
make <name>_defconfigand diffed against the fragment stacks' resolved configs: identical except for the profile symbols, set lines andis not setlines alike.make mister_de10nano_defconfig && makeon the Phase C tree rebuilt nothing (target-finalize and images only);ci-tests.sh366 pass / 0 fail / 6 skip.scripts/check-defconfigs.shreplaces the golden-hash machinery with upstream's own idiom (check-dotconfig.py) plus: canonicalsavedefconfigform, every profileselectlands, the boards agree on the oldcommonlayer. Two real Kconfig traps it enforces: aselectof achoicemember is silently ignored (soBR2_PACKAGE_ZLIB_NGstays in the defconfig), and so is aselectof a nonexistent symbol (it caught one inmister-initramfs).Makefile: 799 → 99 lines
Pin, fetch/verify/unpack (
scripts/fetch-buildroot.sh), the GNU-install shim (scripts/hostshim.sh),allwith a configure-first hint, three aliases CI and docs use (de10nano-defconfig,de25nano-defconfig,de25),sdcard, clean/distclean, help, and%forwarding. Baremakebuilds, as in Buildroot.Retired
configs/fragments/(all),stacks.mk,golden.sha256,check-config-fragments.sh,hash-sync-golden.sh(hash-sync case 8),scripts/lib/config-stacks.sh. Every consumer is repointed atconfigs/mister_de10nano_defconfig(both kernel pins live there now;BR2_PACKAGE_LINUX_RT_VERSIONdeliberately has no Kconfig default sosavedefconfigkeeps the pin and Renovate can bump it).Still open
Rig boot of both kernels; Option G (toolchain as a hash-verified release asset).
🤖 Generated with Claude Code
https://claude.ai/code/session_01V21CRKVv5f66XFNbcrteMD