Skip to content

tests/brainstorm-server/lifecycle.test.js: bash -lc helpers capture login-profile stdout (fastfetch/neofetch banners) and break tests #2190

Description

@HoneyTyagii

Summary

tests/brainstorm-server/lifecycle.test.js spawns bash -lc (login shell) in three helper functions and captures all of stdout, assuming the only output is the command's own result. On any machine whose login profile prints anything to stdout (fastfetch/neofetch banners, motd scripts, etc.), the helpers return polluted garbage and tests fail even though nothing is wrong with the server code.

This is the same class of bug as #292 (-l flag in run-hook.cmd breaking Windows startup), just in the test suite instead of a hook.

Affected code

tests/brainstorm-server/lifecycle.test.js, three spots:

// line 104-106
function makeShellTempDir(prefix) {
  return execFileSync('bash', ['-lc', `mktemp -d "\${TMPDIR:-/tmp}/${prefix}-XXXXXX"`], { encoding: 'utf8' }).trim();
}

// line 108-110
function removeShellPath(p) {
  execFileSync('bash', ['-lc', 'rm -rf "$1"', 'bash', p], { stdio: 'ignore' });
}

// line 112-117
function newestSessionDir(projectDir) {
  const sessionDir = execFileSync('bash', [
    '-lc',
    'find "$1/.superpowers/brainstorm" ...',

None of these need a login shell: they only run mktemp, rm, and find.

Repro

On Linux with a login profile that prints a banner to stdout (e.g. fastfetch invoked from ~/.bash_profile, a very common setup):

git clone https://github.com/obra/superpowers && cd superpowers/tests/brainstorm-server
npm ci
node --test

Result: start-server.sh --idle-timeout-minutes sets the timeout fails, plus cleanup errors like:

mkdir: cannot create directory '.',;::::;,'.  honey@fedora\n .';:ccccccc...': File name too long
.../start-server.sh: line 141: <banner text>: File name too long
Command failed: bash -lc rm -rf "$1" bash <banner text>

The banner output gets captured as the "temp dir path", then leaks into --project-dir, $SERVER_ID_FILE, and cleanup commands.

Root cause

bash -l sources /etc/profile and ~/.bash_profile, so anything those scripts echo lands in the captured stdout before the actual command output. .trim() only removes surrounding whitespace, it cannot separate a multi-line banner from the payload.

Suggested fix

Drop -l; plain -c is sufficient since no login environment is needed:

-  return execFileSync('bash', ['-lc', `mktemp -d "\${TMPDIR:-/tmp}/${prefix}-XXXXXX"`], { encoding: 'utf8' }).trim();
+  return execFileSync('bash', ['-c', `mktemp -d "\${TMPDIR:-/tmp}/${prefix}-XXXXXX"`], { encoding: 'utf8' }).trim();

Same change at lines 109 and 114. I verified locally on an affected machine (Fedora 44, fastfetch in the login profile): with -lc the file reports 1 failing test, after switching the three occurrences to -c all 13 lifecycle tests pass.

A more defensive alternative (or addition) is taking only the last non-empty line of captured stdout in makeShellTempDir/newestSessionDir, but removing -l alone fixes every case where the pollution comes from the login profile.

Environment

  • OS: Fedora Linux 44, bash 5.3.9
  • Node: v22.x
  • superpowers @ main (b36e082), v6.3.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions