Repository navigation
fix(ptc): expose the session result cache inside a bwrap private /tmp - #338
Merged
Merged
Conversation
On Linux hosts where the sandbox selects bwrap, workspace-write children get a private tmpfs over /tmp. The result cache lives below the host's tmpdir(), so the confined PTC worker behind ops_result never saw it: every ref:// page failed with REFERENCE_EXPIRED and the session purge completed against an empty tmpfs, leaving the cache behind. Bind exactly that one private cache directory back into the bwrap argv for page/put and for the session purge. Other runners, read-only bwrap and Windows keep their argv unchanged. Refs #337
This was referenced Oct 20, 2026
bwrap accepts the private temp mount as either "--tmpfs /tmp" or "--tmpfs=/tmp". Recognize both spellings before adding the session cache bind, and keep every other runner argv byte-identical.
Assert the single-token bwrap form gains the same cache bind, and state what the Linux runner-shim check actually verifies: the cache bind lands before the wrapped program, not that a real private tmpfs exposes the cache.
# Conflicts: # docs/CHANGELOG.md
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.
Closes #337
What was wrong
On Linux hosts where
@deepseek-ai/dsh-sandbox-localselects bwrap (any distribution that does not restrict unprivileged user namespaces — Arch, Fedora, Debian…), everyref://result reference was unusable. The first call returned a reference, the nextops_result pagereturnedREFERENCE_EXPIRED: Reference cache is missing, expired, or destroyed.posixCacheLocation()keeps the session cache at<tmpdir()>/dsh-ops-results-<key>(0700, owner-checked).workspace-writeprofile mounts--tmpfs /tmpfor the child, so the confined PTC worker behindops_resultstarts in an empty private/tmpand never sees that directory. (The Native file worker is not confined, which is why the reference could be created at all.)completed, and leaves the blobs in the real/tmp.CI stays green because the Ubuntu runners restrict user namespaces, the bwrap probe fails, and the host falls back to Landlock, which shares the real
/tmp. On a bwrap hostmainfails 9 cases indocx-host,pdf-host,table-host,native-result,ptc-sdkandresult-storage-host; replacingbwraponPATHwith a stub that exits 1 makes the same tree pass.The change
src/kernel/result-storage.ts:exposePosixCache(argv, storage)adds--bind <cache> <cache>immediately before the runner's--separator, only when the runner isbwrap, its own options (not the wrapped program's) contain--tmpfs, and the storage is a POSIX location. The purge path applies it to its confined argv.src/ptc/worker.ts: the confined worker argv goes through the same function once storage is known.Only the one session directory is exposed, which is narrower than the Landlock profile's writable
/tmp. Landlock, Seatbelt, Windows (--tempgrant) and read-only bwrap (no tmpfs) keep their argv byte-for-byte. Deliberately not done: moving the cache into the workspace (#257 asks for nothing to be written there) or running the PTC worker unconfined.Validation
New checks in
test/result-storage-host.test.mjs:only a bwrap private /tmp gains a bind for the one session cache, before the wrapped program— argv transform, including the unchanged cases (Landlock, read-only bwrap,--tmpfsafter the separator, Windows storage, relative root, no storage).a bwrap-style private /tmp still sees the session cache for put, page and session purge— a runner shim namedbwraprecords its argv and execs the worker; asserts put, page and the session purge all carry the bind. This runs on CI without a usable bwrap. Withsrc/reverted it fails (and so does the existingreal host references …check on a bwrap host):With the change, real bwrap (Arch, bwrap 0.13.0, Rust 1.97.1 worker built from this tree):
## [Unreleased]entry (EN + ZH)package.jsonchangeCI (
pull_requestrun): see checks below; URL added once it completes.Environment
Arch Linux x64, kernel 6.18 LTS, bwrap 0.13.0, Node 24.21.0, Rust 1.97.1, upstream
main@a9ff940, built from source (npm ci --ignore-scripts,npm run build:ptc).PR-triggered CI: https://github.com/T-Auto/dsh-ops/actions/runs/39470903973 —
pull_request, aggregateCI required: SUCCESS (Windows x64, Linux x64, macOS arm64 and required supporting jobs passed).Combined local validation
The submitted heads of #338, #340, #341, #342, #343, #344 and #345 were applied together in an isolated local verification worktree, including their combined changelog entries. With ordinary PATH selecting real bwrap 0.13.0 and real dsh-TUI 0.16.1 host/worker/renderer suites enabled,
node scripts/verify-gate.mjs --skip-installpassed all 11 release-gate steps: 129 suites passed, 0 skipped; 46 Rust unit tests passed; manifest 73/59. This Linux combined-tree evidence is separate from each PR's own cross-platform CI; no upstream merge or host installation was performed.