Interactive verbs explain non-interactive consoles instead of silent no-ops (#2097) - #2098
Conversation
…no-ops (#2097) In the PowerShell ISE, remote sessions, and redirected stdin, ReadLine() returns null immediately and stderr -- where these verbs put their prompts and failure lines -- is not surfaced at all. So --encrypt-password (the FIRST setup step) read as a hung tool, and the --configure-network wizard bailed with a misleading 'No changes made.' Both now write actionable guidance to STDOUT naming the cause and the paths forward (real console, or pipe the value in). The wizard tells EOF apart from an explicit quit: guidance + exit 1 vs the quiet 'No changes made.' + exit 0. Test drives the wizard with an exhausted reader (the exact ISE shape) and pins both behaviors. Closes #2097 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| var plaintext = Console.ReadLine(); | ||
| if (string.IsNullOrEmpty(plaintext)) | ||
| { | ||
| /* #2097: on a non-interactive host (ISE/remote/redirected stdin) ReadLine returns null instantly | ||
| and stderr is invisible — the guidance must ride STDOUT, the stream every host shows. */ | ||
| Console.Error.WriteLine("No password read from stdin."); | ||
| DarlingCliCommands.WriteNonInteractiveGuidance(Console.Out); | ||
| return 1; | ||
| } |
There was a problem hiding this comment.
Correctness: --encrypt-password conflates EOF with an empty interactive answer, so the new guidance can lie to a real console user.
var plaintext = Console.ReadLine();
if (string.IsNullOrEmpty(plaintext))
{
Console.Error.WriteLine("No password read from stdin.");
DarlingCliCommands.WriteNonInteractiveGuidance(Console.Out);
return 1;
}Console.ReadLine() returns null on EOF (the actual non-interactive signal) but returns "" when an interactive user just presses Enter at the Password: prompt without typing anything. string.IsNullOrEmpty treats both the same, so a real, interactive operator who hits Enter by mistake now gets told:
"This console appears to be non-interactive (PowerShell ISE, a remote/PSRemoting session, or redirected stdin)..."
which is false in that case and exactly the kind of misdiagnosis this PR is fixing elsewhere.
This PR gets the distinction right in ConfigureNetworkAsync (DarlingCliCommands.cs), which explicitly checks choice is null for EOF separately from choice.Length == 0 for a deliberate empty/quit answer — and the Prompt helper's own doc comment says as much: "Returns null on EOF (input exhausted); an empty line yields defaultValue (or "")." This verb should follow the same split, e.g.:
if (plaintext is null)
{
Console.Error.WriteLine("No password read from stdin.");
DarlingCliCommands.WriteNonInteractiveGuidance(Console.Out);
return 1;
}
if (plaintext.Length == 0)
{
Console.Error.WriteLine("No password read from stdin.");
return 1;
}Worth noting this path also isn't covered by the new test in DarlingCliCommandsTests.cs — that test only drives ConfigureNetworkAsync through its injectable TextReader/TextWriter, while this verb reads Console.ReadLine() directly in Program.cs and has no equivalent regression test.
Review summaryReviewed the diff (CHANGELOG.md, Darling/PerformanceMonitor.Darling.Service/{Program.cs,DarlingCliCommands.cs}, Darling/Darling.Tests/DarlingCliCommandsTests.cs). Scope check: this only touches Darling (interactive CLI wizard for What's solid:
One correctness bug found (see inline comment on |
Closes #2097 — implemented essentially as the reporter suggested.
Root cause (as diagnosed in the report, verified)
On non-interactive hosts (ISE, PSRemoting, redirected stdin),
Console.ReadLine()returns null instantly, and both verbs put their prompts and failure messages on stderr — which those hosts don't surface.--encrypt-password(the very first setup step) read as a hung tool;--configure-networkprinted a misleading "No changes made."Fix
WriteNonInteractiveGuidancewrites the explanation to stdout — cause + both remedies (real console, orRead-Host -Prompt 'password' | …for single-value verbs).--encrypt-password: null/empty read → guidance + exit 1 (stderr line kept for real consoles).q/empty keeps the quiet "No changes made." + exit 0. (Mid-wizard EOFs already print visible "Cancelled" lines on stdout.)> blob.txt) unaffected — guidance only appears on the failure path where stdout carries no blob.Test
Drives the wizard with an exhausted reader (the exact ISE shape): exit 1 + guidance on stdout; and pins that explicit
qstays quiet with exit 0.🤖 Generated with Claude Code