Root-cause and fix the four reported container regressions plus two adjacent confirmed bugs. - Memory balloon (CPU 100% + output freeze that never recovered): the autoballoon drove the whole-VM target from a per-container cgroup figure with no guest swap, spinning a swapless guest in perpetual direct reclaim. Default memoryManagement to off; make the target whole-VM-aware (reserveBytes) so it never inflates below the working set plus the guest's non-cgroup footprint; deflate the balloon on a failed stats read instead of freezing it inflated. - Stop button: signal the agent's whole process group (new vendored LinuxProcess.killProcessGroup, negative pid) so forked children die too; replace the unbounded wait() in every teardown/shutdown with a bounded terminate() that escalates SIGTERM -> SIGKILL; interrupt escalates to a group kill so a wedged agent always stops. - MCPApprovalServer port-0 race: single-flight start(host:) so concurrent sessions sharing one control-container server all receive the real bound port; publish listener+port only after .ready (a failed bind no longer pins a stale port 0); guard the Claude call site against port 0. - Container CPU metric: divide the CPU delta by the actual measured window instead of a fixed 200 ms, so it stops over-reading under load. - Command interceptor: drop the ~40 coreutil Node shims so cat/grep/etc run their native binaries (no Node-per-command); the bash tracer still records them as metadata. - Make the bash command tracer opt-in (commandTracingEnabled, default off) — the per-command DEBUG trap only activates when enabled; the git/gh interception the conflict/merge system relies on stays always-on. Co-Authored-By: Claude Opus 4.8 <[email protected]>
3.0 KiB
Vendored containerization — Nucleic patches
This is a vendored copy of apple/containerization
at upstream commit 6b7b42ca3efeee8c706070e4355e6a807c5336ae, referenced by the root Package.swift
via .package(path: "third_party/containerization") instead of the github URL.
It is vendored (not pulled) because we carry a local patch upstream doesn't have. Keeping it in-tree means the patch can't be lost to a dependency re-resolve.
What's changed vs. upstream
-
Sources/Containerization/LinuxContainer.swift— forward VM extensions.LinuxContainer.Configurationgains avmExtensions: [any Sendable]field, andLinuxContainerassigns it intoVMConfiguration.extensionswhen it builds the VM config. Upstream already supportsVMConfiguration.extensions+ theVZInstanceExtensionhook (configureVZ/didCreate), butLinuxContainer— the only entry point we use — never forwarded it, so there was no way to attach a device (e.g. a virtio memory balloon) to a container's VM. Search for the marker comment[Nucleic vendored patch]to find both edit sites.Nucleic uses this to attach a
VZVirtioTraditionalMemoryBalloonDeviceConfigurationand drive its target at runtime for automatic VM memory reclamation — seeMemoryBalloon.swift/ContainerEnginein NucleicCore. -
Sources/Containerization/LinuxProcess.swift— process-group kill.LinuxProcessgainskillProcessGroup(_:), which signals the negative pid (-pid) so the guest'skill(2)targets the exec'd process's whole process group, not just the leader. Every exec issetsid()'d byvmexec, so the process is its own group leader (pgid == pid) and a group signal reaches the children it forked. Upstream only exposes the leader-onlykill(_:), which let a forked child survive a Stop in a long-lived shared container. Marked with[Nucleic vendored patch]; used byContainerizedProcessHandle.sendSignalin NucleicCore. -
Trimmed for footprint (no behavior change).
Tests/,docs/,examples/, andimages/were dropped, and the corresponding.testTarget(...)entries removed fromPackage.swift. The library/executable targets we build are untouched.
Re-vendoring a newer upstream commit
git cloneupstream (or copy.build/checkouts/containerizationafter bumping the URL pin temporarily), check out the desired commit.rsync -a --exclude=.git --exclude=.build --exclude=.swiftpm --exclude=Tests/ --exclude=docs/ \ --exclude=examples/ --exclude=images/ <upstream>/ third_party/containerization/- Remove the
.testTarget(...)blocks fromthird_party/containerization/Package.swift. - Re-apply patch #1 (the
vmExtensionsfield + thevmConfig.extensions = …forward) and patch #2 (LinuxProcess.killProcessGroup(_:)). Grep for[Nucleic vendored patch]to find every site. - Update the commit hash above and in the root
Package.swiftcomment. swift buildand run the balloon tests.