Uh oh!
There was an error while loading. Please reload this page.
Conversation
…op-319 chore: back-merge main → develop after #319 promote
…ert (cli#289) (#312) New advisory workflow (head-drift-canary.yml), cron + dispatch only, never blocking: checks data-ingestors develop HEAD (NOT the pin) two ways — 1. goldens check vs HEAD: sync-validator-goldens.sh --check against a checkout of HEAD, catching verdict/value changes the next pin bump would have to adopt. 2. mirrored-source drift: git content comparison (pin vs HEAD) over the upstream surface internal/push + internal/schema mirror (validators/, modalities/, coercion/columns/constants/validators_mapping, csv_ingestor/record_processor/base/preflight, file_transfer, schema_inference, database, schema/) — catching the di#365 class: a new or extended upstream validator with no corpus case, invisible to the goldens check by definition. On either signal it opens or comments on a SINGLE tracking issue keyed by the head-drift-canary marker label (label auto-created idempotently); all-clear runs just emit a notice. Drift never reds the run — the job captures the goldens verdict instead of failing on it. An unreachable pin SHA (rewritten upstream history) is reported as drift too. Verified locally against real history: the path-list diff at the OLD pin 7b4ecac flags exactly the di#358+di#365 surface (9 files incl. mask_id_validator.py, image_validator.py); at the current pin 8f89aec it is empty. Issue-body construction exercised with sample env; goldens check vs HEAD ran green locally. actionlint clean. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…ct (#297) (#314) data delete is the destructive, script-invoked verb with zero JSON support today. Add --output-json mirroring data_list.go's contract exactly: - RunE splits streams the same way (human -> stderr via printerForWriter, JSON -> stdout) and, like data ingest's implies---no-input, never wires a prompter in JSON mode — a scripted delete must say --yes (or --dry-run) explicitly, else it fails closed (exit 3). - runDataDelete gains the jsonEmitted + deferred-error-writer pattern (Bugbot #53 lineage): every failure return emits {status:"error", error, exit_code} so stdout is never empty; the error shape is byte-compatible with writeDataListErrorJSON's. - Terminal statuses: deleted / dry-run / declined — all exit 0 like the human flow, so scripts branch on status. The payload carries the case-RESOLVED table spelling (backend#1027), namespace, release, database, pvc_paths and removed_paths ([] never null). - Exit codes unchanged; documented in the command Long text. docs/json-output.md (new): which commands emit JSON (version, data ingest, data list, data delete), the one-object-on-stdout rule, the shared error shape, exit-code lockstep, and the additive-only stability promise. doctor/resources/auth status extension deferred pending epic OQ5. Tests: success (case-resolved spelling + stream separation), dry-run ([] not null), confirm-declined, early failure (exit 2), off-TTY refusal (exit 3), late teardown failure (exit 7), and a wiring-level test pinning that --output-json never prompts. Fixes#297 Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…act tests (#291) (#317) WS-D.2 of the CLI hardening epic (backend#1106): the unit tests feed internal/api hand-written JSON, which pins the CLI's expectations but drifts silently when the backend renames a field — the new body decodes green and callers get Go zero values (empty account, id 0, adopted never true). This closes that class end to end: - scripts/sync-backend-fixtures.sh (cloned from sync-schema.sh's shape) vendors the REAL serialized responses for all 9 endpoints the CLI calls — generated + shape-asserted in backend CI (metaApi/tests/test_cli_response_contracts.py, backend#1108) — from tracebloc/backend at scripts/.backend-ref into internal/api/testdata/. Backend is private, so it fetches via the authenticated contents API (BACKEND_CONTRACTS_TOKEN / GH_TOKEN / gh auth token). - NEW pinned scripts/.backend-ref (backend#1009 pattern): an unrelated backend commit can't red every open CLI PR; adopting upstream shapes is a deliberate SHA bump + re-sync. - internal/api/contracts_test.go replays every fixture through the client's real decode paths: load-bearing fields must decode non-zero, the RFC 8628 error enums must map to their sentinels, 200-adopt vs 201-mint must drive the adopted flag, 426 must carry min_version, and the 409 bodies must carry the fields conflictMessage parses. A manifest completeness check fails when a synced fixture has no assertions. - backend-fixtures-drift.yml runs the --check in CI; skips with a warning until a read-only BACKEND_CONTRACTS_TOKEN secret exists (backend is private; the default GITHUB_TOKEN can't read it). Fixtures live in backend CI as plain pytest output — no backend PR ever blocks on the CLI. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…l) (#303) Pure moves of whole top-level declarations out of the 1539-line data.go, same package cli, zero behavior change: - data_ingest_cmd.go — newDataIngestCmd (flag surface incl. hidden deprecated aliases) + runDataIngestArgs - data_ingest_local.go — sortedKeys / expandHome / statDatasetPath + printLocalSummary + runLocalPreflight - data_ingest_cluster.go — runIngestionRun + shouldReclaimStaging + printClusterSummary + test seams + destTableExists + existingTableAction - data_ingest_output.go — pushJSONResult/pushJSONSummary + writePushJSON/writePushErrorJSON + classifyPushOutcome (kept together with writePushJSON — mutation-hardened lockstep) data.go keeps the data group command, the deprecation-alias notice, and runDataIngest itself (extracted separately in cli#283). Only new text is each file's header comment + package/import clauses; every moved section was verified verbatim against the pre-split file. data_test.go is untouched and compiles unchanged. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…it di#358 (cli#286) (#305) * chore(schema): bump data-ingestors pin to develop HEAD 8f89aec (cli#286) Adopts the 6 upstream commits since the 7b4ecac (di#359) pin: - di#358 — require-and-enforce semseg mask_id validator (backend#816) - di#365 — min_size values validated as positive ints at construction (#348) - di#369 — orphan-row reconcile before retry ingest (write path only) - di#366 — content-comparison e2e (tests only) - di#368 — ingest correlation id (write path only) - the 0.7.0 version bump Both sync scripts re-run against the new pin: - scripts/sync-schema.sh: ingest.v1.json + layout.v1.json byte-identical (no upstream schema change in the range) — no diff. - scripts/sync-validator-goldens.sh: regenerated against the REAL validators at 8f89aec — byte-identical goldens, so no verdict or value-level drift for the existing corpus. di#358 only adds the semseg MaskIdColumnValidator (no semseg parity cases yet) and di#365 only changes verdicts for malformed min_size values the corpus never emits. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(push): adopt di#365 min_size contract + audit CheckMaskIdColumn vs merged di#358 (cli#286) di#365 adoption (ValidateImages/spec): the upstream ImageResolutionValidator now validates min_size VALUES at construction — each side must be a positive integer (integer-valued floats coerced; strings/bool/None/non-integral floats rejected as a config error instead of surfacing as a phantom corrupt-image error). No CLI code change is needed: ParseMinSize's WxH grammar (Atoi + >0) is the equivalent gate at flag-parse time, so spec.file_options.min_size can only ever carry the positive ints upstream accepts. Documented on SpecArgs.MinSize + ValidateImages, and TestParseMinSize now pins the float boundary ('16.5x32', '32.0x32' both rejected). di#358 audit (CheckMaskIdColumn vs the merged MaskIdColumnValidator at 8f89aec) — semantics verified point for point, no divergence found: - exact-lowercase 'mask_id' required after whitespace strip (ReadCSVHeader trims like CSVIngestor's columns.str.strip()) - case/whitespace variant → rename hint (matchColumnIndex ≙ _match_column) - empty scan tests the RAW untrimmed cell against NA_SENTINELS (naSentinels is byte-identical, 12 tokens) + whitespace-only/missing — not trimmed-then- matched (the #239/#240 padded-sentinel null-set trap) - mid-read error fails closed on both sides - duplicate stripped-equal headers: both sides inspect the FIRST exact match - schema-declaration half satisfied by construction (buildImage always declares mask_id VARCHAR(255)); csv_options dialect threading N/A (CLI stages comma-separated UTF-8) Recorded as a doc block on CheckMaskIdColumn. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…ise (#299) (#300) Decision recorded on the epic (Lukas, 2026-07-14): GitHub Releases plus the cosign-verified install.sh are the install path. Drop both deferred follow-ups rather than keep advertising them: - delete the disabled bump-homebrew-tap job from release.yml (and the header bullet promising it) - delete scripts/homebrew-formula.rb.tmpl - README: state the install path plainly; annotate the roadmap row - RELEASE_CHECKLIST: remove the tap one-time-setup + vanity-URL sections, the tap verify bullet, and the brew install alternative Everything is recoverable from git history if a customer ever asks. Kept deliberately: the cosign pre-install hint (brew install cosign), delete.go's brew-managed-binary uninstall hints, and RFC-0001 history — those are not distribution promises. Fixes#299 Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* ci: run e2e on develop pushes; ratchet + extend coverage floors Scheduled workflows execute the default branch's tree (main), which trails develop by ~46 commits — discovery_e2e_test.go, delete_e2e_test.go, and the delete-teardown job don't exist there, so the nightly never actually ran them. Add push: branches: [develop] to e2e.yml so the suite runs against the tree it was written for. Ratchet the coverage floors to just under current develop numbers and add the two missing load-bearing packages: internal/cli 68 -> 80 (current 82.9%) internal/submit 72 -> 78 (current 80.4%) internal/push NEW 87 (current 89.0%) internal/cluster NEW 75 (current 78.5%) Verified locally: ./scripts/coverage-floor.sh passes all four floors. Fixes#293Fixes#294 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(ci): cluster floor 73 — CI runner measures 74.6%, not the local 78.5% internal/cluster coverage is environment-dependent: the kubeconfig-resolution paths only execute on a machine that has a real ~/.kube/config, so a dev laptop reads 78.5% while the bare ubuntu runner reads 74.6% (first CI run on this PR). The floor gates on CI, so it must be set against the CI number: 73 (= actual - 1), not the ticket's proposed 75. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…unDataIngest (#321) runDataIngest was 586 lines; every pre-cluster step and the cluster pre-flight now live in two named stanza functions, moved verbatim: - resolveLocalInput (data_ingest_local.go) — steps 0–4 + the P3 content preflight: flag guard, banner, guided prompts, ~-expansion + existence-first check, table-name/category/misapplied-flag validation, layout walk, per-category spec resolution, spec synthesis + schema validation, local summary. Mutates a in place (via *runDataIngestArgs) so the --output-json defer and the cluster steps see the resolved spec exactly as before. - connectIngestTarget (data_ingest_cluster.go) — steps 5–8a: kubeconfig resolve, release + PVC discovery, verbose cluster summary, and the destination-table guard (incl. the folded interactive replace decision, which still flips a.Overwrite). The jsonEmitted/named-return defer dance stays INSIDE runDataIngest, next to the err it reads — both extracted functions feed that named return, so the error-JSON contract is unchanged. The dry-run stop (which sets jsonEmitted) also stays inside. Only in-stanza edits are what the new signatures force: multi-value returns on error paths, := to = where a named result already exists, and &a -> a where a is already a pointer. Step order, output order, and exit codes are untouched. data.go: 693 -> 240 lines; runDataIngest: 586 -> 138. Safety net: the #187 outcome-matrix table test + #264 mutation pins pass untouched; full suite green under -race; coverage floors hold (82.7%). Co-authored-by: Lukas Wuttke <lukas@tracebloc.io> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…mand docs table (#315) * refactor(cli): name every exit-code site + cross-command docs table internal/cli/exitcodes.go names every exit code the CLI produces; every non-test &exitError construction site now uses a named constant instead of a bare number. exit.go keeps owning the extraction — this is a naming sweep, not a redesign; all numeric values are unchanged (and documented as frozen: they're the scripting contract customers branch on). Site census (the ticket's count of 138 grep hits includes one doc comment in exit.go; 137 are real construction sites): 61x1, 25x2, 23x3, 7x4, 4x5, 1x6, 5x7, 2x8, 4x9, 2x130, 2x kubeconfigExitCode(...) (the helper now returns named constants), 1x variable (runLocalPreflight's BadFlag fold, now built from constants). Zero numeric literals remain at non-test sites. Codes that grew more than one per-command meaning get one constant per MEANING sharing the value (2: exitBadInput / doctor's exitChecksFailed; 5: exitAuth / data delete's exitNoSuchDataset; 7: exitStagingFailed / exitTeardownFailed / exitQueryFailed), so each site reads honestly. docs/troubleshooting.md gains the cross-command exit-code table (code, meaning, producing commands, constant name), sourced from the per-command long-help blocks — data ingest's (data_ingest_cmd.go, pre-split data.go:236-252) is the fullest. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci: file-budget line-count ratchet (scripts/file-budget.sh) wired into make ci + build.yml (#316) * refactor(cli): extract resolveLocalInput + connectIngestTarget from runDataIngest runDataIngest was 586 lines; every pre-cluster step and the cluster pre-flight now live in two named stanza functions, moved verbatim: - resolveLocalInput (data_ingest_local.go) — steps 0–4 + the P3 content preflight: flag guard, banner, guided prompts, ~-expansion + existence-first check, table-name/category/misapplied-flag validation, layout walk, per-category spec resolution, spec synthesis + schema validation, local summary. Mutates a in place (via *runDataIngestArgs) so the --output-json defer and the cluster steps see the resolved spec exactly as before. - connectIngestTarget (data_ingest_cluster.go) — steps 5–8a: kubeconfig resolve, release + PVC discovery, verbose cluster summary, and the destination-table guard (incl. the folded interactive replace decision, which still flips a.Overwrite). The jsonEmitted/named-return defer dance stays INSIDE runDataIngest, next to the err it reads — both extracted functions feed that named return, so the error-JSON contract is unchanged. The dry-run stop (which sets jsonEmitted) also stays inside. Only in-stanza edits are what the new signatures force: multi-value returns on error paths, := to = where a named result already exists, and &a -> a where a is already a pointer. Step order, output order, and exit codes are untouched. data.go: 693 -> 240 lines; runDataIngest: 586 -> 138. Safety net: the #187 outcome-matrix table test + #264 mutation pins pass untouched; full suite green under -race; coverage floors hold (82.7%). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor(cli): name every exit-code site + cross-command docs table internal/cli/exitcodes.go names every exit code the CLI produces; every non-test &exitError construction site now uses a named constant instead of a bare number. exit.go keeps owning the extraction — this is a naming sweep, not a redesign; all numeric values are unchanged (and documented as frozen: they're the scripting contract customers branch on). Site census (the ticket's count of 138 grep hits includes one doc comment in exit.go; 137 are real construction sites): 61x1, 25x2, 23x3, 7x4, 4x5, 1x6, 5x7, 2x8, 4x9, 2x130, 2x kubeconfigExitCode(...) (the helper now returns named constants), 1x variable (runLocalPreflight's BadFlag fold, now built from constants). Zero numeric literals remain at non-test sites. Codes that grew more than one per-command meaning get one constant per MEANING sharing the value (2: exitBadInput / doctor's exitChecksFailed; 5: exitAuth / data delete's exitNoSuchDataset; 7: exitStagingFailed / exitTeardownFailed / exitQueryFailed), so each site reads honestly. docs/troubleshooting.md gains the cross-command exit-code table (code, meaning, producing commands, constant name), sourced from the per-command long-help blocks — data ingest's (data_ingest_cmd.go, pre-split data.go:236-252) is the fullest. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci: file-budget line-count ratchet (scripts/file-budget.sh) Clones the coverage-floor.sh pattern for file size: path:max_lines pairs, checked by wc -l, portable to bash 3.2, with the same malformed-entry guard — plus a missing-file guard so a moved/renamed budgeted file makes the stale list loud instead of silently un-budgeting it. Ceilings are a RATCHET: only ever lowered as files shrink; raising one is a deliberate, reviewed edit to the checked-in script. Seeds sit just above today's reality (develop + the WS-B split): internal/push/preflight.go:1650 (now 1635) internal/cli/data.go:500 (now 240 post cli#282/#283) internal/cli/client.go:1050 (now 1027) internal/cli/home.go:850 (now 841) Wired into `make ci` (new file-budget target, keeping the Makefile's "make ci green => CI green" invariant) and into build.yml's lint job as one surgical step. Exercised all three failure paths locally (over budget, missing file, malformed entry) — each exits 1 with a ::error:: annotation; shellcheck clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(file-budget): seed preflight.go at true size (Bugbot #316 HIGH) The ratchet seeded internal/push/preflight.go at 1650, but the file is 1655 lines (wc -l, same count the gate uses) and the check is strict- greater — so `make file-budget` would fail the moment this landed on develop. Raise the ceiling to 1700, the next round-50 ratchet value just above actual, matching how the other seeds sit above their files (client.go 1050>1027, home.go 850>849, data.go 500>240). Also correct the header comment to reality (preflight ~1655, home ~849); it wrongly read ~1635 / ~841. Proof: `bash scripts/file-budget.sh` now passes (preflight 1655 <= 1700). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* test: SwapSeam helper + advisory gremlins mutation workflow internal/testutil.SwapSeam(t, ptr, stub) replaces the hand-rolled save/stub/restore blocks around package-level seam variables: swap, then LIFO-restore via t.Cleanup. Generic, so non-function seams (timeouts) work too. Converted the three blocks in internal/submit (watch_test.go x2, run_watch_test.go x1); internal/push has none. The ~26 blocks in internal/cli are deliberately left for the decomposition work to pick up; converting them here would collide. mutation.yml formalizes the gremlins ritual that produced #262-#264: workflow_dispatch only, one package per run, advisory (lived mutants never fail the job — no thresholds). Prints a survivors-to-triage summary, uploads the JSON report, and CONTRIBUTING.md documents how survivors get triaged into pinning-test issues. Fixes#295 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci: harden gremlins mutation workflow (Bugbot #306) - Reject a zero timeout-coefficient. The digit check accepted `0`/`00`, which collapses gremlins' per-mutant timeout so survivors report TIMED OUT instead of KILLED/LIVED — the exact failure mode this input guards against. Now require a positive integer (> 0), matching the error text. - Add `set -o pipefail` to the run step. The implicit default shell is `bash -e {0}` (no pipefail), so `gremlins | tee` masked a non-zero gremlins exit behind tee's 0, letting a broken suite pass the job — contradicting the workflow's "tool/test health fails the run" contract. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…i#287) (#308) * ci: goldens-drift job — validator goldens vs data-ingestors @ pin (cli#287) New dedicated workflow (goldens-drift.yml): checks out tracebloc/data-ingestors at the pinned ref (scripts/.data-ingestors-ref), installs its runtime requirements, and runs scripts/sync-validator-goldens.sh --check — failing any PR whose committed parity goldens have drifted from the REAL validators at the pin. Closes the wired-into-no-CI hole: until now the goldens were only regenerated by hand, so a corpus/generator/pin change could land with stale goldens and CI stayed green. Triggers: PRs touching internal/push/**, the pin, or the sync harness; weekly Monday cron as a backstop; manual dispatch. Cross-repo access: data-ingestors is currently PUBLIC (verified via gh), so the default workflow token suffices — the cli#62 precedent (install-path-persist.yml) also checks out a sibling repo with no secret. The job still prefers an org secret CROSS_REPO_READ_TOKEN when present and skips-with-warning (never hard-fails) if the repo becomes unreadable, so a future privatization flips to 'create the secret' instead of redding every open PR. Deps: pip install -r data-ingestors/requirements.txt, not just pandas+pillow — the generator's import chain also needs sqlalchemy, tenacity, ijson et al (verified in a clean venv; pandas+pillow alone fails on import). requirements.txt is all light pure-python wheels. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci: goldens-drift probe falls back to github.token on invalid PAT (cli#287) A set-but-invalid CROSS_REPO_READ_TOKEN (expired / wrong scope) made the readability probe pick only the PAT, fail, and skip the whole drift check while data-ingestors is still public and the default token would work. Probe now tries the PAT, and if it fails falls back to github.token before marking access failed — only skip-with-warning when BOTH fail. It emits a `use_pat` selector so the checkout uses exactly the token the probe validated, keeping the two in lockstep. Still read-only, least-privilege, skip-not-hard-fail. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…rt the 8 CLI-assumed invariants (#311) * ci: pinned-ref chart-invariant gate against tracebloc/client The CLI hardcodes 8 invariants about the tracebloc/client chart — discovery labels + jobs-manager Deployment name forms, the jobs-manager Service on 8080, the client-pvc mount at /data/shared, the ingestion-authz ConfigMap + "ingestor" SA fallback, the INGESTOR_IMAGE_DIGEST env, the requests-proxy Deployment, and the POST /internal/submit-ingestion-run port. A chart rename ships green in both repos and breaks discovery/doctor/ingest in the field. New scripts/.client-ref pins the client commit the gate renders (the scripts/.data-ingestors-ref pattern, backend#1009): chart-drift.yml checks out tracebloc/client at that ref, helm-templates it with the same CI values the client repo's own drift job uses, and scripts/chart-invariants asserts every invariant with a mapping back to the CLI constant it protects. Triggers: PRs touching internal/cluster/** or internal/doctor/** (or the gate's own files, weekly cron, manual dispatch. The client-side half extends that repo's scripts/tests/check-drift.sh so renaming chart PRs fail at the source. Refs #290 (WS-D.1, backend#1106) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> EOF ) * fix(chart-gate): assert the SELECTED jobs-manager Service exposes 8080 Invariant 3 passed if any jobs-manager/<release>-jobs-manager Service exposed 8080, but pickJobsManagerService (internal/cluster/discover.go) selects the unprefixed "jobs-manager" first by existence, ignoring ports. With both Services rendered and only the non-selected one on 8080, the gate passed while the CLI would port-forward to the wrong target. Now the gate mirrors that precedence and checks the selected Service. Adds a regression case covering the both-Services-only-sibling-has-8080 scenario. Fixes a Cursor Bugbot finding on #311. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…release policy (#307) * docs: truth pass — README/nav-map/checklist match the v0.8 surface; release policy (#296) Every claim re-verified against the actual command tree (go run ./cmd/tracebloc --help + each subcommand on develop @ 5af9a80): README: - v0.3.0 status blurb -> v0.8.0 latest release + a lifecycle command table (login/logout/auth, client/status, resources show+set, data ingest/list/delete/validate, cluster info, doctor, delete, version/completion/home screen); notes what landed post-v0.8.0 - 15-of-16 tasks -> all 16 (semantic_segmentation shipped in #247; registry verified: 16x CLISupported, zero false) - roadmap tail: 9-of-10-modalities + v0.2/v0.3 story -> v0.2-v0.8 arc; semseg removed from Next (done); cloud-source kept (backed by RFC-0002 + the in-help 1 GiB cap copy) - links the navigation map docs/cli-navigation.md: - stale-basis disclaimer removed (was develop @ 27c5392) - resources set (#241) + status-aware home screen (#244) un-dashed — both merged; proposed classDef dropped - nonexistent home-screen-spec.md references removed (point at #244) - doctor node: top-level doctor shipped, cluster doctor = hidden alias (pinned by TestClusterCmd_DoctorIsHiddenAlias) - known-gaps list pruned to what is still true (offboard partial teardown still exits 0 — re-verified in delete.go) scripts/RELEASE_CHECKLIST.md: - 5-line release policy: trigger = customer-visible merge or weekly, owner = DevEx squad (role, not person) - EKS smoke: dataset push -> data ingest; v0.1-ticket pre-flight genericized release.yml: header comment claimed release notes come from CHANGELOG.md — no such file exists; it's generate_release_notes: true. Fixes#296 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: refresh README latest-release refs v0.8.0 -> v0.9.1 (#296) Addresses Asad's review on #307: this truth pass predated the v0.9.0 and v0.9.1 cuts, so a few version claims went stale. - Status blurb: "v0.8.0 is the latest release" -> "v0.9.1 is the latest release". - The post-v0.8.0 "ships with the next release" framing for resources / status-aware home screen / top-level doctor / semantic_segmentation -> "Shipped in v0.9.0" (they released in v0.9.0, no longer "next"). - Roadmap tail: "Since the v0.8.0 cut, develop gained ..." -> a "v0.9 added ...; v0.9.1 is the current latest" entry, extending the v0.2-v0.8 arc. Historical v0.8.0 references (the v0.8.0 cut, cluster doctor in v0.8.0) kept as deliberate contrasts. Homebrew tap stays dropped (#300) - no reintroduction. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…> 67 cases) (#310) Every schema category now ends with >=1 parity case; every mirrored preflight check ends with >=1 valid + >=1 violation case (cli#288, WS-C.3 of tracebloc/backend#1106). New coverage, in the ticket's priority order: - object_detection (4): CheckAnnotationPairing both directions + a documented PascalVOCXMLValidator under-preview (objdet-bad-xml). - semantic_segmentation (4): CheckMaskPairing (missing mask, non-_mask name) + semseg-missing-mask-id — a PIN-SCOPED divergence: the CLI previews the backend#816 mask_id contract, but the pinned ingestor (7b4ecac, di#359) predates di#358's MaskIdColumnValidator, so its preflight accepts. Flip to reject/reject at the cli#286 pin bump. - keypoint_detection (3): happy path (Annotation/Visibility JSON), kp-res-mismatch pinning the image-family commons cover keypoint too, + a documented KeypointAnnotationValidator under-preview. - text formats (13): token_classification (BIO ok / missing label column / bad-tag under-preview), sentence_pair_classification (ok+value-parity / uniform-label / malformed-pair under-preview), mlm, clm, seq2seq, embeddings happy paths + emb-malformed and mlm-missing-files (IngestableRecords file cross-check has no text mirror), text-clf-label-uniform. - tabular_regression / TSF / TTE (8): happy paths, tabreg-label-uniform as an over-reject guard (no diversity gate for regression on either side), tabreg-label-missing (the read-time divergence twin), and documented under-previews: TSF global time order, TSF fixed-timestamp schema rule, TTE negative-time. Goldens regenerated from the REAL ingestor validators at the pinned ref (scripts/gen-validator-goldens.py; existing 35 entries byte-identical). runGoPreflight now populates LocalLayout.Sidecars (annotations/, masks/, texts/, sequences/) the way production Discover does — without it the object_detection/semseg pairing previews would see an empty sidecar set. Fixes#288 Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…58) (#322) The goldens-drift check went red on develop once cli#286 bumped the data-ingestors pin past di#358, whose MaskIdColumnValidator now REQUIRES mask_id to be a *declared schema column* (an undeclared mask_id is dropped at ingest -> stored table lacks it -> the training client raises FileNotFoundError, backend#816). Root cause was in the goldens harness, not the CLI or the ingestor: the CLI's real semseg ingest declares the mask_id column (spec.go sets schema={'mask_id':'VARCHAR(255)'}), but gen-validator-goldens.py only injected a schema for tabular/time-series categories. So it drove the validators WITHOUT the schema the CLI sends, and MaskIdColumnValidator spuriously rejected every semseg case (incl. semseg-ok). Fix: mirror spec.go for semantic_segmentation cases (an explicit per-case schema still wins, so the reject-path cases keep exercising the contract). Also flips semseg-missing-mask-id's ingestor_verdict accept->reject: it has no mask_id column, so post-di#358 the ingestor correctly rejects it (both sides now agree). This is exactly the reconciliation the case's own note predicted at pin-bump time. Regenerated goldens; only that one entry changes. 'validator goldens in sync'; internal/push parity tests green. Part of tracebloc/backend#1106 (WS-C validator mirrors). Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Adds a label-gated (+nightly) CI job that catches a PATH-persistence regression in this repo's scripts/install.sh from the CLI side, pre-merge: a change that persists PATH only where a fresh non-login shell can't read it (the class that shipped green originally) fails CI before it merges. The fresh-shell harness is the single source of truth in tracebloc/client (scripts/tests/path-persist.sh); this job checks it out and points it at the PR's install.sh. Tracks the harness on client's develop (it has since merged there), resolving the original pin-to-feature-branch TODO. Part of #737. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
LukasWodka
commented
Jul 14, 2026
👋 Heads-up — Code review queue is at 47 / 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.
…findings (#302) * ci: re-enable staticcheck (pinned standalone) + fix the 5 non-ST1005 findings Pinned staticcheck@2025.1.1 joins the standalone lint set in both the Makefile lint target and build.yml's lint job (-checks all,-ST1005), mirroring the errcheck/ineffassign pin pattern. The golangci-lint OOM story that originally disabled it is stale for the standalone binary: a full run is ~12s wall locally. Findings fixed (the full non-ST1005 set): - ST1008: runSet (resources_set_test) returns (string, error), error last - ST1003: CheckMaskIdColumn -> CheckMaskIDColumn (+ call sites/comments) - ST1003: errors_as -> errorsAs, io_eof_or_similar -> ioEOFOrSimilar - ST1020: CoreFloorText doc comment starts with the function name ST1005 stays excluded: it flags ~58 customer-visible error strings that need a wording review, not a mechanical sweep — separate follow-up. Rebased onto develop: union-merged the lint job with develop's govulncheck job (#278), coverage-floor step (#301) and deadcode advisory gate; kept the audit comment #286 added above CheckMaskID*Column. The 'going back to the action' comment in build.yml is KEPT (not deleted) — #6 is still open on develop, so golangci-lint-action stays disabled and that rationale still holds. Detached the four data_ingest_*.go header comments (#303 split) plus exitcodes.go's (#284, which develop merged after this branch was cut) from the package clause so the newly-enabled staticcheck gate is ST1000-clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci: goimports -local gate + Dependabot config (gomod weekly, actions monthly) (#304) * ci: goimports -local gate + Dependabot config (gomod weekly, actions monthly) goimports -local github.com/tracebloc/cli now blocks in both loops: build.yml's lint job (pinned goimports@v0.48.0, same x/tools version as the deadcode pin) and the Makefile's fmt-check target, with make fmt extended to auto-fix. .golangci.yml already declared this grouping via local-prefixes but nothing enforced it — 4 files had drifted (data.go, data_test.go, ingestion_run_test.go, resources_set_test.go), fixed here with import-grouping-only diffs. .github/dependabot.yml extends the org's backend-only Dependabot pilot: gomod weekly (k8s.io/* + sigs.k8s.io/* grouped, golang.org/x/* grouped), github-actions monthly. Unlike backend's security-only config, the CLI takes real version updates — customers install this binary, so staying current is security posture (see #276). Org-wide rollout decision flagged to Asad on the PR. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci: canonicalize import grouping in data_test.go for the goimports gate Regroups imports into the layout goimports -local github.com/tracebloc/cli emits (stdlib / third-party / tracebloc-local). gofmt and goimports only sort within existing blank-line groups, so the manual groups passed fmt-check as-is but were not the canonical single-block output; Bugbot and our precheck both flagged the divergence. Verified idempotent under the pinned goimports v0.48.0 and green on make fmt-check + go build ./... Rebased onto ci/279 (post-#303 data.go split): data.go's import block is already canonical from the #303 split, so its canonicalization here is a no-op and dropped — this commit now regroups data_test.go only. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * ci: flip deadcode gate to blocking; delete the 3 dead #127 leftovers (#313) * ci: goimports -local gate + Dependabot config (gomod weekly, actions monthly) goimports -local github.com/tracebloc/cli now blocks in both loops: build.yml's lint job (pinned goimports@v0.48.0, same x/tools version as the deadcode pin) and the Makefile's fmt-check target, with make fmt extended to auto-fix. .golangci.yml already declared this grouping via local-prefixes but nothing enforced it — 4 files had drifted (data.go, data_test.go, ingestion_run_test.go, resources_set_test.go), fixed here with import-grouping-only diffs. .github/dependabot.yml extends the org's backend-only Dependabot pilot: gomod weekly (k8s.io/* + sigs.k8s.io/* grouped, golang.org/x/* grouped), github-actions monthly. Unlike backend's security-only config, the CLI takes real version updates — customers install this binary, so staying current is security posture (see #276). Org-wide rollout decision flagged to Asad on the PR. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci: canonicalize import grouping in data_test.go for the goimports gate Regroups imports into the layout goimports -local github.com/tracebloc/cli emits (stdlib / third-party / tracebloc-local). gofmt and goimports only sort within existing blank-line groups, so the manual groups passed fmt-check as-is but were not the canonical single-block output; Bugbot and our precheck both flagged the divergence. Verified idempotent under the pinned goimports v0.48.0 and green on make fmt-check + go build ./... Rebased onto ci/279 (post-#303 data.go split): data.go's import block is already canonical from the #303 split, so its canonicalization here is a no-op and dropped — this commit now regroups data_test.go only. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci: flip deadcode gate to blocking; delete the 3 dead #127 leftovers The deadcode CI step loses continue-on-error (and the Makefile target its '|| true'): both now run scripts/deadcode-check.sh, which fails on any function unreachable from ./cmd/tracebloc that isn't declared in scripts/deadcode-allowlist.txt. The tool itself always exits 0, so the old advisory step never could have blocked — the gate keys on output. Deleted (verified still dead with the pinned deadcode@v0.48.0): - config.clearAll + its three dedicated tests (TestClearAll, TestClearAll_HomeError, TestClear) — logout uses Save, nothing else ever called it - push.allCategoryIDs — moved verbatim into category_registry_test.go (the registry-pinning tests legitimately iterate every id; the shipped binary shouldn't carry the helper) - submit.isSubmitError — moved into client_test.go as the test-local assertion helper it always was (orphaned 'errors' import dropped) Allowlisted with reasons (the 4 legit findings): Status.String + JobOutcome.String (fmt-reflection Stringers) and ReadLabelValues + inferColumnType (di#349 test-only parity harnesses). Stale allowlist entries warn without failing; line numbers are stripped so edits that shift code don't red the gate. Coverage floors still clear after the test deletions (cli 82.9% >= 68, submit 80.3% >= 72). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…n list contracts (#324) assertProvisionedClient asserts every ProvisionedClient field decodes non-zero — the silent-drift class. That is right for the three hand-pinned single fixtures (create/adopt/patch), but TestContractListClientsPaginated applied it to every row of a real synced list (edge_device_list.json). status==0 is STATUS_OFFLINE and cluster_id is "Empty on legacy / not-yet-backfilled clients" (client.go), so the next re-sync of a list that includes an offline or unanchored row would fail CI even though decoding is correct. This is the Cursor Bugbot "contract test rejects valid values" finding on #323. Add assertDecodesFrom, used per-row by the list test. It catches BOTH silent drift directions without rejecting legitimate zeros: - struct-tag drift (a Go json tag renamed): the wire still carries the old key with a value while the struct decodes zero -> value mismatch -> caught. - backend rename/drop on re-sync (the wire field renamed, fixture reseeded): the old key vanishes, so a pure value compare reads zero on both sides. A presence assertion on the always-present keys (id/first_name/username/ namespace/status) catches this. cluster_id is presence-optional (legit empty), its rename stays covered by the strict single-fixture tests. status==0 is tolerated (key present, value 0). The single pinned fixtures keep the strict non-zero helper. Also harden TestContractListClientAdmins (surfaced by the same-class sweep): email is a domain-guaranteed identifier -> assert present + wire-match (a renamed email tag decodes "" -> caught); name is a display name that can be legitimately blank -> assert wire-fidelity only, not non-empty. Proven by mutation: struct-tag rename and backend key-rename both fail the list test; an offline/unanchored fixture row passes; a blank admin name passes; an admin email-key rename fails. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Uh oh!
There was an error while loading. Please reload this page.
The HEAD-drift canary set drift=true on ANY non-zero exit from sync-validator-goldens.sh --check. But that exit also covers harness failures -- missing deps, a bad DATA_INGESTORS_DIR, a generator crash -- so the tracking issue reported "DRIFT -- verdicts/values changed" even when parity was never evaluated, sending someone down the pin-bump playbook for an infra bug. (Cursor Bugbot, Medium, surfaced on the #323 promotion.) sync-validator-goldens.sh --check now uses reserved exit codes so consumers can tell the two apart: 0 in sync 2 HARNESS ERROR -- could not regenerate; parity NOT evaluated (not drift) 3 DRIFT -- verdicts / read-path values changed The required goldens-drift check is unaffected (it reds on any non-zero). The canary maps those codes and, crucially, adapts the ENTIRE tracking issue to the signal via a pin_actionable flag (real drift OR source diff OR unreachable pin): - exit 3 / source diff / bad pin -> drift framing: pin-bump Playbook, the "HEAD has drifted" title, and the "close when the pin bump lands" footer. - exit 2 / unexpected, harness-only -> harness framing: NO pin-bump Playbook, a "could not run (harness error)" title, and a "fix the harness, do NOT bump the pin" footer. The "All clear" step now requires evaluated=true so it cannot mask a harness failure. Verified: --check with no data-ingestors exits 2 with a HARNESS ERROR message and does not mutate goldens.json; the reporting script, run under both a harness-only and a real-drift scenario, produces the correct row / playbook / footer / title each time; actionlint + shellcheck clean; YAML valid. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The HEAD-drift canary set drift=true on ANY non-zero exit from sync-validator-goldens.sh --check. But that exit also covers harness failures -- missing deps, a bad DATA_INGESTORS_DIR, a generator crash -- so the tracking issue reported "DRIFT -- verdicts/values changed" even when parity was never evaluated, sending someone down the pin-bump playbook for an infra bug. (Cursor Bugbot, Medium, surfaced on the #323 promotion.) sync-validator-goldens.sh --check now uses reserved exit codes so consumers can tell the two apart: 0 in sync 2 HARNESS ERROR -- could not regenerate; parity NOT evaluated (not drift) 3 DRIFT -- verdicts / read-path values changed The required goldens-drift check is unaffected (it reds on any non-zero). The canary adapts the WHOLE tracking issue to the signal via a pin_actionable flag (real drift OR source diff OR unreachable pin): - pin_actionable -> drift framing: the pin-bump Playbook, the "HEAD has drifted" title, and the "close when the pin bump lands" footer. - harness-only (evaluated=false, no source diff, pin reachable) -> harness framing: NO Playbook, a "could not run (harness error)" title, and a "fix the harness, do NOT bump the pin" footer. The harness-error note is purely factual (no bump/don't-bump wording) so it never contradicts the Playbook when a harness error co-occurs with a real source diff. The title is recomputed from the current signal and refreshed on EVERY run (issue edit, not only create) so a persistent issue's title never lags the latest failure mode. "All clear" requires evaluated=true so it cannot mask a harness failure. Verified: --check with no data-ingestors exits 2 with a HARNESS ERROR message and does not mutate goldens.json; the reporting script, exercised across harness-only, harness+source-diff, real-drift, and existing-vs-new-issue scenarios, produces a self-consistent row / note / playbook / footer / title each time; actionlint + shellcheck clean; YAML valid. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The HEAD-drift canary set drift=true on ANY non-zero exit from sync-validator-goldens.sh --check. But that exit also covers harness failures -- missing deps, a bad DATA_INGESTORS_DIR, a generator crash -- so the tracking issue reported "DRIFT -- verdicts/values changed" even when parity was never evaluated, sending someone down the pin-bump playbook for an infra bug. (Cursor Bugbot, Medium, surfaced on the #323 promotion.) sync-validator-goldens.sh --check now uses reserved exit codes so consumers can tell the two apart: 0 in sync 2 HARNESS ERROR -- could not regenerate; parity NOT evaluated (not drift) 3 DRIFT -- verdicts / read-path values changed The required goldens-drift check is unaffected (it reds on any non-zero). The canary adapts the WHOLE tracking issue to the signal via a pin_actionable flag (real drift OR source diff OR unreachable pin): - pin_actionable -> drift framing: the pin-bump Playbook, the "HEAD has drifted" title, and the "close when the pin bump lands" footer. - harness-only (evaluated=false, no source diff, pin reachable) -> harness framing: NO Playbook, a "could not run (harness error)" title, and a "fix the harness, do NOT bump the pin" footer. The harness-error note is purely factual (no bump/don't-bump wording) so it never contradicts the Playbook when a harness error co-occurs with a real source diff. The title is recomputed from the current signal and refreshed on EVERY run (issue edit, not only create) so a persistent issue's title never lags the latest failure mode. "All clear" requires evaluated=true so it cannot mask a harness failure. Verified: --check with no data-ingestors exits 2 with a HARNESS ERROR message and does not mutate goldens.json; the reporting script, exercised across harness-only, harness+source-diff, real-drift, and existing-vs-new-issue scenarios, produces a self-consistent row / note / playbook / footer / title each time; actionlint + shellcheck clean; YAML valid. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
LukasWodka
commented
Jul 14, 2026
@BugBot run |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
…-ingestors jobs (#326) Two Cursor Bugbot findings surfaced on the #323 promotion re-review of the data-ingestors drift jobs: 1. Invalid PAT breaks canary checkout (Medium). head-drift-canary.yml passed `secrets.CROSS_REPO_READ_TOKEN || github.token` straight to actions/checkout. `||` only falls back when the secret is EMPTY, so a set-but-expired / mis-scoped PAT reds the weekly canary even though data-ingestors is public and github.token would work. Ported goldens-drift.yml's reachability probe: a `git ls-remote` check picks the PAT only when it actually works and falls back to the default token otherwise (use_pat output, kept in lockstep with the checkout). goldens-drift.yml already had this probe. 2. Pin ref lacks shape guard (Low). goldens-drift.yml and head-drift-canary.yml read scripts/.data-ingestors-ref and (for goldens-drift) pass it straight to actions/checkout after only an emptiness check, unlike chart-drift.yml which validates ref shape. Added the same guard to both: SHA / branch / tag characters only and no "..", so a malformed pin fails with a clear error instead of an opaque checkout failure. Verified: the shape guard accepts the real pin, branch/tag/SHA refs, and rejects "..", shell metacharacters, and empty; the probe's no-token path selects github.token; actionlint + shellcheck clean; YAML valid. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
LukasWodka
commented
Jul 14, 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 0bf4b9f. Configure here.
Uh oh!
There was an error while loading. Please reload this page.
* chore(deps): bump softprops/action-gh-release from 2 to 3 Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2 to 3. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](softprops/action-gh-release@v2...v3) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-version: '3' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * chore: back-merge main → develop after #323 promote (#335) * chore(deps): bump the k8s group with 3 updates (#331) Bumps the k8s group with 3 updates: [k8s.io/api](https://github.com/kubernetes/api), [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) and [k8s.io/client-go](https://github.com/kubernetes/client-go). Updates `k8s.io/api` from 0.36.1 to 0.36.2 - [Commits](kubernetes/api@v0.36.1...v0.36.2) Updates `k8s.io/apimachinery` from 0.36.1 to 0.36.2 - [Commits](kubernetes/apimachinery@v0.36.1...v0.36.2) Updates `k8s.io/client-go` from 0.36.1 to 0.36.2 - [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md) - [Commits](kubernetes/client-go@v0.36.1...v0.36.2) --- updated-dependencies: - dependency-name: k8s.io/api dependency-version: 0.36.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s - dependency-name: k8s.io/apimachinery dependency-version: 0.36.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s - dependency-name: k8s.io/client-go dependency-version: 0.36.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Asad Iqbal (Saadi) <asad.dsoft@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump github.com/schollz/progressbar/v3 (#333) Bumps [github.com/schollz/progressbar/v3](https://github.com/schollz/progressbar) from 3.19.0 to 3.19.1. - [Release notes](https://github.com/schollz/progressbar/releases) - [Commits](schollz/progressbar@v3.19.0...v3.19.1) --- updated-dependencies: - dependency-name: github.com/schollz/progressbar/v3 dependency-version: 3.19.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Asad Iqbal (Saadi) <asad.dsoft@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump helm/kind-action from 1.10.0 to 1.14.0 (#328) Bumps [helm/kind-action](https://github.com/helm/kind-action) from 1.10.0 to 1.14.0. - [Release notes](https://github.com/helm/kind-action/releases) - [Commits](helm/kind-action@v1.10.0...v1.14.0) --- updated-dependencies: - dependency-name: helm/kind-action dependency-version: 1.14.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Asad Iqbal (Saadi) <asad.dsoft@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump actions/add-to-project from 1.0.2 to 2.0.0 (#327) Bumps [actions/add-to-project](https://github.com/actions/add-to-project) from 1.0.2 to 2.0.0. - [Release notes](https://github.com/actions/add-to-project/releases) - [Commits](actions/add-to-project@v1.0.2...v2.0.0) --- updated-dependencies: - dependency-name: actions/add-to-project dependency-version: 2.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Asad Iqbal (Saadi) <asad.dsoft@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump actions/stale from 9 to 10 (#332) Bumps [actions/stale](https://github.com/actions/stale) from 9 to 10. - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](actions/stale@v9...v10) --- updated-dependencies: - dependency-name: actions/stale dependency-version: '10' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Asad Iqbal (Saadi) <asad.dsoft@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix(ci): point Dependabot at develop, not main (#336) All work in this repo flows feature → develop → main (promote PRs). Dependabot defaults to the repo default branch (main), so the first batch of bumps (#327–#334) targeted main directly — bypassing develop and set to regress on the next promote (develop carries the older deps). Set target-branch: "develop" on both ecosystems so bumps ride the normal review + promote path. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * ci: bump artifact actions to v7 (upload + download together) (#337) Supersedes Dependabot #329, which bumped actions/upload-artifact 4→7 but left actions/download-artifact@v4 in release.yml's publish job. GitHub requires matching upload/download majors — a v7↔v4 pair breaks the release artifact merge (download-artifact can't read v7-format uploads). Bump all four refs together: upload-artifact in build.yml, mutation.yml, release.yml, and download-artifact in release.yml. CI/release-only; no CLI-binary change. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * Merge pull request #339 from tracebloc/fix/338-heartbeat-single-client fix(cli): home heartbeat fetches one client, not the whole account (#338) * chore(deps): bump github.com/spf13/cobra from 1.8.1 to 1.10.2 (#340) Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.8.1 to 1.10.2. - [Release notes](https://github.com/spf13/cobra/releases) - [Commits](spf13/cobra@v1.8.1...v1.10.2) --- updated-dependencies: - dependency-name: github.com/spf13/cobra dependency-version: 1.10.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Note
Medium Risk
Large CI surface area and new cross-repo gates (several skip until secrets exist), but runtime CLI exit semantics stay numeric-equivalent; release pipeline loses the dormant Homebrew bump path.
Overview
This PR expands CI and local
make ciwith pinned staticcheck, goimports grouping, blocking deadcode (allowlisted unreachables), and a per-file line budget, plus Dependabot for groupedgomodand monthly Actions updates.It adds cross-repo drift workflows that compare pinned upstream refs to vendored contracts: backend API fixtures (
internal/api/testdata+contracts_test.go), validator goldens vsdata-ingestors, Helm chart invariants vstracebloc/client, and an advisory HEAD-drift canary that files tracking issues when the pin goes stale. E2E also runs ondeveloppushes so scheduled jobs exercise the same tree as active development; install PATH persist reuses the client harness against this PR’sinstall.sh. A manual-only gremlins workflow documents the mutation-testing ritual in CONTRIBUTING.Release drops the disabled Homebrew tap job and uses GitHub-generated release notes instead of
CHANGELOG.md. Docs/README/navigation are refreshed;docs/json-output.mdand a troubleshooting exit-code table document scripting contracts. CLI packages swap raw1/130exits for named constants fromexitcodes.go(behavior unchanged).Reviewed by Cursor Bugbot for commit 0bf4b9f. Bugbot is set up for automated code reviews on this repo. Configure here.