fix(backup): name the per-dir failure cause in backup failure messages - #6631
Conversation
backup-all and snapshot create collapsed every per-dir backup failure into an opaque list: 'backup failed (identity, devices, credentials)'. A permission problem (tar cannot read content the backup user does not own) and a directory that never materialized from a clean extraction are different operator problems, but the message could not tell them apart. backupSandboxState now records a per-dir cause alongside failedDirs: - 'permission denied' tar reported Permission denied for the dir - 'tar read error' tar reported other read errors for the dir - 'absent after extraction' tar succeeded but the dir never materialized and the backup-all / snapshot create failure messages render it: 'backup failed (identity (permission denied), ...)'. Dirs without an attributable cause render unchanged, and failedDirs keeps its shape for existing consumers. Verified live against a snapshot-restored clone with root-owned state dirs (the NVIDIA#6455 construction): the failure line names the cause, and restoring ownership returns backup-all to exit 0. Fixes NVIDIA#6455 Signed-off-by: Hokonoken <41166525+Hokonoken@users.noreply.github.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: 📒 Files selected for processing (6)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughBackup failures now retain per-directory causes, including permission errors, tar read errors, and missing directories after extraction. Backup-all and snapshot creation format these causes in failure messages, with tests covering annotated and unannotated output. ChangesBackup failure reporting
Estimated code review effort: 3 (Moderate) | ~20 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/lib/state/sandbox.ts (1)
774-786: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider placing
formatFailedBackupItemsin a domain module rather than the state layer.This is a pure, I/O-free decision/formatting function shared by two action files (
maintenance.ts,snapshot.ts), but it lives insrc/lib/state/sandbox.ts. As per path instructions,src/lib/{actions,domain,adapters,state}/**should be reviewed against layer ownership where "domain modules make pure decisions" while "state modules own persisted files and state I/O." Moving this helper to a domain module (keepingBackupResult/failedDirReasonstypes in state) would better align with that boundary; not blocking given the pragmatic co-location withBackupResult.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/lib/state/sandbox.ts` around lines 774 - 786, The pure formatting helper formatFailedBackupItems is placed in the state layer despite having no state or I/O responsibilities. Move it to an appropriate domain module, update maintenance.ts and snapshot.ts imports to use the new location, and leave BackupResult and failedDirReasons state types in sandbox.ts.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/lib/state/sandbox.ts`:
- Around line 774-786: The pure formatting helper formatFailedBackupItems is
placed in the state layer despite having no state or I/O responsibilities. Move
it to an appropriate domain module, update maintenance.ts and snapshot.ts
imports to use the new location, and leave BackupResult and failedDirReasons
state types in sandbox.ts.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 1ede3c3b-158e-414f-bc79-16ad4766d48e
📒 Files selected for processing (5)
src/lib/actions/maintenance.test.tssrc/lib/actions/maintenance.tssrc/lib/actions/sandbox/snapshot.tssrc/lib/state/sandbox.tstest/snapshot.test.ts
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
E2E Advisor RecommendationRequired E2E: Dispatch hint: Full advisor summaryE2E Recommendation AdvisorBase: Required E2E
Optional E2E
New E2E recommendations
Dispatch hint
|
E2E Target RecommendationRequired E2E targets: Dispatch required E2E targets:
Full E2E target advisor summaryE2E Target AdvisorBase: Required E2E targets
Optional E2E targets
Relevant changed files
|
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
|
Maintainer follow-up at exact head d5f91e7:
No merge action taken. |
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
<!-- markdownlint-disable MD041 --> ## Summary Release-prep documentation for v0.0.81 now summarizes user-facing changes merged since v0.0.80. It also closes the Hermes dashboard-profile backup gap and distinguishes direct blueprint-runner actions from public host CLI commands. ## Changes - Add the `v0.0.81` section to `docs/about/release-notes.mdx` with links to the detailed user guides. - Document that Hermes rebuilds preserve `.hermes/dashboard-home/`, including Dashboard `MEMORY.md` and `USER.md`. - Update Hermes manual backup and restore examples to transfer those two profile files without copying generated configuration or the secret-bearing dashboard `.env`. - Explain the new per-item backup failure causes. - Clarify that migration snapshot retention fragments are direct-runner arguments and are not exposed by the host `nemoclaw` CLI. ### Source summary - #6445 -> `docs/about/release-notes.mdx`, `docs/manage-sandboxes/backup-restore.mdx`, and `docs/manage-sandboxes/workspace-files.mdx`: Summarize manifest-owned key-level restore and current-config authority. - #6617 -> `docs/about/release-notes.mdx` and `docs/manage-sandboxes/backup-restore.mdx`: Record the fail-closed `/proc` fallback used to verify an idle Deep Agents runtime before snapshot creation. - #6685 -> `docs/about/release-notes.mdx`, `docs/manage-sandboxes/backup-restore.mdx`, and `docs/manage-sandboxes/workspace-files.mdx`: Document Hermes Web Dashboard profile persistence and safe manual transfer. - #6649 -> `docs/about/release-notes.mdx`: Summarize host-validated loopback compatible-endpoint routing through the sandbox gateway. - #6643 -> `docs/about/release-notes.mdx`: Summarize automatic `max_completion_tokens` handling for GPT-5 and o-series models. - #6661 -> `docs/about/release-notes.mdx`: Summarize bounded connection reuse for eligible provider-validation probes. - #6704 -> `docs/about/release-notes.mdx`: Record that direct blueprint apply stops instead of persisting incomplete state after provider or inference setup fails. - #6677 -> `docs/about/release-notes.mdx`: Summarize transactional recovery for legacy Docker containers whose managed supervisor disappeared after restart. - #6625 -> `docs/about/release-notes.mdx`: Record Hermes managed-startup persistence across direct Docker restarts. - #6597 -> `docs/about/release-notes.mdx`: Record final-sandbox gateway cleanup on macOS. - #6680 -> `docs/about/release-notes.mdx`: Summarize managed Deep Agents first-run and process-tree cleanup improvements. - #6647 -> `docs/about/release-notes.mdx`: Record fail-closed validation for the managed Deep Agents fetch CA bundle. - #6645 -> `docs/about/release-notes.mdx`: Summarize WhatsApp loopback pairing and trusted npm plugin provenance. - #6673 -> `docs/about/release-notes.mdx` and `docs/manage-sandboxes/backup-restore.mdx`: Document stopped-sandbox backup remediation. - #6631 -> `docs/about/release-notes.mdx` and `docs/manage-sandboxes/backup-restore.mdx`: Document per-item backup failure causes. - #6620 -> `docs/about/release-notes.mdx`: Record the created-but-not-ready sandbox lifecycle receipt. - #6664 -> `docs/about/release-notes.mdx`: Record prompt-aware onboarding progress output. - #6598 -> `docs/about/release-notes.mdx`: Summarize stale replay-result invalidation during resumed onboarding. - #6593 -> `docs/about/release-notes.mdx`: Summarize contextual OpenClaw audit findings for managed dashboard compatibility settings. - #6650 -> `docs/about/release-notes.mdx`: Record redaction of token-shaped URL query values. - #6638 -> `docs/about/release-notes.mdx`: Record the exact-path MCP `DELETE` policy recipe for session termination. - #5453 -> `docs/reference/host-files-and-state.mdx`: Clarify that snapshot retention actions belong to direct runner integrations and are not standalone host CLI commands. ### Skipped from docs-skip - #6633 matched the `openclaw-sandbox-permissive.yaml` path in `docs/.docs-skip` and produced no documentation in this update. ## Type of Change - [ ] Code change (feature, bug fix, or refactor) - [ ] Code change with doc updates - [ ] Doc only (prose changes, no code sample modifications) - [x] Doc only (includes code sample changes) ## Quality Gates - [ ] Tests added or updated for changed behavior - [ ] Existing tests cover changed behavior — justification: - [x] Tests not applicable — justification: This is a documentation-only release-prep update; behavior is protected by the merged source PRs, and the documentation build validates the changed examples and routes. - [x] Docs updated for user-facing behavior changes - [ ] Docs not applicable — justification: - [ ] Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging) - [ ] Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: - [ ] Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue: ## Verification - [x] PR description includes the DCO sign-off declaration and every commit appears as `Verified` in GitHub - [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or `npm run check:diff` passed when hooks were skipped or unavailable - [x] Targeted behavior tests pass for the current change set, or tests are marked not applicable above — tests are not applicable for this documentation-only change; `npm run docs` completed successfully. - [ ] Applicable broad gate passed — `npm test` for broad runtime/test-harness changes; `npm run check` for repo-wide validation/coverage changes — command/result: not run for this documentation-only change. - [x] Quality Gates section completed with required justifications or waivers - [x] No secrets, API keys, or credentials committed - [ ] `npm run docs` builds without warnings (doc changes only) — 0 errors; two existing Fern warnings remain. - [x] Doc pages follow the [style guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md) (doc changes only) - [ ] New doc pages include SPDX header and frontmatter (new pages only) — no new pages. --- Signed-off-by: Carlos Villela <cvillela@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Documentation** - Added release notes for v0.0.81 covering state preservation, inference setup, sandbox recovery, session setup, pairing, diagnostics, and security policy updates. - Expanded backup and restore guidance to include dashboard profile files and clarify files that must not be copied. - Added dashboard profile persistence details to workspace and rebuild documentation. - Clarified snapshot retention guidance and the distinction between host CLI capabilities and direct runner actions. - Added more detailed backup failure reporting information. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Signed-off-by: Carlos Villela <cvillela@nvidia.com>
NVIDIA#6631) <!-- markdownlint-disable MD041 --> ## Summary `backup-all` and `snapshot create` collapse every per-directory backup failure into one opaque list — `backup failed (identity, devices, credentials)` — which cannot distinguish a permission problem (tar cannot read content the backup user does not own) from a directory that never materialized from the extraction. These are different operator problems: the first points at whatever wrote sandbox state with the wrong ownership; the second at the archive pipeline. This PR records a per-directory failure cause and names it in the failure message, as proposed in the NVIDIA#6455 triage. ## Related Issue Addresses NVIDIA#6455 ## Changes - `backupSandboxState` (`src/lib/state/sandbox.ts`) records an optional `failedDirReasons` map alongside `failedDirs`, populated at the three attribution points: `permission denied` (tar reported `Permission denied` for the dir), `tar read error` (other tar read errors), `absent after extraction` (tar succeeded but the dir never materialized on the host). `failedDirs` keeps its shape for existing consumers. - `failedDirsFromTarStderr` returns the per-dir cause instead of a bare set; matching logic unchanged. - New exported `formatFailedBackupItems` renders `identity (permission denied)`; items without an attributable cause render unchanged. - `backup-all` (`src/lib/actions/maintenance.ts`) and `snapshot create` (`src/lib/actions/sandbox/snapshot.ts`) use it in their failure messages. Before → after on the failing clone from NVIDIA#6455: ```text ✗ clone-test: backup failed (identity, devices, credentials) ✗ clone-test: backup failed (identity (permission denied), devices (permission denied), credentials (permission denied)) ``` ## Type of Change - [x] Code change (feature, bug fix, or refactor) - [ ] Code change with doc updates - [ ] Doc only (prose changes, no code sample modifications) - [ ] Doc only (includes code sample changes) ## Quality Gates - [x] Tests added or updated for changed behavior - [ ] Existing tests cover changed behavior — justification: - [ ] Tests not applicable — justification: - [ ] Docs updated for user-facing behavior changes - [x] Docs not applicable — justification: error-message wording and an optional additive result field; no documented workflow or user-facing behavior contract changes. - [x] Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging) - [ ] Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: requested — `src/lib/state/sandbox.ts` is on the sandbox path; the change is additive diagnostics (no change to what is backed up, audited, or extracted). Awaiting maintainer review. - [ ] Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue: ## Verification - [x] PR description includes the DCO sign-off declaration and every commit appears as `Verified` in GitHub - [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or `npm run check:diff` passed when hooks were skipped or unavailable - [x] Targeted behavior tests pass for the current change set, or tests are marked not applicable above — command/result: `npx vitest run --project cli src/lib/actions/maintenance.test.ts` → 19 passed (2 new: cause rendering via the real formatter, and unchanged rendering when no cause is recorded); `npx vitest run --project integration test/snapshot.test.ts` → 48 passed (2 existing partial-tar tests extended with `failedDirReasons` assertions covering both `permission denied` and `absent after extraction`). - [ ] Applicable broad gate passed — justification: change is confined to backup failure attribution and message rendering; no runtime harness or repo-wide validation surface is altered. - [x] Quality Gates section completed with required justifications or waivers - [x] No secrets, API keys, or credentials committed - [ ] `npm run docs` builds without warnings (doc changes only) - [ ] Doc pages follow the style guide (doc changes only) - [ ] New doc pages include SPDX header and frontmatter (new pages only) ### Evidence Verified live against a Docker sandbox stack (Ubuntu 24.04/WSL2, OpenShell CLI 0.0.72, `main`), using the construction from the NVIDIA#6455 triage: a snapshot-restored clone (`snapshot restore baseline --to clone-test`) with `chown -R root:root` applied to `identity`, `devices`, and `credentials`: ```text $ nemoclaw backup-all # exit measured with no pipe ✗ clone-test: backup failed (identity (permission denied), devices (permission denied), credentials (permission denied)) Pre-upgrade backup: 1 backed up, 1 failed, 8 skipped BACKUP-ALL EXIT=1 ``` Restoring ownership (`chown -R 998:998`) returns the same stack to a clean pass — no false positive from the new attribution: ```text ✓ clone-test: 14 dirs, 1 files → ~/.nemoclaw/rebuild-backups/clone-test/2026-07-10T08-59-40-080Z Pre-upgrade backup: 2 backed up, 0 failed, 8 skipped BACKUP-ALL EXIT=0 ``` The `absent after extraction` cause is pinned by the extended integration test (`marks non-attributed directories failed when they are missing from partial extraction`), which asserts `{ agents: "permission denied", workspace: "absent after extraction" }` from one partial-tar run. --- Signed-off-by: Hokonoken <41166525+Hokonoken@users.noreply.github.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - Improved backup and snapshot failure reporting by showing each failed directory/file with a specific failure cause (e.g., permission denied, tar read error, absent after extraction). - Updated console output formatting to include per-directory reasons when they’re available. - **Tests** - Extended backup and snapshot test coverage with mixed backup outcomes and new assertions for the populated failure-cause mappings and rendered messages. - Added domain-level test coverage for failure classification and formatting behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Hokonoken <41166525+Hokonoken@users.noreply.github.com> Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com> Signed-off-by: Carlos Villela <cvillela@nvidia.com> Co-authored-by: Prekshi Vyas <prekshiv@nvidia.com> Co-authored-by: Carlos Villela <cvillela@nvidia.com>
<!-- markdownlint-disable MD041 --> ## Summary Release-prep documentation for v0.0.81 now summarizes user-facing changes merged since v0.0.80. It also closes the Hermes dashboard-profile backup gap and distinguishes direct blueprint-runner actions from public host CLI commands. ## Changes - Add the `v0.0.81` section to `docs/about/release-notes.mdx` with links to the detailed user guides. - Document that Hermes rebuilds preserve `.hermes/dashboard-home/`, including Dashboard `MEMORY.md` and `USER.md`. - Update Hermes manual backup and restore examples to transfer those two profile files without copying generated configuration or the secret-bearing dashboard `.env`. - Explain the new per-item backup failure causes. - Clarify that migration snapshot retention fragments are direct-runner arguments and are not exposed by the host `nemoclaw` CLI. ### Source summary - NVIDIA#6445 -> `docs/about/release-notes.mdx`, `docs/manage-sandboxes/backup-restore.mdx`, and `docs/manage-sandboxes/workspace-files.mdx`: Summarize manifest-owned key-level restore and current-config authority. - NVIDIA#6617 -> `docs/about/release-notes.mdx` and `docs/manage-sandboxes/backup-restore.mdx`: Record the fail-closed `/proc` fallback used to verify an idle Deep Agents runtime before snapshot creation. - NVIDIA#6685 -> `docs/about/release-notes.mdx`, `docs/manage-sandboxes/backup-restore.mdx`, and `docs/manage-sandboxes/workspace-files.mdx`: Document Hermes Web Dashboard profile persistence and safe manual transfer. - NVIDIA#6649 -> `docs/about/release-notes.mdx`: Summarize host-validated loopback compatible-endpoint routing through the sandbox gateway. - NVIDIA#6643 -> `docs/about/release-notes.mdx`: Summarize automatic `max_completion_tokens` handling for GPT-5 and o-series models. - NVIDIA#6661 -> `docs/about/release-notes.mdx`: Summarize bounded connection reuse for eligible provider-validation probes. - NVIDIA#6704 -> `docs/about/release-notes.mdx`: Record that direct blueprint apply stops instead of persisting incomplete state after provider or inference setup fails. - NVIDIA#6677 -> `docs/about/release-notes.mdx`: Summarize transactional recovery for legacy Docker containers whose managed supervisor disappeared after restart. - NVIDIA#6625 -> `docs/about/release-notes.mdx`: Record Hermes managed-startup persistence across direct Docker restarts. - NVIDIA#6597 -> `docs/about/release-notes.mdx`: Record final-sandbox gateway cleanup on macOS. - NVIDIA#6680 -> `docs/about/release-notes.mdx`: Summarize managed Deep Agents first-run and process-tree cleanup improvements. - NVIDIA#6647 -> `docs/about/release-notes.mdx`: Record fail-closed validation for the managed Deep Agents fetch CA bundle. - NVIDIA#6645 -> `docs/about/release-notes.mdx`: Summarize WhatsApp loopback pairing and trusted npm plugin provenance. - NVIDIA#6673 -> `docs/about/release-notes.mdx` and `docs/manage-sandboxes/backup-restore.mdx`: Document stopped-sandbox backup remediation. - NVIDIA#6631 -> `docs/about/release-notes.mdx` and `docs/manage-sandboxes/backup-restore.mdx`: Document per-item backup failure causes. - NVIDIA#6620 -> `docs/about/release-notes.mdx`: Record the created-but-not-ready sandbox lifecycle receipt. - NVIDIA#6664 -> `docs/about/release-notes.mdx`: Record prompt-aware onboarding progress output. - NVIDIA#6598 -> `docs/about/release-notes.mdx`: Summarize stale replay-result invalidation during resumed onboarding. - NVIDIA#6593 -> `docs/about/release-notes.mdx`: Summarize contextual OpenClaw audit findings for managed dashboard compatibility settings. - NVIDIA#6650 -> `docs/about/release-notes.mdx`: Record redaction of token-shaped URL query values. - NVIDIA#6638 -> `docs/about/release-notes.mdx`: Record the exact-path MCP `DELETE` policy recipe for session termination. - NVIDIA#5453 -> `docs/reference/host-files-and-state.mdx`: Clarify that snapshot retention actions belong to direct runner integrations and are not standalone host CLI commands. ### Skipped from docs-skip - NVIDIA#6633 matched the `openclaw-sandbox-permissive.yaml` path in `docs/.docs-skip` and produced no documentation in this update. ## Type of Change - [ ] Code change (feature, bug fix, or refactor) - [ ] Code change with doc updates - [ ] Doc only (prose changes, no code sample modifications) - [x] Doc only (includes code sample changes) ## Quality Gates - [ ] Tests added or updated for changed behavior - [ ] Existing tests cover changed behavior — justification: - [x] Tests not applicable — justification: This is a documentation-only release-prep update; behavior is protected by the merged source PRs, and the documentation build validates the changed examples and routes. - [x] Docs updated for user-facing behavior changes - [ ] Docs not applicable — justification: - [ ] Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging) - [ ] Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: - [ ] Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue: ## Verification - [x] PR description includes the DCO sign-off declaration and every commit appears as `Verified` in GitHub - [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or `npm run check:diff` passed when hooks were skipped or unavailable - [x] Targeted behavior tests pass for the current change set, or tests are marked not applicable above — tests are not applicable for this documentation-only change; `npm run docs` completed successfully. - [ ] Applicable broad gate passed — `npm test` for broad runtime/test-harness changes; `npm run check` for repo-wide validation/coverage changes — command/result: not run for this documentation-only change. - [x] Quality Gates section completed with required justifications or waivers - [x] No secrets, API keys, or credentials committed - [ ] `npm run docs` builds without warnings (doc changes only) — 0 errors; two existing Fern warnings remain. - [x] Doc pages follow the [style guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md) (doc changes only) - [ ] New doc pages include SPDX header and frontmatter (new pages only) — no new pages. --- Signed-off-by: Carlos Villela <cvillela@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Documentation** - Added release notes for v0.0.81 covering state preservation, inference setup, sandbox recovery, session setup, pairing, diagnostics, and security policy updates. - Expanded backup and restore guidance to include dashboard profile files and clarify files that must not be copied. - Added dashboard profile persistence details to workspace and rebuild documentation. - Clarified snapshot retention guidance and the distinction between host CLI capabilities and direct runner actions. - Added more detailed backup failure reporting information. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Summary
backup-allandsnapshot createcollapse every per-directory backup failure into one opaque list —backup failed (identity, devices, credentials)— which cannot distinguish a permission problem (tar cannot read content the backup user does not own) from a directory that never materialized from the extraction. These are different operator problems: the first points at whatever wrote sandbox state with the wrong ownership; the second at the archive pipeline. This PR records a per-directory failure cause and names it in the failure message, as proposed in the #6455 triage.Related Issue
Addresses #6455
Changes
backupSandboxState(src/lib/state/sandbox.ts) records an optionalfailedDirReasonsmap alongsidefailedDirs, populated at the three attribution points:permission denied(tar reportedPermission deniedfor the dir),tar read error(other tar read errors),absent after extraction(tar succeeded but the dir never materialized on the host).failedDirskeeps its shape for existing consumers.failedDirsFromTarStderrreturns the per-dir cause instead of a bare set; matching logic unchanged.formatFailedBackupItemsrendersidentity (permission denied); items without an attributable cause render unchanged.backup-all(src/lib/actions/maintenance.ts) andsnapshot create(src/lib/actions/sandbox/snapshot.ts) use it in their failure messages.Before → after on the failing clone from #6455:
Type of Change
Quality Gates
src/lib/state/sandbox.tsis on the sandbox path; the change is additive diagnostics (no change to what is backed up, audited, or extracted). Awaiting maintainer review.Verification
Verifiedin GitHubpre-commit,commit-msg, andpre-pushhooks passed, ornpm run check:diffpassed when hooks were skipped or unavailablenpx vitest run --project cli src/lib/actions/maintenance.test.ts→ 19 passed (2 new: cause rendering via the real formatter, and unchanged rendering when no cause is recorded);npx vitest run --project integration test/snapshot.test.ts→ 48 passed (2 existing partial-tar tests extended withfailedDirReasonsassertions covering bothpermission deniedandabsent after extraction).npm run docsbuilds without warnings (doc changes only)Evidence
Verified live against a Docker sandbox stack (Ubuntu 24.04/WSL2, OpenShell CLI 0.0.72,
main), using the construction from the #6455 triage: a snapshot-restored clone (snapshot restore baseline --to clone-test) withchown -R root:rootapplied toidentity,devices, andcredentials:Restoring ownership (
chown -R 998:998) returns the same stack to a clean pass — no false positive from the new attribution:The
absent after extractioncause is pinned by the extended integration test (marks non-attributed directories failed when they are missing from partial extraction), which asserts{ agents: "permission denied", workspace: "absent after extraction" }from one partial-tar run.Signed-off-by: Hokonoken 41166525+Hokonoken@users.noreply.github.com
Summary by CodeRabbit
Bug Fixes
Tests