Fix hooks: PowerShell quoting, stopTeammate helper, output docs#177
Fix hooks: PowerShell quoting, stopTeammate helper, output docs#177maystudios merged 1 commit intomainfrom
Conversation
…output format docs - Fix PowerShell WAV path quoting in playSound() to use double-quote escaping instead of single-quote escaping, which handles more special characters safely - Add stopTeammate() exported helper for permanent teammate termination via JSON stdout - Add JSDoc output format documentation to teammate-idle and task-completed hooks Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR updates MaxsimCLI hook utilities and hook script documentation to improve Windows sound playback reliability and to document/enable “stop teammate” control via JSON stdout.
Changes:
- Adjust Windows PowerShell command construction in
playSound()for WAV playback. - Add an exported
stopTeammate(reason)helper that emits the JSON stop payload to stdout. - Add inline documentation to TeammateIdle/TaskCompleted hooks describing exit-code vs JSON-stdout control semantics.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| packages/cli/src/hooks/shared.ts | Updates PowerShell WAV command quoting and adds stopTeammate() JSON-stop helper. |
| packages/cli/src/hooks/maxsim-teammate-idle.ts | Adds hook output-format documentation (allow/block/stop). |
| packages/cli/src/hooks/maxsim-task-completed.ts | Adds hook output-format documentation (allow/block/stop). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| process.stdout.write(`${payload}\n`); | ||
| process.exit(0); |
There was a problem hiding this comment.
stopTeammate() writes to stdout and immediately calls process.exit(0). process.exit() can terminate the process before stdout is flushed when stdout is a pipe, which risks dropping the JSON control payload. To make the stop signal reliable, exit only after the write callback fires (or end stdout) instead of exiting synchronously right after write().
| process.stdout.write(`${payload}\n`); | |
| process.exit(0); | |
| process.stdout.write(`${payload}\n`, () => { | |
| process.exit(0); | |
| }); |
| export function stopTeammate(reason: string): never { | ||
| const payload = JSON.stringify({ continue: false, stopReason: reason }); | ||
| process.stdout.write(`${payload}\n`); | ||
| process.exit(0); | ||
| } |
There was a problem hiding this comment.
stopTeammate() introduces new hook-control behavior but isn’t covered by the existing hooks/shared.ts unit tests. Adding a small test that spies on process.stdout.write and process.exit would prevent regressions in the JSON payload format and exit semantics.
| // Use double-quoted string which handles spaces and most special chars | ||
| const escaped = soundFile.replace(/"/g, '\\"'); | ||
| spawnSync( | ||
| 'powershell', | ||
| [ | ||
| '-NoProfile', | ||
| '-NonInteractive', | ||
| '-Command', | ||
| `$p='${soundFile.replace(/'/g, "''")}'; (New-Object System.Media.SoundPlayer $p).PlaySync()`, | ||
| `$p="${escaped}"; (New-Object System.Media.SoundPlayer $p).PlaySync()`, | ||
| ], | ||
| { stdio: 'ignore' }, |
There was a problem hiding this comment.
The Windows-specific quoting/PowerShell command behavior in playSound() changed, but the existing hooks/shared.ts unit tests don’t assert the PowerShell argument string (and won’t exercise the win32 branch on non-Windows runners). Consider adding a unit test that mocks os.platform() to win32 and asserts the spawnSync('powershell', [...]) args so quoting regressions are caught.
| // Use double-quoted string which handles spaces and most special chars | ||
| const escaped = soundFile.replace(/"/g, '\\"'); | ||
| spawnSync( | ||
| 'powershell', | ||
| [ | ||
| '-NoProfile', | ||
| '-NonInteractive', | ||
| '-Command', | ||
| `$p='${soundFile.replace(/'/g, "''")}'; (New-Object System.Media.SoundPlayer $p).PlaySync()`, | ||
| `$p="${escaped}"; (New-Object System.Media.SoundPlayer $p).PlaySync()`, | ||
| ], |
There was a problem hiding this comment.
The PowerShell -Command string now uses a double-quoted literal ($p="..."). In PowerShell, double-quoted strings perform variable/subexpression expansion (e.g. $, $(), and backtick escapes), so valid Windows path characters like $ or ` can be misinterpreted and break playback (and it also makes the “handles special chars” comment inaccurate). Consider avoiding interpolation entirely by passing the path as a separate argument and reading it via $args[0] (or revert to a single-quoted literal with proper escaping).
|
🎉 This PR is included in version 5.13.1 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Summary
stopTeammate()exported helper function for permanent teammate termination via JSON stdout protocolTest plan
npm test— all 529 tests passnpm run build— clean build with no errorsnpm run lint— no new lint warnings introduced🤖 Generated with Claude Code