Repository navigation
perf(stack): copy snapshot directories with one host command - #6709
Conversation
There was a problem hiding this comment.
Superseded by a newer AI review
🤖 AI Review
Only Claude's independent review was available; the Codex pass did not complete. All nine findings were verified, although claude-1 is narrowed and downgraded to minor, claude-5 is downgraded to nit, and claude-6 is restated to reflect that the existing test would exercise the fast path on macOS but is not run there in CI and cannot force either branch. The main correctness concerns are the fail-closed optimization probe, inconsistent handling of non-directory sources, ignored cleanup failures, and uninterruptible subprocesses.
Findings
| Severity | Location | Category | Sources | Claim |
|---|---|---|---|---|
| 🟡 MINOR | packages/stack/src/storage/DirectoryCopy.ts:181 |
error-handling |
claude | A failure to execute or complete the macOS find optimization probe aborts copyDirectory instead of falling back to the portable traversal. |
| 🟡 MINOR | packages/stack/src/storage/DirectoryCopy.ts:182 |
correctness |
claude | On macOS, a regular-file source can pass the find gate and be accepted by cp, bypassing the directory validation used by the portable path. |
| 🟡 MINOR | packages/stack/src/storage/DirectoryCopy.ts:184 |
error-handling |
claude | If clone cleanup fails, its error is ignored and the portable fallback can instead fail with an unrelated destination-exists error, masking the clone and cleanup failures. |
| 🟡 MINOR | packages/stack/src/storage/DirectoryCopy.ts:199 |
concurrency |
claude | The full find and cp subprocess lifetimes are uninterruptible and receive no abort signal, so Effect interruption cannot cancel these potentially long-running operations. |
| 🟡 MINOR | packages/stack/src/storage/DirectoryCopy.ts:181 |
test-coverage |
claude | Tests do not force either the macOS clone-success branch or clone-failure fallback, and this test file is not included in the repository's macOS CI integration subset. |
| ⚪ NIT | packages/stack/src/storage/DirectoryCopy.ts:2 |
conventions |
claude | The new subprocess boundary bypasses the package's established Effect ChildProcessSpawner, and the lint suppression incorrectly cites missing FileSystem operations as its justification. |
| ⚪ NIT | packages/stack/src/storage/DirectoryCopy.ts:202 |
dead-code |
claude | The typeof result === "string" branch is unreachable because promisified execFile resolves to an object containing stdout and stderr. |
| ⚪ NIT | packages/stack/src/storage/DirectoryCopy.ts:214 |
security |
claude | The macOS system utilities are resolved through the inherited PATH, allowing an earlier shadowing find or cp executable to run. |
| ⚪ NIT | packages/stack/src/storage/DirectoryCopy.ts:192 |
readability |
claude | runExec places operation last even though error construction and the file's other operation-labelled helpers put it first, making call sites inconsistent. |
Stats
Claude findings: 9 · Codex findings: 0 · Confirmed: 9 · Refuted: 0 · Uncertain: 0
Models: claude-opus-5 + gpt-5.6-sol · Trigger: auto · Workflow run
This review runs once per PR. A maintainer can request another with a /ai-review comment.
Compiled CLI builds now enable minification, ESM, and bytecode at depth 2 to reduce startup work. Release, local, and E2E binaries share the same compilation options, including the local npm release workflow. Depth 2 limits the binary-size cost compared with compiling all nested functions ahead of time. --------- Co-authored-by: Julien Goux <hi@jgoux.dev>
A Postgres data directory is mostly small files, so one clone is cheaper than a clone per file. Unsupported entries still use the per-file copy.
Linux reflinks when the filesystem can, and Windows uses robocopy. A failed or interrupted host copy removes the partial tree first.
eb070af to
5d46e26
Compare
A cancel during chmod left the failed host copy in place, and the interrupt test read the last argument, which is /NP on Windows.
Keep develop's oxfmt stub and root-key default. Keep the host-command directory copy and the spawner it needs.
|
/ai-reivew |
|
/ai-review |
There was a problem hiding this comment.
🤖 AI Review
The new host-copy path introduces two cleanup risks in the exported copy function: cleanup can follow a symlink and change permissions outside the destination, and a failed copy can remove a destination created by another process. The current snapshot caller reduces the second risk by copying into a UUID stage under a cross-process lock. Most remaining findings concern diagnostics, fallback performance, and tests. One claimed fork convention is contradicted by other tests in the repository.
Findings
| Severity | Location | Category | Sources | Claim |
|---|---|---|---|---|
| 🔴 CRITICAL | packages/stack/src/storage/DirectoryCopy.ts:348 |
security |
codex | Cleanup can follow a symlink introduced after the source scan and recursively change permissions outside the partial destination. |
| 🟠 MAJOR | packages/stack/src/storage/DirectoryCopy.ts:195 |
data-loss |
codex | A failed host copy can remove a destination created by another process after the initial absence check. |
| 🟡 MINOR | packages/stack/src/storage/DirectoryCopy.ts:238 |
error-handling |
claude | runExec discards stdout when constructing a failed command's error, losing robocopy diagnostics written there. |
| 🟡 MINOR | packages/stack/src/storage/DirectoryCopy.ts:206 |
observability |
claude | The host-copy failure cause is discarded without a log before the per-file fallback runs. |
| 🟡 MINOR | packages/stack/src/storage/DirectoryCopy.ts:205 |
correctness |
claude | An accepted host-copy exit status returns success without verifying that the destination exists. |
| 🟡 MINOR | packages/stack/src/storage/DirectoryCopy.ts:396 |
performance |
claude | If macOS clone copy fails, there is no plain cp candidate; the code falls straight back to the per-file walk. |
| ⚪ NIT | packages/stack/src/storage/DirectoryCopy.ts:382 |
error-handling |
claude | The unanchored usage-error regex can classify an ordinary cp error as option misuse when a path in its message contains a matched phrase. |
| ⚪ NIT | packages/stack/src/storage/DirectoryCopy.ts:2 |
comment-accuracy |
claude+codex | The lint-disable reason does not explain the newly added native readdir import. |
| ⚪ NIT | packages/stack/src/storage/DirectoryCopy.ts:298 |
testability |
claude | The Windows pre-flight scan bypasses an injected FileSystem service, so substituting that service cannot control the scan. |
| ⚪ NIT | packages/stack/src/storage/DirectoryCopy.ts:209 |
performance |
claude | After a copyability scan succeeds and the host copy fails, fallback traverses the source again in both validateTree and copyTree. |
| ⚪ NIT | packages/stack/src/storage/DirectoryCopy.ts:396 |
robustness |
claude | Some find and cp candidates can interpret a source or destination beginning with a hyphen as an option. |
| ⚪ NIT | packages/stack/src/storage/DirectoryCopy.integration.test.ts:203 |
test-coverage |
claude | On unsupported platforms, the mocked-spawner interrupt tests wait for signals that no host-copy command can send. |
Refuted findings (kept for transparency, not posted as review comments)
packages/stack/src/storage/DirectoryCopy.integration.test.ts:203(test-quality): Bare Effect.forkChild violates an established repository convention and makes the interrupt tests timing-sensitive.
Refuted: The claimed convention does not exist: the same package uses bare Effect.forkChild in Orchestrator.integration.test.ts:157 and :268-269 and Service.integration.test.ts:1048. The new tests await Deferred signals at lines 205 and 245 before interrupting, so they synchronize on the event they need.
Stats
Claude findings: 11 · Codex findings: 3 · Confirmed: 12 · Refuted: 1 · Uncertain: 0
Models: claude-opus-5 + gpt-6-sol · Trigger: manual · Workflow run
This review runs once per PR. A maintainer can request another with a /ai-review comment.
The node:fs imports fail the required quality check.
## Summary - Reuse a Docker volume helper within each stack owner. Distinct owner identities prevent one CLI process from stopping another process's active snapshot. Interrupted helper commands retire only that owner's helper. - Reuse the recorded Docker daemon identity when its volume is present, avoiding repeated daemon probes during warm shadow diffs. - Reduce durability work for disposable shadow databases. Explicit stops still allow PostgreSQL to checkpoint before a snapshot. - Wait for shadow containers to stop and be removed before deleting their data. Namespace destruction attempts every service and reports any failures together. The snapshot directory copy changes from supabase#6709 are included in the merged develop base. --------- Co-authored-by: Julien Goux <hi@jgoux.dev>
Native database snapshots copy plain directory trees with one host command:
cpon macOS and Linux, orrobocopyon Windows. This speeds up the host snapshot copy used duringdb diff.The copy keeps metadata, rejects symlinks and special files through portable validation, and removes a partial destination after failure or interruption. Windows junctions are checked with
lstatand excluded fromrobocopy. Docker snapshots continue to use the volume helper.