Skip to content

feat(data delete): --output-json + the one-page JSON scripting contract#314

Merged
saadqbal merged 1 commit into
developfrom
feat/297-data-delete-output-json
Jul 14, 2026
Merged

feat(data delete): --output-json + the one-page JSON scripting contract#314
saadqbal merged 1 commit into
developfrom
feat/297-data-delete-output-json

Conversation

@LukasWodka

@LukasWodka LukasWodka commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

What

WS-F.3 of the customer-surface pass (epic tracebloc/backend#1106): data delete is the destructive, script-invoked verb, and it had zero --output-json support. This adds it, mirroring data_list.go's contract exactly, plus the one-page JSON scripting policy the epic asked for.

Changes

internal/cli/data_delete.go (strictly this file — the sibling WS-B PR owns data.go):

  • --output-json flag; RunE splits streams exactly like data list (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 pass --yes (or --dry-run), else it fails closed with the documented exit 3.
  • runDataDelete gains the jsonEmitted + deferred error-writer pattern copied from runDataList (Bugbot feat: add dataset list command #53 lineage): every failure return emits {status:"error", error, exit_code}, byte-compatible with writeDataListErrorJSON's shape, so --output-json | jq never sees empty stdout.
  • Terminal statuses deleted / dry-run / declined — all exit 0, matching the human flow (exit codes are unchanged; scripts branch on status). Payload carries the case-resolved table spelling (backend#1027), namespace, release, database, pvc_paths, removed_paths ([], never null).

docs/json-output.md (new one-pager): 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. Extension to doctor/resources/auth status explicitly deferred pending epic OQ5.

internal/cli/data_delete_json_test.go (new): success (case-resolved spelling + no human leak into the JSON stream), dry-run ([] not null), confirm-declined, early failure (exit 2, pre-discovery), off-TTY refusal (exit 3), late teardown failure (exit 7), and a wiring-level test pinning that --output-json never prompts (root's SilenceUsage mirrored in-test).

Verification (ran locally)

  • go build ./..., go vet ./internal/cli/, gofmt -l clean.
  • Full go test ./... green (all 15 packages).
  • Manual smoke: go run ./cmd/tracebloc data delete --help shows the new flag + the Long-text JSON note.
  • golangci-lint not installed on this machine — CI's lint gate is the check for that.

Independent of the other WS-F PRs (#300/#307) — no shared files; merge order flexible.

Fixes #297

🤖 Generated with Claude Code


Note

Medium Risk
Touches a destructive cluster teardown path, but behavior matches existing JSON commands, requires explicit --yes in JSON mode, and only changes machine-readable output—not teardown logic itself.

Overview
Adds --output-json to tracebloc data delete, aligned with data list / data ingest: one JSON object on stdout, human UI on stderr, documented exit codes unchanged, and failures always emit {status:"error", error, exit_code} via a deferred writer so parsers never see empty stdout.

JSON mode is non-interactive (no prompts); scripts must pass --yes or --dry-run, otherwise the command fails closed (exit 3). Success payloads use status values deleted, dry-run, or declined (all exit 0—branch on status, not exit code alone), and include case-resolved table, database, pvc_paths, and removed_paths (empty arrays as [], not null).

Introduces docs/json-output.md as the cross-command scripting contract (which verbs emit JSON, stdout/stderr split, shared error shape, additive stability promise, and data delete requirements).

Adds data_delete_json_test.go covering success, dry-run, declined confirm, early/late failures, stream separation, and wiring that JSON mode never prompts.

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

…ct (#297)

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>
@LukasWodka
LukasWodka requested a review from saadqbal July 14, 2026 12:35
@LukasWodka

Copy link
Copy Markdown
Contributor Author

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

  • averaging-service#181 — feat(weights): normalize-on-read — mixed cycles average instead of rejecting (SEC-03 §8 step 2) · author: @shujaatTracebloc · no reviewer assigned
  • averaging-service#182 — feat(weights): averaging writes SafeTensors (TF + PyTorch) — SEC-03 §8 step 4 · author: @shujaatTracebloc · no reviewer assigned
  • backend#1079 — feat(global_meta): edge dataset_meta exposure + attributes contract at ingest (#924 G4a) · author: @divyasinghds · no reviewer assigned
  • backend#1086 — docs(rfc): SafeTensors weight-format migration — SEC-03 Phase 1 (RFC 0004) · author: @shujaatTracebloc · no reviewer assigned
  • backend#1093 — chore(deps): bump django from 5.2.14 to 5.2.15 · author: @dependabot · no reviewer assigned
  • backend#1095 — feat(experiment): configurable preprocessing knobs incl. tabular scaler — RFC 0003 L1 + L1b (#1094) · author: @LukasWodka · no reviewer assigned
  • backend#1100 — fix(boot): pin SDK install to tracebloc==0.11.2, drop 404 dev line (#1098) · author: @LukasWodka · reviewer: @saqlainsyed007
  • backend#1105 — perf(api): query micro-fixes — notifications N+1, cached data_scientist, composite index, sampling (#975) · author: @aptracebloc · no reviewer assigned
  • backend#1107 — perf(experiments): prefetch ExperimentListSerializer relations + cache carbon intensity (#977) · author: @aptracebloc · reviewer: @saadqbal
  • backend#1108 — test(api): CLI response-shape contract fixtures for the 9 CLI endpoints (WS-D.2) · author: @LukasWodka · reviewer: @saadqbal

Pull from review before opening new work. (This is a nudge from the kanban WIP check, not a block.)

@LukasWodka LukasWodka self-assigned this Jul 14, 2026
@LukasWodka

Copy link
Copy Markdown
Contributor Author

@BugBot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ 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 3453bb2. Configure here.

@saadqbal saadqbal left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

👍 Careful feature. The stdout-always-JSON contract is the crux and it's right — the deferred error-JSON emit (with the exitError code, guarded by jsonEmitted) covers every failure return, so a scripted delete never gets empty stdout (good that Bugbot #53's gap is closed). JSON mode never prompts, the table field is the case-resolved spelling, and exit codes are unchanged. Solid 233-line test. Clean.

@saadqbal
saadqbal merged commit 300733c into develop Jul 14, 2026
22 checks passed
@saadqbal
saadqbal deleted the feat/297-data-delete-output-json branch July 14, 2026 14:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants