Repository navigation
devguard, runner, server: launch governed executions once under DevGuard (CSRG-U4) - #90
Merged
Merged
Conversation
…d (CSRG-U4) A prepared execution in a workspace that requires resource participation can now be launched instead of cancelled, when its owner has a launch helper: - codespace-devguard: BeginLaunch in a bounded owner session, sent once. Only a permit that comes with this attempt's committed record is a grant. AbandonLaunch reports a grant the owner holds no helper for. The helper's invocation comes from DevGuard's helper_command but is spawned by CodeSpace: it exposes the helper's arguments and its two private descriptors (permit carrier, transcript writer) and reads the transcript to its end. - codespace-pty: spawn_inheriting passes named descriptors through the pinned Codex PTY's inherited_fds path (Codex 0.154, unchanged). - runner: exclude_unrelated_except keeps exactly those two descriptors in the helper's pipe child; the PTY spawn makes them inheritable only for the spawn. PreparedExecution::launch_managed checks locally, sends BeginLaunch once, settles a lost answer with one lookup (cancel when still prepared, AbandonLaunch when committed and unclaimed), spawns the helper into the prepared slot and reads the transcript: READY then close is a running command; exec failure, refusal, failure or an end before READY is reported, the last three after the helper is reaped. The gateway and the worker do not use it yet. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… (CSRG-U4) With --devguard register and the new --devguard-launch-helper (the absolute path of devguard-launch from the DevGuard release that serves the socket), the execution owner launches each execution of a workspace that requires resource participation once, instead of cancelling it: - InProcess: the gateway's preparer launches through its launcher. - UDS: the gateway passes the helper's path to the worker it starts. The worker states `launch` in its Hello only with a registration and a helper, and answers one `launch` request per execution, which is never cached or sent again. A lost answer is an unknown dispatch for the process_id; a request that never left is owner_unreachable. - exec_command arms the workspace lease for dispatch and returns the process_id with dispatch_status confirmed or unknown, or the refusal of a command that did not start. Without a helper, U3's admit-then-refuse stays. - workspace_info reports governs_execution true when the owner is registered and has a helper. - check_helper accepts a group write only from root's group (wheel), which only root can do. - An uncertain launch reports that the owner holds no helper once its process has ended, so an unclaimed grant does not stay charged. Validation builds devguard-launch from the DevGuard client pin with DevGuard's own lockfile (cargo install --locked --git ... --rev) and names it in CODESPACE_DEVGUARD_LAUNCH_BIN; macos-core also runs the runner's launch tests. Gateway tests launch through the fixture authority and the real helper in both modes, on pipes and PTYs, with stdin, resize, termination and status, and check D6 with concurrent launches beside ordinary children of the same gateway. Documentation: the managed launch section and its Korean counterpart, and the helper's provenance in the upstream records. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…es (CSRG-U4) - A launch test in a process of its own checks that the owner holds neither of the helper's descriptors once the helper has started, on a pipe and on a PTY. - A governed process times out as any other, through CodeSpace's own timeout, on a pipe and on a PTY. - The registration participation's description no longer says that nothing is admitted or launched through the authority. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… it (CSRG-U4) `helper_bin` is used only by the adapter's native launch tests, which run on macOS. On Linux the test build left it unused, and CI's `clippy-adapters` failed with dead code under `-D warnings`. It now lives in the `native` module, beside its only callers. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…form's default path (CSRG-U4) CI's Linux integration job failed ten runner launch tests. In nine, the stand-in helper ended before READY: it was a `/bin/sh` script that redirects the carriers by number, and dash, Linux's `sh`, takes only one-digit descriptor numbers in redirections, while the carriers sit above 9 in a busy test process. The stand-in now runs under bash. The real helper is DevGuard's Rust program. In the tenth, `resolve_program` searched macOS's default path (`/usr/bin:/bin`) on every platform when the environment has no `PATH`, while glibc's `execvp` searches `/bin:/usr/bin`, so on Linux it could name a different file than the spawn would. It now uses the platform's default. Managed launch is not supported on Linux yet, so no execution reached this. The documentation's helper rule now states the group write by gid 0 that `check_helper` accepts. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
CI's macOS job failed the D6 test: DevGuard refused a governed launch of a later round with resource_unavailable. Each round was admitted while earlier rounds' attempts were still charged: DevGuard releases a launched attempt only once its reconciler has seen the scope end, and the test waited for that only after its last round. On the 3-CPU runner DevGuard's CPU work capacity is 480 m (3000 less 2000 of host headroom, 500 for the system and 20 reserved), nine 50 m attempts, which the rounds outgrew. With the request raised so that this Mac also holds nine, the unchanged test was refused the same way, with 0, 2, 4, 6 and 8 attempts charged at the round starts; waiting at the end of each round, every round started with none charged. The test now waits for, and asserts, each round's release. The product is unchanged: DevGuard refused, and CodeSpace reported a refusal that started nothing. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ADY (CSRG-U4) macos-core failed once here on a_governed_process_times_out_like_any_other: the launch was reported as not started (HelperEnded). The test set the request's timeout to 300 ms, and CodeSpace's timeout runs from the spawn, which is the helper's. Under the load of the parallel tests the stand-in helper had not reported READY by then, so the timeout ended it first and the launch was rightly reported as not started. With a 5 ms timeout the test failed this way in three runs of three. The test means a timeout of the running command, so it now allows 2 s (the command sleeps 30 s); the macos-core runner command then passed in five runs of five. The documentation now says that a governed execution's timeout runs from the helper's spawn, and so also covers the helper's exchange with DevGuard before READY. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
novelKR
marked this pull request as ready for review
October 9, 2026 14:25
novelKR
pushed a commit
to novelKR/DevGuard
that referenced
this pull request
Oct 9, 2026
CSRG-U4 merged in CodeSpace on 2026-10-09 as novelKR/CodeSpace#90 (3e5e3e8, at head c1c7859, whose CI passed in full; the merge commit has that head's tree). Record U4 as merged-verified with the units dated 2026-10-09, keep U5 and U6 not started, and say so in AGENTS.md, the milestone table and note, the planning index and the CS-RG plan, English and Korean. CS-RG stays in-progress with qualification not-run, and the suspension of the CSRG-C00-C09 plan is unchanged. Korean counterparts reviewed; planning-readme and planning-milestones-cs-rg hashes recorded. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This was referenced Oct 9, 2026
novelKR
pushed a commit
to novelKR/DevGuard
that referenced
this pull request
Oct 11, 2026
The owner directed CSRG-U5 to start on 2026-10-09, together with merging CodeSpace's test-timing cleanup, after CSRG-U4 merged in CodeSpace as novelKR/CodeSpace#90 (3e5e3e8), recorded here by #29. The cleanup merged as novelKR/CodeSpace#91 (470069c) on 2026-10-11 and U5 started that day. Record U5 as active with the units dated 2026-10-11, keep U6 not started, and say so in AGENTS.md, the milestone table and note, the planning index and the CS-RG plan, English and Korean. CS-RG stays in-progress with qualification not-run, and the suspension of the CSRG-C00-C09 plan is unchanged. Korean counterparts reviewed; planning-readme and planning-milestones-cs-rg hashes recorded. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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.
Requested by Seongjae
CSRG-U4: managed launch. A prepared execution in a workspace that requires resource participation is now launched exactly once under DevGuard:
BeginLaunchonce, a one-time permit, DevGuard'sdevguard-launchhelper started by CodeSpace's own pipe or PTY spawner, DevGuard binding and policing the helper's process group as the attempt's scope, then the payload. CodeSpace keeps spawn, PTY, process handles, output, timeout, termination and reaping. No Codex or DevGuard pin change.Issue
Scope: the CSRG-U4 section of the owner's U1–U6 order (DevGuard
docs/handoff/2026-10-02-cs-rg-u1-u6-instruction.md), with the standing rules of the U2 order (sections 1, 11–14) and the CS-RG handoff of 2026-10-03 (section 5). It does not close an issue. Tracking: #76 and novelKR/DevGuard#14.Base, head and pins
main, started frome0610c4(#89's merge, the DevGuard pin move to6e7e065)c1c785962fc830cb41519c202c24814c56edd6c40de8f6e(adapterBeginLaunch/AbandonLaunch/helper invocation, PTY adapterspawn_inheriting, runner launch flow and descriptor exclusion),6710f8b(gateway and worker wiring,launchwire op, CI helper build, docs),d1dc658(tests: the owner keeps no carrier once the helper started, timeouts of governed processes; the domain doc line),8894955(the adapter's helper lookup moved into its macOS-only tests, for Linux clippy),8bc8af0(the runner tests' stand-in helper under bash, for Linux;resolve_programon the platform's default path; the documentation's helper rule),d5ef68a(the D6 test lets DevGuard release each round before the next, for small hosts),c1c7859(the governed timeout test leaves the helper room to report READY; the documentation says where a governed timeout starts)6e7e065a0dd5b3876dc7f4546ab76069489937d1(devguard-client,devguard-contract; dev-onlydevguard-daemonfixture), unchangeddevguard-launchbuilt from that same commit with DevGuard's own lockfile (cargo install --locked --git https://github.com/novelKR/DevGuard --rev 6e7e065…); never linked6b9826e3aa83b1a5947db50f4332cb9c65f1b340(rust-v0.154.0), unchangedmain6e7e065at start;df3c537now (novelKR/DevGuard#28, ledger only: CSRG-U4 active). Nothing undercrates/changed since the pinSummary
Launch order (
PreparedExecution::launch_managed, after U3's preparation):process_id, PTY choice and deadline (U3); a usable helper; the program resolved to an absolute path on the execution's ownPATH; no Linux command sandbox and noEnablednetwork. A failure cancels the unstarted attempt (precondition: never launched).BeginLaunch, exactly once, in a bounded owner session (Register, thenBeginLaunch). Only a permit that arrives with this owner's committed record of this attempt and fingerprint is a grant (LaunchAnswer::Granted); any other answer isRefused(an error answer committed nothing, so the attempt is cancelled),NotSent(cancelled) orUnknown.helper_commandbuilds the invocation (arguments carry no secret; two private descriptors, the permit carrier and the transcript writer, close-on-exec in the owner). CodeSpace spawns it through its own pipe or PTY spawner as its direct child, into the prepared slot. The owner's copies of both descriptors close as soon as the spawn returns, on every path.exec_commandStarted)dispatch_status: confirmed; a lookup records what DevGuard applied per resource and the scope rootexec_failedPROCESS_SPAWN_FAILED; DevGuard settles the claimed grant through its scoperefused,failedor end before READYAbandonLaunch(helper_exited)dispatch_status: unknownfor theprocess_id; the transcript is still read, and the owner reports holding no helper once the process has endeddrainingandreleasedare represented and mapped from DevGuard's record when observed; U4 never cancels a committed launch, so it does not causedraining.No replay. After
Unknown, oneLookup: still Prepared →Cancel(not committed); LaunchCommitted without a scope →AbandonLaunch(grant_not_received), which DevGuard releases asno_helper_created(known not started); anything else reported as found; no answer →unknown.BeginLaunchis never sent again, and the prepared execution is consumed bylaunch_managed, so no second launch exists.AbandonLaunch(spawn_failed)covers a helper that could not be created. A report never releases a claimed grant.Execution owner per mode (the same owner as U2/U3; DevGuard requires the helper's parent to be the registered owner):
in-processPreparer::with_launcherbeside its ownInProcessRunneruds+--runtime-binlaunchrequest, stated aslaunchin the worker'sHelloonly when it registers and has a helper; never cached or sent again. A lost answer isdispatch_status: unknown; a request that never left isowner_unreachableuds+--runner-socketRESOURCE_POLICY_UNSUPPORTED), as in U2/U3Registration and identity mapping are U2's, unchanged. The helper's ticket names the owner's socket, consumer, generation, attempt ID and the owner's registered instance ID.
Participation policy.
requiredwith--devguard registerand--devguard-launch-helperlaunches under DevGuard; without a helper it is admitted and refused (MANAGED_LAUNCH_UNAVAILABLE, U3's behavior); without registration it is refused before anything exists.requirednever runs outside DevGuard.offis unchanged.Carrier choice and D6 (U4 sections 4 and 9)
Choice: DevGuard's own carriers (a socket pair holding the permit, its writer closed, and a pipe for the transcript, both created under DevGuard's
spawn_guardabove the standard three, close-on-exec), delivered by CodeSpace's spawners:tokio::process::Commandgetsexclude_unrelated_except: in the child, every descriptor above 2 except the two is marked close-on-exec (the Investigate descriptor inheritance between concurrent spawns on macOS #79 exclusion), and close-on-exec is cleared on the two only there. If either is not open, the spawn fails.inherited_fds, its descriptor-keeping path). The two are made inheritable in the owner's process just before that spawn and closed when it returns. During that window every other spawner in the process excludes unrelated descriptors from its children (pipe, PTY, patch helper, sandbox helper, worker spawn; audited bygrepof everyCommand::newin the gateway, runner and worker), and the Codex PTY child closes every other inheritable descriptor itself.Why this is the smallest choice satisfying N1 and N2: it uses DevGuard's existing carriers and helper unchanged and CodeSpace's existing spawners and #79 exclusion; no new backend, no CodeSpace PTY implementation, no change to process ownership. The alternatives recorded in DevGuard's W3 packet (a regular-file permit, results through the authority, FIFO readers) need DevGuard changes; Codex
ChildFds::Attachedneeds a pin past 0.157. With #79 merged, the condition W3 named for this choice (every same-process spawner excludes unrelated descriptors) holds, and the tests below check it rather than assume it.D6 controls, against CodeSpace's real spawners:
descriptors::only_the_kept_descriptors_reach_the_child(an inheritable fd and two close-on-exec "carriers": a plain child holds only the inheritable one; the guarded child holds exactly the two); gatewayconcurrent_launches_pass_their_descriptors_to_no_other_child(an inheritable socket held by every unguarded control spawn and by no CodeSpace child)the_executable_keeps_none_of_the_helpers_descriptors(real helper; payload probes 3..1023); gateway D6: no child holds a socket, and no child's environment or output contains the consumer secret; the permit never appears inDebug, arguments or errors (a_permit_never_shows_itself,an_invocation_names_its_two_descriptors_and_carries_no_secret)only_the_helper_receives_its_two_descriptors_and_the_command_none(stand-in helper lists exactly what it received: exactly its--permit-fdand--report-fd, pipe and PTY);during_a_pty_spawn_only_guarded_children_are_safe(inside the PTY window an unguarded child holds both, a guarded child neither)c1c7859: "12 governed launches and 24 ordinary children held no descriptor beyond stdio; the unguarded control held the inheritable descriptor 24/24")Pipe and PTY semantics (U4 section 8)
Tested on the governed path: PTY initial size 24×80,
process_resizeto 40×120, session leader with its controlling terminal (pgid == pid), stdin and output, EOF; pipe stdin, stdout and stderr through CodeSpace's pumps, process status, termination; timeout and termination use CodeSpace's own tasks unchanged. Differences from an ungoverned execution, documented:argv[0]is its resolved absolute path (DevGuard's helper execs by path), found on the execution'sPATH, or on the C library's default asexecvpwould when it has none;Contract changes
--devguard-launch-helper PATH/CODESPACE_DEVGUARD_LAUNCH_HELPER(absolute path; withregisteronly). The worker takes the same flag from the gateway. Feature-off CLI unchanged.exec_commandon a governed workspace now returns aprocess_idwithdispatch_status: confirmedorunknown, or a refusal. Messages end with "nothing was started" when no helper process existed and "the command was not started" when one did. No new error code:ADMISSION_UNKNOWNnow also covers a launch commit whose answer was lost and whose attempt stays unknown.resource_authority.governs_executionistruewhen the owner is registered and has a helper.launchop,launchedresult,Hello.launch(omitted when false).WIRE_PROTOCOLstays 7; the op is sent only to a worker that states it./tmpaside). Checked before every launch.Error mapping:
dispatch_status: confirmeddispatch_status: unknowncancelledMANAGED_LAUNCH_UNAVAILABLEcancelledMANAGED_LAUNCH_UNAVAILABLEPATH;EnablednetworkcancelledPROCESS_SPAWN_FAILEDcancelledRESOURCE_POLICY_UNSUPPORTEDBeginLaunchrefusedcancelledRESOURCE_UNAVAILABLE,RESOURCE_POLICY_UNSUPPORTED, elseRESOURCE_AUTHORITY_UNAVAILABLEBeginLaunchsession ended before sendingcancelledRESOURCE_AUTHORITY_UNAVAILABLEBeginLaunchno answercancelled,released, found, orunknownADMISSION_UNKNOWNwhenunknown, elseRESOURCE_AUTHORITY_UNAVAILABLEreleased(afterAbandonLaunch(spawn_failed))PROCESS_SPAWN_FAILEDreleased(unclaimed) orlaunched(claimed)BeginLaunchrefused /RESOURCE_AUTHORITY_UNAVAILABLEreleasedorlaunchedPROCESS_SPAWN_FAILEDlaunchedPROCESS_SPAWN_FAILEDlaunchlost after sendingdispatch_status: unknownlaunchnever sentnot_asked(owner_unreachable)RESOURCE_AUTHORITY_UNAVAILABLESupported and unsupported modes
in-processuds+--runtime-binuds+--runner-socketEnablednetworkSupported means the workload class whose processes end with the root. A descendant that outlives the root keeps the attempt charged; one CodeSpace reaps past before DevGuard observes it leaves the attempt suspect (CSRG-U5). On a pipe,
terminate_processand a timeout kill the root only, as before.Tests
Local validation ran on the owner's Mac (macOS 27.0, Apple M1, 8 CPUs; Rust 1.98.0) with
scripts/validate-upstream.py, against DevGuard's fixture authorities (the in-processTestAuthorityand thefixture_authorityprocess) and adevguard-launchbuilt from the pin, never the installed DevGuard service or its helper. Failed attempts are kept in the evidence set, each with the hypothesis stated before its re-run.On the final head
c1c7859:alllinux-isolationnot run (Linux only, CI runs it);integrationandunit-codex-runtimefailed on the worker's first launch, outside this PR (below)macos-core,macos-fork-raceintegrationandunit-codex-runtimeby hand, the worker launched once before the testscargo test --workspace(runner 105, gateway 30, store 47, domain 29, policy 21, protocol 4 and the integration tests), gateway--features devguard60 (5 ignored), runner 140 and domain 32 with--features devguard;runtime_binary6Ignored tests are the child halves of parent tests, which their parents run in separate processes.
CI:
d1dc658Rust / Clippy (adapters)on Linux,helper_binunused (a test helper only the macOS tests call; fixed by8894955);Rust / Integrationon Linux, 10 of the runner's 140--features devguardtests (fixed by8bc8af0); macOS cancelled by the next push8894955Rust / Integration: the same 10; macOS cancelled by the next push8bc8af0Rust / macOS contractsfailed the D6 test, a DevGuard capacity refusal (fixed byd5ef68a, below)d5ef68ac1c7859Rust / macOS contractsandRust / Integrationincluded, and the docs buildWhat the failures were (all found by tests; the only product change among the fixes is
resolve_program's default path, a defect in this PR's own new code):8bc8af0). Nine used a stand-in helper written for/bin/shthat redirects the carriers by number; dash, Linux'ssh, rejects descriptor numbers above 9 ("Bad fd number"). The same nine fail on macOS with the stand-in under/bin/dashand pass under bash, which it now uses. The tenth found a defect in this PR's newresolve_program: withoutPATHit searched macOS's default path on every platform, while glibc'sexecvpsearches/bin:/usr/bin; it now uses the platform's default. Linux registers nobody yet, so no managed launch reached it.d5ef68a). DevGuard refused a governed launch of a later round (resource_unavailable), and CodeSpace reported a refusal that started nothing, as it should. DevGuard's CPU work capacity on the 3-CPU runner is 480 m (3000 m less 2000 m of host headroom, 500 m for the system and 20 m of control reservations): nine of the test's 50 m attempts. The six rounds ran back to back while DevGuard had not yet released earlier rounds (it releases a launched attempt once its reconciler has seen the scope end). With the request raised so that this Mac also holds nine, the unchanged test was refused the same way in three runs of three, with 0, 2, 4, 6 and 8 attempts charged at the round starts; waiting for each round's release, every round started with none charged, its attempts released 0.73–0.95 s after its processes ended, and all three runs passed.c1c7859). It set a 300 ms request timeout, which runs from the helper's spawn; under load the stand-in had not reported READY in time, so the timeout ended it and the launch was reported as not started (HelperEnded), as it should be. A 5 ms timeout reproduces it in three runs of three. It now allows 2 s, and the macos-core runner command passed in five runs of five.Two failures outside this PR, macOS local only:
integrationandunit-codex-runtimefail or pass by chance with "worker socket not ready": tests that launch the worker binary wait about 2 s for its socket (the gateway'swait_for_socket,crates/codex-runtime/tests/runtime_binary.rs), and the first launch of each newly placed worker file takes macOS 2.2–2.8 s here (later launches 11–23 ms; a byte-identical copy 1.3 s and a new hard link 1.0 s also pay it). Every cargo command that includes the worker places it again. With the worker launched once first, both stages pass. The gateway's DevGuard tests already launch their worker once for this reason (CSRG-U2); U3's validation met the same failure.codespace-runnerlinux_sandbox::tests::prepare_stdout_flood_is_too_large(unchanged since Investigate descriptor inheritance between concurrent spawns on macOS #79) timed out once under load incargo test --workspace: its stand-in writes one byte perprintfand must fill 64 KiB within the 2 s prepare bound. It runs on Linux in CI'sIntegration, not inmacos-core.Earlier heads:
6710f8b: u4-local-1;d1dc658: u4-local-2 to u4-local-4;8894955: u4-local-5 to u4-local-7;8bc8af0: u4-local-8 to u4-local-10;d5ef68a: u4-local-11 to u4-local-13. u4-local-4 is void: a source file was edited while it ran (the fix for CI's clippy failure).Verified: the launch flow, refusals, lost answers, the carriers and D6, pipe and PTY semantics, timeouts and termination on macOS against the fixture authority and the real helper; the same flow on Linux with a scripted authority and the stand-in helper (CI); feature-off builds and tests.
Not verified: managed launch on Linux (unsupported until DG-LINUX); the installed DevGuard service (never used); descendants that outlive the root, observation before reap and release paths (CSRG-U5); qualification (CSRG-U6).
Security scenarios
Debug; the adapter'sPermitcannot be cloned or printed and is consumed by the invocation.requirednever runs a command outside DevGuard; every failure before the helper's READY is a refusal, and uncertainty is reported asdispatch_status: unknown, never as success or as "not started".Dependency delta
crates/pty: dev-dependencylibc = "0.2"(already in that lockfile; one line added tocrates/pty/Cargo.lock). No product dependency change.devguard-launchis built from the pinned DevGuard source only by the validation stages; it is not a CodeSpace dependency, and no product graph contains it.scripts/upstream_dependencies.py,aarch64-apple-darwin, development edges excluded): all nine (root, root+devguard, codex-runtime, codex-runtime+devguard, devguard, pty, patch, file-system, linux-sandbox) have the same packages and edges asmaine0610c4, and no violations (u4-local-14, onc1c7859).Feature-off result
Without the
devguardfeatures the managed-launch code is not compiled (launchmodule, wire op, CLI flag); the pipe and PTY spawners take the same paths as before;cargo test --workspaceand the feature-off runner tests pass (u4-local-14: clippy without features passed; u4-local-16:cargo test --workspacepassed, runner 105 and gateway 30 without features).Rollback
Revert this PR. Operationally, without reverting: drop
--devguard-launch-helperto return governed workspaces to U3's admit-then-refuse, or setresources.participationtooffto run them ungoverned as before. Processes already launched remain CodeSpace processes; DevGuard settles their attempts through their scopes. No stored data or wire version changes (a U3 worker withoutlaunchis driven as in U3).Out of scope
wait_for_socketandruntime_binary.rs, and the timing ofprepare_stdout_flood_is_too_large(see Tests); candidates for a separate change.RESOURCE_UNAVAILABLEalthough earlier ones have ended (seen in the D6 analysis above: nothing released while rounds ran back to back for about 2 s). Faster release belongs to CSRG-U5's release paths.