Per-run logging scope: in-memory sink onto BuildContext (FT-6)#453
Draft
ChrisonSimtian wants to merge 4 commits into
Draft
Per-run logging scope: in-memory sink onto BuildContext (FT-6)#453ChrisonSimtian wants to merge 4 commits into
ChrisonSimtian wants to merge 4 commits into
Conversation
The active ParameterService is now the per-run instance held on BuildContext.Parameters; the static ParameterService.Instance becomes a facade over BuildContext.Current. This is the first service to ride the FT-2 rail: production and tests now exercise the same instance form (killing the test/prod divergence — tests already `new ParameterService(funcs)`), and the per-run instance + its mutable fields (ArgumentsFromFilesService / ArgumentsFromCommitMessageService) no longer leak across runs. A lazy fallback covers access outside a build run (no cross-run state to leak there); it can retire once that path is confirmed dead. Non-breaking — the static API is unchanged.
Four cases on the FT-4 seam: the static facade resolves the running context's instance, it falls back to a stable ambient instance outside a run, each run gets its own service, and a mutated per-run field does not survive into the next run.
Logging.InMemorySink is now owned per-run by BuildContext.LogSink; the static InMemorySink.Instance becomes a facade over BuildContext.Current, with a lazy ambient fallback for logging outside a run. ConfigureInMemory wires the sink at the top of the run and WriteErrorsAndWarnings reads it at the end — both inside the scope — so a build's warnings and errors are discarded with its context instead of resurfacing in the next in-process invocation. The FT-1 InMemorySink.Clear() on dispose is dropped: there is no shared sink left to clear. Clear() itself stays for explicit resets. The sink constructor becomes internal so a context (and a spec) can create its own. Non-breaking — the public Logging surface is unchanged.
BuildContextSpecs mirrors the FT-4 parameter-service cases for the sink: the facade resolves the running context's sink, falls back to a stable ambient sink outside a run, and each run gets its own. Two existing cases assumed a process-wide sink and had to move with the mechanism: - Dispose_runs_the_per_run_teardown used the shared sink as its witness and fails once dispose stops clearing it — it becomes Log_events_do_not_carry_into_the_next_run, asserting the guarantee directly (the next run's sink never saw the previous run's events); - Disposing_a_superseded_context_leaves_the_shared_state_intact drops its sink witness and keeps the resolver-config one, since the sink is no longer shared state. InMemorySinkSpecs now exercises its own instance rather than the singleton, so it no longer needs the process-global collection or a normalising reset between cases.
ChrisonSimtian
force-pushed
the
engine/ft6-logging-scope
branch
from
July 26, 2026 10:41
55bbddc to
42aa1da
Compare
ChrisonSimtian
added a commit
to ChrisonSimtian/Fallout
that referenced
this pull request
Jul 26, 2026
Runs a fixture build end-to-end, twice in one process, and asserts what the de-static work promised: both runs succeed, the second gets its own context/parameter service/log sink, it opens on an empty sink, and the static facades inside a run point at that run. This is what the original FT-9 commit set out to do. Its unit-level assertions have since landed with the steps they belong to (FT-2 in Fallout-build#451, FT-4 in Fallout-build#452, FT-6 in Fallout-build#453), so what is left here is the end-to-end case they could not cover — and it immediately found the leaked file-sink logger fixed in the previous commit. Verified as a real guard: reverting that fix fails 4 of these 5 specs. Two process-wide inputs are pinned to make a build runnable under a test host — the argument parser (swapped and restored) and the statically-resolved root directory (asserted to carry the .fallout marker, since UpdateNotification prompts for input without it). Both are de-statification candidates in their own right.
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.
⏳ Stacked on #452 (FT-4) — the diff includes its two commits until it merges. FT-1 and FT-2 have landed and are gone from the diff.
Engine de-statification ([Foundation] epic #315) — FT-6 / #311. Second service to ride the
BuildContextrail.Logging.InMemorySinkis now owned per-run byBuildContext.LogSink; the staticInMemorySink.Instanceis a facade overBuildContext.Current, with a lazy ambient fallback outside a run.ConfigureInMemorywires the sink at the top of the run andWriteErrorsAndWarningsreads it at the end — both inside the scope — so a build's warnings and errors are discarded with its context instead of resurfacing in the next in-process invocation.The FT-1
InMemorySink.Clear()on dispose is dropped: there is no shared sink left to clear.Clear()itself stays for explicit resets, and the constructor becomesinternalso a context (or a spec) can make its own.Tests — mirrors the FT-4 cases for the sink (facade resolves the run's sink, ambient fallback outside a run, each run gets its own). Two existing cases moved with the mechanism:
Dispose_runs_the_per_run_teardownused the shared sink as its witness and fails once dispose stops clearing it — verified against this branch. It becomesLog_events_do_not_carry_into_the_next_run, asserting the guarantee directly instead of via the reset.Disposing_a_superseded_context_leaves_the_shared_state_intactdrops its sink witness (no longer shared state) and keeps the resolver-config one.InMemorySinkSpecsnow exercises its own instance, so it leaves the process-global collection.Non-breaking — the public
Loggingsurface is unchanged;InMemorySink.Instancekeeps its signature and only changes which sink it hands back during a run. Full build + full spec suite green (14 projects, 0 failures;Build.Specs160 → 164).🤖 Generated with Claude Code