fix: correct wipe backup-skip flow and harden error handling#808
fix: correct wipe backup-skip flow and harden error handling#808
Conversation
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>
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Snapshot WarningsEnsure 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 FilesNone |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (3)
📜 Recent review details🧰 Additional context used📓 Path-based instructions (3)cli/**/*.go📄 CodeRabbit inference engine (CLAUDE.md)
Files:
cli/cmd/**/*.go📄 CodeRabbit inference engine (CLAUDE.md)
Files:
cli/**📄 CodeRabbit inference engine (CLAUDE.md)
Files:
🧠 Learnings (2)📚 Learning: 2026-03-24T08:21:25.712ZApplied to files:
📚 Learning: 2026-03-24T08:21:25.712ZApplied to files:
🧬 Code graph analysis (2)cli/cmd/backup.go (1)
cli/cmd/wipe.go (1)
🪛 GitHub Check: CodeQLcli/cmd/wipe.go[failure] 411-411: Uncontrolled data used in path expression 🔇 Additional comments (13)
WalkthroughThe PR increases the admin backup POST request timeout from 30s to 60s and changes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
Summary of ChangesHello, 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 Highlights
Using Gemini Code AssistThe 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
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 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
|
There was a problem hiding this comment.
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.
| 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 | ||
| } |
There was a problem hiding this comment.
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
}There was a problem hiding this comment.
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
📒 Files selected for processing (2)
cli/cmd/backup.gocli/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.gocli/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.gocli/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.gocli/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 createin 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 inaccessiblecompose.yml.This preserves the existing init hint for
ErrNotExistwhile 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, nilkeeps this branch consistent with an explicit negative response and avoids routing a normal cancellation througherrWipeCancelled.
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 newready/errorsplit 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>
🤖 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->3 and @types/node 22->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>
Summary
ensureRunningForBackupreturned onlyerror, soofferBackupcould 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).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.waitForBackendHealthnow returns an error so an unhealthy backend immediately triggersaskContinueWithoutBackupinstead of proceeding to a doomed 60s backup API call (eliminates ~90s of wasted waiting).checkOverwriteprompt warns before silently overwriting an existing file at the backup save path.checkOverwriteand the compose.yml existence check now distinguishErrNotExistfrom other stat errors (e.g. permission denied) instead of silently proceeding.synthorg backup createtimeout raised from 30s to 60s to matchsynthorg wipebackup timeout.Test plan
go vet ./...passesgo test ./...passesgo build ./...passesgolangci-lint run-- 0 issuessynthorg wipe-> Yes to backup -> No to start containers -> should skip directly to wipe confirmation (no save path prompt)synthorg wipe-> Yes to backup -> containers running but unhealthy -> should prompt to continue without backupsynthorg wipe-> confirm wipe -> Yes to restart -> restart fails -> should show "Factory reset complete" with manual-start hintPre-reviewed by 5 agents (docs-consistency, go-reviewer, go-security-reviewer, go-conventions-enforcer, silent-failure-hunter), 4 findings addressed.
🤖 Generated with Claude Code