Conversation
… can't find tracebloc (#305) * fix(client#304): don't claim "verified on your PATH" when the current shell can't find tracebloc _cli_on_fresh_path spawns fresh shells to prove the CLI persists into new terminals. But the caller's current shell (the one running the installer) predates the rc PATH edit when the binary lands in ~/.local/bin — so the success branch printed "verified on your PATH" while the very next `tracebloc …` the user typed there failed with command-not-found (#304). Gate the clean "verified on your PATH" verdict on `has tracebloc` (current shell resolves it too). When it persists for new terminals but this shell can't see it yet, say so honestly and point to a new terminal / `source <rc>` instead of re-appending the line the rc already carries. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(supply-chain): regenerate manifest.sha256 for the CLI PATH-message fix install-cli.sh changed; refresh the R8 signed-manifest checksum so gen-manifest.sh --check passes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…one (#306) * fix(client#303): refuse a second client BEFORE minting, so we don't orphan one On the browser path, `tracebloc client create` mints a fresh client whenever the backend can't match this cluster to a client in the signed-in account — e.g. a pre-anchor client whose cluster_id is still null, or one owned by a different account. The one-client-per-machine guard only ran later, in the Helm step, so by the time it refused, a brand-new client was already registered on the dashboard and would never install — an orphan (#303). Add a pre-flight in provision_client, after sign-in and before the mint: if a client is already installed locally (shared detect_installed_client probe, now also used by the Helm guard) and the signed-in account demonstrably does NOT own its namespace (via `client list`), refuse before calling create. Namespace is the only stable join key — the local Helm release stores the UUID clientId, `client list` shows the numeric id. The pre-flight fires only on a positive "not yours"; a fresh machine, an owned local client (create adopts), or an inconclusive list read all fall through to create's own idempotent adopt/conflict handling, so the same-account re-run/upgrade path is unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(supply-chain): regenerate manifest.sha256 for the provisioning pre-flight install-client-helm.sh + provision.sh changed; refresh the R8 signed-manifest checksums so gen-manifest.sh --check passes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(client#303): don't refuse a legacy tracebloc-namespace client the account owns (Bugbot) The pre-flight keyed ownership on the local Helm release namespace via `client list`. But a client installed under the legacy fixed `tracebloc` namespace is listed on the dashboard under its minted slug, so `client list` never shows `tracebloc` even for the account's OWN older client — a skew install_client_helm reconciles by clientId (the reliable key `client list` doesn't expose). The namespace-only check wrongly refused that valid re-run. Refuse only when the absent namespace is a non-legacy slug (confident foreign); for `tracebloc`, defer to `client create` (adopts if it's yours, 409s if truly cross-account) and the Helm-step one-client guard, which both key on clientId. Regenerates manifest.sha256 for the provision.sh change (R8). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
… jobs (#280) - The `schema` job re-rendered each platform's values to /dev/null — exactly what `template` already does (and `template` also kubeconform-validates the output), so `schema` added 4 matrix jobs of zero extra coverage. Removed. (Not a required status check — branch protection requires only Lint + Unit tests.) - helm-ci's `lint`/`unittest` jobs were named "Lint"/"Unit tests", colliding with the same-named required checks that standard-checks.yml emits unconditionally on every PR. Renamed to "Helm lint"/"Helm unit tests" so the required contexts come unambiguously from standard-checks. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…aming, location fix, clearer errors) (#307) * feat(installer): overhaul first-run UX — plainer output, location auto-detect, real errors Line-by-line pass over the one-command install experience, driven by a real production run that failed opaquely on a mistyped location zone ("berlin"). - Bootstrap: reframe supply-chain verification as plain-language reassurance (drop cosign/manifest/keyless jargon and the alarming "cosign not found"), lowercase brand, drop the redundant "Running… environment setup" line. - Welcome banner: drop the inaccurate "nothing modified outside ~/.tracebloc and Docker" promise (the installer also brew-installs Docker + system deps); fix brand casing on the sudo prompt. - Step 1: de-duplicate the Apple-Silicon messaging and warn on the real limitation (no GPU training on macOS) rather than on the chip itself. - Step 3 (provision): auto-detect the carbon-reporting zone from the system timezone via the OS's own zone.tab (no network call, no embedded zone list to drift) and let the user Enter-to-accept / override / skip; surface the ACTUAL client-create failure inline (e.g. an unrecognized zone) instead of a generic "see the log". - Step 4 + summary + PowerShell: advertise the shipped dataset commands (dataset push/rm → data ingest/delete). - Drop internal ticket refs (RFC-0001 R8) that leaked into user-facing errors. Tests: provision, bootstrap, install-cli, summary bats suites green (50/50). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(installer): copy spec interim — collaborators, client noun, goal-led next steps, location fixes Interim slice of the installer UX v2 spec (full restructure gated on the next CLI release): - Banner: drop the vendor value-prop lines (bash + ps1) — the trust claim lives in the verified connected summary. - vendors → other collaborators everywhere user-facing; training phrased as gated on the user's approval. - Next steps rewritten around the goal: ingest data → create your use case (real /my-use-cases URL) → invite other collaborators; dashboard + CLI help demoted to footnotes. - "Name this machine" → "Name this client" (entity noun rule). - Location prompt: fix the live skip-path bug — the released CLI (v0.5.1) hard-requires --location when it can't prompt, so a blank/skip answer doomed the create with a buried error. Now: Enter accepts the detected zone; no detection → re-ask (3 tries) instead of minting a doomed request; unattended runs fall back to the detected zone silently. Tests: 67/68 bats green (1 pre-existing environmental failure on validate_config, identical on develop). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test+chore: sync manifest.sha256 and assertions to the v2 copy strings - Regenerate scripts/manifest.sha256 (7 script hashes changed by the copy pass) — the Static analysis drift check diffs it against the tree. - Update two bats assertions to the new user-facing strings: the no-name fatal now says 'name for this client' (noun rule) and the bootstrap happy path prints 'installer files verified'. Caught by Linux CI only: on macOS, bats silently passes failing [[ ]] assertions (bash 3.2 errexit quirk), so local green was misleading. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(installer): harden location fallback + create-output temp path (review nits) Two small robustness fixes from PR review, both in provision_client: - Trim name/location BEFORE the silent auto-detect fallback. A whitespace-only location answer (spaces then Enter) was non-empty at the fallback check, so it slipped through untrimmed and only got emptied afterward — re-dooming the create with a buried error, the exact failure this PR fixes. Now it degrades to the detected zone. - When mktemp is unavailable, capture client-create output inside the install dir (HOST_DATA_DIR, which we own) instead of a predictable world-writable /tmp path that is a symlink-clobber target under sudo. Manifest regenerated for the provision.sh change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Asad Iqbal <asad.dsoft@gmail.com>
The generated values hardcoded RESOURCE_LIMITS/REQUESTS to
cpu=2,memory=8Gi with no way to override — the 'default configuration'
was frozen. One env knob now sets both (requests == limits, Guaranteed
QoS, matching client-runtime's lockstep default):
TRACEBLOC_TRAINING_RESOURCES="cpu=4,memory=16Gi" bash <(curl … i.sh)
Groundwork for the `tracebloc resources` command (design approved by
Lukas 2026-07-06): that command becomes the friendly layer over the
same chart values; this is the install-time escape hatch.
+2 bats tests (override lands in generated values; default unchanged).
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… cluster info -> push) (#214) * test: add cross-repo fresh-shell last-mile E2E harness Adds the two-leg install-journey harness that closes the gap which let a PATH-persistence regression ship green: no existing test opens a fresh shell after install and asserts the documented next command works. Leg 1 — scripts/tests/path-persist.sh: runs in a plain distro container, installs the tracebloc CLI via cli/install.sh (configurable ref via TRACEBLOC_CLI_REF), then for each shell among bash/zsh/fish spawns a fresh login AND non-login shell and asserts `command -v tracebloc` resolves and `tracebloc version` runs. A fresh non-login bash reads ~/.bashrc (not ~/.profile), so this catches the whole PATH-persistence class — red on the pre-fix installer, green on the fixed one. Leg 2 — scripts/tests/e2e-journey.sh: extends the e2e-cluster pattern. Brings the cluster up via create_cluster(), installs the CLI, applies a credential-free stub matching the CLI's real discovery contract (a *-jobs-manager Deployment with the chart's hallmark labels + an `ingestor` ServiceAccount), points the kubeconfig context's namespace at it, and asserts `tracebloc cluster info` succeeds AND resolves from a fresh shell, then `dataset push --dry-run` on a tiny sample CSV. Long steps run under a watchdog timeout so a hang fails instead of spinning. The context-on-default namespace auto-discover sub-assertion is gated pending the CLI change. CI: new path-persist job (distro matrix, like distro-prereqs, fail-fast false) and e2e-journey job (amd64, nightly + `e2e` label only, mirroring cli's e2e.yml gating). Both new scripts added to the static shellcheck list. Part of #737. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test: default install-journey harness to the public release installer cli#61's PATH-persistence fix shipped in cli v0.3.1 and is in every release since (verified: the served releases/latest install.sh persists PREFIX to ~/.bashrc / ~/.zshrc / fish config). Switch both legs' default TRACEBLOC_CLI_REF from the now-merged fix/install-path-persist branch raw URL to https://github.com/tracebloc/cli/releases/latest/download/install.sh and drop the TODO(cli#61) — the guard now exercises the shipped installer and would go red if a future release regressed the PATH class. Re-validated the e2e-journey stub against the current CLI discovery contract (internal/cluster/discover.go @ v0.5.1): selector app.kubernetes.io/name=client,app.kubernetes.io/managed-by=Helm, a *-jobs-manager Deployment, instance/version labels, and the `ingestor` SA for the cluster-info TokenRequest — unchanged, stub still valid. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test(ci): bootstrap bash before path-persist so alpine:3 actually runs The path-persist matrix ran `docker run <distro> bash path-persist.sh` as the container entrypoint. Alpine's base image ships only busybox `sh` — no bash — so the container died at init (exit 127, "bash: executable file not found") before a single line of the script ran. The Alpine cell was never testing the installer; it was failing at container startup. The script's own apk-aware _pm_install can't help — you need bash to reach the code that installs bash. Wrap the entrypoint in a POSIX `sh -c` that ensures bash then execs the script. `command -v bash` short-circuits on every glibc distro (bash already present); the apk branch fires only on Alpine. Now the Alpine cell exercises the real installer. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Asad Iqbal <asad.dsoft@gmail.com>
… label trigger (#310) (#311) The install-journey harness merged in #214 asserted nothing: guard() captured `local rc=$?` inside the `then` branch of `if ! timeout ...`, so rc read the NEGATED status (always 0). Every assertion runs under guard, so set -e never tripped and the job printed E2E JOURNEY PASS even when steps failed or hung. Reproduced: a step exiting 3 and a 124 hang both returned 0. - guard(): run the command, capture status via `|| rc=$?`, then act on it — a failed step now propagates, a 124 hang is treated as a hard failure. - Add a negative-control self-test at startup: guard() must return non-zero for a command that exits non-zero, or the script refuses to run. Locks the vacuous-pass class so it can't regress silently (bash -n and shellcheck both passed on the buggy version). - installer-tests.yaml: add timeout-minutes to path-persist (20) and e2e-journey (30) — every other job already had one; and add `labeled` to the pull_request trigger types so adding the `e2e` label starts a run immediately instead of on the next push. Remaining from the #214 review (path-persist has no red/green signal) is tracked separately on #310 — it's a genuine rewrite that needs CI validation across the distro matrix. Refs #310. Follow-up to #214 (review by @aptracebloc). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
resource-monitor is the only backend-calling workload whose pod gets NO proxy env from the chart - jobs-manager, pods-monitor, requests-proxy, image-refresh, auto-upgrade and the egress check all include tracebloc.proxyEnv already. Behind a corporate egress proxy its api-token-auth and edge-device-heartbeat POSTs dial direct and fail, so proxied clusters show stale/no node resource data. One include, appended after the existing env list (the DaemonSet has a fixed env list - no .Values.env passthrough - so the jobs-manager-style exclusion dance does not apply). Renders nothing when HTTP_PROXY_HOST is unset; NO_PROXY carries the cluster-internal ranges and the kubernetes python client ignores ambient proxy env, so in-cluster API calls are unaffected. Companion to tracebloc/client-runtime#154 (shared ProxyConfig + resource_monitor threading the split-key settings); with this include alone, current images already work via requests' trust_env handling of the URL-form vars. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ix + interactive per-shell (#310) (#313) As merged in #214 the path-persist guard could not distinguish a fixed installer from a broken one: - It ran as root, so cli/install.sh landed the binary in /usr/local/bin (on every PATH). The installer only PERSISTS a PATH entry for an off-PATH prefix, so no rc was ever written and every shell resolved the binary trivially — green on a broken installer too. - The login × non-login matrix mis-modelled 'open a new terminal': a non-interactive `bash -c` reads NO rc file, and a *login* bash reads ~/.profile, not the ~/.bashrc the installer writes on Linux. Rewrite to actually exercise persistence: - Pin INSTALL_PREFIX=$HOME/.local/bin (a $HOME dir the installer always persists, off the default root PATH). Precondition-check it's not already on PATH, else bail rather than assert nothing. - install.sh persists to ONE rc keyed off $SHELL, so install once per shell with SHELL=bash/zsh/fish, then assert a fresh INTERACTIVE shell of that kind (bash -ic / zsh -ic / fish -ic) — the one that reads that rc. - Per-shell negative control (bash/zsh): a fresh NON-interactive shell must NOT resolve the binary; if it does, the prefix leaked onto the base PATH and a pass would be meaningless. (Skipped for fish: fish_add_path writes a universal var and `fish -c` still sources config.fish.) Verified locally: with an isolated binary name (the dev host has a real tracebloc on PATH), a non-interactive shell does NOT resolve it while a fresh interactive shell does + `version` runs. bash -n, shellcheck (error + warning), actionlint all clean. The full distro × shell matrix is CI-only (real cli binary download + per-distro shell installs). Fixes #310. Follow-up to #214. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
jobs-manager validates ingest.yaml at submit time against a schema that now tracks data-ingestors' newer categories (sentence_pair_classification, embeddings, seq2seq, causal_language_modeling — client-runtime#162). Those first ship in the ingestor 0.5 line (v0.5.6); the 0.3 float tag only supports 11 categories. Leaving the spawned ingestor on 0.3 while the submit schema accepts 15 re-opens the submit-vs-run drift bug: a customer submitting one of the new categories passes validation, a Job is minted, and the 0.3 image can't process it. Point the default float tag at the 0.5 line so the spawned ingestor supports the full catalogue the schema accepts. `0.5` auto-tracks 0.5.x patches (imagePullPolicy=Always); a future 0.6 needs an explicit bump. - values.yaml: images.ingestor.tag 0.3 -> 0.5 (+ rationale comment). - jobs-manager-deployment.yaml: --reuse-values nil-guard fallback 0.3 -> 0.5 so a pre-images.ingestor-key release upgraded with --reuse-values doesn't silently fall back to the drifting 0.3. - jobs_manager_test.yaml: default-wiring assertion 0.3 -> 0.5. Verified: `helm template` renders INGESTOR_IMAGE_TAG "0.5" on both the default and nil-guard paths. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit fcb89ef. Configure here.
1 task
divyasinghds
added a commit
that referenced
this pull request
Jul 7, 2026
…bugbot) Address two Cursor Bugbot findings on the develop→main promotion (#309): 1. Whitespace bypasses the location requirement. In the no-timezone-detection path, `client_location` was checked with `[[ -n ]]` before trimming, so a whitespace-only answer broke the retry loop and skipped the "location is required" error, then fell through to a `client create` with no --location. Trim inside the prompt loops, before the non-empty checks (both the detected and no-detection paths). 2. mktemp failure skipped the client guard. detect_installed_client did `mktemp || return 0`, treating an environment error as "no client here" and silently skipping the Helm one-client guard and the #303 ownership check. Fall back to a path in a dir we own (same pattern as the create step) and only give up when there is genuinely nowhere to write. Regenerated scripts/manifest.sha256 for the changed scripts. NOTE: Bugbot's third finding ("Wrong CLI command in summary" — claiming `tracebloc data ingest` should be `tracebloc dataset push`) is a FALSE POSITIVE and is intentionally NOT changed. Per tracebloc/cli internal/cli/data.go, the canonical command group is `data` with subcommand `ingest`; `dataset`/`push` are deprecated aliases kept for one deprecation cycle. The summary's `tracebloc data ingest ./data` is the correct, current form. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…bugbot) (#315) Address two Cursor Bugbot findings on the develop→main promotion (#309): 1. Whitespace bypasses the location requirement. In the no-timezone-detection path, `client_location` was checked with `[[ -n ]]` before trimming, so a whitespace-only answer broke the retry loop and skipped the "location is required" error, then fell through to a `client create` with no --location. Trim inside the prompt loops, before the non-empty checks (both the detected and no-detection paths). 2. mktemp failure skipped the client guard. detect_installed_client did `mktemp || return 0`, treating an environment error as "no client here" and silently skipping the Helm one-client guard and the #303 ownership check. Fall back to a path in a dir we own (same pattern as the create step) and only give up when there is genuinely nowhere to write. Regenerated scripts/manifest.sha256 for the changed scripts. NOTE: Bugbot's third finding ("Wrong CLI command in summary" — claiming `tracebloc data ingest` should be `tracebloc dataset push`) is a FALSE POSITIVE and is intentionally NOT changed. Per tracebloc/cli internal/cli/data.go, the canonical command group is `data` with subcommand `ingest`; `dataset`/`push` are deprecated aliases kept for one deprecation cycle. The summary's `tracebloc data ingest ./data` is the correct, current form. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…316) The guard() watchdog added in #310/#311 wraps steps in `timeout`, which execs an external command in a fresh process and cannot see shell functions. create_cluster is a function sourced from cluster.sh, so `guard 600 "create_cluster" -- create_cluster` failed with "timeout: failed to run command 'create_cluster': No such file or directory" (exit 127) before the cluster was ever created — failing the E2E last-mile journey job. Run create_cluster inside a real `bash` (which timeout CAN exec) that re-sources the libs. Exported CLUSTER_NAME / TRACEBLOC_NO_AUTOSTART / USER carry through the env, and the CLI binaries install_* dropped into /usr/local/bin are on the inherited PATH. Refs #310 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
… --dry-run (#318) Step 4 only ran for real once #316 fixed the create_cluster exit-127 regression (the old vacuous guard() and then the step-1 crash had hidden it). It failed with "table name is required (set --table)". `dataset push --dry-run` is no longer an offline check: the current CLI runs cluster discovery AND a Bound-PVC check (resolveClusterTarget with needPVC=true) before its dry-run stop, and this harness's credential-free stub creates no PVC — so that path can't pass here regardless of flags. Switch to `tracebloc data validate <spec>`, the CLI's purpose-built offline schema check (validates against the embedded ingest.v1.json, no cluster) — exactly the "offline-validatable, no creds, no reachable platform" smoke the step was always meant to be. Assert both directions (valid spec passes, invalid spec rejected) so a green run isn't vacuous, mirroring the guard() self-test. Spec shape matches the CLI's own known-good fixture (testdata/smoke/valid-image-classification.yaml). Verified against the real released binary (tracebloc/cli v0.6.0, which releases/latest resolves to): valid -> exit 0, missing-intent -> exit 2. Closes #317. Follow-up to #316 / #310. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
divyasinghds
approved these changes
Jul 7, 2026
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.

Summary
Related
Type of change
Test plan
Screenshots / recordings
Deployment notes
Checklist
Note
Medium Risk
Touches provisioning ownership gates and default ingestor version (runtime ingestion behavior); installer script changes are broad but heavily tested via new e2e and bats coverage.
Overview
Installer & first-run UX — Copy and summaries steer users toward
tracebloc data ingest, collaborator wording, and a clearer post-connect “what’s next” flow. Bootstrap verification messaging is friendlier (RFC references trimmed).TRACEBLOC_TRAINING_RESOURCESsets spawned-job CPU/RAM in generated Helm values; CLI post-install messaging distinguishes “verified on PATH” vs “verified for new terminals” when the current shell hasn’t reloaded rc (#304).Provisioning hardening (#303) — Shared
detect_installed_clientfor Helm one-client checks. Beforeclient create, refuse minting when a local client exists in a namespace the signed-in account doesn’t own (with a legacytraceblocnamespace exception). Carbon zone prompts use timezone-based detection and clearerclient createfailure surfacing.Helm chart — Default spawned ingestor float tag
0.3→0.5(aligns with jobs-manager task catalogue / client-runtime#162). resource-monitor getstracebloc.proxyEnvfor corporate egress (client-runtime#154).CI —
path-persist(distro matrix, fresh interactive shell PATH) and label-gatede2e-journey(k3d → CLI → stub release →cluster info+data validate). Installer workflow listens for PRlabeledso thee2elabel runs journey without a push. Helm CI drops redundant per-platform schema job; job names clarified.manifest.sha256updated for touched scripts.Reviewed by Cursor Bugbot for commit 90f6d19. Bugbot is set up for automated code reviews on this repo. Configure here.