Skip to content

hooks: PowerShell always-on fallback keeps trailing blank lines, so it disagrees with the Node and sh hooks #172

Description

@dajiaohuang

hooks/always-on.ps1 does not drop trailing newlines from the skill body, so a SKILL.md that ends in blank lines makes the PowerShell fallback inject a different banner than the Node and sh hooks.

Repro

hooks/always-on.mjs trims with .replace(/(?:\r?\n)+$/, ""), and hooks/always-on.sh gets the same result for free from $(...) command substitution. The PowerShell fallback joins [System.IO.File]::ReadAllLines() with [Environment]::NewLine and never trims, so every trailing blank line survives into the injected context.

Fixture "---\nname: fixture\n---\nFixture body.\n\n\n", opt-in flag present, stdout normalized (\r\n\n):

runtime tail of stdout
node ...off for good.\n\nFixture body.\n
sh ...off for good.\n\nFixture body.\n
powershell ...off for good.\n\nFixture body.\n\n\n

tests/test_always_on_hooks.py already asserts byte-equality across runtimes (assertEqual(1, len(set(outputs.values())))), but both existing fixtures end the body with a single \n, so neither exercises trailing blank lines. .opencode/plugins/i-have-adhd.mjs and extensions/i-have-adhd.ts trim as well, which leaves the PowerShell hook as the only implementation that does not.

Impact

Cosmetic today: the shipped skills/i-have-adhd/SKILL.md ends with one newline, so nothing diverges in practice. It turns into a real difference between Claude Code installs the moment that file gains a trailing blank line, and it contradicts the parity contract the hook tests encode.

Suggested fix

Trim the assembled body in hooks/always-on.ps1 ($body.TrimEnd([char]13, [char]10)) and add a fixture ending in blank lines to the parity test.

Provenance: autonomous agent-authored. A RepoStew worker on Claude Code (deepseek-flash) found the divergence, reproduced it on Windows across all three runtimes, and drafted this report. The submitting human authorized the run and reviewed the scope; no independent human re-ran the reproduction, and no paid model calls were made.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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