Uh oh!
There was an error while loading. Please reload this page.
release-train: develop -> staging - #499
Conversation
…ws installer (#422) (#477) * chore(#422): honest step labels + per-tool heartbeat/progress in the PS installer Step 1/5 "Checking system requirements" actually installed ~700 MB of tools, nearly all console-silent (downloads with the progress overlay off since #471, plus silent winget/Add-AppxPackage/installer invocations), which reads as a hang. The k3d start path also streamed raw INFO[...] lines past the style system. - Split Step 1 into "Checking system requirements" (preflight/GPU/virtualisation) and a dedicated "Installing system tools" step; renumber to /6. - Invoke-WithHeartbeat: run a blocking op in a background job with a live spinner (built on the existing Wait-JobWithProgress) so no op sits silent >10s. Wired into every tool download (kubectl/k3d/helm/winget/Docker Desktop), the winget installs, Add-AppxPackage, and the Docker Desktop installer. - Get-ToolSummaryLine: one honest line per tool (name, version, size, elapsed), printed as each tool becomes ready. - Route `k3d cluster start` through Invoke-WithHeartbeat: capture its raw output to the log + show a styled heartbeat instead of streaming INFO[...] lines (and fail loudly if start fails, instead of always reporting "started"). - Tests: Pester for Get-ToolSummaryLine, Invoke-WithHeartbeat, and source guards for the 6-step split + no-raw-k3d-output. The copy catalog is bash-driven and the bash installer already splits check (step a) from install (step b) with real progress, so its golden is unaffected. Closes#422 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#422): job-runspace TLS 1.2 floor + k3d start exit-code check (Bugbot) Two High-severity findings from moving work into Start-Job via Invoke-WithHeartbeat: - TLS 1.2 doesn't carry into job runspaces (PS 5.1 defaults to TLS 1.0/1.1), so in-job HTTPS downloads (kubectl/k3d/helm/winget/Docker Desktop) could fail SSL/TLS on hosts that need the explicit floor. Re-apply Tls12 in $script:JobInit (OR-in, don't clobber), which every job runs before its scriptblock. - A native `k3d cluster start` non-zero exit leaves the job state 'Completed', so Invoke-WithHeartbeat never threw and the installer reported "Compute environment started." on a stopped cluster. The start scriptblock now checks $LASTEXITCODE and throws its captured output, so the existing catch surfaces a real Err. Adds a functional in-job-TLS test and a source guard for the exit-code throw. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#422): surface heartbeat failure detail + fail loudly on Docker install (Bugbot) Two follow-on findings from the Start-Job/heartbeat design: - Invoke-WithHeartbeat threw a generic 'Failed while: ...' and swallowed the job's real error (Receive-Job -ErrorAction SilentlyContinue), so the k3d-start detail never reached the log/Err. Now capture output+error (2>&1) and the job's terminating reason, and include it in the throw; the k3d-start catch passes it as Err detail too. - The Docker Desktop installer Start-Process had no -ErrorAction Stop and no exit check, so a spawn/install failure completed the job as success and Step 2 continued. Now -ErrorAction Stop + PassThru + exit-code throw, wrapped so it Errs cleanly with the real detail. Adds a heartbeat failure-detail test + a Docker-installer source guard. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#422): print k3d/helm summary only after the execute-gate (Bugbot) k3d and helm printed their green Get-ToolSummaryLine 'ready' line inside the download branch, before Assert-ToolRuns — so a corrupt/wrong-arch binary showed as ready and then failed the gate (kubectl already gates first). Compute the summary at download time (correct elapsed) but defer the Ok until after the execute-gate passes. Adds a source guard. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#422): winget Docker install falls back + fails loudly (Bugbot) The winget Docker path soft-logged failures, never checked $LASTEXITCODE, and had no direct-download fallback when winget was present — so a failed winget install let Step 2 continue and only surfaced as the 10-minute Docker-wait timeout later. Now: the winget scriptblock throws on a non-zero exit; if winget is absent OR didn't land the exe, fall through to the direct download (parity with k3d/helm); and a final Test-Path guard Errs immediately if neither path installed Docker. Adds a source guard. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#422): run installers as killable processes, not orphan-prone jobs (Bugbot) Start-Process -Wait / winget install inside Invoke-WithHeartbeat (a background job) leaks the child process on timeout: Stop-Job ends the job runspace but the installer keeps running, and the winget path could time out then fall through to a second concurrent install. Switch the Docker Desktop installer + all winget installs (Docker, k3d, helm) to Start-Process -PassThru + Wait-ProcessWithDeadline, which shows the spinner AND kills the actual process on timeout, then checks the exit code. Downloads (Invoke-WebRequest) stay on Invoke-WithHeartbeat — no child process to orphan. Updates the Docker source guards accordingly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#422): run k3d cluster start as a killable process too (Bugbot) Same orphan hazard as the installers: k3d cluster start ran inside Invoke-WithHeartbeat (a job), so Stop-Job on timeout left the native k3d child running. Switch it to Start-Process -PassThru + Wait-ProcessWithDeadline (kills on timeout), redirecting its raw INFO[...] to temp files for the log; check both the deadline and the exit code so a failed/stuck start Errs with the real reason instead of a false 'started'. Now every process-spawning op is killable; only in-runspace downloads + Add-AppxPackage remain on the job-based heartbeat. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…omise (#481) Bugbot on the staging promotion (#480): the Tier-1 branch printed 'no administrator rights needed' BEFORE _ensure_subid_ranges / _ensure_cgroup_delegation ran - on hosts where either fires, the operator saw a no-admin promise immediately contradicted by an announced sudo touch or a prepare-host handoff. The header now stays neutral ('user-space install'); the two prerequisite helpers already announce themselves or hand off when they actually apply. Tier 0's claim is unconditionally true and stays. Manifest regenerated.
…ce (#417) (#483) * fix(#417): report host RAM consistently + achievable memory advice The preflight memory check preferred Docker's WSL2 VM budget over physical RAM, so the same 15 GB laptop reported "7 GB" with Docker up and "15 GB" with it down -- flip-flopping across re-runs -- and recommended "give Docker >= 16 GB" on a 15 GB host (impossible). - Get-PfMemGb now returns HOST RAM only (physical, via CIM) -- identical whether Docker is up or down. The runtime VM budget is read separately (Get-PfRuntimeMemGb) and shown as its own labeled line ("Docker's current share: N GB"). - Get-PfMemRecommendation caps every suggestion at (host - 2 GB), so we never advise more memory than the machine physically has; floors at 1 GB. - Step-1 (Test-Preflight) and Step-2 (Test-PreflightRuntimeMem) now give one consistent, host-aware message; Step-2's recommendation is capped too. Tests: Get-PfMemRecommendation (cap/floor/16-on-15 cases), Get-PfMemGb reports host RAM regardless of the Docker budget (Windows + cross-platform decoupling), and Test-PreflightRuntimeMem caps its recommendation at host RAM. Updated the former "Get-PfMemGb prefers docker" test (it asserted the flip-flop bug). Closes#417 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#417): don't dangle unachievable memory advice on too-small hosts (Bugbot) Two follow-ups to the capped-recommendation logic: - Step-1's middle branch (host below the training threshold) told 5-7 GB hosts to give Docker host-2 GB (3-5 GB) 'to train locally' — which can't train (~8 GB/job). It now states the truth: runs fine, but local training needs a bigger machine (~warnMemGb+2 GB+), with no impossible target. - Test-PreflightRuntimeMem said 'Raise Docker to N' even when N <= the current budget (a no-op on a host already at its achievable cap). It now only recommends raising when that's actually possible; otherwise it names the real fix (more RAM). Tests updated: the capped-rec test uses a 9 GB host (cap 7, not the 8 target), and a new test asserts no no-op 'raise to' when already at the cap. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#417): training-warn threshold accounts for the OS reserve (Bugbot) Step-1 marked memory Ok at host >= warnMemGb (8), but sparing an 8 GB Docker budget also needs ~2 GB for the OS (the cap in Get-PfMemRecommendation), so an 8-9 GB host got a green check that Step-2 then contradicted with 'can't spare more'. Extend the too-small-for-training branch to host < warnMemGb + 2 so Step-1 agrees with Step-2. Adds a test that a 9 GB host is flagged, not Ok. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test(#417): make the host-RAM decoupling test host-independent (Bugbot) The cross-platform decoupling test asserted Get-PfMemGb -Not -Be 8 while mocking docker to 8 GiB but not CIM, so on a real 8 GB Windows host (where host RAM is genuinely 8) it would flakily fail even though the fix is correct. Assert instead that Get-PfMemGb never invokes docker (Should -Invoke docker -Times 0) - the true decoupling guarantee, host-independent - and add a separate positive test that Get-PfRuntimeMemGb still follows the docker budget. The exact host figure stays locked by the Windows-gated CIM-mocked sibling test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#417): grade the effective memory figure, keep host RAM as the label (Asad) Reworked per review: Step-1 graded host RAM and demoted the Docker budget to a decorative string, so a throttled budget (e.g. 32 GB host / 2 GB Docker) showed a green Ok and the 15/7 machine from #417 lost its warning. New Show-MemoryStatus (shared by Step-1 and the post-Docker re-check): - Grades the EFFECTIVE figure the client actually gets (Docker's VM budget when known, else host RAM), so a throttled budget is never green-OK'd; both the min 'will OOM' and warn 'training may OOM' floors apply to the budget. - Always REPORTS host RAM as the label (no flip-flop); when host RAM is unreadable (CIM blocked) but the budget is, reports the budget labelled as Docker's share instead of skipping. - Threads recMemGb back into the training target (was dead on Windows), capped at host - OS reserve, so the number is achievable (13 on a 15 GB host, not 10/16). - Single $script:PfOsReserveGb constant (was the literal 2 in three places); the warnMemGb+2 rung is gone, so PF_WARN_MEM_GB no longer means two things by OS. Tests: comprehensive Show-MemoryStatus grading (reviewer's 32/2, 16/4, 15/7, 10/5, host-down, CIM-blocked, healthy) + Step-1/Step-2 delegation. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#417): don't cap memory advice at the throttled budget when host RAM is unknown (Bugbot) When CIM was blocked (host RAM unreadable), $capHost fell back to the Docker budget, so recommendations were capped at (budget - reserve) -- producing backwards, contradictory hints like 'Give Docker at least 5 GB (up to 2 GB)' on a 4 GB budget. The budget is the current throttled value, not a ceiling. Now only cap at the host when host RAM is known; when it isn't, advise the raw targets (at least minMemGb, up to warnMemGb). Adds a regression test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…d#1303) (#486) Backlog at zero fleet-wide; the quality contexts are already required on develop. Also adds a workflow_dispatch(all-files) trigger for whole-tree scans (gitleaks baseline). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…en current (#414) (#484) * fix(#414): WSL update survives Store-blocked networks + skips when current The installer ran `wsl --update` through the Microsoft Store with a 90s silent- timeout job: on Store-blocked corporate networks it silently skipped (Docker Desktop then confronted the user with its own install-WSL prompt + reboot), it re-ran up to 90s on every re-run even when the kernel was current, and its output went only to the log. New Update-Wsl: - Skips when WSL is already current (Test-WslCurrent parses `wsl --version`), so the block finishes in <2s on a re-run. - Uses `wsl --update --web-download`, which fetches from Microsoft's servers instead of the Store, so a Store-blocked machine still updates the kernel with no Docker Desktop WSL prompt. Runs as a killable tracked process with a deadline. - On failure, surfaces the exact manual MSI step on screen (github.com/microsoft/ WSL/releases), not swallowed to the log. Scope note: the issue also suggested auto-falling-back to the GitHub-releases MSI. That isn't implemented automatically because it would require api.github.com (the WSL asset name carries a 4th version component the API-free /releases/latest redirect can't resolve), and #410 -- enforced by a test -- forbids the rate-limited GitHub API in this installer. The manual step is surfaced clearly instead; a test guards against a regression that re-adds the API. Tests: Test-WslCurrent parsing; source guards for --web-download, skip-when-current, no bare Store-path job, the manual step, and the #410 no-API invariant. Closes#414 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#414): decode wsl --version as UTF-16 so skip-when-current fires (Bugbot) wsl.exe writes UTF-16LE; capturing it via 'cmd /c ... | Out-String' left the output null-interleaved, so Test-WslCurrent never matched -- skip-when-current never fired and every re-run attempted a full (up to 5 min) web update and could show a false MSI warning. Capture wsl --version with [Console]::OutputEncoding set to Unicode (the same pattern the wsl --list reader already uses), restored in a finally. Adds a source guard. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#414): name the arch-matched WSL MSI in the manual hint (Bugbot) The manual fallback hint hardcoded wsl.<version>.x64.msi, but Get-WindowsArch returns arm64 on ARM hosts and GitHub ships wsl.<version>.arm64.msi. An ARM operator following the x64 step installs the wrong package and still hits the Docker Desktop WSL prompt this path avoids. Compute the MSI arch from the host. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#414): detect WSL via the version number, not the localized label (Bugbot) Test-WslCurrent matched the English 'WSL version:' label, but wsl --version localizes it (e.g. Japanese 'WSL バージョン:'), so skip-when-current never fired on non-English Windows and every re-run attempted the full web update. Match the dotted version number instead, which modern WSL always prints regardless of locale. Adds a non-English test case. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#414): harden WSL update per review — floor, bounded probe, retry, real errors Reworked Update-Wsl to address Asad's review: - Test-WslCurrent now grades a version FLOOR, not mere presence: it pulls the first dotted version (the WSL version line, locale-independent) and requires >= TB_WSL_MIN_VERSION (default 2.1.0), so a stale modern WSL (2.0.x) still updates instead of being green-OK'd forever. - The wsl --version probe is BOUNDED: Get-WslVersionOutput runs it in a job with Wait-JobWithProgress -TimeoutSec 20 (like the wsl --list reader) and returns "" on timeout, so a wedged LxssManager can't freeze Step 1. The encoding restore is wrapped (finally { try {...} catch {} }) so it can't kill the installer on a console-less host. - Invoke-WslUpdate runs wsl --update as a tracked process with a deadline, redirects stdout/stderr to temp files (logged), and classifies the outcome (ok / not-found / timeout / failed) — so failures leave real WSL evidence in the log + -Diagnose, and wsl's \r progress no longer fights the spinner. - Two-rung ladder: on a non-zero web-download exit (unpatched wsl.exe rejects the flag), retry plain `wsl --update` before giving up. - Differentiated failure messages: not-found / timed out / exited N — no longer the single "the Store may be blocked" line that --web-download rules out. Tests: Update-Wsl is now EXECUTED (mocked deps) across skip / web-download / retry / timeout / not-found branches; Test-WslCurrent covers the stale-floor + custom- floor cases; source guards anchored on the real invocations; dropped the duplicate #410 guard (the #410 Describe owns that invariant). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#414): raise WSL currency floor to Docker Desktop's 2.1.5 minimum (Bugbot) The 2.1.0 floor let 2.1.0-2.1.4 boxes skip the update yet still hit Docker Desktop's update-WSL prompt (it requires >= 2.1.5). Default the floor to 2.1.5. Adds a 2.1.4 boundary test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…22) (#485) * feat(install): Tier-1 no-systemd fallback + Tier-2 fall-through (#1222) Last slice of #1177 (LPI Tier 1) — the code hardening that completes the rootless path. Everything stays behind the opt-in TB_TIER1_ROOTLESS flag; the §5 host-matrix validation (fuse-overlayfs perf) and the flag flip to default-on are host-gated and NOT in this PR (deferred, tracked on #1222). - _user_systemd_available: detect a usable per-user systemd manager via `systemctl --user is-system-running` (a state word => present, even on non-zero exit; empty => no manager/bus) plus XDG_RUNTIME_DIR. - _start_rootless_nohup: on hardened/HPC nodes with no user-systemd, start dockerd-rootless.sh via nohup under an owned XDG_RUNTIME_DIR, poll the socket to Ready, skip linger. Still user-space, no root. Sets TB_ROOTLESS_NO_LINGER. - install_rootless_docker branches systemd-vs-nohup; the daemon-verify failure now routes via _tier2_fallthrough (prepare-host remedy) instead of a bare error — no proceeding on a broken socket, no false Tier-1. - summary.sh::_reboot_note: honest "will NOT restart automatically" note on the no-linger path (takes precedence over the autostart flag). Tests: no-systemd nohup branch; daemon-never-Ready -> Tier-2 fall-through; the 5 existing install_rootless_docker tests updated to model is-system-running; the reboot-note no-linger case. shellcheck clean; full bats suite green; manifest regen. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(install): address Bugbot #485 — persist the exact rootless runtime dir (no-systemd path) On the nohup fallback, /run/user/<uid> may be unwritable so the socket lands under $HOME/.tracebloc-rootless-run. Before, the persisted DOCKER_HOST used the generic ${XDG_RUNTIME_DIR:-/run/user/$(id -u)} template (→ wrong socket in a fresh no-systemd shell) and the restart guidance omitted XDG_RUNTIME_DIR (dockerd-rootless.sh refuses without it), so the operator couldn't bring the daemon back. Now: - _start_rootless_nohup records TB_ROOTLESS_RUNTIME_DIR and shows the full 'XDG_RUNTIME_DIR=<dir> nohup dockerd-rootless.sh &' restart command. - _persist_docker_host persists 'export XDG_RUNTIME_DIR=<dir>' before DOCKER_HOST, so a new shell resolves the SAME socket the install used AND can restart the daemon. - summary.sh::_reboot_note carries the exact dir in the restart hint. - Tests: rc sourced with XDG unset resolves DOCKER_HOST to the $HOME socket; the runtime dir is recorded; the reboot-note hint carries the dir. manifest regenerated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(install): address Bugbot #485 r2 — honest 'Started' claim + setuptool Tier-2 fall-through - _start_rootless_nohup: only claim "Started rootless Docker…" once the poll confirms the daemon answered (_up). A bare "Started…" before a failed poll contradicted the shared verify's "daemon never answered" fall-through moments later (Bugbot medium). - install_rootless_docker: guard both install paths (dockerd-rootless-setuptool.sh / get.docker.com/rootless) with '|| _tier2_fallthrough', so a setuptool/installer failure routes to the prepare-host remedy instead of a bare set -e abort with the spinner log tail — _tier2_fallthrough's documented setuptool coverage was not actually wired (Bugbot medium). - Tests: nohup daemon-never-answers => no false "Started" + Tier-2; setuptool install failure => Tier-2 fall-through naming the setuptool. manifest regenerated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(install): address Bugbot #485 r3 — don't clobber a session XDG_RUNTIME_DIR The r1 persist wrote 'export XDG_RUNTIME_DIR=<dir>' unconditionally into the shell rc. ~/.bashrc is sourced on every host sharing the home (HPC NFS), so that clobbered a legitimate pam/systemd /run/user/<uid> on a systemd node and broke user-systemd there — a regression from the r1 fix. Guard it: 'export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-<dir>}"', supplying our dir only when the session hasn't set one. The test now also asserts a pre-set XDG is preserved (not clobbered) alongside the no-systemd resolve case. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(install): address Bugbot #485 r4 — holistic rewrite of the no-systemd persist/launch path - _launch_dockerd_rootless: add </dev/null so the backgrounded daemon can't inherit the installer's `curl | bash` pipe stdin and consume the rest of the script (Bugbot High). - _persist_docker_host: rewrite as an atomic BEGIN/END managed block, stripped + re-appended each run. The prior per-line append landed a re-run's XDG line AFTER DOCKER_HOST, so it never took effect (Bugbot medium). The runtime dir is now baked into the DOCKER_HOST fallback (order-independent resolution); the guarded ${XDG_RUNTIME_DIR:-…} line supplies it for the daemon restart without clobbering a systemd node's /run/user/<uid>. - Self-review hardening: same-dir temp + `cat` (not `mv`) so a symlinked/stow'd rc + perms survive and a full disk bails before touching the rc; strip only a WELL-FORMED block (both markers) so a malformed rc isn't eaten past a missing END marker. - Tests: systemd→nohup transition; </dev/null guard; unrelated-content/malformed-block safety. full setup-linux + summary suites green; shellcheck clean; manifest regenerated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(install): descope the no-systemd nohup fallback from #1222 -> Tier-2 (#1354) Six consecutive Bugbot rounds landed on the no-systemd nohup fallback (async daemon + set -e + curl|bash stdin + shared-home rc persistence), none validatable without a real HPC host. Descope it: a host with no per-user systemd now routes to the Tier-2 prepare-host remedy (honest + testable) instead of a blind nohup bring-up. - Delete _start_rootless_nohup + _launch_dockerd_rootless; install_rootless_docker's no-systemd branch now calls _tier2_fallthrough. - Revert _persist_docker_host to the simple systemd-path form (pam sets XDG_RUNTIME_DIR; no $HOME-fallback / atomic-block / XDG-persist complexity). - Drop the now-dead TB_ROOTLESS_NO_LINGER branch in summary.sh::_reboot_note. - Tests: no-systemd => Tier-2 fall-through; removed the nohup / persist-XDG / launch tests. full setup-linux + summary suites green; shellcheck clean; manifest regenerated. The nohup fallback is tracked for a host-available slice in #1354. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(install): gate on user-systemd BEFORE installing (Bugbot #485) install_rootless_docker checked _user_systemd_available only AFTER the setuptool install + the user proxy drop-in. The setuptool sets up a `systemctl --user` unit and fails first on a no-systemd host, so the operator got a vague setuptool reason plus a partial ~/bin install + drop-ins before the Tier-2 remedy. Move the gate to the TOP -> fail fast to _tier2_fallthrough with the accurate "no per-user systemd" reason and no artifacts. The later systemd branch is now unconditional (the redundant re-check is removed). Test now also asserts the setuptool never runs on the no-systemd path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(install): name the researcher in _tier2_fallthrough's prepare-host remedy (Bugbot #485) _tier2_fallthrough printed a bare `prepare-host` hint with no TB_PREPARE_USER / username. run_prepare_host only grants docker-group access + provisions subuid ranges when the user is named, so an admin who followed the bare hint prepared the host but NOT the researcher — looping them back into the same fall-through. Name the researcher (id -un), matching _ensure_subid_ranges' hand-off verbatim (export TB_PREPARE_USER=<user>, `prepare-host <user>`). Test asserts the remedy names them. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…end (#419) (#487) * feat(#419): install Docker Desktop unattended with the WSL2 backend On the winget path the installer couldn't pass Docker Desktop's own installer args (winget's manifest defaults decided), leaving first-launch license/onboarding prompts possible and the backend implicit; the direct path passed --quiet --accept-license but not --backend=wsl-2. - winget: add --override 'install --quiet --accept-license --backend=wsl-2 --always-run-service' so Docker's installer flags apply through winget. - direct: add --backend=wsl-2 --always-run-service to match. - --always-run-service (Docker's documented unattended flag) starts the engine service without a GUI first-run, so a fresh machine reaches a running engine with zero Docker Desktop interaction. Tests: source guards that both paths select the WSL2 backend + run the service unattended, and that winget uses --override. Closes#419 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#419): pass winget --override as a single quoted string (PS 5.1 safe, Bugbot) The --override value was one ArgumentList array element containing spaces; PS 5.1's Start-Process joins array elements without quoting, so winget received '--override install' plus stray --quiet/--accept-license tokens and the Docker installer flags never applied (winget failed -> fell back to the 600 MB direct download). Build the winget args as a single command-line string with the override value explicitly double-quoted, so it reaches winget as one argument. Updated the source guards accordingly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…e docs (#421) (#489) * feat(#421): self-elevate an un-elevated PowerShell run + cmd-safe docs Real users paste the one-liner into a normal PowerShell (or cmd) and the install either dies on the admin requirement or errors syntactically. #386 added elevation instructions; this automates the common case. - On an un-elevated interactive run, offer to relaunch elevated: one consent -> Start-Process -Verb RunAs (UAC) -> install proceeds. Get-ElevationCommand builds the relaunch args -- re-run the on-disk .ps1 when present, else re-fetch the one-liner (irm|iex) -- forwarding -NoReboot/-Diagnose. Non-interactive/declined/ failed falls back to the followable Win+X -> Terminal (Admin) steps (#386). - docs/INSTALL.md: add the cmd-safe form (powershell -ExecutionPolicy Bypass -Command "irm ... | iex") so a paste into cmd.exe runs instead of a syntax error, plus the exact Win11 admin steps. Env-var config (TRACEBLOC_*) is intentionally not forwarded across RunAs (no env inheritance; secrets on a command line are unsafe) -- documented; env-driven runs should be launched elevated. Tests: Get-ElevationCommand (file vs one-liner, switch forwarding) + gate source guards. Website snippet + screenshot are a separate repo (noted in the PR). Closes#421 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#421): elevation re-fetches the one-liner for temp-dir runs + forwards switches (Bugbot) Two elevation-relaunch defects: - The documented irm|iex flow runs install-k8s.ps1 from a bootstrap TEMP dir the un-elevated process deletes on exit, so -File <tempfile> in the elevated window hit a missing script. Only use -File for a DURABLE (non-temp) path; otherwise re-fetch the one-liner. - The one-liner branch dropped -NoReboot/-Diagnose. iex can't take args, so when switches must be forwarded, invoke the fetched shim as a scriptblock with them; keep the plain irm|iex form when there are none. Adds temp-dir and switch-forwarding tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#421): quoted command-line string + drop unforwardable one-liner switches (Bugbot) Two elevation follow-ups: - Get-ElevationCommand now returns a single command-line STRING and quotes the -File path, so a script path with spaces survives PS 5.1's Start-Process -ArgumentList (which doesn't quote array elements; same class as #419). - The one-liner path no longer tries to forward switches via a scriptblock: the shim (i.ps1) has no param block, so & ([scriptblock]) -Diagnose fails on an unknown named parameter; and an irm|iex launch can't have set a switch anyway. Keep the exact documented irm|iex form. Tests updated for the string contract + the no-scriptblock one-liner path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…CDN (#497) * fix(ci): read index.yaml via the contents API, not the raw CDN verify-index fetched index.yaml from raw.githubusercontent.com seconds after the release job may have pushed gh-pages. raw.* is CDN-fronted and serves a stale copy for a while after a push, and ?nocache= does not reliably bust it -- so the job could read a clean index while the customer-facing one was already polluted, greening the exact backstop it exists to be. Now read through the contents API at ?ref=gh-pages, which is read-after-write consistent for a ref, and fail loudly on an empty read rather than reporting the invariants as holding on no data. Found by Bugbot on the staging->main promotion (client#495). * fix(ci): emit the empty-read error on stdout so it annotates Actions parses workflow commands from stdout only, so an ::error:: sent to stderr fails the step with no annotation. Every sibling ::error:: in this file already uses stdout (Bugbot, client#497).
LukasWodka
commented
Jul 30, 2026
bugbot run |
…ted window (#418) (#493) * feat(#418): provision Docker for the daily user during the elevated window Hospital/enterprise reality: the researcher gets a temporary admin window (or IT installs), then elevation is revoked -- leaving the standard account unable to use Docker, a cluster that may not recover, and a 50%-of-RAM VM that OOMs training. The installer runs elevated, so provision the day-to-day account now. New Set-DailyUserProvisioning (warn-only; TRACEBLOC_SKIP_DAILY_USER opts out): - Resolves the daily user (-DailyUser param, else prompt when an admin installs for someone else, else the current account); Resolve-DailyUser strips the domain. - net localgroup docker-users <user> /add so the standard account can use Docker. - Docker Desktop autostart via the per-user Run key (current user). The engine also runs as a service (--always-run-service, #419), so Docker is usable on sign-in regardless; cluster nodes already carry restart=unless-stopped (Set-ClusterAutostart). - Writes a training-sized %UserProfile%\.wslconfig (Get-WslConfigMemoryGb: physical RAM - 4 GB, floored) for the daily user, preserving an existing tuned file. It applies at the daily user's next sign-in -- the acceptance scenario -- so we do NOT wsl --shutdown and tear down the just-built cluster mid-install. - Prints a "Configured for <user>: ..." summary so IT can review what changed. Tests: Get-WslConfigMemoryGb (cap/floor), Get-WslConfigContent, Resolve-DailyUser, plus source guards for docker-users / .wslconfig-preserve / opt-out + wiring. Closes#418 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#418): address Bugbot round 1 on daily-user provisioning - .wslconfig merge: Add-WslMemorySetting keeps an existing memory= AND preserves any other tuning (processors/swap/other sections) instead of overwriting the whole file. Inserts under an existing [wsl2] header, else appends a section. - missing profile: when the daily user has never signed in (Get-UserProfileDir null), note ".wslconfig after first sign-in" in the summary instead of silently skipping. - elevation: forward -DailyUser through Get-ElevationCommand / Invoke-SelfElevate so the choice survives the UAC relaunch. - input hygiene: sanitize the prompted username via ConvertTo-SanitizedInput before it reaches net localgroup and profile paths. Tests: Add-WslMemorySetting (create/keep/insert-preserve/append-preserve), Get-UserProfileDir null, plus wiring guards for the merge helper, the no-profile note, the sanitize call, and -DailyUser elevation forwarding. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#418): address Bugbot round 2 on docker-users provisioning - Never hide a docker-users failure behind a green summary (High). Membership is the make-or-break step; track $dockerUsersOk and, when it doesn't take, WARN loudly (with the manual `net localgroup ... /add` to run while admin is still available) even if autostart/.wslconfig succeeded. Green "Configured for" now only prints when membership is confirmed. - Verify membership by STATE QUERY instead of string-matching 2>&1-merged native output (Medium; learned PS rule). New Test-LocalGroupMember (Get-LocalGroupMember, falling back to `net localgroup <group>` STDOUT) + pure Test-NameInGroupOutput (domain-stripped, case-insensitive) replace the locale-fragile `-match 'already a member'` classification. Tests: Test-NameInGroupOutput (bare-name/domain/case/empty), plus source guards for the state-query verification and the loud-warn-on-failure summary. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#418): note .wslconfig as manual step when host RAM undetectable Bugbot round 3 (Medium): when Get-PfMemGb returns null the .wslconfig budget was skipped with no summary note -- unlike the null-profile path -- so a green "Configured for" could print while the training memory budget was never applied. Add the matching note ("couldn't detect host RAM -- set [wsl2] memory manually") so IT sees the gap. Guard test added. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#418): surface a thrown .wslconfig write in the summary Bugbot round 4 (Medium): if the .wslconfig merge/write throws (permissions/disk), the catch only Logged and recorded no summary note, so with docker-users already confirmed the green "Configured for" line still printed as if the memory budget was set. Add a "couldn't write .wslconfig -- set [wsl2] memory manually" note in the catch, matching the null-profile / RAM-unknown paths. Guard test added. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
LukasWodka
commented
Jul 30, 2026
👋 Heads-up — Code review queue is at 40 / 30 Above the WIP limit. The team convention is to review existing PRs before opening new work. Open PRs currently in Code review (oldest first):
Pull from review before opening new work. (This is a nudge from the kanban WIP check, not a block.) |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
LukasWodka
commented
Jul 30, 2026
Both findings valid, both ticketed as #500, neither a promotion blocker.
Both are in the Windows installer epic's area (backend#1285) and flagged to @saadqbal on #500. For the record on why this PR didn't merge: it was not these findings. The staging fr-gate failed with Resolving these so the re-fire isn't held. |
Inside WSL2 the environment IS Linux, so the existing Linux tiers apply unchanged — no separate Windows code path. Make the installer WSL-aware: - probe.sh: _probe_wsl (WSL_DISTRO_NAME/WSL_INTEROP env, or microsoft/WSL in the kernel release; paths overridable for tests) + PROBE_WSL in run_host_probes (Linux-only, read-only, never-fatal). Classification is UNCHANGED — a usable Docker (incl. Docker Desktop's WSL integration, if present) is Tier 0, else Tier 1 rootless. - render_host_audit: a WSL2 "Environment" row surfacing the rootless-preferred stance; the Tier-2 unsupported-os message now points Windows users at WSL2 (rootless) as the preferred path over Docker Desktop. - docs/INSTALL.md: WSL2 quick-start note — enabling WSL2 as the one-time Windows admin step + the rootless-over-Docker-Desktop preference with the licensing rationale. - 8 probe.bats tests; shellcheck clean; manifest regenerated (R8). End-to-end verification inside a real WSL2 Ubuntu is host-gated (needs a Windows host); the probe/audit/messaging is unit-tested here. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
LukasWodka
commented
Jul 30, 2026
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 80bee57. Configure here.
LukasWodka
commented
Jul 30, 2026
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 80bee57. Configure here.
Uh oh!
There was an error while loading. Please reload this page.
Automated promotion by the release train (RFC-0008 D14). Head is the train-managed
release-train/to-stagingbranch (a mirror ofdevelop), so it never collides with a human PR. Merged only when the fr-gate is green.Note
Medium Risk
Large, customer-facing installer and CI gate changes (hard-fail code quality, Helm index backstop); well-tested but any regression affects fresh installs on Windows and Linux/WSL.
Overview
Automated develop → staging promotion with client chart
1.9.8(Chart.yamlversion/appVersion).CI / release: Code quality now fails on findings (
soft-fail: false) and supportsworkflow_dispatchfull-repo scans. Post-publish Helm index verification readsindex.yamlvia the GitHub Contents API (avoids staleraw.githubusercontent.com) and treats an empty read as failure; workflow errors go to stdout for Actions annotations.Windows installer (
install-k8s.ps1): Flow is 6 steps (preflight vs “Installing system tools”). Adds UAC self-elevation for non-admin runs,Invoke-WithHeartbeat/ tool summary lines, killableStart-Process+ deadlines for winget/Docker/k3d, silent Docker Desktop (wsl-2,--always-run-service), smarter WSL update (--web-download, version floor), daily-user Docker provisioning (docker-users,.wslconfig), and memory preflight that labels host RAM but grades Docker’s budget (Show-MemoryStatus).Linux installer:
probe.shdetects WSL2 and updates Tier 2 / audit copy (WSL2 rootless preferred).setup-linux.shgates rootless on per-user systemd, routes failures through_tier2_fallthrough→prepare-hostwithTB_PREPARE_USER, and tightens messaging on privileged prerequisites.Docs:
INSTALL.mdexpands Windows paths (cmd one-liner, WSL2 rootless, admin / relaunch behavior).scripts/manifest.sha256and large Pester/bats coverage for the new behavior.Reviewed by Cursor Bugbot for commit 80bee57. Bugbot is set up for automated code reviews on this repo. Configure here.