Skip to content

feat(installer): first-time install run-through (1. Downloading / 2. Installing a–f) + healthy re-run bailout#341

Open
LukasWodka wants to merge 13 commits into
developfrom
feat/installer-first-run-ux
Open

feat(installer): first-time install run-through (1. Downloading / 2. Installing a–f) + healthy re-run bailout#341
LukasWodka wants to merge 13 commits into
developfrom
feat/installer-first-run-ux

Conversation

@LukasWodka

@LukasWodka LukasWodka commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Reworks the first-time install run-through (macOS) into the copy + structure Lukas and I locked turn-by-turn this session (validated against the byte-faithful preview-install.sh / preview-rerun.sh built on the real common.sh helpers). Terminology follows docs#61: secure environment (never "workspace"/"client"), collaborators, the tracebloc CLI, this machine.

The install is now presented as:

  • 1. Downloading (bootstrap: fetch + cosign-verify) → ✔ Installer downloaded — N files / ✔ Signature verified — published by tracebloc (Sigstore keyless) / ✔ All N files intact
  • 2. Installing — an a–f plan list up front, then each step runs with a gerund header:
    • a) Checking your machine — one-line arch · cores · memory · disk, connectivity spinner → combined Connected: line, Local storage (~/.tracebloc), macOS GPU note
    • b) Installing what tracebloc needs — password once, Docker .dmg %-bar, system tools, the tracebloc CLI (moved here from provisioning — step d needs it to sign in)
    • c) Creating your secure environmentspinner around the previously-silent k3d create
    • d) Registering this machine — device-flow sign-in copy, Registered as "<slug>"
    • e) Installing tracebloc — services intro (what the containers are) + honest N-of-M count bar
    • f) Connecting to the tracebloc network — real readiness wait → rich summary (live 🟢, dashboard, non-dim "What's next" ×3, Run tracebloc CTA, dim footer + reboot tip)

Re-run early bailout (new, in the bootstrap)

Before fetching anything, if tracebloc is already on PATH and tracebloc doctor reports healthy, print ✓ Already set up and healthy — nothing to download or install. and exec tracebloc (the home screen) — no download, no re-verify. Safe because it runs only the already-installed binary and downloads/runs zero new code; cosign verification only matters when running new install code. Bounded (backgrounded doctor + poll + kill on overrun, so a wedged CLI can't hang the bootstrap) and its exit code is the gate — an old CLI that doesn't know doctor returns non-zero and falls straight through to a normal install. Bypassed by --force/--reinstall, TRACEBLOC_FORCE_REINSTALL=1, the unverified/dev path, and any pinned REF/BRANCH.

Deliberate deviations from the preview (honesty rule — flagged for FR)

  • Step c has no separate %-bar for the k3s image pull — a multi-layer pull has no honest byte-percentage, so the whole create (pull + boot) is one spinner.
  • Step e/f "Starting the services…" / "Connecting…" fold into wait_for_client_ready's real per-deployment readiness wait (honest multi-minute progress, not a fake single spinner). Step e ends at tracebloc installed.
  • count_bar counts containers reporting a populated imageID and labels them "services" (self-adjusting; the preview's "6" was illustrative).

Scope guards

  • Interim name/location prompt KEPT verbatim in provision.sh with a comment — the deployed CLI still hard-requires --name without a TTY; it's removed when cli#137 reaches prod (backend#992).
  • Linux/GPU untouched & preservedsetup-linux.sh, detect-gpu.sh, gpu-*.sh, both .ps1 have an empty diff vs develop; OS-specific bits (Docker Desktop vs Engine, reboot note, disk probe, GPU) stay guarded. The Linux/GPU copy variant is a deliberate follow-up.
  • client#339 gate slot — a clearly-commented guarded no-op call site in install-k8s.sh::main() (after banner, before roadmap) so that branch's assess.sh reconciles cleanly. No gate logic here.
  • Docker %-bar — genuine, because setup-macos.sh fetches Docker.dmg via single-file curl (download_with_progress).

Test plan

  • bash -n + shellcheck --severity=error: clean on all 10 changed scripts.
  • gen-manifest.sh --check: up to date (hashes match — installs won't break).
  • bats: written (count_bar/step_header/roadmap/banner, hw-summary/connectivity, _download_services_progress guards, bootstrap bailout) but not run locally — the suite hangs in-sandbox (spin/sleep/read/no-TTY) and macOS [[ ]] is unreliable; Linux CI is the authority. The one live poller is env-guarded (TB_NO_SERVICE_PROGRESS), bounded, and non-fatal.
  • Runtime-unvalidated: spinners/count-bar/bailout are statically checked only — they need Linux CI + a real end-to-end run for behavioural sign-off (this PR is the vehicle for FR-on-dev).

Known follow-ups

🤖 Generated with Claude Code


Note

Medium Risk
Medium risk: installer flow and step order changed (CLI before provision/Helm) and new early-exit paths (doctor bailout, spinners/poll loops) affect every customer install; supply-chain verification and manifest hashes are updated but behavioral regressions need CI/e2e validation.

Overview
Reworks the macOS/Linux bash installer UX into a two-phase story: 1. Downloading in install.sh (banner, fetch spinner, cosign copy) and 2. Installing with an upfront a–f roadmap and step_header gerunds instead of numbered “Step 1/5”.

install.sh adds a pre-fetch bailout: bounded tracebloc doctor (spinner + timeout); if healthy and not forced/pinned, skip download and exec tracebloc. Sets TRACEBLOC_BANNER_SHOWN / TRACEBLOC_INSTALL_REF so the child installer does not duplicate the title.

install-k8s.sh reorders work: CLI install moves to step b (before registration); steps are a preflight/GPU, b OS deps + CLI, c k3d cluster, d provision_client, e Helm, f readiness + summary. Adds a no-op hook for future assess_existing_install (client#339).

UX helpers: step_header, count_bar, collapsed preflight (PF_QUIET_SUCCESS + hardware/connectivity summary lines), k3d create spinner, Helm step N-of-M “services” pull bar (_download_services_progress, non-fatal), terminology “secure environment”, richer connected summary and provision “Registered as …” copy. manifest.sha256 and bats updated for new behavior (bootstrap bailout, roadmap, count_bar, etc.).

Reviewed by Cursor Bugbot for commit ff2e69c. Bugbot is set up for automated code reviews on this repo. Configure here.

LukasWodka and others added 12 commits July 12, 2026 16:43
…elpers

- print_banner: new title 'Setting up tracebloc on your machine · <version>'
  (tracebloc bold-cyan) + rule; TB_VERSION from TRACEBLOC_INSTALL_REF; skips
  when the bootstrap already drew it (TRACEBLOC_BANNER_SHOWN).
- print_roadmap: the '2. Installing' a–f plan.
- step_header: bold gerund running headers for steps a–f.
- count_bar: honest N-of-M render helper for multi-image pulls.
- preflight_sudo: step-b password intro copy.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Early bailout: if the tracebloc CLI is present and `tracebloc doctor` reports
  healthy (bounded, exit-code gated), print the healthy line and exec the home
  screen — skipping the download entirely. Skipped on --force/--reinstall,
  TRACEBLOC_FORCE_REINSTALL, the dev/unverified path, or an explicit REF/BRANCH.
- Draw the first-run banner here and export TRACEBLOC_BANNER_SHOWN (so
  install-k8s.sh does not draw a second) + TRACEBLOC_INSTALL_REF.
- "1. Downloading" copy: Installer downloaded — N files / Verifying it's
  authentic (cosign)… / Signature verified / All N files intact — nothing was
  altered. Local colour palette (common.sh not yet sourced).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…pinner

- run_preflight renders the run-through's step-a view: one hardware line
  ('arch · N CPU cores · N GB memory · N GB free disk'), a connectivity spinner
  + combined 'Connected: …' line, and a 'Local storage (~/.tracebloc)' line.
- PF_QUIET_SUCCESS suppresses the per-check ✔ lines only inside run_preflight
  (folded into the summary); called directly (bats), the checks still print their
  ✔/info lines, so the unit contracts hold. Warnings + hard-fails always print.
- Connectivity probes stay in the foreground (PF_HARD_FAIL propagation) with a
  no-sleep per-host spinner frame.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Real %-by-bytes bar for the Docker Desktop .dmg (single-file curl via
  download_with_progress); fresh-Mac intro copy on the label.
- 'Docker ready' and 'System tools ready (k3d, helm, kubectl)' to match the
  run-through. Linux (Docker Engine) copy left untouched — a deliberate follow-up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- _create_new_cluster wraps the 1-2 min k3d create in a spinner ('Creating your
  secure environment…'), the real fix for the long silent gap; spin() waits for
  the backgrounded create so exit-code capture + proxy-config cleanup are intact.
- Runtime intro copy; terminology 'compute environment' → 'secure environment'.
- _wait_for_api owns the single 'Secure environment ready' (API confirmed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Reworked sign-in copy: "open the link on this or any device and enter the
  code" (print-only; the CLI prints the URL/code/wait — no auto-open claim).
- Success line → Registered as "<slug>" (the minted namespace = dashboard name).
- CLI install call removed (now step b); keeps the has-tracebloc FATAL guard.
- KEPT the interim name/location prompt (deployed CLI still hard-requires --name
  without a TTY, backend#992) + comment: remove when cli#137 ships.
- No internal step header (main() prints "d) Registering this machine").

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fully-clean verdict (usable now + in new terminals) → "tracebloc CLI ready …
verified on your PATH", matching the run-through's Docker/System-tools/CLI
"ready" pattern. Edge-case lines stay "installed" (installed but not yet usable
here). Test assertion updated to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Services intro copy (training runner / data manager / live monitor / local
  database; runs on your machine, data never leaves).
- _download_services_progress: honest N-of-M count bar as service images pull
  (imageID-populated count), bounded + non-fatal; guarded by
  TB_NO_SERVICE_PROGRESS (set in the bats setup so the mocked-kubectl poll cannot
  hang). Never a fabricated aggregate %.
- Success line "Connected to tracebloc" → "tracebloc installed" (step f/summary
  owns "Connected"); dropped the internal step 4/5 headers (main owns a–f).
- Tests: retarget the 3 assertions + guard the poller.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ough

- connected summary: "✔ Connected to tracebloc"; Environment/Version/Mode block;
  "live 🟢" + dashboard; NON-dim "What's next" with 3 numbered steps
  (tb data ingest / my-use-cases / invite collaborators); prominent
  "Run tracebloc to get started."; dim footer (Logs · Data) with the reboot tip
  as the LAST dim line. Dropped the green ━━━ border.
- Terminology: "secure environment"; trust claim "never leaves this machine".
- _reboot_note stays OS-guarded (Linux: restarts automatically; macOS: open
  Docker Desktop) — Linux not regressed.
- wait_for_client_ready intro reframed as step-f "Connecting…".
- Tests updated to the new copy.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…e slot

- main() now: banner → [client#339 gate SLOT] → roadmap → a) Check your machine →
  b) Install what tracebloc needs → c) Create your secure environment → d)
  Register this machine → e) Install tracebloc → f) Connect to the tracebloc
  network, each with a step_header + trailing blank-line pair.
- Step b now owns prerequisites AND the tracebloc CLI (moved out of provisioning;
  step d needs it to sign in).
- Gate slot: guarded NO-OP call to assess_existing_install, clearly commented as
  client#339's — logic NOT implemented here; positioned after banner/before
  roadmap so it reconciles cleanly with that branch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…nges

Content hashes for the 9 edited sub-scripts (common/preflight/setup-macos/
cluster/provision/install-cli/install-client-helm/summary/install-k8s). No files
added or renamed, so install.sh's FILES array is unchanged; gen-manifest.sh
--check passes (both bootstrap-sync checks green).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ity)

- common.bats: count_bar (render/clamp/bad-input/divide-by-zero), step_header,
  print_roadmap (a–f plan), print_banner (version + bootstrap-suppression).
- preflight.bats: _pf_hw_summary_line, connectivity combined 'Connected:' line,
  run_preflight collapsed step-a view (per-check ✔ lines folded away).
- install-client-helm.bats: _download_services_progress guards (TB_NO_SERVICE_
  PROGRESS / no-kubectl / empty-ns) so the poller can never hang the suite.
- install-bootstrap.bats: early bailout — healthy doctor execs home screen (no
  download), unhealthy does not bail, --force skips the bailout.

Not run locally (macOS [[ ]] blindspot + spin/sleep/read block without a TTY);
assertions written fail-loud against the exact emitted copy for Linux CI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@LukasWodka LukasWodka requested a review from saadqbal as a code owner July 12, 2026 15:21
@LukasWodka

Copy link
Copy Markdown
Contributor Author

👋 Heads-up — Code review queue is at 53 / 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.)

Comment thread scripts/lib/summary.sh
echo -e " ${CYAN}https://ai.tracebloc.io/clients${RESET}"
# "What's next" is deliberately NOT dim — it's the primary call to action.
echo -e " ${BOLD}What's next${RESET}"
echo -e " 1. Ingest your data ${CYAN}tb data ingest${RESET}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary shows invalid tb command

Medium Severity

The connected-install “What’s next” step tells users to run tb data ingest, but the installer installs and documents the tracebloc binary (for example tracebloc data ingest ./data in install-cli.sh and the PowerShell installer). There is no tb command on PATH after setup, so copying that line fails with “command not found.”

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5a0fe0b. Configure here.

Comment thread scripts/install.sh
# Hand off to the home screen (exec replaces this process); if that somehow
# fails, we've already told the user it's healthy, so exit 0.
exec tracebloc || true
exit 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Healthy bailout exits after failed exec

Low Severity

When tracebloc doctor succeeds, the bootstrap prints that the machine is already healthy, then runs exec tracebloc || true followed by unconditional exit 0. If exec fails (missing execute bit, bad interpreter, or similar), the script still exits successfully without running the installer or launching the home screen.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5a0fe0b. Configure here.

Linux CI caught two stale assertions the local checks couldn't (macOS
[[ ]] blindspot):
- install-bootstrap happy path grepped the old "installer files
  verified" line, now "All N files intact — nothing was altered".
- _pf_storage_type local-fs test grepped the fstype (ext4), which the
  first-run redesign moved into the log; the visible line is now the
  clean "Local storage (…)". Assert that instead.

Both tests keep their original intent; no code behavior changed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ff2e69c. Configure here.

Comment thread scripts/install.sh
}

if [[ "$_tb_bail_ok" == "1" ]] && command -v tracebloc >/dev/null 2>&1; then
printf '\n'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bailout misses ~/.local/bin CLI

Medium Severity

The new early bailout gates on command -v tracebloc before any PATH adjustment. The tracebloc CLI installer commonly places the binary in ~/.local/bin, which provision_client explicitly prepends to PATH, but this bootstrap does not. A healthy install can be skipped for detection and trigger a full re-download.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit ff2e69c. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant