Skip to content

v5.5.2

Choose a tag to compare

@andrehrferreira andrehrferreira released this 04 May 22:51
· 75 commits to main since this release

Fixed — tests/terse-hooks-shell.test.ts flaked on Windows runners

"less tokens please" activates the default mode failed intermittently
on windows-latest, Node 20 with ENOENT reading
.rulebook/.terse-mode, even though the hook had written it
successfully (CI run #25346776699). Root cause: the hook writes via
mktemp + mv -f; on GitHub-hosted Windows runners, antivirus / filter
drivers can briefly hold the renamed file invisible to other processes
after MoveFileExW returns success. macOS, Linux, and faster Windows
runners win the race; the slow Windows-Node20 runner occasionally
loses it.

Fix: replaced every readFileSync(...) after a run() in
tests/terse-hooks-shell.test.ts with a readFlag() helper that polls
existsSync up to ~1s before reading. No-op cost on POSIX.

Fixed — rulebook init produced CRLF shell scripts that broke Claude Code on macOS/Linux

Twelve .sh templates in templates/ were stored on disk with CRLF
line terminators despite .gitattributes declaring *.sh text eol=lf.
On macOS/Linux, bash interprets a trailing \r as part of the command
(set -\r u is invalid, function() {\r fails to parse), so every
hook crashed at session start. Because three of the affected hooks fire
on SessionStart, UserPromptSubmit, and Stop, Claude Code became
completely unresponsive — the user reported zero assistant responses
across a full session.

Root cause: templates were authored on Windows and committed without
honoring the .gitattributes rule, so the npm package shipped CRLF
bytes verbatim.

Fix:

  1. Re-normalized twelve template files to LF
    (templates/hooks/{terse-activate,terse-mode-tracker,resume-from-handoff,on-compact-reinject,check-context-and-handoff,enforce-team-for-background-agents}.sh,
    templates/ralph/ralph-{init,run,status,pause,history}.sh,
    templates/skills/workflows/ralph/install.sh).
  2. Defense in depth in init: new writeShellScript /
    normalizeLineEndings helpers in src/utils/file-system.ts. Wired
    into claude-settings-manager.ts (hook installation),
    ralph-scripts.ts (Ralph script copy), and git-hooks.ts
    (pre-commit/pre-push wrappers). Every .sh written by rulebook init is now guaranteed LF, regardless of how the template is stored
    on disk. POSIX writes also set mode 0o755.
  3. CI guard: scripts/check-sh-eol.mjs (run via npm run check:sh-eol) fails CI if any tracked *.sh / *.bash file under
    templates/ or scripts/ contains a CR byte. Wired into
    .github/workflows/lint.yml so a regression cannot reach a
    published version again.
  4. Regression tests in tests/file-system.test.ts,
    tests/claude-settings-manager.test.ts, and
    tests/ralph-scripts.test.ts assert zero CR bytes in every emitted
    .sh file.

Affected versions: 5.4.x and 5.5.x. Workaround for already-installed
projects: tr -d '\r' < hook.sh > hook.sh.tmp && mv hook.sh.tmp hook.sh && chmod +x hook.sh for each broken script in .claude/hooks/.