* chore(#3546): migrate hook advisory assertions onto typed output surfaces Add additive typed fields to 5 hook scripts' PreToolUse/PostToolUse advisory output alongside the existing additionalContext prose: - gsd-read-guard.js: code ('READ_BEFORE_EDIT'), fileName - gsd-context-monitor.js: severity ('warning'|'critical') - gsd-prompt-guard.js: findings ([{ruleId, match}], module-local RULE_IDS + renderFinding mapper mirroring gsd-read-injection-scanner.js's #3523 pattern) - gsd-read-injection-scanner.js: severity ('LOW'|'HIGH'), source (its findings array already existed from #3523) - gsd-workflow-guard.js: code ('WORKFLOW_ADVISORY') on the advisory leg, distinct from the existing force-add block leg's code additionalContext stays byte-identical in every hook (verified per-hook against the pristine HEAD version across a spread of payload shapes). Migrates all 20 assertion sites named in the issue off additionalContext.includes(...)/assert.match(...) substring-matching onto the new typed fields, per CONTRIBUTING.md's prohibition on raw text matching on test outputs. Closes #3546 * test: fix undersized commit-class timeout in gsd-statusline.test.cjs's commitN helper Surfaced by gsd-test on the #3546 checkpoint: `commitN()`'s loop called gitOrThrow(['add','-A']/['commit',...]) without a timeoutMs override, so each call used DEFAULT_GIT_TIMEOUT_MS (15s) -- a bound git-fixture.cjs's own doc comment says is sized for plumbing reads (rev-parse/branch/log), not write-heavy add/commit spawns. That file already documents the exact same defect class from a prior incident (PR #3323) and exports GIT_FIXTURE_TIMEOUT_MS (60s) for fixture-construction call sites - commitN just wasn't using it. Observed failure: `git commit -m filler 9` timed out under normal bench load, unrelated to any of this PR's own diff (hooks/*.js + 5 other test files). Not a flake: root-caused to the timeout bound being sized for the wrong call class, per this repo's no-flakes rule. * chore(#3546): backfill changeset PR number (#4167) --------- Co-authored-by: sim <sim@local>
This commit is contained in:
@@ -84,9 +84,10 @@ describe('gsd-read-guard hook', () => {
|
||||
const output = JSON.parse(result.stdout);
|
||||
assert.ok(output.hookSpecificOutput, 'should have hookSpecificOutput');
|
||||
assert.ok(output.hookSpecificOutput.additionalContext, 'should have additionalContext');
|
||||
assert.ok(
|
||||
output.hookSpecificOutput.additionalContext.includes('Read'),
|
||||
'guidance should mention Read tool'
|
||||
assert.equal(
|
||||
output.hookSpecificOutput.code,
|
||||
'READ_BEFORE_EDIT',
|
||||
'guidance should carry the READ_BEFORE_EDIT reason code'
|
||||
);
|
||||
});
|
||||
|
||||
@@ -103,7 +104,7 @@ describe('gsd-read-guard hook', () => {
|
||||
assert.ok(result.stdout.length > 0, 'should produce output');
|
||||
|
||||
const output = JSON.parse(result.stdout);
|
||||
assert.ok(output.hookSpecificOutput.additionalContext.includes('Read'));
|
||||
assert.equal(output.hookSpecificOutput.code, 'READ_BEFORE_EDIT');
|
||||
});
|
||||
|
||||
// ─── No-op cases: should NOT inject guidance ────────────────────────────
|
||||
@@ -179,9 +180,10 @@ describe('gsd-read-guard hook', () => {
|
||||
});
|
||||
|
||||
const output = JSON.parse(result.stdout);
|
||||
assert.ok(
|
||||
output.hookSpecificOutput.additionalContext.includes('myfile.ts'),
|
||||
'guidance should include the filename being edited'
|
||||
assert.equal(
|
||||
output.hookSpecificOutput.fileName,
|
||||
'myfile.ts',
|
||||
'guidance should name the file being edited'
|
||||
);
|
||||
});
|
||||
|
||||
@@ -348,7 +350,7 @@ describe('bug #2344: read guard skips on CLAUDECODE env var', () => {
|
||||
assert.equal(result.exitCode, 0);
|
||||
assert.ok(result.stdout.length > 0, 'advisory should fire on non-Claude-Code runtimes');
|
||||
const output = JSON.parse(result.stdout);
|
||||
assert.ok(output.hookSpecificOutput?.additionalContext?.includes('Read'));
|
||||
assert.equal(output.hookSpecificOutput?.code, 'READ_BEFORE_EDIT');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -487,7 +489,7 @@ describe('bug #2520: read guard detects Claude Code without relying on CLAUDECOD
|
||||
assert.equal(result.exitCode, 0);
|
||||
assert.ok(result.stdout.length > 0, 'advisory should fire on non-Claude-Code hosts');
|
||||
const output = JSON.parse(result.stdout);
|
||||
assert.ok(output.hookSpecificOutput?.additionalContext?.includes('Read'));
|
||||
assert.equal(output.hookSpecificOutput?.code, 'READ_BEFORE_EDIT');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -529,7 +531,7 @@ describe('#2304: Kimi tool vocabulary is normalized by the read guard', () => {
|
||||
assert.equal(result.exitCode, 0);
|
||||
assert.ok(result.stdout.length > 0, 'Kimi WriteFile should produce the advisory');
|
||||
const output = JSON.parse(result.stdout);
|
||||
assert.ok(output.hookSpecificOutput?.additionalContext?.includes('Read'));
|
||||
assert.equal(output.hookSpecificOutput?.code, 'READ_BEFORE_EDIT');
|
||||
});
|
||||
|
||||
test('StrReplaceFile on an existing file injects guidance like Edit', () => {
|
||||
@@ -544,7 +546,7 @@ describe('#2304: Kimi tool vocabulary is normalized by the read guard', () => {
|
||||
assert.equal(result.exitCode, 0);
|
||||
assert.ok(result.stdout.length > 0, 'Kimi StrReplaceFile should produce the advisory');
|
||||
const output = JSON.parse(result.stdout);
|
||||
assert.ok(output.hookSpecificOutput?.additionalContext?.includes('Read'));
|
||||
assert.equal(output.hookSpecificOutput?.code, 'READ_BEFORE_EDIT');
|
||||
});
|
||||
|
||||
test('module-qualified kimi_cli.tools.file:WriteFile is recognized', () => {
|
||||
|
||||
Reference in New Issue
Block a user