Context
lite_scons_harness.py communicates its result to script_runtime.rs by writing JSON to stdout (json.dump(result, sys.stdout), line ~742). But user extra_scripts are exec'd in-process, so any direct print() in a user script lands on the same stdout ahead of the JSON. script_runtime.rs:146 then fails with:
build error: build failed: failed to parse extra_scripts runtime output: expected value at line 1 column 1
Found while standing up the #942 profiling harness: NightDriverStrip env:demo inherits extra_scripts = pre:tools/install_intelhex.py, pre:tools/pio_audit.py, pre:tools/bake_site.py, post:tools/merge_image.py, and both pio_audit.py and bake_site.py print progress banners (>>> NightDriver Coding Standard Audits, Baked index.html -> index.html.gz: 2693 B) straight to stdout. Reproduced by invoking the harness directly with those scripts — stdout begins with the banners, rc=0, JSON unparseable. Printing from PlatformIO extra_scripts is extremely common, so this breaks many real projects, not just NightDriverStrip.
Proposal
In lite_scons_harness.py, capture the real stdout handle at startup and exec user scripts (and Builder/Action callables) with sys.stdout/sys.stderr redirected to buffers. Surface captured text in the result payload (e.g. per-script stdout/stderr fields in lite_scons_records or notes) so output is preserved for verbose logs instead of discarded. Emit the final JSON to the saved real stdout only.
Acceptance criteria
Decisions
- Severity: HIGH — user-facing build failure on common real-world projects.
- Fix location: harness-side redirect, not Rust-side "skip garbage until
{" — the JSON boundary must stay unambiguous.
Part of #942 (blocks its Phase 1 baseline: the benchmark workload cannot build without this).
Context
lite_scons_harness.pycommunicates its result toscript_runtime.rsby writing JSON to stdout (json.dump(result, sys.stdout), line ~742). But userextra_scriptsare exec'd in-process, so any directprint()in a user script lands on the same stdout ahead of the JSON.script_runtime.rs:146then fails with:Found while standing up the #942 profiling harness: NightDriverStrip
env:demoinheritsextra_scripts = pre:tools/install_intelhex.py, pre:tools/pio_audit.py, pre:tools/bake_site.py, post:tools/merge_image.py, and bothpio_audit.pyandbake_site.pyprint progress banners (>>> NightDriver Coding Standard Audits,Baked index.html -> index.html.gz: 2693 B) straight to stdout. Reproduced by invoking the harness directly with those scripts — stdout begins with the banners, rc=0, JSON unparseable. Printing from PlatformIO extra_scripts is extremely common, so this breaks many real projects, not just NightDriverStrip.Proposal
In
lite_scons_harness.py, capture the real stdout handle at startup and exec user scripts (and Builder/Action callables) withsys.stdout/sys.stderrredirected to buffers. Surface captured text in the result payload (e.g. per-scriptstdout/stderrfields inlite_scons_recordsornotes) so output is preserved for verbose logs instead of discarded. Emit the final JSON to the saved real stdout only.Acceptance criteria
print()at import time and inside SCons callbacks no longer breaks overlay parsing.script_runtime_tests.rs(or the lite_scons acceptance suite) covering a printing script.env:demoextra_scripts evaluation succeeds (validated in the meta: profiling-driven build performance burndown (Docker Linux, NightDriverStrip, cold vs hot cache) #942 Docker harness).Decisions
{" — the JSON boundary must stay unambiguous.Part of #942 (blocks its Phase 1 baseline: the benchmark workload cannot build without this).