From 314cb5f4a57629c927927b230fabd5b43eecc635 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 7 Sep 2026 08:07:41 +0200 Subject: [PATCH] fix(headless): S7 report why a multi-session process never attaches the console A configured process with 2+ sessions and --console silently skipped console attachment (the plan's "single-session only for the first cut"), indistinguishable from --console simply having worked. Report it explicitly through the same HeadlessDiagnosticWriter.Message stream every other structured event already uses. TwoSessionsWithConsoleFlagReportsSingleSessionOnly was shown to fail against the silent-skip branch (mutation: the else-branch body removed) -- the diagnostics stream carried only the ordinary lifecycle/resource JSON lines, with no "single-session only" message anywhere. Co-Authored-By: Claude Fable 5.1 --- .../Hosting/HeadlessProcessHost.cs | 8 +++ .../HeadlessConsoleTests.cs | 52 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/src/AcDream.Headless/Hosting/HeadlessProcessHost.cs b/src/AcDream.Headless/Hosting/HeadlessProcessHost.cs index f0e10b2f5..323d80152 100644 --- a/src/AcDream.Headless/Hosting/HeadlessProcessHost.cs +++ b/src/AcDream.Headless/Hosting/HeadlessProcessHost.cs @@ -192,6 +192,14 @@ internal sealed class HeadlessProcessHost : IDisposable }; console = controller; } + else if (consoleEnabled) + { + // S7 (2026-09-07 review round): a silent skip here read as + // "--console worked" to an operator with no way to tell + // otherwise — the launcher's multi-session mode is a + // legitimate, common configuration, so say so explicitly. + _diagnostics.Message("console", "single-session only"); + } _console = console; _consoleRendererSubscription = consoleRendererSubscription; } diff --git a/tests/AcDream.Headless.Tests/HeadlessConsoleTests.cs b/tests/AcDream.Headless.Tests/HeadlessConsoleTests.cs index 3aded57cf..4a0b5f45e 100644 --- a/tests/AcDream.Headless.Tests/HeadlessConsoleTests.cs +++ b/tests/AcDream.Headless.Tests/HeadlessConsoleTests.cs @@ -564,6 +564,58 @@ public sealed class HeadlessConsoleTests Assert.Equal(expectDimmed, text.Contains("[2m")); } + /// + /// S7: a multi-session process with --console must tell the + /// operator why the console never attached (the launcher's multi-session + /// mode is a legitimate, common configuration) instead of silently + /// doing nothing — see HeadlessDiagnosticWriter.Message's "console" + /// category. + /// + [Fact] + public void TwoSessionsWithConsoleFlagReportsSingleSessionOnly() + { + // StandardInput credentials (one line per session, consumed by + // HeadlessCredentialResolver BEFORE the console reader thread ever + // starts — see HeadlessProcessHost's own constructor comment) avoid + // needing an ACE-shaped Environment credential just to reach the + // console-wiring branch this test targets. + HeadlessSessionDescriptor StandardInputDescriptor(string id) => + Descriptor() with + { + Id = id, + Credential = new HeadlessCredentialReference + { + Provider = HeadlessCredentialProviderKind.StandardInput, + Reference = "fixture", + }, + }; + var configuration = new HeadlessConfiguration + { + Version = 1, + Sessions = + [ + StandardInputDescriptor("one"), + StandardInputDescriptor("two"), + ], + }; + var operations = new FixtureSessionOperations(); + using var diagnostics = new StringWriter(); + using var input = new System.IO.StringReader( + "password-one" + Environment.NewLine + + "password-two" + Environment.NewLine); + using var host = new HeadlessProcessHost( + configuration, + HeadlessPathSet.Resolve(new HeadlessPathOverrides()), + input, + diagnostics, + operations, + new FakeTimeProvider(), + directCredentials: null, + consoleEnabled: true); + + Assert.Contains("single-session only", diagnostics.ToString()); + } + private static bool WaitForEndOfInput(HeadlessConsoleController controller) => controller.Reader.EndOfInput.Wait(TimeSpan.FromSeconds(5));