Repository navigation
fix(shell): preserve Python stdio env defaults - #115
Conversation
Merge task environment overlays without dropping shell defaults. Resolve explicit Windows variable overrides case-insensitively while retaining child environment sanitization. Verification: sandbox tests 23 passed, 0 failed; native Python tool tests 2 passed, 0 failed for each of system Python 3.14 and bundled Python 3.13.14; Git Bash shell regression 1 passed, 0 failed. Restoring the old builders made both native tests fail for both interpreters. Signed-off-by: zhuowp <9426526+zhuowp@users.noreply.github.com>
JensenChen28
left a comment
There was a problem hiding this comment.
Standards
No findings. The overlay reuses the single-variable builder; Windows casing handling is platform-scoped, and execution still uses the existing child-environment sanitizer.
Spec
No findings. Empty and non-empty overlays preserve the shell UTF-8 stdio default, explicit overrides remain possible, and foreground/background/PTY/interactive/encoded retry paths share the corrected builder. Python file/default-text encoding is unchanged. Tests cover the reported failure modes and disclose native opt-in requirements.
Validation: reviewed both changed files and production consumers, checked repository/TUI guidance, whitespace, and a read-only integration simulation against the current maintenance branch. Current-head fork CI is green. I did not run Cargo or native Python integration tests locally; the reported 23 sandbox and interpreter regressions are author-provided evidence, not this reviewer's executions.
Summary: Standards 0 findings; Spec 0 findings. Approval covers this candidate only.
|
CI follow-up: the |
asto18089
left a comment
There was a problem hiding this comment.
Round-1 review (fresh, 5 parallel lanes + local verification)
Rebase state checked first: head 104649398 sits directly on the current pinvou3-clean tip 083cebfd9 (merge-base == base head), so no rebase was needed.
Verified correct
- Root cause TRUE, fix complete for the claimed scope. Old
with_envdidself.env = env, and the overlay attools/shell.rs:2184/:2303is unconditional, so the WindowsPYTHONIOENCODING=utf-8seed (windows_shell_default_env,sandbox/mod.rs:298) was wiped on everyexec_shellcall, not just hook/task-overlaid ones — the body actually understates the blast radius. All four claimed paths (foreground sync, background/PTY viaapply_to_pty_command, interactive, encoded PowerShell retry at:2245-2254) route through the fixed builder and now preserve the seed; no remaining clobber path exists (only.env =left is MCP config; terminal_session struct literal is unix-only). - Elegant, no reinvention. Production code is byte-identical to upstream codewhale-hq#7041 (fork adds a 2-line comment); the fork's test set is a superset of upstream's. Minimal diff, correct
retainsemantics (matches Rust std's WindowsEnvKeyASCII case folding and the repo's ownchild_env::normalize_key). - No smuggling. Exactly 2 files, every hunk on-topic. Commit message conventional, DCO signs off.
- Sanitizer preserved.
child_env.rsuntouched; hook/task vars were already injected as trusted overrides under the old replace semantics, so the merge can only add back the constantutf-8default — no weakening path. - No caller regression. All 3 production
with_envcall sites audited: two want merge (the fix), one is a map-onto-itself no-op. Off-Windows the change is provably a no-op (seed map is empty ⇒ replace ≡ merge). Perf: worst case ~30×30 ASCII compares per spawn — negligible. - Linux verification. Full
cargo test -p codewhale-tui --libon this head: sandbox 84/84, shell-tool 125/125, ~12.2k total identical to base (+1 = the new passing test);cargo fmt --checkandgit diff --checkclean. (Tworuntime_apistack overflows and a fewremote_controlflakes reproduce identically on base083cebfd9— pre-existing environment issues, not this PR.) - Required checks (
Check Signed-off-by,gate,Gitleaks,check) all green; parent integration PR codewhale-hq#750 registers the topics/fingerprints correctly.
MAJOR
M1 — forkguard_windows_shell_env_overlays_keep_python_stdio_utf8 can pass with the bug reintroduced; its mutation kill is environment-dependent. (sandbox/mod.rs:974-1022) Unlike the two opt-in tests in tools/shell/tests.rs:284-285, this test sets no parent sentinel. It spawns via apply_to_command → sanitized_child_env, which passes the parent process env and the Windows registry Environment keys (both allowlisted for PYTHONIOENCODING). Revert with_env to self.env = env on any machine whose process env or registry carries PYTHONIOENCODING=utf-8 — the standard workaround for exactly this garbling bug, and therefore likely present on machines that run Windows regressions — and the child still prints utf-8, the assert passes, and the buggy code ships green. Please add lock_test_env + EnvVarGuard::set("PYTHONIOENCODING", "gbk") here, mirroring the opt-in tests, so the kill is deterministic. This matters doubly because parent codewhale-hq#750 fingerprints these test functions as fork-behavior pins; a self-satisfying pin is worse than none.
M2 — No CI lane will ever run any of the four Windows-gated tests on pinvou3-clean; say so plainly in the PR body. fork-ci.yml (the only workflow triggered on pinvou3-clean PRs/pushes) is ubuntu-only (all three jobs runs-on: ubuntu-latest); the windows-latest legs in ci.yml trigger only on master/main. So on this branch, the only mutation-killing test CI executes is the cross-platform builder test command_spec_env_overlays_preserve_existing_values — which covers the merge but neither the #[cfg(windows)] retain nor any end-to-end encoding behavior. The Windows verification in the body is honest but dev-machine-only; one sentence in the body making that explicit (and noting upstream codewhale-hq#7041's CI as the eventual net) would close the gap. Adding a Windows lane is the maintainer's call; the disclosure is the ask.
MINOR
- m1 —
linkcheck is red. The body has neither a closing keyword norNo-Issue:. Not a required check, but every recently merged fork PR (#107, #108, #111, #112, #113) carriesNo-Issue:— one line, e.g.No-Issue: mirrored upstream codewhale-hq#7041; parent integration tracked in Pinvou/pinvou-agent#750. - m2 — "Sandbox tests: 23 passed" is not reproducible from any natural filter. At this head,
sandbox::testscounts 19 Windows-compilable tests; the wholesandbox::module counts 59. If 23 came from a specific filter or command, please state it in the body (the same figure propagates to upstream codewhale-hq#7041 and the parent register). - m3 — Residual garble path outside this PR's claim (pre-existing, follow-up candidate): the read-only hardened lane builds
CommandSpec::programwith an empty env (tools/shell.rs:2172-2179), sopython script.pyunder a read-only policy on Windows still runs with locale stdio encoding; same for thecodew sandbox runCLI path. Not this PR's scope and not a regression — worth an issue if the codewhale-hq#4202 objective is "all Windows Python stdio is UTF-8".
NIT
windows_python_stdio_fixture's bareis_powershell()assert (tools/shell/tests.rs:215-219) panics without a message when the opt-in command is run from Git Bash (SHELLis set → dispatcher picks bash). A message pointing at "run from PowerShell/cmd" would save the next person a confusing failure.- The sandbox e2e test drives
cmd.output()directly, so the 30 s spec timeout is never enforced (a wedged shell hangscargo test). Matches the existingforkguard_powershell_encoded_spec_*convention, so noting only for awareness.
Verdict: REQUEST CHANGES — the code fix itself is correct, complete for its claim, and regression-free; the two MAJORs are about the durability of the regression net this fork's guard model depends on, and both are small fixes (a sentinel + a body sentence). Everything else can ride along in the same push.
Signed-off-by: zhuowp <9426526+zhuowp@users.noreply.github.com>
|
Round-2 update:
Final local verification: default filter 23/23, native foreground/background 2/2 with system Python 3.14 and 2/2 with bundled Python 3.13.14, separate Git Bash probe 1/1; workspace formatting and whitespace checks pass. Parent architecture and fast fork guard checks also pass (229 registered behavior names). Parent codewhale-hq#750 still awaits this PR's actual squash-merged maintenance SHA and the separately reviewed dependency-advisory fix codewhale-hq#747; its public submodule gate remains unchanged. Please re-review this candidate. |
JensenChen28
left a comment
There was a problem hiding this comment.
Reviewed current candidate af50096ff and the complete two-file increment from 104649398, together with the original environment fix and current review discussion. APPROVED.
Standards
0 new findings. The production builder/sanitizer is unchanged. The default Windows probe now serializes environment changes and installs a GBK parent sentinel before running, so an inherited UTF-8 workaround cannot satisfy the test after reverting the fix. Tokio timeout plus kill_on_drop bounds the direct child. The opt-in fixture now explains the PowerShell/SHELL requirement.
Spec
0 new findings. Both round-one major requests are addressed: the regression is structurally independent of the inherited UTF-8 workaround, and the body explicitly discloses Ubuntu-only maintenance CI, author-local Windows evidence and the pre-existing direct-program/read-only boundary. The exact substring filter and No-Issue entry clarify the smaller comments. No native Windows CI run is implied.
Actual reviewer validation: full diff/call-site inspection, git diff --check passed, production-prefix comparison unchanged, and current maintenance target independently confirmed at 083cebf. I did not run Cargo, native Codewhale/Windows regressions or the author's mutation tests locally; their counts remain author evidence. Current-head checks remain independent of this code approval. Parent candidate-to-actual-maintenance-SHA replacement and unchanged public-submodule gate are still integration requirements.
Summary: Standards 0; Spec 0. No merge, queue or auto-merge action.
asto18089
left a comment
There was a problem hiding this comment.
Round-2 re-review: round-1 fixes verified, approving
My round-1 CHANGES_REQUESTED items are all addressed in af50096ff (test-only on top of 104649398) and were re-verified fresh this round by independent review shards plus local runs on the pinned tree:
- M1 (environment sentinel):
forkguard_windows_shell_env_overlays_keep_python_stdio_utf8now takeslock_test_env+EnvVarGuard::set("PYTHONIOENCODING", "gbk")(sandbox/mod.rs:978-979) before probing, so an inherited or registry-provided UTF-8 workaround can no longer mask a reintroduced bug; mechanism re-derived viaapply_to_tokio_command's env_clear + allowlisted parent env + upserted overrides. - M2 (CI disclosure): the body now states plainly that
pinvou3-cleanCI is Ubuntu-only, the Windows evidence is author-local, and upstream codewhale-hq#7041 is the path to Windows CI coverage. - m1:
No-Issue:trailer present. m2: the body explains the 23 = 19 + 4 arithmetic — correct for Windows (a static cfg census gives 19 windows-runnable sandbox tests + 4 repl; Linux selects 22 + 4 = 26, measured locally at 26 passed / 0 failed; both are right on their own OS). m3: the direct-CommandSpec::programlanes (read-only laneshell.rs:2172,codew sandbox runlib.rs:10216) are disclosed as out of claim and predate this PR. NITs addressed: the fixture's dispatcher assert carries an actionable message, and the e2e probe now wrapscmd.output()intokio::time::timeout(spec.timeout)withkill_on_drop(true), so a wedged shell can no longer hang the suite. - Fresh correctness confirmation: production change (merge semantics +
#[cfg(windows)]case-insensitive retain) is correct with no caller regression — all three productionwith_envcall sites audited, none relied on replace-as-removal; sanitizer, explicit overrides, and Python's file/default-text encoding policy untouched. Mutation controls: revertingwith_envto replace semantics is killed by the cross-platform unit test; the fork-guard fingerprints for all five new tests resolve at this head.
Standing disclosure (unchanged, now documented in the body): Ubuntu CI never compiles the cfg(windows) tests, so the Windows kill-power rests on author-local runs.
Summary
Fix Windows Python Chinese output becoming garbled during ordinary shell execution. Every such execution calls
with_env, even when no hook/task environment is supplied. It previously discarded the constructor'sPYTHONIOENCODING=utf-8, so Python fell back to its locale encoding while PowerShell expected UTF-8.Merge overlays instead of replacing defaults, and handle explicit Windows variable names case-insensitively. This revision leaves the reviewed production fix unchanged and hardens the Windows test against inherited UTF-8 workarounds, enforces its timeout, and explains how to select PowerShell for opt-in Python tests.
Verification
cargo test -p codewhale-tui --lib --locked sandbox::tests -- --test-threads=1: 23 passed, 0 failed. Cargo's substring filter selects 19sandbox::tests::*plus 4repl::sandbox::tests::*in this maintenance fork.PYTHONIOENCODING=gbk, and bounds shell execution to 30 seconds with child cleanup. Reintroducing the old replacingwith_envunder an outerPYTHONIOENCODING=utf-8made it fail (0 passed, 1 failed), proving an inherited UTF-8 workaround cannot hide the defect. The final source was restored byte-for-byte and all positive checks rerun.bashtool and background ShellManager: 2 passed, 0 failed with system Python 3.14 and 2 passed, 0 failed with bundled Python 3.13.14. These opt-in tests cover Python stdout/stderr under a GBK parent environment and 64 KiB of preceding output. In the earlier verification, both tests failed for each interpreter when only the original environment builders were restored, with corrupted Python Chinese and intact PowerShell Chinese.Opt-in command:
cargo test -p codewhale-tui --lib --locked forkguard_windows_python_stdio -- --ignored --test-threads=1. Use PowerShell or cmd withSHELLunset; setCODEWHALE_TEST_PYTHONto select an interpreter.Coverage and integration boundaries
Windows encoding evidence above comes from local author executions. The maintenance fork's
pinvou3-cleanCI is Ubuntu-only; it does not execute the Windows-gated regressions. Upstream codewhale-hq#7041 is the path for eventual upstream Windows CI coverage, not evidence that a native Windows CI lane has already run.The common shell builder covers foreground, background/PTY, interactive, and encoded PowerShell retry paths. The hardened read-only Python lane and
codew sandbox runuse directCommandSpec::programconstruction, which already lacked this shell default before the change; those paths are outside this fix's claim. Python file/default-text encoding, explicit environment overrides, and the child-environment sanitizer remain unchanged.No PowerShell 7 verification, customer-device replay, installer build, or release was performed.
Review candidate:
af50096ff843617f3f68f47bc6fc45bbffe3c937. Targetpinvou3-clean. Parent Pinvou/pinvou-agent#750 must replace its review-candidate gitlink with the actual public maintenance commit after this PR merges, recount the history, and pass the unchanged public submodule gate. The immutable baseline tag stays unchanged.No-Issue: mirrored upstream in codewhale-hq#7041; parent integration tracked in Pinvou/pinvou-agent#750.