Skip to content

Commit f5968c4

Browse files
Akagilncdpnascimentojacksondc
committed
fix(hooks): strict empty-stdout assert; qualify updatedInput in spike
Round-3 fixer pass on fix/auq-hook-neutral-passthrough. M1 — empty-stdin crash-safety case now asserts res.stdout directly (no ?? '' / || '' mask). Matches expectNoDecision, garrytan#1924 original, and every other empty-stdout assertion in-repo. Sh1 — spike Answer + updatedInput semantics keep the platform fact but qualify that plan-tune lives on deny+reason (Implementation examples), so the headline no longer contradicts the live-hook section. Co-authored-by: dpnascimento <dpnascimento@users.noreply.github.com> Co-authored-by: jacksondc <jacksondc@users.noreply.github.com>
1 parent eb6aa31 commit f5968c4

2 files changed

Lines changed: 7 additions & 5 deletions

File tree

docs/spikes/claude-code-hook-mutation.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ answer via `updatedInput`? If yes, what's the exact protocol?
1313

1414
## Answer
1515

16-
**Yes.** `updatedInput` is the supported mechanism. Source:
17-
https://code.claude.com/docs/en/hooks (confirmed 2026-04 reference).
16+
**Yes.** `updatedInput` is the supported mechanism (platform capability;
17+
this plan-tune hook does not take that path — see Implementation examples).
18+
Source: https://code.claude.com/docs/en/hooks (confirmed 2026-04 reference).
1819

1920
## Hook stdin schema (PreToolUse + PostToolUse)
2021

@@ -60,8 +61,9 @@ the pass-through path that lets the permission flow continue unchanged.
6061

6162
**`updatedInput` semantics:** shallow merge of fields present in the returned
6263
object onto the original `tool_input`. Only valid with
63-
`permissionDecision: "allow"`. This is what lets us substitute an
64-
auto-decided answer for `never-ask` preferences.
64+
`permissionDecision: "allow"`. This is what would let a hook substitute an
65+
auto-decided answer for `never-ask` preferences; the live plan-tune hook
66+
instead uses `deny` + reason (see Implementation examples).
6567

6668
## Matcher schema
6769

test/question-preference-hook.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ describe('passes through (no enforcement)', () => {
174174
const res = spawnSync(HOOK, [], { env, input: '', encoding: 'utf-8' });
175175
expect(res.status).toBe(0);
176176
// Crash-safety pass-through: empty stdout only (no permissionDecision).
177-
expect(res.stdout ?? '').toBe('');
177+
expect(res.stdout).toBe('');
178178
});
179179

180180
test('non-AUQ tool_name → no decision (defensive)', () => {

0 commit comments

Comments
 (0)