Skip to content

v0.2.0.0 feat: preserve source directory structure in backups - #4

Merged
ryota-murakami merged 3 commits into
mainfrom
codex/preserve-backup-paths
Oct 7, 2026
Merged

ryota-murakami merged 3 commits into
mainfrom
codex/preserve-backup-paths

Conversation

@ryota-murakami

@ryota-murakami ryota-murakami commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Preserve selected source hierarchy: backup cooking/too.txt stores only cooking/too.txt, while backup cooking copies its contents recursively under cooking/.
  • Map home-relative and absolute paths beneath home consistently, create missing parents, and retain old flattened backups and unselected files.
  • Validate mapped ancestors and tracked prefixes before copying; preserve the selected mapping through source revalidation, exact-byte staging, and packaged Node execution.

Test Coverage

CODE PATHS — 24 logical changed-behavior/dependency paths
src/cli.ts -> backup()
  P01 [★★★ TESTED] Omitted source registers; empty source reaches validation, fails, and never copies — backup.test.ts:269, edge-cases.test.ts:391
resolveBackupPath() -> metadataAlias()/isWithin()
  P02 [★★★ TESTED] Relative spelling, dot segments, current directory, spaces and leading dashes preserve hierarchy — path-mapping.test.ts:10
  P03 [★★★ TESTED] Tilde/redundant separators/home absolute paths retain home hierarchy — path-mapping.test.ts:27,49; backup.test.ts:508,583
  P04 [★★ TESTED] Outside-home and similarly prefixed home names retain basename — path-mapping.test.ts:59; package.test.ts:23
  P05 [★★★ TESTED] Empty/root/relative escape boundaries reject before copy — path-mapping.test.ts:75,106; edge-cases.test.ts:391
  P06 [★★★ TESTED] Raw metadata components cannot disappear through normalization; unrelated ordinary components pass — path-mapping.test.ts:85,99; backup.test.ts:231
  P07 [★★★ TESTED*] Native drive/UNC/drive-relative and POSIX literal-backslash contracts — path-mapping.test.ts:114,124,134,165
  P08 [★★ TESTED] Absolute/home input survives a removed invocation directory — core.test.ts:434
scanSource() -> realpath/lstat/readEntry()/visit()
  P09 [★★★ TESTED] Canonical parent aliases retain approved mapping; exact 100 MiB passes with an explicit approved key; overlap, metadata, unsupported and oversized source entries reject — core.test.ts:351; backup.test.ts:561,231,250; regressions.test.ts:240,260; edge-cases.test.ts:288
  P10 [GAP] Defensive internal destinationName/manifest-root rejection for forged Source values (scanSource/copySource guards)
validateDestination() -> destinationAncestors()/checkDestinationDirectory()/Git index streams
  P11 [★★★ TESTED] Required parents: absent/create, existing/reuse, file or symlink/reject before descendants — backup.test.ts:454,531; edge-cases.test.ts:419
  P12 [★★★ TESTED] Selected file/directory/link type conflicts abort every selected write — edge-cases.test.ts:11; backup.test.ts:212
  P13 [★★★ TESTED*] Case/Unicode tracked-ancestor collisions reject; ordinary unrelated prefixes pass — core.test.ts:401; backup.test.ts:531
  P14 [★★★ TESTED] Tracked ancestors and gitlinks/submodules cannot become selected directories — edge-cases.test.ts:419
  P15 [★★★ TESTED] Selected skip-worktree/assume-unchanged rejects; flagged unselected siblings remain allowed — backup.test.ts:192; edge-cases.test.ts:470
copySource() -> destinationAncestors()/prepareDestinationParents()/checkDestinationDirectory()
  P16 [★★★ TESTED] Source suffix is resolved below the original root, independent of mapped destination depth; same-basename selections retain distinct keys — backup.test.ts:423,454,480; core.test.ts:351; regressions.test.ts:277
  P17 [★★★ TESTED] Replaced clone root and preflighted parent links reject before escaping writes — core.test.ts:74,282,323
  P18 [★★★ TESTED] Missing-parent mkdir permission failure reports recovery, stages nothing, and never pushes — edge-cases.test.ts:493 (independently rated)
  P19 [GAP] Parent appears/replaces another between the missing check and mkdir/canonical recheck (EEXIST and late alias race)
  P20 [★★★ TESTED] Copied bytes/types/modes must still match the scanned manifest — core.test.ts:100,262; regressions.test.ts:90
  P21 [★★★ TESTED] Final mapped rescan rejects same-byte inode replacement — core.test.ts:463 (independently rated)
  P22 [GAP] Final mapped directory rescan rejects changed source membership
  P23 [★★★ TESTED] Same-kind merges retain absent entries; selected symlinks preserve text across repeat/replace — backup.test.ts:18,306; regressions.test.ts:119
stageSource() -> exact NUL paths -> verified index/commit
  P24 [★★★ TESTED] Nested selection stages only selected bytes; literal paths, conversion errors and hidden flags stay protected — core.test.ts:383; backup.test.ts:269; edge-cases.test.ts:470

USER FLOWS — 6 integration paths
  F01 [★★★ TESTED] [→E2E] Nested file -> missing parents -> commit/push -> restore exact bytes; sibling excluded — backup.test.ts:423,454
  F02 [★★★ TESTED] [→E2E] Nested directory -> recursive copy -> remote tree; exact .git excluded, unrelated siblings retained — backup.test.ts:18,480
  F03 [★★★ TESTED] [→E2E] Tilde and shell-expanded home paths -> same remote key -> unchanged retry/no extra commit — backup.test.ts:508,583
  F04 [★★★ TESTED] [→E2E] Upgrade existing flattened backup -> create nested key -> retain old copy and unrelated siblings — backup.test.ts:531
  F05 [★★★ TESTED] [→E2E] Invalid/unsafe path -> actionable failure -> no selected writes or remote updates — edge-cases.test.ts:391,419; core.test.ts:74
  F06 [★★★ TESTED] [→E2E] Packed Node CLI -> nested selection -> real bare remote -> recovery without Bun — package.test.ts:23

COVERAGE: 27/30 paths have tests (90.0%); 27/30 value-weighted (90.0%).
Code paths: 21/24 any test, 21/24 rated. User flows: 6/6 rated.
QUALITY (path groups): ★★★ 25; ★★ 2; ★ 0; unrated 0. GAPS: 3.
Legend: ★★★ behavior/edge/error; ★★ happy-path behavior; GAP = no test.
[→E2E] paths use existing Node CLI integration tests with real local/bare Git; only GitHub API/transport is stubbed.
* Windows-only resolver cases are present and skipped locally on macOS; native CI rerun is pending. Case/Unicode checks are filesystem-dependent; the mkdir-permission fixture is POSIX-only.

This is a bounded logical-path audit, not an instrumented line/branch-coverage percentage. The diagram groups closely related guards within the 30-path cap. GUI motion and LLM evals do not apply.

Remaining proposals:

  • P10: Value: protects=invalid internal mapping or manifest keys cannot escape the selected destination; fails_when=scanSource or copySource loses its defensive key validation; why_new=current CLI inputs cannot construct invalid approved mappings or forged Source values; seam=none. No test generated: current production callers preserve this invariant; adding a forged internal structure has low user-facing regression value.
  • P19: Value: protects=concurrent parent creation is accepted only for safe directories; fails_when=EEXIST escapes handling or a raced parent alias permits an unsafe write; why_new=existing race tests replace parents before copy, not inside check/mkdir/recheck; seam=none. Requires a reliable real-filesystem concurrency fixture; do not add test-only production hooks.
  • P22: Value: protects=mapped directory backups reject added or removed source entries before staging; fails_when=the final source-membership rescan is omitted or its count comparison is removed; why_new=existing byte mutations fail before final membership validation; seam=none. Use a bundled Node-only test fixture at scan/copy boundaries. An initial direct-Bun directory fixture timed out with recursive scan stacks before assertions; it was removed after one fixture correction. No Node product failure was demonstrated.

Changes from the previous audit:

  • Applied the existing independent three-star ratings to P18 and P21. Their test bodies and value cards are unchanged. Value-weighted coverage rises from the original unrated 83.33% artifact to the already-established final 90%; this fixture repair does not increase coverage.
  • The existing exact-100-MiB test now passes the approved destination key limit.bin to scanSource. It keeps both original assertions. Windows temporary sources beneath home correctly map through AppData under the default resolver, so the old basename assertion mixed size validation with a host-layout assumption. Fixing the fixture isolates the existing size contract; it does not change production mapping behavior or add a logical path.
  • Home-contained, outside-home, drive/UNC and relative mapping tests remain unchanged, including their exact expected keys. No coverage or quality downgrade is warranted.
  • Refreshed the two shifted regression-test references and placed the same-basename contract with P16. No production scope change; all 30 logical paths and all three gap proposals remain.

Regression proof: no product regression reproduced by this re-audit. The parent reproduced the existing fixture assertion failure with TMPDIR beneath home, then verified the same assertions pass with the explicit approved key. This is test-fixture repair evidence, not a new production-regression test or base control; regression_proof counts remain zero.
Tests: 6 → 6 (+0 new files) during the original audit and this re-audit. Branch base: 5 → 6 (+1 test file).
Generated across this ship run: 2 retained test definitions / 2 scenarios in existing files; 0 extensions; 2 redundant proposals rejected. Final re-audit pass 2/2 was audit-only with zero generation allowance; 0 tests generated or extended in this pass. No source edits, test execution, commits or pushes by this re-auditor. The only new file from this re-audit is the requested temporary coverage-final.json artifact.
Validation: the parent reports the latest required local check after fixture repair passed with 142 tests, 4 Windows-only skips, 0 failures and 311 assertions. Evidence: 2026-10-07T09-36-10-697Z-tests-49112-63dec835.log, completed 2026-10-07T09:37:45Z. This re-audit did not rerun tests. Native CI rerun remains pending; no native CI success is claimed. Earlier generation evidence remains 2 targeted passes / 0 failures / 9 assertions with TypeScript and git diff --check passing.
Audit snapshot: HEAD 7daa7ec plus the existing two-line test/regressions.test.ts fixture correction, against origin/main.

Coverage gate: PASS — 90% value-weighted, 27/30 logical paths, 0 weak paths, 3 explicit additional-test proposals. The existing independent ratings remain valid after the test-only fixture repair. This is not instrumented line coverage.

Pre-Landing Review

Parent checklist and fresh native adversarial review completed on the final source tree. One misleading zero-copy error sentence and a host-dependent test fixture were fixed; the final passes found no remaining actionable implementation defect. Claude Code structured review: NO_FINDINGS. The final outside adversarial pass also found no actionable defect. All new source and tests are committed. Test fixtures were summary-only in adversarial reviews; their execution and test-value audit are separate evidence.

Exploratory QA

  • Scope: CLI path mapping, recursive copying, parent failure boundaries, exact-byte staging, and installed-package recovery.
  • Isolation: Synthetic home/config, temporary clones and local bare remotes; GitHub API and SSH transport are stubbed. Real user backup data and the global installation were not test targets.
  • Contracts: Initial smoke passed 3 mapped-copy cases and 4 parent-conflict/recovery cases. After the error wording fix, the required full suite revalidated these same contracts: 142 pass, 4 native Windows-only skips, 0 fail, 311 assertions.
  • Evidence: Full suite receipt 2026-10-07T09:37:45.506Z; native three-OS CI is now verified in the current results below. Exact selected remote paths, exclusion of unselected siblings, and recovered literal bytes are asserted by the integration/package tests.
  • CI repair: The first Windows run exposed a location-dependent 100 MiB fixture expectation. Reproducing with an owned temporary directory beneath home failed before the fix and passed afterward. The size-only scan now uses an explicit destination name, retaining its original hardcoded assertions; production mapping behavior is unchanged.
  • Limits: No browser surface. The existing policy excludes guarantees against arbitrary simultaneous filesystem writers. Windows-only cases are not counted as locally passed.

Design Review

No frontend files changed — design review skipped.

Eval Results

No prompt-related files changed — evals skipped.

Scope Drift

Scope Check: CLEAN. The approved path-mapping feature, safety checks, tests, and documentation are present; no unrelated implementation changes.

Plan Completion

Static plan-completion audit refreshed against origin/main at HEAD 7daa7ec plus the sole working-tree change in test/regressions.test.ts. Counts cover implementation and test creation only. All 30 deliverables remain complete; npm package metadata remains 0.2.0.

  • CODE: Reusable resolveBackupPath(input, { cwd, home }) returns lexical absolute source and destination root; existing containment and metadata helpers are reused (src/utils/resolve-backup-path.ts:14; src/utils/metadata-alias.ts:6).
  • CODE: Relative, ./, nested, literal-home, home-contained absolute, outside-home, current-directory and home-root mappings follow the contract (src/utils/resolve-backup-path.ts:24-63).
  • CODE: Reject empty/root/relative escapes and raw metadata components; preserve literal whitespace, Unicode, leading dashes and normalized in-boundary paths (src/utils/resolve-backup-path.ts:18-63; src/cli.ts:48-67).
  • CODE: Native Windows drive/UNC parsing and drive-relative rejection preserve POSIX literal backslashes (src/utils/resolve-backup-path.ts:19-45,63).
  • CODE: Source keeps its documented shape and canonical-parent location; scans and rescans preserve one destination mapping (src/filetree.ts:29-35,113-177,437).
  • CODE: Copy origins use only the suffix beneath source.name; entries outside the selected root fail (src/filetree.ts:368-379).
  • CODE: Required destination ancestors are separate from selected entries and created clone-root downward without selecting siblings (src/filetree.ts:185-190,247-252,333-353).
  • CODE: Preflight validates ancestor types, containment, tracked prefixes, submodules and filesystem case/normalization collisions (src/filetree.ts:199-221,231-310).
  • CODE: Raw/selected metadata aliases remain protected, exact .git descendants remain excluded, and selected leaf symlinks remain links (src/utils/metadata-alias.ts:6; src/filetree.ts:127-145,167-174,275-286,415-422).
  • CODE: Lock, synchronization, post-fetch validation, preflight, copy, commit verification and pinned push sequence remain intact (src/backup.ts:113-223).
  • CODE: Stage only selected non-directory entries; mapped copied bytes, source stability and staged entries are verified with the same keys (src/filetree.ts:423-549).
  • CODE: Retain existing overwrite/no-delete behavior, old flattened copies, pending history and failed-push recovery (src/filetree.ts:411-422; src/backup.ts:204-229; test/backup.test.ts:61,84,531).
  • CODE: Retain one-source syntax, size/file-type rules, private-repository/Actions checks and existing lock behavior (src/cli.ts:48-67; src/filetree.ts:61-102; src/backup.ts:35-94).
  • DOCS: Mapped destination appears in results/recovery/commit subjects, and help/README explain relative versus home/absolute mapping with examples (src/backup.ts:148,175,205,223-229; src/cli.ts:9-33; README.md:38-68).
  • DOCS: Help and README state ancestor restrictions and old flattened-copy retention; the verified HELP update rejects file/symlink/submodule parents, metadata and conflicting tracked spellings, and retains old flattened backups/unselected files (src/cli.ts:15-17; README.md:54-59).
  • DOCS: CHANGELOG describes changed path semantics, old-copy retention and ancestor protections (CHANGELOG.md:3-19).
  • TEST: Resolver creation covers the ten planned core scenarios with literal expectations and AAA comments (test/path-mapping.test.ts:10-112).
  • TEST: Additional resolver cases cover Windows drive-relative/native/UNC forms, POSIX backslashes, leading dashes, normalized current-directory inputs, raw invocation metadata and home-prefix variants (test/path-mapping.test.ts:10-19,99-175).
  • TEST: Selected nested files exclude siblings, report/commit the exact mapped path and restore exact bytes from a fresh clone (test/backup.test.ts:423-452).
  • TEST: A deep selected file creates all missing parents and commits only its path (test/backup.test.ts:454-478).
  • TEST: Recursive directory behavior and nested-directory hierarchy/exclusions are covered (test/backup.test.ts:18-59,480-506).
  • TEST: Literal tilde and home-contained absolute inputs are equivalent when invoked outside home (test/backup.test.ts:508-529; test/helpers.ts:76-85,127-135).
  • TEST: Repeats create no duplicate commit; updates retain old flattened copies and unrelated siblings (test/backup.test.ts:531-559).
  • TEST: Replace flattened same-basename expectation with coexistence and exact remote bytes for one/foo.md and two/foo.md (test/regressions.test.ts:277-300).
  • TEST: Invalid inputs and file/symlink/submodule ancestors fail before payload copying/push; missing-parent creation failure preserves recovery reporting (test/edge-cases.test.ts:391-467,493-534).
  • TEST: Deterministic replacement coverage exercises post-fetch ancestors, post-preflight inside/outside symlinks and replaced clone roots without escaped payload writes (test/core.test.ts:74-98,282-350).
  • TEST: Mapped byte mutation, same-byte identity mutation, stable parent aliases and staged-byte conversion have regressions (test/core.test.ts:262-281,351-399,463-492).
  • TEST: Ancestor case/NFC collisions and unselected sibling index flags have supported-platform coverage (test/core.test.ts:401-432; test/edge-cases.test.ts:470-489).
  • TEST: Installed npm tarball runs its built CLI under Node, checks exact remote paths/no sibling/root flattening and restores literal bytes from a fresh clone (test/package.test.ts:23-135; test/helpers.ts:127-135,193-215).
  • CONFIG: Existing Linux/macOS/Windows CI matrix and rebuild-before-tests check remain wired; fixture-only repositories and package installation remain isolated (package.json scripts.check; .github/workflows/ci.yml:16-37; test/helpers.ts:69-141; test/package.test.ts:24-45).

Refresh evidence: compared source, test, README and CI files against feature commit 0d22fbf. The only subsequent change in those surfaces is test/regressions.test.ts:248-253: the existing exact-100-MiB test now supplies the validated destination name limit.bin to scanSource. The original 100 * 1024 * 1024 size, ['limit.bin'] keys assertion and 'file' kind assertion remain unchanged (test/regressions.test.ts:240-258). This removes host temp/home location dependence without changing production mapping or weakening the size-boundary contract. Home-contained absolute mapping remains covered separately (test/path-mapping.test.ts:27-73; test/backup.test.ts:508-529). No new feature scope is introduced.

Execution-only verification handoff (outside completion counts; this audit ran no tests):

  • Source: spec Testing Plan, line 97: "Run bun run check so the CLI bundle is rebuilt before integration tests. Confirm package acceptance coverage and the existing three-OS CI matrix. Use fixture repositories only; do not write to the user's real backup clone or global installation during development verification." Required command: bun run check. Expected: typecheck/build and all applicable tests pass, including installed-package acceptance. Parent reports the current repaired-input full local check completed at 2026-10-07T09:37:45Z: 142 passed, 4 Windows-only skipped, 0 failed, 311 assertions. Parent evidence: 2026-10-07T09-36-10-697Z-tests-49112-63dec835.log. The audit did not independently execute that command. Parent also reports the former failure was reproduced with an owned TMPDIR beneath home and passed after this fixture repair.
  • Source: spec Acceptance Criteria, line 82: "The existing test suite passes with only the intentional basename-collision expectation changed. New scenarios pass on Linux, macOS, and Windows through the existing CI matrix; npm package acceptance runs the installed built CLI under Node." Parent-reported initial native CI results before the test-only repair: Linux 140 passed / 6 skipped / 0 failed; macOS 142 passed / 4 skipped / 0 failed; Windows 134 passed / 13 skipped / 1 failed. Windows failure was the old size-boundary fixture's location-dependent basename expectation, because the absolute temporary source lay beneath home and correctly retained its hierarchy. Current repaired-input native CI rerun is pending. Inspect all three Test jobs and applicable platform cases; neither the local pass nor this static audit establishes current native CI success.
  • Source: spec Engineering Clarifications, line 142: "Package acceptance must verify the installed entry under Node, inspect the remote tree for the exact nested path and absence of unselected paths, clone the remote freshly, and compare literal byte expectations. Reuse the package fixture and recover helper." Executable through bun run check (or existing bun run test:package for a focused run); expected remote path cooking/too.txt, absent too.txt and cooking/other.txt, restored bytes 'selected packaged bytes\n', and no Bun invocation. Test creation remains complete; native execution evidence must be retained with the final CI results.

Linked Spec

Closes #3. All implementation and native three-OS acceptance checks are verified on 4ffc684.

Spec archive: 20261007-preserve-source-paths-issue-3.md; filed 2026-10-07T08:06:22.163108+00:00.

Verification Results

3 PASS, 0 FAIL, 0 BLOCKED, 0 NOT RUN:

Obligation Result
bun run check: typecheck, build, full applicable suite PASS — 142 passed, 4 Windows-only skipped, 0 failed; 311 assertions
Installed npm tarball runs under Node and restores exact selected nested bytes from a fresh clone PASS — included in the same required suite
Existing Linux/macOS/Windows CI matrix PASS — all three jobs passed on 4ffc684; current CI checks

The first CI run passed on Linux/macOS and failed one Windows test fixture. The two-line correction is committed in 4ffc684; no production code changed. The repaired commit passed all three native jobs.

Native OS Passed Skipped Failed
Linux 140 6 0
macOS 142 4 0
Windows 135 13 0

Skips follow platform/filesystem conditions. Installed npm-package execution under Node and fresh-clone recovery passed on every OS. Both Socket Security checks also passed; all five current-HEAD checks are successful.

The static Plan Completion and coverage audits above record their snapshot-time evidence. Current execution outcomes are tracked here; snapshot mentions of pending CI are historical once this table updates. This section supplies the current execution outcomes. No verification risk was waived.

Documentation

Status: current. README.md and CHANGELOG.md match the complete selected release candidate, including the Windows-independent 100 MiB test fixture repair. No documentation edits or blockers were found.

Audit scope: 16 release files relative to base 27e4fbe935a18d117027beb6e77c73f6aa4e32f9. At the audit snapshot, HEAD was 7daa7ec17c8a0e51ce966c1781b0c0fcec3692b8 and the two-line repair in test/regressions.test.ts was unstaged. This records the audited input and does not describe the branch state after the parent commits or publishes it. Recursive, NUL-safe discovery found two authored documentation files; both were read in full. Relevant path-mapping implementation, CLI help, the repaired test, and release metadata were checked. Other candidate bytes match the completed first audit, including production source and generated CLI output.

Documentation health:

  • README.md — Current: hierarchy preservation, recursive directory copying, home-relative and absolute paths, destination validation, old-backup retention, mapped commit messages, and the 100 MiB limit agree with the implementation. The test fixture repair changes no public contract.
  • CHANGELOG.md — Current: 0.2.0.0 records the release behavior and fixes, agrees with release metadata, and is discoverable through README.md.
  • ARCHITECTURE.md, CONTRIBUTING.md, repository AGENTS.md, and TODOS.md — Skipped: absent from the tracked and nonignored inventory.

Documentation coverage:

Changed public behavior Reference How-to Tutorial Explanation
Nested files and recursive directories README.md README.md examples No separate tutorial README.md mapping rules
Home-relative and absolute source mapping README.md README.md examples No separate tutorial README.md lexical-path rules
Retention of old flattened backups README.md and CHANGELOG.md README.md upgrade example No separate tutorial README.md upgrade guidance
Rejected paths and destination ancestors README.md README.md alternate-path and retry guidance No separate tutorial README.md validation limits

Coverage debt: no critical gaps or reference-only public behavior were found. Existing reference, examples, and explanations cover this CLI change; no separate tutorial was added. Internal helpers and the test fixture repair introduce no separately published API.

Diagram drift: none. No architecture diagrams were found in the authored documentation.

This was a static documentation audit, not test execution or CI verification. Native CI was pending at the audit snapshot and remains a separate parent-owned verification step. npm 0.2.0 and VERSION/CHANGELOG 0.2.0.0 follow the supplied release decision. No protected metadata, source, tests, generated output, Git state, or PR content was modified by this audit.

Test plan

  • bun run check — 142 pass, 4 Windows-only skips, 0 fail; includes typecheck/build and installed Node-package recovery.
  • Focused mapped-file/directory/home cases — 3 pass; revalidated by the full suite after the final source fix.
  • Focused ancestor-conflict/missing-parent recovery cases — 4 pass; revalidated by the full suite after the final source fix.
  • bun run build and node dist/cli.js --version — rebuilt release reports 0.2.0.
  • git diff --check — clean.
  • Linux, macOS, and Windows PR CI — 140 / 142 / 135 passed respectively, zero failures on all platforms.

Prepared with OpenAI Codex using the gstack ship workflow.

ryota-murakami and others added 3 commits October 7, 2026 18:22
Keep relative and home-contained paths in the destination, create safe
missing parents, and retain mapped paths through byte and source checks.
Cover nested selections, recursive copying, collisions, recovery, and the
installed Node package with isolated Git fixtures.
Co-Authored-By: OpenAI Codex <noreply@openai.com>
Use an explicit mapping for the 100 MiB scan fixture so temporary paths
beneath the Windows home directory do not change its size-only assertion.
Reproduced with an owned temporary directory beneath home before and after
the fixture correction; production mapping behavior is unchanged.
@ryota-murakami
ryota-murakami merged commit cb7ae14 into main Oct 7, 2026
5 checks passed
@ryota-murakami
ryota-murakami deleted the codex/preserve-backup-paths branch October 7, 2026 10:28
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.

feat: preserve source directory structure in backups

1 participant