Wave 4: TUI, snapper, --from/--to, declarative installs#7
Merged
Conversation
Phase B stage (order 25) that provisions Snapper for btrfs roots: installs snapper + snap-pac, creates the root config (grep-guarded), sets sane retention, and enables the timeline/cleanup timers. A clean no-op unless layout is btrfs and btrfs.snapshots is snapper (nil-Btrfs guarded). Closes the Wave 2 gap left at archinstall.go's snapshot hook. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New stages.Within post-filter narrows the Select result to an inclusive [from,to] window, resolving each bound by name or order-number like --only. --only still wins; --from/--to compose with --skip/disable. Wired as one filter line after Select in runPhase plus two persistent flags. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
flatpak_remotes is now the complete remote list (no implicit flathub); each flatpaks entry is a remote:appid ref installed from its named remote. Validate the ref shape and that the remote is declared. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
bubbletea viewport with follow/autoscroll, WindowSizeMsg resize, and stage/output/done messages. A teaWriter pumps Runner output into the model so long installers stay live without going to os.Stdout. Promote bubbletea/bubbles/x-term from indirect to direct deps. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add SetSink so Header/Step/OK/Info/Warn/Error flow to the TUI viewport in TUI mode and to os.Stderr in plain mode. Plain mode (sink nil) is unchanged; a test asserts byte-for-byte output. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
runPhase enters the bubbletea alt-screen on a TTY (skipped by --plain, --dry-run, and interactive Phase A installs that prompt). Stage loop extracted to runStages, shared by plain and TUI paths. Update the CLAUDE.md gotcha to the viewport-sink rule. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Render archinstall Kernels from cfg.Kernel.Base instead of the hardcoded [linux]. Add kernel.base (required, min=1) and extend the kernel.default membership check to base union packages. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The pacstrap set is now a required list rendered verbatim into the archinstall config; nothing is prepended in code. The removed base six must be listed explicitly. The old pacstrap_extra key now errors with a rename-to-pacstrap migration message for one release. preflight emits advisory warnings (never injection) for recommended-but- absent entries: AUR build deps, networkmanager, microcode, a kernel. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
# Conflicts: # internal/archinstall/archinstall_test.go # internal/archinstall/bootloader_render_test.go # internal/archinstall/btrfs_test.go # internal/archinstall/encryption_test.go # internal/archinstall/plain_test.go # internal/archinstall/testdata/configs/btrfs-subvols.yaml # internal/archinstall/testdata/configs/ext4-sata.yaml # internal/archinstall/testdata/configs/lvm-zram.yaml # internal/archinstall/testdata/configs/multi-disk-lvm.yaml # internal/archinstall/testdata/configs/single-disk-lvm.yaml # internal/archinstall/volumes_test.go # internal/config/disks_test.go # internal/config/encryption_test.go # internal/config/selectors_config_test.go # internal/stages/hooks_expand_test.go # internal/stages/hooks_test.go # internal/stages/rootdevice_test.go # internal/stages/swap_test.go
# Conflicts: # internal/config/config.go
…landed Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The light e2e job renders its own config.yaml inline; Wave 4 made pacstrap and kernel.base required, so validate now rejects it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The viewport model is value-copied by bubbletea on every Update; a non-zero
value strings.Builder panics ('illegal use of non-zero Builder copied by
value'). Make buf a *strings.Builder so only the pointer is copied.
The alt-screen also owns stdin, so sudo's password prompt (the one interactive
Phase B prompt) corrupted the view. Cache sudo credentials in normal terminal
mode before starting the program, with a 1-min keep-alive.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Hoist the destructive Phase A prompts (ERASE confirmation + user/root password) into Context.CollectInstallPrompts, called in normal terminal mode before the alt-screen; the archinstall stage falls back to it inline for the plain path. Drops the willPrompt gate so install gets the viewport (including the streamed archinstall pacstrap). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The alt-screen TUI owns stdin, so interactive subprocess prompts (e.g. the cachyos-repo.sh Y/N questions in user repos[].setup scripts) can't be answered inside it. Cleanly forwarding them would need a full PTY multiplexer for arbitrary, unpredictably-interactive shell blobs — brittle and heavy for a single-machine tool, and exactly what the original design avoided. Revert Agent A's TUI plus the panic/sudo/prompt-hoist follow-ups: remove internal/tui, the ui output sink, --plain, sudo pre-cache and install-prompt hoist. Output once again streams stdout/stderr straight through (Runner.Out nil), so subprocess prompts read from the real terminal. The rest of Wave 4 (snapper, --from/--to, declarative pacstrap/flatpak/kernel) is unaffected. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bind the lipgloss renderer to os.Stderr so colour detection matches where output lands (clean plaintext when redirected, colour on a TTY); add --no-color and honour NO_COLOR. Frame each run with a banner (version · phase · stage count, DRY RUN badge) and a summary with total time; print an [i/n] progress header and elapsed time per stage, and a red failure summary naming the stage that failed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
Wave 4 — TUI, snapper,
--from/--to, and declarative install sourcesSix features built by parallel worktree agents (TDD, idiomatic Go), merged into one branch. Full suite green:
gofmt -l .clean,go vet ./...,go build,go test ./...all pass;config.example.yamlvalidates.Features
internal/tui/bubbletea viewport (header/footer, follow/autoscroll, resize).uioutput routed through a swappable sink +teaWriterpump. Behind a TTY check +--plain; plain mode stays byte-for-byte unchanged. Prompts run first, in plain mode (two bubbletea programs can't share the terminal).internal/stages/snapper.go(Order 25). No-op unlessbtrfslayout andsnapshots: snapper; otherwise installssnapper/snap-pac, grep-guardedcreate-config, retention, enables the timeline/cleanup timers. Closes the Wave 2 gap.--from/--toresumestages.Withinpost-filter (name-or-number bounds, inclusive).--onlystill wins; composes with--skip/disable.pacstrappacstrap_extra+ the in-code base set with a verbatim required list;pacstrap_extranow errors with a migration hint. Advisory preflight warnings (never injection).flatpak_remotesremote:appidrefs, validated at config time.kernel.baseKernels: [linux];kernel.defaultmust be inbase ∪ packages.Notable integration work (hand-merged centrally)
stages.Selectline stable; C'sWithinslots right after).pacstrap) and D3 (kernel.base) both made a field required, colliding in ~15 shared inline-YAML fixtures — resolved by union, exceptarchinstall_test.gowhere a blind union would have kept the now-illegalpacstrap_extrakey.TestRegistry/TestWithinexpectations were centrally updated.kernel.base.Deferred (deliberate)
set-configunit names — still need a real archinstall 4.3 QEMU run before hardware.See
docs/extensibility-review.md→ "Wave 4 retrospective" for full notes.🤖 Generated with Claude Code