feat(cache): add tar.gz pack/unpack helpers for remote-cache artifacts - #12
Merged
Conversation
Pure helpers that bridge the v10 on-disk layout and the Turbo /v8/artifacts wire body. Shells out to system tar (GNU on Linux, BSD on macOS, MS bundled on Windows 10+) via Bun.spawn — streaming stdin/stdout, no temp files. Public surface - packArchive(stageDir) → Uint8Array: tar+gzip everything under stageDir. - unpackArchive(buf, destDir): extract a tar.gz into destDir, mkdir -p first. - packAndDiscard(stageDir): pack then rm -rf the stage. Convenience. - tarPath(...segs): POSIX-safe join (normalizes backslashes, collapses //). - uniqueStageDir(parent, prefix): pid+timestamp-suffixed path for races. The caller (LayeredCache, next PR) stages a tree shaped per the remote-cache design doc: meta.json outputs/<project-relative paths> …then packs it for the wire, or unpacks the wire body back into a stage dir before materializing into the local cache. Tests: 12 new (209 total, up from 197). Cover round-trip, binary preservation, empty dirs, deep trees, ArrayBuffer input, error paths (missing source dir, corrupt tarball), tarPath edge cases.
3 tasks
Exelord
added a commit
that referenced
this pull request
Aug 24, 2026
The fourth output mode (Turbo parity, comparison gap #7): one line per task — outcome word, task id, cache key — with zero log output. The run's audit trail of which key each task resolved to. discardsOutput covers the new mode so output the mode promises never to print is never buffered, the same reasoning none already had. Pinned byte-exact (the exact-expected-set rule: a mangled leak sails past not.toContain) across success/hit/failure/skip, plus parse pins for both spellings and the typo message naming all four modes. The comparison doc audit that sourced this also surfaced two stale cloud references, corrected in place: gap #1 advertised the removed platform's S3 blob backend (now points at the archived design doc), and gap #12 claimed the deleted dashboard covers last-run replay — its removal raises that gap's value, and the entry now says so.
Exelord
added a commit
that referenced
this pull request
Aug 25, 2026
Comparison gap #12, closed the wave after its value was re-assessed: the deleted dashboard had been this gap's answer, and vx last is the CLI surface that replaces it. Bare = the most recent run (verdict, command, timing, branch @ sha, CI, counts, per-task table with failures first); vx last <runId> replays a specific run; --list[=N] prints recent run ids; --format json emits {invocation, tasks}. Entirely read-only over the existing metrics layer — zero new SQL, no config evaluation, no cache probe. The verb slots beside vx why: same DB-reading grammar, same parser conventions including why's flag-name-first lesson. Pinned e2e via bin.ts subprocesses (replay content, --list round-trip, a FAILED run with failures first, JSON shape, unknown-id fails loud pointing at --list) plus parser units for both flag spellings and every rejection message.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Pure tar+gzip helpers used by the upcoming
LayeredCacheto bridge the v10 on-disk layout and the Turbo/v8/artifactswire body.Implementation note: shells out to system
tarviaBun.spawn— streaming stdin/stdout, no temp files for the archive bytes themselves. tar ships with every supported platform (GNU/BSD on Linux/Mac, MS-bundled on Windows 10+), so this avoids adding a JS tar dep.What this enables (PR #11b)
The caller will build a stage dir matching the design doc layout:
…and
packArchive(stage)becomes the PUT body. On GET,unpackArchive(body, stage)reproduces the same tree, which the LayeredCache then materializes into the v10 local layout (DB row +<hash>/<rel paths>+logs/<hash>.{stdout,stderr}).Test plan
bun run format:check— cleanbun run lint— cleanbun test src/— 209 / 209 (was 197; +12)New tests (
src/cache-archive.test.ts)meta.json+outputs/survives pack→unpack with identical content.unpackArchivecreatesdestDirif missing.packArchiverejects on missing source.unpackArchiverejects corrupt tarballs.ArrayBufferandUint8Arrayinputs.tarPath: backslash normalization, double-slash collapse.https://claude.ai/code/session_016HXj6HW6bxSn8EYuKcxTD9
Generated by Claude Code