Skip to content

fix: correct wipe backup-skip flow and harden error handling#808

Merged
Aureliolo merged 4 commits intomainfrom
fix/fix-backup-skip-flow-cli
Mar 24, 2026
Merged

fix: correct wipe backup-skip flow and harden error handling#808
Aureliolo merged 4 commits intomainfrom
fix/fix-backup-skip-flow-cli

Conversation

@Aureliolo
Copy link
Copy Markdown
Owner

Summary

  • Fix backup-skip flow bug: ensureRunningForBackup returned only error, so offerBackup could not distinguish "containers ready" from "user chose to skip backup". After skipping, the CLI still asked for a save path and attempted a doomed backup API call. Changed to return (bool, error).
  • Graceful post-wipe restart failure: If startContainers() fails after the wipe (data already gone), the CLI now warns and shows a manual-start hint instead of returning a hard error that hides the "Factory reset complete" message.
  • Short-circuit unhealthy backend: waitForBackendHealth now returns an error so an unhealthy backend immediately triggers askContinueWithoutBackup instead of proceeding to a doomed 60s backup API call (eliminates ~90s of wasted waiting).
  • Overwrite protection: New checkOverwrite prompt warns before silently overwriting an existing file at the backup save path.
  • Stat error hardening: checkOverwrite and the compose.yml existence check now distinguish ErrNotExist from other stat errors (e.g. permission denied) instead of silently proceeding.
  • Timeout alignment: synthorg backup create timeout raised from 30s to 60s to match synthorg wipe backup timeout.

Test plan

  • go vet ./... passes
  • go test ./... passes
  • go build ./... passes
  • golangci-lint run -- 0 issues
  • Manual: synthorg wipe -> Yes to backup -> No to start containers -> should skip directly to wipe confirmation (no save path prompt)
  • Manual: synthorg wipe -> Yes to backup -> containers running but unhealthy -> should prompt to continue without backup
  • Manual: synthorg wipe -> confirm wipe -> Yes to restart -> restart fails -> should show "Factory reset complete" with manual-start hint

Pre-reviewed by 5 agents (docs-consistency, go-reviewer, go-security-reviewer, go-conventions-enforcer, silent-failure-hunter), 4 findings addressed.

🤖 Generated with Claude Code

Aureliolo and others added 2 commits March 24, 2026 10:38
The backup-skip flow in `synthorg wipe` had a logic error: when the user
chose to skip backup (via askContinueWithoutBackup), ensureRunningForBackup
returned nil which offerBackup interpreted as "containers ready, proceed
with backup". This caused the CLI to ask for a save path and attempt a
doomed backup API call even after the user explicitly chose to skip.

Fix by changing ensureRunningForBackup to return (bool, error) so the
caller can distinguish "ready for backup" from "user chose to skip".

Additional fixes in the same area:
- Post-wipe restart failure is now graceful instead of a hard error. The
  wipe is already done so startContainers failure should warn and fall
  through to the success message with a manual-start hint.
- waitForBackendHealth now returns an error so unhealthy backend
  short-circuits to askContinueWithoutBackup instead of proceeding to a
  doomed 60s API call (eliminates ~90s of wasted waiting).
- Add overwrite check when save path already exists.
- Align backup create API timeout (30s -> 60s) with wipe backup timeout.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Address review findings from 5 agents:

- checkOverwrite: distinguish ErrNotExist from other stat errors (e.g.
  permission denied) instead of silently proceeding. Surfaces actionable
  error early rather than failing later with a confusing copy error.
- runWipe compose.yml check: handle non-ErrNotExist stat errors explicitly
  instead of falling through to cryptic Docker errors.
- confirmWipe: add comment explaining Ctrl-C semantics (matches existing
  comment on promptStartAfterWipe).
- checkOverwrite: document TOCTOU race acknowledgement (acceptable for
  local CLI, would require restructuring both write paths to resolve).

Pre-reviewed by 5 agents, 4 findings addressed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 24, 2026

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Snapshot Warnings

⚠️: No snapshots were found for the head SHA 876565e.
Ensure that dependencies are being submitted on PR branches and consider enabling retry-on-snapshot-warnings. See the documentation for more information and troubleshooting advice.

Scanned Files

None

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 24, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ecd018a7-ff45-443e-a36c-f8196ff8b2c3

📥 Commits

Reviewing files that changed from the base of the PR and between 928b36d and 828a933.

📒 Files selected for processing (3)
  • cli/cmd/backup.go
  • cli/cmd/wipe.go
  • cli/cmd/wipe_test.go
📜 Recent review details
🧰 Additional context used
📓 Path-based instructions (3)
cli/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

cli/**/*.go: CLI (Go): Go 1.26+, cross-platform binary with Cobra commands, use go -C cli (not cd cli) for tooling commands
Go tooling: golangci-lint as tool in go.mod (run via go -C cli tool golangci-lint), govulncheck, go vet, go test (with fuzz support via -fuzz flag)

Files:

  • cli/cmd/backup.go
  • cli/cmd/wipe_test.go
  • cli/cmd/wipe.go
cli/cmd/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

CLI commands: init, start, stop, status, logs, doctor, update, cleanup, wipe, config, etc.

Files:

  • cli/cmd/backup.go
  • cli/cmd/wipe_test.go
  • cli/cmd/wipe.go
cli/**

📄 CodeRabbit inference engine (CLAUDE.md)

CLI dependencies: Go 1.26+, Cobra, charmbracelet/huh, charmbracelet/lipgloss, sigstore-go, go-containerregistry, go-tuf

Files:

  • cli/cmd/backup.go
  • cli/cmd/wipe_test.go
  • cli/cmd/wipe.go
🧠 Learnings (2)
📚 Learning: 2026-03-24T08:21:25.712Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-24T08:21:25.712Z
Learning: Applies to cli/internal/**/*.go : CLI internal modules: version, config, docker, compose, health, diagnostics, images, selfupdate, completion, ui, verify

Applied to files:

  • cli/cmd/wipe.go
📚 Learning: 2026-03-24T08:21:25.712Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-24T08:21:25.712Z
Learning: Applies to cli/cmd/**/*.go : CLI commands: init, start, stop, status, logs, doctor, update, cleanup, wipe, config, etc.

Applied to files:

  • cli/cmd/wipe.go
🧬 Code graph analysis (2)
cli/cmd/backup.go (1)
cli/internal/docker/client.go (1)
  • Detect (34-66)
cli/cmd/wipe.go (1)
cli/internal/health/check.go (1)
  • WaitForHealthy (22-52)
🪛 GitHub Check: CodeQL
cli/cmd/wipe.go

[failure] 411-411: Uncontrolled data used in path expression
This path depends on a user-provided value.

🔇 Additional comments (13)
cli/cmd/backup.go (2)

312-313: LGTM!

Timeout increase from 30s to 60s is appropriate for large datasets and aligns with the wipe backup timeout as noted in the PR objectives.


486-518: LGTM!

Returning errors on post-restore restart failures improves observability for scripts and CI pipelines. The error messages correctly indicate partial completion ("restore succeeded but post-restore restart failed"), and the manual recovery hints are shown before the error is returned.

cli/cmd/wipe_test.go (1)

16-48: LGTM!

Test updates correctly match the isEmptyPS signature change. The new "malformed JSON array" case verifies that parse errors are properly surfaced, and the assertion order (error check before boolean) prevents false negatives.

cli/cmd/wipe.go (10)

84-89: LGTM!

Good hardening—distinguishing os.ErrNotExist from other stat errors (e.g., permission denied) prevents the CLI from silently proceeding when it cannot actually access the compose file.


144-167: LGTM!

Good UX decision to downgrade restart failures to warnings after a successful wipe. The user sees a qualified success message and gets a manual-start hint rather than an error that might obscure the fact that the wipe itself completed.


192-200: LGTM!

Correct handling—returning (false, nil) for Ctrl-C at the final confirmation is equivalent to choosing "Cancel" since the wipe hasn't executed yet. The caller's !confirmed branch already shows the appropriate hint.


206-216: LGTM!

Correctly propagates parsing errors from the updated isEmptyPS signature.


229-235: LGTM!

Returning the error from health.WaitForHealthy allows callers to short-circuit on an unhealthy backend rather than waiting and attempting a doomed backup call.


270-318: LGTM!

The refactored ensureRunningForBackup correctly distinguishes "ready for backup" from "user chose to skip" using the (bool, error) return. The askToSkip helper reduces duplication, and importantly, Line 313 ensures waitForBackendHealth is called after startContainers before attempting the backup.


405-441: Residual static analysis warning acknowledged.

The CodeQL warning about "uncontrolled data used in path expression" on Line 411 is expected for user-provided save paths in a CLI tool. The mitigations are in place:

  • Path is cleaned via filepath.Clean() and made absolute via filepath.Abs() in promptSavePath() before reaching checkOverwrite()
  • os.Stat() is a read-only operation
  • IsDir() check rejects directories (per prior review)
  • TOCTOU race is acknowledged in the comment; resolving it would require restructuring both write paths (tarDirectory and docker compose cp)

The risk is appropriately documented and acceptable for a local CLI tool.


443-466: LGTM!

Good UX improvement—distinguishing "Backup creation failed" from "Backup was created but could not be copied locally" gives users actionable context. The hint about the backup existing in the container (but being destroyed by wipe) sets appropriate expectations.


503-516: LGTM!

Capturing and logging the first error before attempting the fallback improves diagnostics. Users can now understand why the compressed archive wasn't available when reviewing stderr output.


611-629: LGTM!

Good hardening—isEmptyPS now surfaces JSON parsing failures as errors rather than silently treating malformed output as "not empty". This prevents masking underlying issues with Docker Compose output.


Walkthrough

The PR increases the admin backup POST request timeout from 30s to 60s and changes handleRestartAfterRestore to return an error when post-restore restart steps fail (still returning nil if the compose file is missing). The wipe flow was reworked: interactive prompts reordered and extended for save-path overwrite, compose.yml preflight distinguishes missing vs other errors, restart-after-wipe failures are downgraded to warnings (containers may not be restarted), Ctrl‑C during final confirmation returns (false, nil), waitForBackendHealth() now returns error, ensureRunningForBackup returns (ready bool, err error), checkOverwrite(savePath) added, copyBackupFromContainer and isEmptyPS made more robust (now returns (bool, error)) and tests updated accordingly.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main changes: fixing the backup-skip flow bug and improving error handling throughout the wipe functionality.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, detailing specific fixes and improvements made across the affected files.
Docstring Coverage ✅ Passed Docstring coverage is 71.43% which is sufficient. The required threshold is 40.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the robustness and user experience of the wipe command, particularly around backup and container restart processes. It addresses several edge cases and error conditions, ensuring that the CLI behaves more predictably and gracefully. The changes prevent scenarios where users might be prompted for unnecessary information, wait for operations that are destined to fail, or accidentally overwrite existing files, leading to a more reliable and user-friendly factory reset workflow.

Highlights

  • Backup-skip flow bug fix: The ensureRunningForBackup function now returns a boolean indicating if containers are ready for backup, allowing offerBackup to distinguish between 'containers ready' and 'user chose to skip backup', preventing incorrect prompts for save paths after skipping.
  • Graceful post-wipe restart failure: If startContainers() fails after a wipe, the CLI now issues a warning and provides a manual-start hint instead of a hard error, ensuring the 'Factory reset complete' message is still displayed.
  • Short-circuit unhealthy backend: The waitForBackendHealth function now returns an error if the backend is unhealthy, immediately triggering askContinueWithoutBackup and avoiding a prolonged wait for a doomed backup API call.
  • Overwrite protection: A new checkOverwrite prompt has been added to warn users before silently overwriting an existing file at the specified backup save path.
  • Stat error hardening: Error handling for checkOverwrite and the compose.yml existence check now explicitly distinguishes os.ErrNotExist from other file system errors (e.g., permission denied), providing more precise feedback.
  • Timeout alignment: The synthorg backup create timeout has been increased from 30 seconds to 60 seconds to match the synthorg wipe backup timeout, ensuring consistency.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces several valuable fixes and hardening improvements to the wipe command, particularly around the backup flow. The changes correctly address a bug in the backup-skip logic, make error handling more robust for container restarts and file system access, and align API timeouts. The overall logic is sound and enhances the command's reliability and user experience. I have one suggestion to refactor a function to improve its maintainability by reducing code repetition.

Comment on lines +263 to 310
func (wc *wipeContext) ensureRunningForBackup() (bool, error) {
running, err := wc.containersRunning()
if err != nil {
wc.errOut.Warn(fmt.Sprintf("Could not check container status: %v", err))
return wc.askContinueWithoutBackup(
if err := wc.askContinueWithoutBackup(
"Could not check container status. Continue with wipe anyway?",
)
); err != nil {
return false, err
}
return false, nil
}
if running {
wc.waitForBackendHealth()
return nil
if err := wc.waitForBackendHealth(); err != nil {
wc.errOut.Warn(fmt.Sprintf("Backend not healthy: %v", err))
if err := wc.askContinueWithoutBackup(
"Backend is not healthy. Continue with wipe anyway?",
); err != nil {
return false, err
}
return false, nil
}
return true, nil
}

startOK, err := wc.promptStartForBackup()
if err != nil {
return err
return false, err
}
if !startOK {
return wc.askContinueWithoutBackup(
if err := wc.askContinueWithoutBackup(
"Backup requires running containers. Continue with wipe anyway?",
)
); err != nil {
return false, err
}
return false, nil
}

if err := wc.startContainers(); err != nil {
wc.errOut.Warn(fmt.Sprintf("Could not start containers for backup: %v", err))
return wc.askContinueWithoutBackup(
if err := wc.askContinueWithoutBackup(
"Could not start containers for backup. Continue with wipe anyway?",
)
); err != nil {
return false, err
}
return false, nil
}
return nil
return true, nil
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The logic within this function for handling various failure scenarios is quite repetitive. Each check that can fail is followed by a similar block of code to warn the user and then call askContinueWithoutBackup. This repetition makes the function longer than necessary and harder to maintain.

To improve readability and reduce the duplicated code, you could define a small, local helper function (a closure) at the beginning of ensureRunningForBackup. This helper would encapsulate the repeated logic of prompting the user and returning the appropriate values, making the main control flow of the function much cleaner and easier to follow.

// ensureRunningForBackup checks whether containers are running. If not,
// it prompts the user before starting them. If the user declines, it
// falls through to askContinueWithoutBackup (backup cannot proceed
// without running containers). Returns true when the backend is ready
// for a backup, or false when the user chose to skip the backup.
func (wc *wipeContext) ensureRunningForBackup() (bool, error) {
	// askToSkip is a local helper to handle the repetitive flow of asking the
	// user to continue the wipe without a backup.
	askToSkip := func(prompt string) (bool, error) {
		if err := wc.askContinueWithoutBackup(prompt); err != nil {
			return false, err // User cancelled wipe.
		}
		return false, nil // User agreed to skip backup.
	}

	running, err := wc.containersRunning()
	if err != nil {
		wc.errOut.Warn(fmt.Sprintf("Could not check container status: %v", err))
		return askToSkip("Could not check container status. Continue with wipe anyway?")
	}

	if running {
		if err := wc.waitForBackendHealth(); err != nil {
			wc.errOut.Warn(fmt.Sprintf("Backend not healthy: %v", err))
			return askToSkip("Backend is not healthy. Continue with wipe anyway?")
		}
		return true, nil
	}

	startOK, err := wc.promptStartForBackup()
	if err != nil {
		return false, err
	}
	if !startOK {
		return askToSkip("Backup requires running containers. Continue with wipe anyway?")
	}

	if err := wc.startContainers(); err != nil {
		wc.errOut.Warn(fmt.Sprintf("Could not start containers for backup: %v", err))
		return askToSkip("Could not start containers for backup. Continue with wipe anyway?")
	}

	return true, nil
}

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@cli/cmd/wipe.go`:
- Around line 400-427: checkOverwrite currently treats an existing directory as
an overwritable file; update checkOverwrite to detect when the existing path is
a directory (use the os.Stat result's IsDir()) and immediately return a clear
error (wrapped) indicating the save path is a directory so the flow aborts
before copyBackupFromContainer/tarDirectory calls os.OpenFile on a directory.
Locate checkOverwrite in wipeContext, check the FileInfo.IsDir() after the
successful os.Stat, and return a descriptive error (do not prompt) so callers
like copyBackupFromContainer and tarDirectory fail fast.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d5cc2678-384d-463e-a9a3-70bab9a540c8

📥 Commits

Reviewing files that changed from the base of the PR and between a908800 and 928b36d.

📒 Files selected for processing (2)
  • cli/cmd/backup.go
  • cli/cmd/wipe.go
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: CLI Test (windows-latest)
  • GitHub Check: CLI Test (macos-latest)
  • GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (3)
cli/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

cli/**/*.go: CLI (Go): Go 1.26+, cross-platform binary with Cobra commands, use go -C cli (not cd cli) for tooling commands
Go tooling: golangci-lint as tool in go.mod (run via go -C cli tool golangci-lint), govulncheck, go vet, go test (with fuzz support via -fuzz flag)

Files:

  • cli/cmd/backup.go
  • cli/cmd/wipe.go
cli/cmd/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

CLI commands: init, start, stop, status, logs, doctor, update, cleanup, wipe, config, etc.

Files:

  • cli/cmd/backup.go
  • cli/cmd/wipe.go
cli/**

📄 CodeRabbit inference engine (CLAUDE.md)

CLI dependencies: Go 1.26+, Cobra, charmbracelet/huh, charmbracelet/lipgloss, sigstore-go, go-containerregistry, go-tuf

Files:

  • cli/cmd/backup.go
  • cli/cmd/wipe.go
🧠 Learnings (2)
📚 Learning: 2026-03-24T08:21:25.712Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-24T08:21:25.712Z
Learning: Applies to cli/internal/**/*.go : CLI internal modules: version, config, docker, compose, health, diagnostics, images, selfupdate, completion, ui, verify

Applied to files:

  • cli/cmd/wipe.go
📚 Learning: 2026-03-24T08:21:25.712Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-24T08:21:25.712Z
Learning: Applies to cli/cmd/**/*.go : CLI commands: init, start, stop, status, logs, doctor, update, cleanup, wipe, config, etc.

Applied to files:

  • cli/cmd/wipe.go
🧬 Code graph analysis (1)
cli/cmd/wipe.go (1)
cli/internal/health/check.go (1)
  • WaitForHealthy (22-52)
🪛 GitHub Check: CodeQL
cli/cmd/wipe.go

[failure] 83-83: Uncontrolled data used in path expression
This path depends on a user-provided value.
This path depends on a user-provided value.
This path depends on a user-provided value.
This path depends on a user-provided value.


[failure] 401-401: Uncontrolled data used in path expression
This path depends on a user-provided value.

🔇 Additional comments (7)
cli/cmd/backup.go (1)

312-312: Timeout alignment looks good.

This keeps manual backup create in sync with the longer-running wipe-triggered backup path and avoids putting a shorter deadline on the same backend operation.

cli/cmd/wipe.go (6)

83-87: Good distinction between missing and inaccessible compose.yml.

This preserves the existing init hint for ErrNotExist while surfacing permission or I/O failures instead of silently treating them as “missing”.


144-145: Making post-wipe restart failures non-fatal is the right trade-off.

The destructive part has already completed here, so downgrading restart failures to a warning keeps the success message and manual recovery path visible.


187-190: Treating pre-wipe Ctrl-C as “Cancel” is correct.

Returning false, nil keeps this branch consistent with an explicit negative response and avoids routing a normal cancellation through errWipeCancelled.


219-223: Returning the backend-health error makes the caller contract much clearer.

ensureRunningForBackup() can now distinguish “backend ready” from “prompt to continue without a backup” instead of relying on side effects.


238-244: The new ready/error split fixes the backup-skip flow cleanly.

Once the user has chosen to continue without a backup, the command no longer falls through into save-path prompting or a doomed backup call.

Also applies to: 263-309


251-253: Checking overwrite before creating the backup is the right order.

This avoids spending backup time against a destination the user may immediately reject.

…iewers

- Fix missing waitForBackendHealth after startContainers (regression)
- Add IsDir() check in checkOverwrite to reject directory paths
- Qualify success message when restart fails ("containers not restarted")
- handleRestartAfterRestore returns error on failure (non-zero exit)
- Distinct messages for backup API failure vs copy failure
- Log first copy error in copyBackupFromContainer before fallback
- isEmptyPS returns (bool, error) instead of silently treating parse
  errors as "containers exist"
- Warn when home directory lookup fails and temp dir is used
- Refactor ensureRunningForBackup with askToSkip closure
- Show full path (not just basename) in overwrite prompt
- Update doc comments: offerBackup, confirmAndWipe, waitForBackendHealth
- Update Long help text to include overwrite step (6 steps, not 5)
- Add timeout comment on backup create API call

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Aureliolo Aureliolo merged commit c05860f into main Mar 24, 2026
36 checks passed
@Aureliolo Aureliolo deleted the fix/fix-backup-skip-flow-cli branch March 24, 2026 10:36
Aureliolo added a commit that referenced this pull request Mar 30, 2026
🤖 I have created a release *beep* *boop*
---
#MAJOR CHANGES; We got a somewhat working webui :)

##
[0.5.0](v0.4.9...v0.5.0)
(2026-03-30)


### Features

* add analytics trends and budget forecast API endpoints
([#798](#798))
([16b61f5](16b61f5))
* add department policies to default templates
([#852](#852))
([7a41548](7a41548))
* add remaining activity event types (task_started, tool_used,
delegation, cost_incurred)
([#832](#832))
([4252fac](4252fac))
* agent performance, activity, and history API endpoints
([#811](#811))
([9b75c1d](9b75c1d))
* Agent Profiles and Detail pages (biography, career, performance)
([#874](#874))
([62d7880](62d7880))
* app shell, Storybook, and CI/CD pipeline
([#819](#819))
([d4dde90](d4dde90))
* Approvals page with risk grouping, urgency indicators, batch actions
([#889](#889))
([4e9673d](4e9673d))
* Budget Panel page (P&L dashboard, breakdown charts, forecast)
([#890](#890))
([b63b0f1](b63b0f1))
* build infrastructure layer (API client, auth, WebSocket)
([#815](#815))
([9f01d3e](9f01d3e))
* CLI global options infrastructure, UI modes, exit codes, env vars
([#891](#891))
([fef4fc5](fef4fc5))
* CodeMirror editor and theme preferences toggle
([#905](#905),
[#807](#807))
([#909](#909))
([41fbedc](41fbedc))
* Company page (department/agent management)
([#888](#888))
([cfb88b0](cfb88b0))
* comprehensive hint coverage across all CLI commands
([#900](#900))
([937974e](937974e))
* config system extensions, per-command flags for
init/start/stop/status/logs
([#895](#895))
([32f83fe](32f83fe))
* configurable currency system replacing hardcoded USD
([#854](#854))
([b372551](b372551))
* Dashboard page (metric cards, activity feed, budget burn)
([#861](#861))
([7d519d5](7d519d5))
* department health, provider status, and activity feed endpoints
([#818](#818))
([6d5f196](6d5f196))
* design tokens and core UI components
([#833](#833))
([ed887f2](ed887f2))
* extend approval, meeting, and budget API responses
([#834](#834))
([31472bf](31472bf))
* frontend polish -- real-time UX, accessibility, responsive,
performance ([#790](#790),
[#792](#792),
[#791](#791),
[#793](#793))
([#917](#917))
([f04a537](f04a537))
* implement human roles and access control levels
([#856](#856))
([d6d8a06](d6d8a06))
* implement semantic conflict detection in workspace merge
([#860](#860))
([d97283b](d97283b))
* interaction components and animation patterns
([#853](#853))
([82d4b01](82d4b01))
* Login page + first-run bootstrap + Company page
([#789](#789),
[#888](#888))
([#896](#896))
([8758e8d](8758e8d))
* Meetings page with timeline viz, token bars, contribution formatting
([#788](#788))
([#904](#904))
([b207f46](b207f46))
* Messages page with threading, channel badges, sender indicators
([#787](#787))
([#903](#903))
([28293ad](28293ad))
* Org Chart force-directed view and drag-drop reassignment
([#872](#872),
[#873](#873))
([#912](#912))
([a68a938](a68a938))
* Org Chart page (living nodes, status, CRUD, department health)
([#870](#870))
([0acbdae](0acbdae))
* per-command flags for remaining commands, auto-behavior wiring,
help/discoverability
([#897](#897))
([3f7afa2](3f7afa2))
* Providers page with backend rework -- health, CRUD, subscription auth
([#893](#893))
([9f8dd98](9f8dd98))
* scaffold React + Vite + TypeScript + Tailwind project
([#799](#799))
([bd151aa](bd151aa))
* Settings page with search, dependency indicators, grouped rendering
([#784](#784))
([#902](#902))
([a7b9870](a7b9870))
* Setup Wizard rebuild with template comparison, cost estimator, theme
customization ([#879](#879))
([ae8b50b](ae8b50b))
* setup wizard UX -- template filters, card metadata, provider form
reuse ([#910](#910))
([7f04676](7f04676))
* setup wizard UX overhaul -- mode choice, step reorder, provider fixes
([#907](#907))
([ee964c4](ee964c4))
* structured ModelRequirement in template agent configs
([#795](#795))
([7433548](7433548))
* Task Board page (rich Kanban, filtering, dependency viz)
([#871](#871))
([04a19b0](04a19b0))


### Bug Fixes

* align frontend types with backend and debounce WS refetches
([#916](#916))
([134c11b](134c11b))
* auto-cleanup targets newly pulled images instead of old ones
([#884](#884))
([50e6591](50e6591))
* correct wipe backup-skip flow and harden error handling
([#808](#808))
([c05860f](c05860f))
* improve provider setup in wizard, subscription auth, dashboard bugs
([#914](#914))
([87bf8e6](87bf8e6))
* improve update channel detection and add config get command
([#814](#814))
([6b137f0](6b137f0))
* resolve all ESLint warnings, add zero-warnings enforcement
([#899](#899))
([079b46a](079b46a))
* subscription auth uses api_key, base URL optional for cloud providers
([#915](#915))
([f0098dd](f0098dd))


### Refactoring

* semantic analyzer cleanup -- shared filtering, concurrency, extraction
([#908](#908))
([81372bf](81372bf))


### Documentation

* brand identity and UX design system from
[#765](#765) exploration
([#804](#804))
([389a9f4](389a9f4))
* page structure and information architecture for v0.5.0 dashboard
([#809](#809))
([f8d6d4a](f8d6d4a))
* write UX design guidelines with WCAG-verified color system
([#816](#816))
([4a4594e](4a4594e))


### Tests

* add unit tests for agent hooks and page components
([#875](#875))
([#901](#901))
([1d81546](1d81546))


### CI/CD

* bump actions/deploy-pages from 4.0.5 to 5.0.0 in the major group
([#831](#831))
([01c19de](01c19de))
* bump astral-sh/setup-uv from 7.6.0 to 8.0.0 in
/.github/actions/setup-python-uv in the all group
([#920](#920))
([5f6ba54](5f6ba54))
* bump codecov/codecov-action from 5.5.3 to 6.0.0 in the major group
([#868](#868))
([f22a181](f22a181))
* bump github/codeql-action from 4.34.1 to 4.35.0 in the all group
([#883](#883))
([87a4890](87a4890))
* bump sigstore/cosign-installer from 4.1.0 to 4.1.1 in the
minor-and-patch group
([#830](#830))
([7a69050](7a69050))
* bump the all group with 3 updates
([#923](#923))
([ff27c8e](ff27c8e))
* bump wrangler from 4.76.0 to 4.77.0 in /.github in the minor-and-patch
group ([#822](#822))
([07d43eb](07d43eb))
* bump wrangler from 4.77.0 to 4.78.0 in /.github in the all group
([#882](#882))
([f84118d](f84118d))


### Maintenance

* add design system enforcement hook and component inventory
([#846](#846))
([15abc43](15abc43))
* add dev-only auth bypass for frontend testing
([#885](#885))
([6cdcd8a](6cdcd8a))
* add pre-push rebase check hook
([#855](#855))
([b637a04](b637a04))
* backend hardening -- eviction/size-caps and model validation
([#911](#911))
([81253d9](81253d9))
* bump axios from 1.13.6 to 1.14.0 in /web in the all group across 1
directory ([#922](#922))
([b1b0232](b1b0232))
* bump brace-expansion from 5.0.4 to 5.0.5 in /web
([#862](#862))
([ba4a565](ba4a565))
* bump eslint-plugin-react-refresh from 0.4.26 to 0.5.2 in /web
([#801](#801))
([7574bb5](7574bb5))
* bump faker from 40.11.0 to 40.11.1 in the minor-and-patch group
([#803](#803))
([14d322e](14d322e))
* bump https://github.com/astral-sh/ruff-pre-commit from v0.15.7 to
0.15.8 ([#864](#864))
([f52901e](f52901e))
* bump nginxinc/nginx-unprivileged from `6582a34` to `f99cc61` in
/docker/web in the all group
([#919](#919))
([df85e4f](df85e4f))
* bump nginxinc/nginx-unprivileged from `ccbac1a` to `6582a34` in
/docker/web ([#800](#800))
([f4e9450](f4e9450))
* bump node from `44bcbf4` to `71be405` in /docker/sandbox
([#827](#827))
([91bec67](91bec67))
* bump node from `5209bca` to `cf38e1f` in /docker/web
([#863](#863))
([66d6043](66d6043))
* bump picomatch in /site
([#842](#842))
([5f20bcc](5f20bcc))
* bump recharts 2-&gt;3 and @types/node 22-&gt;25 in /web
([#802](#802))
([a908800](a908800))
* Bump requests from 2.32.5 to 2.33.0
([#843](#843))
([41daf69](41daf69))
* bump smol-toml from 1.6.0 to 1.6.1 in /site
([#826](#826))
([3e5dbe4](3e5dbe4))
* bump the all group with 3 updates
([#921](#921))
([7bace0b](7bace0b))
* bump the minor-and-patch group across 1 directory with 2 updates
([#829](#829))
([93e611f](93e611f))
* bump the minor-and-patch group across 1 directory with 3 updates
([#841](#841))
([7010c8e](7010c8e))
* bump the minor-and-patch group across 1 directory with 3 updates
([#869](#869))
([548cee5](548cee5))
* bump the minor-and-patch group in /site with 2 updates
([#865](#865))
([9558101](9558101))
* bump the minor-and-patch group with 2 updates
([#867](#867))
([4830706](4830706))
* consolidate Dependabot groups to 1 PR per ecosystem
([06d2556](06d2556))
* consolidate Dependabot groups to 1 PR per ecosystem
([#881](#881))
([06d2556](06d2556))
* improve worktree skill with full dep sync and status enhancements
([#906](#906))
([772c625](772c625))
* remove Vue remnants and document framework decision
([#851](#851))
([bf2adf6](bf2adf6))
* update web dependencies and fix brace-expansion CVE
([#880](#880))
([a7a0ed6](a7a0ed6))
* upgrade to Storybook 10 and TypeScript 6
([#845](#845))
([52d95f2](52d95f2))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
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