mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-07-01 04:21:27 +08:00
fix(hooks): guard doc-file-warning stdin listeners behind require.main (#2358)
* fix(hooks): guard doc-file-warning stdin listeners behind require.main doc-file-warning.js registered process.stdin data/end listeners at module scope while also exporting run(). run-with-flags.js require()s any hook that exports run() for its in-process fast path, so importing this hook attached stray stdin listeners to the dispatcher process, corrupting the PreToolUse stdout JSON contract. This is the exact failure run-with-flags' own SAFETY comment warns about, and 24 sibling hooks already guard against it. - Move the stdin entrypoint into main() and gate it behind require.main === module - pre-write-doc-warn.js now calls main() explicitly instead of relying on the import side effect - Add regression tests: require() attaches no stdin listeners, run()/main() stay exported, and the pre-write-doc-warn shim still warns * docs(hooks): add JSDoc for doc-file-warning main() entrypoint Satisfies the docstring-coverage pre-merge check; documents the stdin entrypoint and why it must not run on require().
This commit is contained in:
@@ -17,7 +17,6 @@ const path = require('path');
|
||||
const { buildPreToolUseAdditionalContext } = require('./pretooluse-visible-output');
|
||||
|
||||
const MAX_STDIN = 1024 * 1024;
|
||||
let data = '';
|
||||
|
||||
// Known ad-hoc filenames that indicate impulse/scratch files (case-sensitive, uppercase only)
|
||||
const ADHOC_FILENAMES = /^(NOTES|TODO|SCRATCH|TEMP|DRAFT|BRAINSTORM|SPIKE|DEBUG|WIP)\.(md|txt)$/;
|
||||
@@ -70,27 +69,40 @@ function run(inputOrRaw, _options = {}) {
|
||||
return { exitCode: 0 };
|
||||
}
|
||||
|
||||
module.exports = { run };
|
||||
/**
|
||||
* Stdin entrypoint for direct/spawnSync execution: reads the hook payload from
|
||||
* stdin (capped at MAX_STDIN), runs the policy, and writes the PreToolUse result
|
||||
* to stdout. Must only run when invoked directly, never on require(), so the
|
||||
* stdin listeners are not leaked into a parent that loads this hook in-process.
|
||||
*/
|
||||
function main() {
|
||||
let data = '';
|
||||
process.stdin.setEncoding('utf8');
|
||||
process.stdin.on('data', c => {
|
||||
if (data.length < MAX_STDIN) {
|
||||
const remaining = MAX_STDIN - data.length;
|
||||
data += c.substring(0, remaining);
|
||||
}
|
||||
});
|
||||
|
||||
// Stdin fallback for spawnSync execution
|
||||
process.stdin.setEncoding('utf8');
|
||||
process.stdin.on('data', c => {
|
||||
if (data.length < MAX_STDIN) {
|
||||
const remaining = MAX_STDIN - data.length;
|
||||
data += c.substring(0, remaining);
|
||||
}
|
||||
});
|
||||
process.stdin.on('end', () => {
|
||||
const result = run(data);
|
||||
|
||||
process.stdin.on('end', () => {
|
||||
const result = run(data);
|
||||
if (result.stderr) {
|
||||
process.stderr.write(result.stderr + '\n');
|
||||
}
|
||||
|
||||
if (result.stderr) {
|
||||
process.stderr.write(result.stderr + '\n');
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(result, 'additionalContext')) {
|
||||
process.stdout.write(buildPreToolUseAdditionalContext(result.additionalContext));
|
||||
} else {
|
||||
process.stdout.write(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(result, 'additionalContext')) {
|
||||
process.stdout.write(buildPreToolUseAdditionalContext(result.additionalContext));
|
||||
} else {
|
||||
process.stdout.write(data);
|
||||
}
|
||||
});
|
||||
module.exports = { run, main };
|
||||
|
||||
// Stdin fallback for spawnSync execution — only when invoked directly, not via require()
|
||||
if (require.main === module) {
|
||||
main();
|
||||
}
|
||||
|
||||
@@ -6,4 +6,5 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
require('./doc-file-warning.js');
|
||||
// doc-file-warning.js guards its stdin entrypoint behind require.main; call main() explicitly.
|
||||
require('./doc-file-warning.js').main();
|
||||
|
||||
Reference in New Issue
Block a user