Skip to content

fix(ui): the plan run's child gets no console on stdin (M14-02) - #291

Merged
sandgraal merged 1 commit into
mainfrom
m14/02-windows-stdin
Oct 19, 2026
Merged

sandgraal merged 1 commit into
mainfrom
m14/02-windows-stdin

Conversation

@sandgraal

@sandgraal sandgraal commented Oct 19, 2026 •

Copy link
Copy Markdown
Owner

Ticket

M14-02 follow-up (#288, merged c8d6f68). The UI server's plan-run child saw a terminal on stdin on Windows; the Windows run on main at c8d6f68 was red for this case (https://github.com/sandgraal/wowlab/actions/runs/39206897102).

Acceptance — with proof

  • The plan run's child has stdin closed and no terminal on every platform: UiServer._start now passes stdin=subprocess.PIPE and closes the writing end right after Popen (before the suspended Windows child is resumed), instead of DEVNULL, whose NUL device is a character device on Windows and reports isatty() True. test_ui_confirm.py::test_a_plan_run_never_carries_yes_and_runs_with_stdin_closed is kept as it was (tty False, stdin reads ""), with a comment on why; it passes locally.
  • Windows: windows.yml run https://github.com/sandgraal/wowlab/actions/runs/39209908024 success on 2f553eb.
  • ui suites plus lab/core/tests/review and tests/scripts/test_readme.py: 963 passed, 8 skipped. make lint clean.
  • make ci green: it ran in full on the M14-02 branch before feat(ui): the confirm flow on snap gc and doctor --yes (M14-02) #288; CI on this PR is the confirmation.
  • luadata.py, guard.py or another parser changed? No.
  • New external-format parsing? No.
  • New runtime dependency? None.
  • User-facing surface: none visible; n/a (no wiki page affected).

Invariants (AGENTS.md)

  • L1 reads never write: unchanged
  • L2 one write gate: unchanged; no write site added
  • L3 no Lua execution: n/a
  • L4 lossless: n/a
  • L5 game data keyed by build: n/a
  • L6 no flavor, product, interface or build constants: none added
  • L7 nothing ADR-0023 excludes: none touched
  • L8 real fixtures: no parser change; the existing test is unchanged; no live calls

Judgment calls

Claims for reviewers to test:

  • Before the fix, cli._interactive() would have counted doctor as interactive under the UI on Windows. This was latent because every UI run carries --json. The closed pipe gives the same guarantee (no terminal, EOF on read) on POSIX and Windows.
  • The writing end is closed right after Popen and before the suspended Windows child is resumed, so the child can never observe an open pipe with a live writer.

Reviews

Reviewed by: code-reviewer (narrow) CLEAN, no findings: "stdin closed" is now true on Windows, subprocess rules hold, _watch uses reader threads and never communicate(); the test failed on #288's Windows run 39206897102 (head d73111e, DEVNULL) for both [snap gc] and [doctor] on tty is False and passes on run 39209908024 (6763 passed, 437 skipped).

security-reviewer (narrow) CLEAN, no findings: the close cannot block (writer closed before the child has written anything and before the suspended Windows child is resumed); no descriptor leak on success or Popen failure (probe 50+50 starts, fd count unchanged); timeout, tree kill, output cap, env scrub, sys.executable argv and shell=False untouched; uv run --frozen pytest -q lab/core/tests/test_ui*.py 379 passed, 1 skipped.


session: 284d1153-c891-4b84-8e47-150842fac4ba
🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sandgraal
sandgraal marked this pull request as ready for review October 19, 2026 07:02
@claude

claude Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

@sandgraal
sandgraal merged commit 826ce3d into main Oct 19, 2026
12 of 13 checks passed
@sandgraal
sandgraal deleted the m14/02-windows-stdin branch October 19, 2026 07:03
sandgraal added a commit that referenced this pull request Oct 19, 2026
…-72; M14-09 pointers (#293)

## What

Conductor docs lane (ADR-0013 amendment, 2026-10-17): `docs/BACKLOG.md`
only.

- Ticks M14-02 (#288), M14-05 (#286), M14-06 (#287), M14-08 (#290).
- M14-02: a dated note on the Windows stdin follow-up (#291, 826ce3d):
why `DEVNULL` made the child's `isatty()` True on Windows, what changed,
and that Windows on `main` at 826ce3d is green.
- M14-08: a dated note from the #290 reviews (shipped-table colours vs
the ticket's "from the model" wording, which is an owner item; the
`aria-live` region; the `page.css` exemption in the colour grep test).
- M14-09: pointers from the #290 code review (the `loadGear` refactor,
the intro paragraph and allowlist test that change, the default-flavor
question, the `aria-live` narrowing).
- New tickets: M13-71 (`guard_bash.py`: `--input` bodies and the
substring allowlist match, from the #289 review; conductor lane) and
M13-72 (`char list --json` carries every full record under the Character
tab, and the colour grep's `page.css` exemption; from the #290 code
review, off that branch).

## Proof

- `grep -c '^## \[' docs/BACKLOG.md` → 87 headings; the four ticks are
the only `[ ]` → `[x]` changes.
- Pre-commit hooks green on the commit (merge-conflict check,
end-of-file).
- Rebased on `main` at 7415e07 (#289); the one conflict (M13-70 and
M13-71 both appended after M13-69) was resolved by keeping both.

## Reviewed by

`code-reviewer` CLEAN at cec1ea3 (every claim checked against main and
the CI history; the one nit, a blank line before M13-72, fixed in the
follow-up commit).

session: 284d1153-c891-4b84-8e47-150842fac4ba

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant