Fix multiline interpolation and exact Rust output - #111
Conversation
Adding CLAUDE.md with task information for AI processing. This file will be removed when the task is complete. Issue: #37
Resolves #37: Multi-line strings containing backticks, dollar signs, and quotes are now properly handled without corruption when used with echo commands. **Changes:** - Enhanced quote() function to detect complex multi-line strings - Updated regex patterns to handle multi-line content (added 's' flag) - Added virtual command bypass for complex echo > file patterns - Created _write_multiline_content virtual command for safe file writing - Added comprehensive test suite for various special character scenarios **Technical Details:** - Complex multi-line strings (with newlines + backticks/dollar signs) are automatically detected and processed via virtual command to bypass shell interpretation entirely - Simple strings continue to work as before (backward compatible) - Content is base64-encoded when passed to virtual command to prevent corruption **Test Coverage:** - Multi-line strings with mixed special characters ✅ - README files, configuration files, code examples ✅ - Backticks, dollar signs, quotes preservation ✅ - Backward compatibility with simple strings ✅ 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
|
We should double check more cases similar like this, make sure we have test coverage similar to all our competitors, and select behavior closer to how it would behave in sh scripts or with least surprise based on best practices from competitors. If there multiple options we should allow to configure, and use closer to sh behavior by default. |
|
🤖 AI Work Session Started Starting automated work session at 2026-09-13T15:04:14.990Z The PR has been converted to draft mode while work is in progress. This comment marks the beginning of an AI work session. Please wait for the session to finish, and provide your feedback. |
Working session summaryInvestigation is complete; no code has been changed yet. The branch remains clean. Root causes:
Recommended design: Alternative designs—porting the virtual writer or introducing a second multiline mode—would duplicate current quoting machinery and produce less shell-like behavior. Please reply yes to approve this design and allow implementation. This summary was automatically extracted from the AI working session output. |
🤖 Solution Draft LogThis log file contains the complete execution trace of the AI solution draft process. 💰 Cost estimation:
📊 Context and tokens usage:
Total: (151.7K + 2.1M cached) input tokens, 15.9K output tokens, $3.403969 cost 🤖 Models used:
📎 Log file uploaded as Gist (1631KB)Now working session is ended, feel free to review and add any feedback on the solution draft. |
🔄 Auto-restart 1/5Reason: CI failures detected; Merge conflicts Starting new session to address the issues. Auto-restart-until-mergeable mode is active. This run will stop after 5 restart iterations in total. |
Drain stdout and stderr concurrently as bytes so capture keeps missing final newlines intact.\n\nRefs #37
Cover stdin and competitor behavior alongside executable exact-write examples.\n\nRefs #37
Document printf and stdin guidance and add patch release metadata.\n\nRefs #37
Resolve documentation conflicts while preserving JSON and multiline guidance.
Use the child's setup output instead of a fixed delay under full-suite load.
Working session summaryResolved and pushed to PR #111.
This summary was automatically extracted from the AI working session output. |
🔄 Auto-restart-until-mergeable Log 1/5This log file contains the complete execution trace of the AI solution draft process. 💰 Cost estimation:
📊 Context and tokens usage:
Total: (963.4K + 36.7M cached) input tokens, 128.6K output tokens, $40.955098 cost 🤖 Models used:
📎 Log file uploaded as Gist (16960KB)Now working session is ended, feel free to review and add any feedback on the solution draft. |
🎉 Auto-mergedThis pull request has been automatically merged by hive-mind.
Auto-merged by hive-mind with --auto-merge flag |
Problem
Multiline template interpolations could be treated as shell source by this
branch's special-case writer. Backticks, dollar signs, quotes, backslashes, and
newlines were therefore corrupted or executed when used in commands such as:
The branch also diverged from the generic literal-interpolation design now on
main, and its fallback path broke multiline program arguments such asnode -e ${script}.Fixes #37.
Solution
mainand use its context-aware rule that every interpolatedvalue is one literal argument, equivalent to a quoted shell variable
resolution rather than maintain a second quoting path
echooptionhandling; use portable
printf '%s'when no trailing newline is requireddeadlocks and preserving whether either stream ended with a newline
concurrent test cleanup cannot change an in-flight command's error behavior
printf '%s', stdin, and direct filesystem writes for exact text orbinary output, with an executable JavaScript example
quoteContext,preQuotedPassthrough, andrawcontrols;no multiline-specific compatibility mode is added
The full issue payload now survives unchanged as data. Shell substitutions in
interpolated values do not execute.
The source-level capture change is intentionally Rust-only because the
JavaScript runner already preserves missing final newlines. The PR therefore
uses the repository's
parity-exemptlabel; behavioral parity is asserted inboth language test suites.
Reproduction and regression coverage
New JavaScript and Rust suites cover:
and embedded newlines
echoandecho -nshell parity, plus portableprintf '%s'exact outputechoredirection formnode -e/ nested-shell programs remaining one argument/bin/shusing a quoted variableportable Unix and Windows fixtures
capacity, guarding against stdout/stderr drain deadlocks
experiments/issue-37-multiline-competitors.mjsprovides a reproduciblecomparison with
/bin/sh, command-stream, Bun Shell, zx, and execa. All fivematched for the tested multiline payload.
This is not a UI change, so screenshots do not apply.
Verification
bun run --cwd js lintbun run --cwd js format:checkbun run --cwd js check:duplicationbun test js/tests/ --timeout 10000— 1,421 passed, 6 skipped, 0 failedcargo fmt --all -- --checkRUSTFLAGS=-Dwarnings cargo clippy --all-targets --all-features -- -D warningsRUSTDOCFLAGS=-Dwarnings cargo doc --no-deps --all-featurescargo test --all-featuresplus doc tests — passedcargo package --allow-dirty, inline release-script tests,file-size check, and crate-size check — passed
Two fixed-wait SIGINT tests also surfaced as flaky under the complete suite;
both now wait for the child process's readiness message before signaling, and
failed fixtures clean up their child processes.