Skip to content

fix(bin/wire-company-brain.sh): heredoc inside $(...) breaks bash 3.2 - #144

Merged
MendixMau merged 3 commits into
masterfrom
fix/wire-brain-bash32
Sep 27, 2026
Merged

MendixMau merged 3 commits into
masterfrom
fix/wire-brain-bash32

Conversation

@MendixMau

Copy link
Copy Markdown
Owner

Lane: Direct

What changed and why (one paragraph)

A colleague's doctor.sh run on macOS reported bin/wire-company-brain.sh unparseable (lines 82/85). Root cause: the script built its marker block with a heredoc inside $(cat <<BLK … BLK). bash 3.2's command-substitution scanner does not recognise a heredoc opened inside $(...); it reads the body as shell text, and the apostrophe in "company's" opens a quote it never closes. bash 5 parses it fine, which is why bash -n here never caught it. The block is now read with IFS= read -r -d '' block <<BLK || true and the trailing newline stripped, so the output is byte-identical. The same trap was live in claude-hooks/hooks/context-ceiling.sh and context-watch.sh (a heredoc feeding python's stdin inside $(...)); both fixed the same way. bin/check-portability.sh gains a rule for the pattern so it cannot come back, with <<< here-strings and $((...)) arithmetic stripped first because both false-triggered the raw grep.

Field evidence

  • Trigger: a workshop attendee's doctor.sh FAIL on macOS stock bash 3.2.57 (screenshot, chat-only).
  • bash -n clean on all four scripts; bin/check-portability.sh clean on the branch (163 files).
  • Output of the rebuilt block diffed byte-identical against the old $(cat <<BLK) form; the two hooks re-verified against a synthetic transcript.
  • Reintroducing the pattern in a scratch file is flagged by the new portability rule; <<< and $((x<<2)) are not.
  • Not verified on a real macOS bash 3.2 box in this session (Linux, bash 5 only). The fix pattern (read -d '') is bash 3.2-native and used elsewhere in this repo.

Checklist

  • No client data (names, paths, hostnames) in the diff or this description
  • Size cap: 5 files, +36/-6
  • Test tier: T1 (syntax + guard run + output diff), T2 pending a macOS run
  • Instrument rules: check-portability.sh change is a new rule with the false-positive exclusions it needed; no new artifact consumer
  • Routing row: n/a (no skill change)
  • CHANGELOG line appended under ## Unreleased
  • Bug entry: n/a

🤖 Generated with Claude Code

https://claude.ai/code/session_01VJgWP5vEoAsNsJYqCDMGNw


Generated by Claude Code

r and others added 2 commits September 25, 2026 15:17
bash 3.2's $(...) scanner does not recognise a heredoc opened inside it: it
scans the body as shell text while hunting for the matching ')', so an
apostrophe in the body ("company's") opens a quote it never closes. Bash 5
parses it fine, so bash -n on a bash-5-only machine cannot reproduce this.

Rebuilt block="$(cat <<EOF ...)" as IFS= read -r -d '' block <<EOF ... EOF,
which keeps every caller's byte-identical output (verified against
init-company-brain.sh + init-project.sh --company: word count, path
resolution, registry, re-wire idempotency, re-point rewrite all unchanged).

The same trap was live in claude-hooks/hooks/context-ceiling.sh and
context-watch.sh (a heredoc feeding python's stdin inside $(...)); fixed the
same way and re-verified end to end against a synthetic transcript (both
correctly computed ctx=6000 from the newest usage record).

Added a bin/check-portability.sh check for the pattern. The raw grep
(\$\([^)]*<<[^<]) false-triggered on $((...)) arithmetic left-shift and <<<
here-strings, so both are stripped before matching; the refined check has
zero hits on the fixed tree and correctly flags a synthetic reintroduction
of the bug.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VJgWP5vEoAsNsJYqCDMGNw
@MendixMau
MendixMau marked this pull request as ready for review September 27, 2026 10:07
@MendixMau
MendixMau merged commit 5db9131 into master Sep 27, 2026
1 check passed
MendixMau pushed a commit that referenced this pull request Sep 27, 2026
Master took #143 (module-rename field report) and #144 (wire-company-brain bash 3.2).
Both conflicts were appends at the same point, kept both sides, ours first:
- CHANGELOG.md, ## Unreleased: this branch's lines, then master's four.
- bug-logs/mxcli-bugs.md: the "Second shape" addendum to
  BUG-DRAFT-layout-merge-in-if-branch, then master's new BUG-DRAFT-* entries.
Master's new entries are BUG-DRAFT-*, so BUG-142..154 still do not collide
(check-pr-discipline clean). Leak guard, private-citations and
render-routing --check clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pm41sykqDGcvioGzsY5H2N
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