repro: always parse JSON from hook output regardless of exit code

This commit is contained in:
Taylor Mullen
2026-02-10 17:03:02 -08:00
parent 5369d6509b
commit 5b371082e3
2 changed files with 15 additions and 13 deletions
+6 -1
View File
@@ -97,9 +97,14 @@ describe('Hooks System Integration', () => {
);
const blockMsg = 'File writing blocked by security policy';
const blockJson = JSON.stringify({
decision: 'deny',
reason: blockMsg,
});
const scriptPath = rig.createScript(
'stderr_block_hook.cjs',
`process.stderr.write('${blockMsg}'); process.exit(2);`,
`process.stderr.write(JSON.stringify({ decision: 'deny', reason: '${blockMsg}' })); process.exit(2);`,
);
rig.setup(
+9 -12
View File
@@ -370,28 +370,25 @@ export class HookRunner {
// Parse output
let output: HookOutput | undefined;
if (exitCode === EXIT_CODE_SUCCESS && stdout.trim()) {
const textToParse = stdout.trim() || stderr.trim();
if (textToParse) {
try {
let parsed = JSON.parse(stdout.trim());
let parsed = JSON.parse(textToParse);
if (typeof parsed === 'string') {
// If the output is a string, parse it in case
// it's double-encoded JSON string.
parsed = JSON.parse(parsed);
}
if (parsed) {
if (parsed && typeof parsed === 'object') {
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
output = parsed as HookOutput;
}
} catch {
// Not JSON, convert plain text to structured output
output = this.convertPlainTextToHookOutput(stdout.trim(), exitCode);
output = this.convertPlainTextToHookOutput(
textToParse,
exitCode || EXIT_CODE_SUCCESS,
);
}
} else if (exitCode !== EXIT_CODE_SUCCESS && stderr.trim()) {
// Convert error output to structured format
output = this.convertPlainTextToHookOutput(
stderr.trim(),
exitCode || EXIT_CODE_NON_BLOCKING_ERROR,
);
}
resolve({