Skip to content

Per-run logging scope: in-memory sink onto BuildContext (FT-6)#453

Draft
ChrisonSimtian wants to merge 4 commits into
Fallout-build:mainfrom
ChrisonSimtian:engine/ft6-logging-scope
Draft

Per-run logging scope: in-memory sink onto BuildContext (FT-6)#453
ChrisonSimtian wants to merge 4 commits into
Fallout-build:mainfrom
ChrisonSimtian:engine/ft6-logging-scope

Conversation

@ChrisonSimtian

@ChrisonSimtian ChrisonSimtian commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

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 BuildContext rail.

Logging.InMemorySink is now owned per-run by BuildContext.LogSink; the static InMemorySink.Instance is a facade over BuildContext.Current, with a lazy ambient fallback 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, and the constructor becomes internal so 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_teardown used the shared sink as its witness and fails once dispose stops clearing it — verified against this branch. It becomes Log_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_intact drops its sink witness (no longer shared state) and keeps the resolver-config one.

InMemorySinkSpecs now exercises its own instance, so it leaves the process-global collection.

Non-breaking — the public Logging surface is unchanged; InMemorySink.Instance keeps its signature and only changes which sink it hands back during a run. Full build + full spec suite green (14 projects, 0 failures; Build.Specs 160 → 164).

🤖 Generated with Claude Code

@ChrisonSimtian ChrisonSimtian added the target/vCurrent Targets the current version label Jun 30, 2026
@ChrisonSimtian ChrisonSimtian added target/vNext Targets the next calendar-version and removed target/vCurrent Targets the current version labels Jul 20, 2026
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
ChrisonSimtian force-pushed the engine/ft6-logging-scope branch from 55bbddc to 42aa1da Compare July 26, 2026 10:41
@ChrisonSimtian ChrisonSimtian added target/vCurrent Targets the current version skip-changelog and removed target/vNext Targets the next calendar-version labels Jul 26, 2026
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-changelog target/vCurrent Targets the current version

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant