Repository navigation
review: capture-intent race, preview 404, silkd session identity, compat removals, docs, cuts - #457
Merged
Merged
Conversation
…ptures the claim A capture waiting on the transition can win it before the failed capture's background settle; it then saved the paused guest, so a later adoption of the hibernate snapshot restored memory older than the disk.
… pool error map The preview proxy mapped three pool errors by hand and answered every other one 502 with an Error log, so a tab polling a released sandbox logged an error per request.
…es that session A removed session's command can see its shell die long after the removal when a setsid child keeps the pipe open; removing by id then killed a session recreated under the same id.
A body of exactly MAX_FRAME bytes passed render_frame but overflowed the Go scanner and the Python reader, which count the newline, killing the stream instead of answering an error frame.
The shipper then lands from the oldest kept line and the lines in between are lost; the API doc promises a collector never loses a window silently.
…godocs to the code
…tion, use stdlib names and imports in tests Moves only: utility funcs below type blocks (sdk keepalive, port, silkdtest, e2e harness, guestserver, rpcbench, mcp tools with the server methods in server.go), MoveOut ahead of Sandbox. Logger tags pool.lift, server.router.fail, usage.shipper.drain/read; tapOf names the inspect call.
… and the PoolResult alias stampIdentity, confirmGone, roundBytes/roundTimeout, fenceGuest and pullFrom fold into their one caller; Prebind's guarded check cannot fail once a pool policy exists; TemplateDigest is never encoded; DefaultMoveDowntime has no reader outside pool. Buffered exec decodes into one scratch buffer, GuestFile appends without a copy, and the volume patch slices omit when empty.
…and the lsp name filters a guest root caller can bypass anyway
… sizes as Go and Rust do
… run skip the cache
…s out, and reuse the shared helpers refillkick's elapsed check is always zero under synctest; a RunParallel worker reports with Error, not Fatal; waitFile fails the test instead of returning; the fetch-cache check names cacheDir; tuneView's shallow copy gives way to editView; dead fields, parameters and a mutex that guards nothing go.
…eping claim wakes it Every silkd since #198 serves RPCs back to back, so the SDKs send the request on their first dial and park the connection without asking. The reader router no longer holds a lone info frame for a pipelined call: info always wakes the claim, since a reader would answer with its own processes and uptime.
…nly and the Python mount=False Per-entry attach_only gives the same claim; nothing outside this repo sends the legacy flag.
…cargo already does, and the image version defaults silkd builds with the pinned toolchain minus rustfmt, clippy and the toolchain file's x86_64 target, as boot/init does since #456; the release profile strips, so the Dockerfile and release workflow no longer strip again. boot, base and android take their version args from the Makefile and CI only, so a bare build fails loudly instead of building from a stale pin. PATCHES becomes PATCHES.md, which the image hash already skips.
…onger did it legacySandbox kept these fakes on a dial per call; without it a second call could take the parked connection the fake is about to close.
CMGS
added a commit
that referenced
this pull request
Nov 5, 2026
…ion and pty, compat cuts (#469) * engine: read cocoon daemon's opening snapshot of a node past 3,000 VMs cocoon sends every VM record in the sync event's one data line, about 300 bytes a record, so the 1 MiB line cap broke the stream at every connect on a full node and liveness fell back to polling vm list for good. * pool: record a release's usage event once the release commits, not after its teardown The claim is durably gone at the commit; a restart or crash during a slow teardown (volume quiesce, vm rm) left a claim event with no release, which the folding rule bills up to the claim's deadline. * pool: load a forked claim's tenant for operator forks too, so its cap applies The quota check reads the tenant cache only; an operator fork skipped the lookup that fills it, so after a cache flush or restart the tenant's max_claims read as none and the fork overshot it. A removed tenant still does not stop the operator. * pool: answer an invalid PUT /v1/pools spec as invalid config naming its pool, not as a bad fork count * server: count a checkpoint claim handed to a peer in sandboxd_claim_redirects_total * test: fix the pool benchmarks the claim index and running count broke, and run every benchmark once in go-test Four benchmarks seeded claims around addClaimLocked or without a store row and failed the cleanup invariants; no CI step ran -bench, so nobody saw it. * cut: drop the info frame's proto field and the keep-alive constant nothing reads since the SDKs stopped probing * cut: resolve a claim's egress layers from its recorded layer alone, dropping the live-pool fallback for records older than the field Every claim records its layer at commit since #216 and adopt and move carry it, so the fallback served only pre-#216 records; the Pooled callback threaded through outbound existed for it alone. * pool: keep a claim's last replica attempt across ticks it cannot replicate replicateOnce dropped the attempt time whenever a claim was hibernated, archiving or settling, so a claim that idles and wakes inside every interval never came due, had no registry row, and was lost with its node. * cut: decode request bodies, config and MCP tool arguments with json/v2's exact names, dropping the v1 case-insensitive matching the v2 move kept A case-variant key is now an unknown member: config and strict bodies reject it, other bodies ignore it. * silkd: end a session command when its shell exits, not only on the shell's stdout EOF A background job started in the session holds the stdout pipe past the shell, so an exit, a set -e failure or an OOM kill of the shell left the command hung, its session's io lock held and the session never reaped. * silkd: open the pty master and slave close-on-exec so the shell and its jobs do not inherit them libc openpty leaves both fds inheritable; every pty shell held a spare master, so a job outliving the shell never saw its terminal hang up. * docs: match the docs and godocs to the code after #457 and #459-#467 Drops the Python mount row and the pre-proto-2 sentences #457 left, the images trigger path, and the old-template digest note; corrects the data_dir entries, the drain error, the shared-store probe, idle upstream conns, env snapshot reads, lineage markers, secret valuation, exit codes, Ready, the tenant_claims help, Metas, the checkpoint fallback and the Python lookup and keep_alive docs. * review: delete restating comments and fold over-long ones to the one fact the code cannot carry * cut: inline single-caller helpers in the reader router, SDK and silkdtest, drop an unreachable preview guard and lint exclusions for directories that do not exist * test: settle refills before counting clones, fail fast on a claims load error, scope table contexts to their subtest, cover every decoder with a fixture, and drop dead or always-true checks The fixture test now ranges the decoder tables instead of a hand list a new verb could miss; the watcher garbage test asserts the error it promises; smoke and bench tools type their 409 check and stop racing the handshake reassignment. * pool: refuse a move while a failed save capture is still settling moveBlocker refused an unsettled hibernate intent but not an unsettled save; a move that won the transition over the save's settle carried SaveSnap to the target and left a listed fork snapshot on the source that the startup sweep keeps.
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.
Whole-repo static audit of
mainat e897bbe: every source file re-read in full under the style, comments, modern-Go, correctness, simplify/LOC, perf and ownership lenses, all 13 declared flows re-read in full (not only changed windows) under correctness, perf and judge, every doc checked statement by statement against the code. No hardware or E2E run in this round.Bugs fixed (each with a test that fails on the old code)
exportSourceandforkSourcesettle first, as hibernate and wake already do; zero cost when no intent is set.TestACaptureSettlesTheIntentAFailedHibernateLeft(fork and checkpoint): old code saves the guest and leaves the intent unadopted.TestPreviewAnswers404ForAReleasedSandbox: old code answers 502.setsidchild kept the pipe open pastsession_rm, the late EOF killed a session recreated under the same id.a_dead_session_command_leaves_a_recreated_session_alone: old code answersno such sessionfor the recreated one.render_frameallowed a body of exactlyMAX_FRAMEbytes; the Go scanner and the Python reader count the newline, so such a frame killed the client stream instead of producing an error frame.render_frame_counts_the_newline_against_the_cap.sandboxd/moves/pg(#445) was never run in CI with a database. Run locally against PostgreSQL 17:TestRegistryContract,TestCellsKeepTheirOwnRecords,TestADownDatabaseIsUnavailablepass, no SKIP.Removed on the owner's ruling (no backward compatibility)
ServeConnOnceand the proto parameter leave silkdtest. The reader router no longer holds a loneinfoframe for a pipelined call:infoon a sleeping claim always wakes it, since a reader would answer with its own processes and uptime (TestSleepingInfoAfterAReadWakesfails on the old routing). Guests captured before sdk/go: keep a handle's relay connection across calls #198 now get one RPC per connection and the SDK reports their close as an error.volumes_attach_only,WithVolumesAttachOnlyand the Pythonmount=False. Per-entryattach_onlymakes the same claim; nothing outside this repository sends the claim-wide flag.PATCHESbecomesPATCHES.md, which the image hash already skips. Cost: merging rebuilds the silkd carrier and the os-images; the boot image changes only an ARG default the builds always override.Cleanups
warm: 0default, not the watermark), root-only move endpoints,GET /v1/infosample, preview token keys, volume claims refuseWithArchiveOnExpiretoo, reader lane,egress_bytesfor tunnels cut by a stop; godocs forSecretSpec,VersionWarning,byID,probeReady,SweepStaging,archives.Put,PoolSpec, silkdReady,guestExecPATH, rpcbench, the LangChain toolkit and boot init.server.go),MoveOutahead ofSandbox; logger tags name the real function (pool.lift,server.router.fail,usage.shipper.*);tapOfnames the inspect call.stampIdentity,confirmGone,roundBytes/roundTimeout,fenceGuest,pullFrom), a guard that cannot fail inPrebind, a JSON tag nothing encodes, thePoolResultalias, buffered exec decodes into one scratch buffer,GuestFileappends without a copy, volume patch slices omit when empty; silkd drops the detached stdin flag, an#[inline]hint and lsp name filters a guest-root caller could bypass anyway; the Python SDK drops an unreachable status check and names its chunk sizes as Go and Rust do.b.Fatalin aRunParallelworker, a silent wait timeout, a literal instead ofcacheDir, a shallow-copy view helper replaced by the cloning one, dead fixture fields.protocol/**(its build context issilkd/), and a manual silkd run can skip the cache.Numbers
Production -186 net (excluding the 18 test lines inside
silkd/src/proto.rs), tests -137 net, docs +31 -36, CI and image files +15 -19. Comment lines in Go and Rust: +30 -51.Coverage
ReaderSafe(#455 fix)Gates
GOWORK=off make go-lint(5 modules x linux/darwin): 10 x0 issues.asl -forwarder=false ./...on both GOOS, all 5 modules: cleanmake lint+make test(Rust) on macOS and inrust:1linux/arm64: greenruff format --check,ruff check, pytest under Python 3.12: sdk/python 278, openai 10, langchain 15 passedGOWORK=off make go-test(race), all 5 modules: green at ef52a34 (the wire-parity test caught a tag change, reverted in that commit)moves/pgagainst PostgreSQL 17 locally: 3 tests pass, no SKIPKept without code
skipIdle,finalPauseforwarders: the names carry the predicate and the estimate.Removeanswering "vm not found" as an error: the test pins it; returning nil changes the engine contract.resolveVolumesandVolumeSpec.directIO: guards at an exported package boundary.readChunkvsio.ReadFull: not equivalent when the last read returns data with EOF.claimusage event: the client never received that claim.readeroff: one extra wait per sleeping claim, until its next wake.m.mu,settlePendingSnapwrapper, template key filter, egress empty-Layerfallback: earlier rulings stand.fs_replaceregex on the runtime, egress usage append before the response, VM-event scan under the manager lock): need a measurement before code.