Repository navigation
[RT-E2] refactor: the launcher runs on its seams' clock, and shipped src bans the system clock - #442
Merged
Merged
Conversation
… the system clock (RT-E2 C) PosixServerLadder, the pump release and the taskkill tree kill now measure their bounds on LauncherSeams.Time; BoundedWait loses its system-clock overload. BannedSymbols.Clock.txt (14 entries) applies to the two shipped src projects only, with five counted composition roots exempted narrowly.
Blind-Striker
force-pushed
the
feat/rt-e2-c-launcher
branch
from
October 17, 2026 15:07
656db84 to
28eb395
Compare
This was referenced Oct 17, 2026
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.
What
The standalone launcher now measures every bound on
LauncherSeams.Time, and shippedsrccan no longer read the system clock outside five counted composition roots. This is RT-E2 PR C of three; A (#429, the background service) and B (#432, terminals) have merged.Closes
PosixServerLadder: itsStopwatchbecomesGetTimestamp/GetElapsedTime, its rawTask.Delaybecomes a provider delay, and its rootWaitAsyncgets the provider;The change
Launcher.
PosixServerLadderandTaskkillTreeKilltake a requiredTimeProvider.PipeOutputPump.ReleaseAsynctakes the owned child's clock.BoundedWaitloses itsTimeProvider.Systemoverload.LauncherSeams.ForCurrentProcesschooses the clock once and passes the same provider to the tree kill.The ban.
BannedSymbols.Clock.txthas 14 entries:Task.Delay×4;CancellationTokenSourcetimed constructors ×2 andCancelAfter×2;Stopwatch;DateTime.UtcNow,DateTimeOffset.UtcNow,Environment.TickCountandTickCount64;TimeProvider.System.Directory.Build.propscondition applies it toOpenCode.SdkandOpenCode.Sdk.Extensionsonly. Tests and tools keep their real-clock hang guards.DateTime.NowandDateTimeOffset.Nowstay banned everywhere inBannedSymbols.txt; listing them twice is RS0031.DateTimeOffset.UtcNowwas red first.Five composition roots, the D-C8 exemption count. Each is a
#pragma warning disable RS0030 // <reason>around the singleTimeProvider.Systemexpression:LauncherSeams.ForCurrentProcess);OpenCodeServer.BackgroundService.The suppression ledger records all five.
Real-time sites in hand-written
src: 12 → 6. What remains is the five roots andPosixChildExitWatch's 100 ms probe cadence, a polling cadence on a dedicated thread that RT-E6 owns. D-C8 does not banThread.Sleep.Second commit (the lead's scope addition).
BannedSymbols.txt's two.Nowmessages pointedsrcatUtcNow, which the clock ban now forbids there. They now read "Use the injected TimeProvider (src) or DateTime[Offset].UtcNow (tests)".Canon.
client-runtime.mdgets a paragraph naming every launcher bound onLauncherSeams.Timeand the D-C8 sentence.platform-and-packaging.mdgets a one-sentence relay.Proof
The ban. A deliberate violation in a
srcfile is red with RS0030 on net10.0 and net472, one spelling at a time:Task.Delay(TimeSpan);new CancellationTokenSource(TimeSpan);CancelAfter(TimeSpan);Stopwatch.StartNew();DateTimeOffset.UtcNow;Environment.TickCount64(net10.0 only; it does not exist on net472);TimeProvider.Systemoutside a root.The same
Task.Delayin a test file compiles and passes.msbuild -getItem:AdditionalFilesshows the clock file in both shipped projects and in no test or tool project.New seam proofs on
ManualTimeProvider. Each waits for its own armed bound (WaitForArmedAsync), then checks that the bound has not fired at bound − ε and has fired at the bound. The mutant class is "the bound removed while the signature is kept".PosixServerLadderTests.RunAsync_Should_Spend_The_Root_Grace_On_The_Supplied_Clock…_Should_Probe_Only_For_The_Grace_Remaining_On_The_Supplied_Clock…_Should_Bound_The_Forced_Root_Wait_On_The_Supplied_ClockOwnedServerChildTests.DisposeAsync_Should_Bound_Pump_Release_On_The_Owned_ClockTaskkillTreeKillTests.KillTreeAsync_Should_Run_The_Supplied_Bound_On_The_Supplied_ClockCompile-forced edits to existing tests. No test name or assertion changed:
TimeProvider.Systemfor the ladder helper, two lifecycleBoundedWaitcalls and the taskkill constructors;OpenCodeServerReadinessTests.AdvanceEarlyEndAsync, the manual clock now advances byPipeOutputPump.ReleaseBound, but only when that bound arms. Why it can arm there:Support/GatedStream, which ignoresDispose.StreamReader.ReadLineAsync()passes no token, so those readers end only when the 5 s release bound expires.Size. Production +25 lines, tests +202, against budgets of 160 and 380.
PublicApi.verified.txtis unchanged, and no internal type was added or removed.Checks.
OpenCode.Sdk.Tools.Testsproject (Category!=Packaging&Category!=NativeAot): green.Local check: GATE PASS on
656db84f(this branch on master3b235436): slopwatch, build, both format passes, clone-detector, verify-clones, 10,500 tests including net472 with 0 failed, and election.Reviews.
ArmedInbefore the product could have armed the bound, which was a race: the watch signal fires insideWatch, before the bound arms.ArmedInimmediately, against the "wait for the specific armed bound" rule.platform-and-packaging.mdchanged what "CancelAsyncis one" referred to.client-runtime.md.Need help on this PR? Tag
@codesmith-botwith what you need.