Uh oh!
There was an error while loading. Please reload this page.
installer: mirror the brand terminal style system (surface 2) - #363
Merged
Conversation
Ports the Go CLI's style system (cli #367) to the bash installer + the Windows ps1, so both surfaces read identically. Same organising idea from the homepage gradient: cyan orients (structure), lime moves (action). common.sh — a colour engine mirroring internal/ui: - Decides mode {none,16,true} + background {dark,light} ONCE at source time (before setup_log_file redirects stdout through tee, so `-t 1` sees the real terminal): NO_COLOR / non-TTY / TERM=dumb / TB_PLAIN=1 → none; COLORTERM=truecolor|24bit → 24-bit; else ANSI-16. COLORFGBG picks the bg. This ALSO adds the colour-off gating the installer never had. - A tone table (_sgr) maps each role to its exact 24-bit hex on dark AND light (primary/secondary ramps) + the nearest ANSI-16 fallback — the same values the Go engine emits (cyan #01a5cc, lime #91e947, soft lime #a7ed6c, …). - Re-points the helpers: success ✔ → lime, warn ⚠ → amber, error ✖ → bold red, step / step_header → cyan headings, labels → dim. Legacy CYAN/GREEN/… kept as tone aliases so untouched call sites stay on-brand and honour the off switch. summary.sh — the connected / starting / error screens: cyan headings, lime commands (`tracebloc data ingest`), cyan-underline links, soft-lime descriptions, lime ● online (replacing the 🟢 emoji), dim label:value rows. install-k8s.ps1 — Windows parity at the 16-colour tier (Write-Host can't do truecolor): summary commands Cyan → Green, the "next" heading → Cyan, metadata labels dim with plain values. Text unchanged (Pester assertions unaffected). scripts/manifest.sha256 regenerated (R8 supply-chain gate) for the three changed installer files. Tests: full bats suite green except the two pre-existing local failures (validate_config / _extract_yaml_value); bash -n + shellcheck clean on the changed libs. No bats test asserts on colour codes, so the new gating is safe. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
LukasWodka
commented
Jul 21, 2026
ContributorAuthor
@BugBot run |
Uh oh!
There was an error while loading. Please reload this page.
The style retheme replaced the 🟢 emoji with a lime ● (design decision: no emoji). summary.bats:68 still asserted *"live 🟢"*, which passed on the local bash/bats but failed in CI (multibyte-glob matching differs across versions — same reason the validate_config / _extract_yaml_value baseline failures invert locally vs CI). Assert the ASCII heading "Your secure environment is live" instead — robust across locale, colour on/off, and bash version. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
aptracebloc
approved these changes
Jul 21, 2026
saadqbal
approved these changes
Jul 21, 2026
Uh oh!
There was an error while loading. Please reload this page.
LukasWodka
commented
Jul 21, 2026
ContributorAuthor
@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 881afb0. Configure here.
LukasWodka added a commit
that referenced
this pull request
Jul 21, 2026
* Enforce the terminal style system + terminology (installer) Guards the style system (STYLE.md, shipped in #363) against regressions from other contributors, layered strongest-first: - scripts/check-style.sh — a CI gate (blocking, in the "Static analysis" job) with three MECHANICAL checks: no hardcoded brand colour outside the tone engine (common.sh), no status/traffic-light emoji, and no "workspace" in user-facing text (→ "secure environment"). Internal identifiers (the DNS-1123 sanitisers), comments, and scripts/tests/ are exempt; a line can opt out with a trailing `# style-guard: allow`. Semantic calls (role misuse, softer wording) stay with review — a grep can't police those. - STYLE.md — the reference: cyan=structure / lime=action, the role→tone table, where the engine lives, and the terminology glossary (SoT = docs TERMINOLOGY.md). - CODEOWNERS — the guard + STYLE.md are code-owned, so the rules themselves can't be quietly weakened. (The engine files under scripts/lib/ + the ps1 are already owned via the R8 trust root.) - PR template — a checklist line pointing at STYLE.md + the guard. Cleaned the two pre-existing violations the guard surfaced so it ships blocking with develop clean: - common.sh --help: "Namespace / workspace label" → "Secure-environment name". - install-k8s.ps1 summary: "Workspace :" → "Environment :" (aligns with the bash summary; re-padded the Version/Mode labels to match). No Pester assertion keys on the label text. Manifest regenerated (R8) for the common.sh + ps1 edits. Guard passes; bash -n + shellcheck clean; the 3 local bats failures are pre-existing on develop (confirmed with the change stashed), unrelated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Address Bugbot: make the brand-colour check case-insensitive The hex scan matched only lowercase (01a5cc), so an uppercase #01A5CC would slip past. Add -i to check 1. (Same fix applied to the cli guard.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Address Bugbot: guard fails closed, anchored comment filter, shellcheck the guard Three findings on #364. 1. Fails open on errors (Medium). scan swallowed grep stderr and read empty as clean, so a scan failure (bad regex/flags, missing tree) passed the blocking gate silently. Now: a missing scripts/ tree exits 2 up front, and grep exit ≥2 sets guard_error → the guard exits 2 (fail closed), never a silent pass. 2. Comment filter matched mid-line (Low). ':[0-9]+: *#' could exempt a user-facing string that merely embeds that shape (e.g. a URL port + fragment). Anchored to the file:line: prefix: '^[^:]+:[0-9]+:[[:space:]]*#'. 3. Guard omitted from ShellCheck (Low). Added scripts/check-style.sh to the Static-analysis ShellCheck step so regressions in the guard itself are caught. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Address Bugbot: make fail-closed actually reachable (parent-shell scan) Follow-up to the previous fail-closed attempt, which didn't work: guard_error was set inside scan, but scan was invoked via $(scan …) — a command-substitution subshell — so the flag never reached the parent and the `exit 2` path was unreachable (Bugbot: "fail-closed path never triggers"). A grep error could still print ok / exit 0. Fix: call scan in the PARENT shell (scan …, not $(scan …)); it now sets a global `hits` plus guard_error directly, and the per-check display filtering moves to the report() argument. Verified: a forced grep error (invalid regex) now propagates guard_error and exits 2. (The other two re-flags — guard omitted from ShellCheck, and the make-ci gap on the cli side — were already fixed in earlier commits; confirmed present.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * check-style: surface grep errors instead of suppressing (still fail-closed) Drop 2>/dev/null on the scan grep so a real internal error prints to stderr; rc>=2 already turns it into a fail-closed exit 2 (verified). Also removes the pattern that kept tripping Bugbot's (now-inaccurate) 'fails open' heuristic — the rc check on the very next line is the actual fail-closed path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
shujaatTracebloc added a commit
that referenced
this pull request
Aug 24, 2026
…1) (#804) Called by nobody. The topology arithmetic lands first, dark and tested, so the flip that changes the default cluster shape stays a separate, revertable PR -- the shape that worked on backend#2220. WHY. Uncapped k3d node containers (`NanoCpus=0 CpuQuota=0 Memory=0`) each report the WHOLE Docker VM, so the DEFAULT topology -- common.sh:821-822 ships SERVERS=1 AGENTS=1 -- tells Kubernetes the machine is twice its size. Measured on k3d v5.9.0 / k3s v1.35.5 / Docker 29.5.2: a 7.75 GiB VM presented as 15.50 GiB, byte-exactly 2.000x. And it is reachable through THIS file: on that cluster _machine_training_resources returned cpu=9,memory=4Gi, and two pods at that envelope both went Running -- 18 cpu / 8 GiB admitted on 10 cpu / 7.75 GiB. WHAT. `_honest_topology` (bash) and `Get-HonestTopology` (ps1): the VM's real size in, an honest node count and per-node memory cap out. Both return the SAME STRING so the twins are compared byte-for-byte by the same fixture rows, and both treat an unreadable VM as NOTHING/$null -- "I cannot answer", which a caller must not read as one node, because collapsing a cluster on a failed probe is worse than leaving the topology alone. Two asymmetries decide the shape, both measured, neither assumed: MEMORY IS CAPPABLE, CREATE-TIME ONLY. k3d caps a node by bind-mounting a SYNTHETIC /proc/meminfo into the container (a "fakeowner" mount), not via the cgroup -- kubelet never reads the cgroup for capacity. `docker update --memory=4g` on a running node set memory.max and left /proc/meminfo at the VM's 8126672 kB, so capacity did not budge even across a restart. An existing cluster cannot be capped in place. CPU IS NOT CAPPABLE AT ALL. k3d 5.9.0 has no CPU flag, and neither `--cpus` (CFS quota, cpu.max 200000 100000) nor `--cpuset-cpus` (nproc 5) moves capacity.cpu off 10, because cadvisor counts /sys/devices/system/cpu/present and /proc/cpuinfo and no cgroup namespaces either. Verified against a forced node de-register/re-register. So memory is made honest by capping and cpu only by FEWER NODE CONTAINERS, which is why the return value carries cpu_honest rather than implying the cap closed it. Same conclusion the GPU path already reached for --gpus=all. CONTRACT v2. New embedded constants: VM_RESERVE_MEM_BYTES (1 GiB, measured -- serverlb 39.27 MiB + tools 14.69 MiB on a live cluster, plus dockerd and guest page cache outside any container) and NODE_MIN_{CPU_MILLI,MEM_BYTES}. The node minimum is overhead + floor = 5 GiB / 2 cores -- DERIVED, but recorded in the contract because neither installer can do arithmetic on JSON. A recorded derivation nobody checks is just a fourth constant waiting to rot, so gen-envelope-embed.sh now re-checks the derivation and REFUSES a contract where it has drifted, before writing anything. That matters here specifically: an embed generated from a half-vendored contract would be wrong in two installers at once, and a generator that rewrites one file then dies is Bugbot#766. That guard also caught its own blast radius: "adopting a changed contract" bumped overhead and left per_node_minimum behind, so the generator refused and the test failed. Correct refusal -- upstream's generator recomputes the derived value, so a vendored contract always arrives consistent. The test now simulates that, and the half-vendored case became a test of its own. Also fixes a comment I got wrong in backend#2220, in BOTH twins (install-client-helm.sh, install-k8s.ps1): "installer-provisioned clusters are single-node k3d, so this is a no-op in the field". They are not -- the default is two nodes. The anchor tie-break is a field no-op only because both k3d nodes report IDENTICAL figures, and they do that because each reports the whole VM, which is this bug. TESTS. 11 topology vectors generated from the contract, replayed through BOTH twins (5 bats + 7 Pester cases), including the sum(nodes x cap) <= usable VM invariant as a property over 12 VM sizes x 5 requested counts, and the unreadable and requested<1 boundaries. Verified out of band that both languages produce byte-identical output on all 11 rows. installer_parity.json deliberately unchanged: this function is pure arithmetic with no external commands and no branching on cluster state, so the contract vectors are its parity mechanism. That fixture exists for CONTROL FLOW -- every backend#2220 divergence lived in a state that was not a clean measurement -- and the eventual CALLER belongs there, because it will shell out to docker and branch. Reasoning recorded in both suites. Local: 461 bats + 887 Pester pass (assess.bats:40 fails on clean develop too, verified by stashing); shellcheck severity=error and -S warning -x clean; PSScriptAnalyzer errors identical to develop; gen-envelope-embed/gen-manifest/ gen-installer-parity --check all clean. No chart files touched, so no version bump. NOT READY: scripts/.client-runtime-ref still pins the client-runtime FEATURE BRANCH commit, which the squash-merge of #363 will orphan. The file carries a DO-NOT-MERGE block with the re-pin recipe. Co-authored-by: Claude Opus 5 <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 freeto 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.
Summary
Surface 2 of 2 — ports the Go CLI's brand terminal style system (tracebloc/cli#367) to the bash installer + the Windows ps1, so every tracebloc surface reads identically. Organising idea from the homepage gradient: cyan orients (structure), lime moves (action). Design spec + real render: the style artifact shared in the thread.
common.sh— a colour engine mirroringinternal/uimode {none,16,true}+bg {dark,light}once at source time — beforesetup_log_fileredirects stdout throughtee, so-t 1sees the real terminal:NO_COLOR/ non-TTY /TERM=dumb/TB_PLAIN=1→ none;COLORTERM=truecolor|24bit→ 24-bit; else ANSI-16.COLORFGBGpicks the background._sgr) maps each role to its exact 24-bit hex on dark and light + the nearest ANSI-16 fallback — the same values the Go engine emits (#01a5cc,#91e947,#a7ed6c, …).success✔ → lime,warn⚠ → amber,error✖ → bold red,step/step_header→ cyan headings, labels → dim. LegacyCYAN/GREEN/… kept as tone aliases so untouched call sites stay on-brand and honour the off switch.summary.sh— the connected / starting / error screensCyan headings · lime commands (
tracebloc data ingest) · cyan-underline links · soft-lime descriptions · lime●online (replacing the 🟢 emoji) · dimlabel : valuerows.install-k8s.ps1— Windows parity (16-colour tier)Write-Hostcan't do truecolor, so Windows gets the ANSI-16 tier of the same roles: summary commands Cyan → Green, the "next" heading → Cyan, metadata labels dim with plain values. Text unchanged → Pester assertions unaffected.Test plan
scripts/manifest.sha256regenerated (R8 supply-chain gate) for the 3 changed installer files.batssuite green except the two pre-existing local failures (validate_config/_extract_yaml_value, unrelated).bash -n+shellcheckclean on the changed libs. The tone escapes were verified to match cli#367 byte-for-byte (38;2;1;165;204cyan,38;2;145;233;71lime). No bats test asserts on colour codes, so the new gating is safe.🤖 Generated with Claude Code
Note
Low Risk
Terminal presentation and checksum manifest only—no install logic, credentials, or cluster behavior changes.
Overview
Ports the tracebloc CLI brand terminal palette (cyan = structure, lime = action) into the bash installer and aligns the Windows summary screen with the same roles.
common.shreplaces flatRED/GREEN/CYANwith a small color engine: picksnone/ 16-color / truecolor fromNO_COLOR, TTY,COLORTERM, and light/dark background; exposes semanticTB_*tones matchinginternal/ui; wiressuccess/warn/error/step/step_headerto those tokens; keeps legacy color names as aliases so existing call sites stay on-brand and now respect color-off (previously escapes always printed).summary.shrestyles the post-install screens: cyan headings, lime commands, underlined cyan links, dim labels, lime●instead of 🟢, and branded error/warn lines.install-k8s.ps1applies the ANSI-16 tier of the same mapping (DarkGraylabels, Cyan “what’s next”, Green runnable commands) without changing copy.manifest.sha256updated for the three touched installer scripts.Reviewed by Cursor Bugbot for commit 530d359. Bugbot is set up for automated code reviews on this repo. Configure here.