Refactor adapter handlers and cmdHook to accept io.Reader/io.Writer params#85
Refactor adapter handlers and cmdHook to accept io.Reader/io.Writer params#85
Conversation
|
Threads Warnings
The To actually verify dispatch, unmarshal the output into the typed struct and assert on real content — e.g. check that
_, _ = fmt.Fprintln(errOut, w)The blank identifiers swallow write errors on the new Notes
The "pi source with claude-shaped payload" case is a good one, but it only checks that
No test case checks the
Clean refactor overall. The prod code changes are straightforward and correct. The main thing worth addressing is the test assertions — right now they prove "something was written" but not "the right thing was written," which undercuts the value of the new Dev Ghost metricsTotal duration: 2m 42s
|
gregology
left a comment
There was a problem hiding this comment.
Address these issues
cmd/sctx/main_test.go ~line 492 — test assertions are too weak
The TestCmdHook cases check for JSON field names as substrings (hookSpecificOutput, additionalContext), but those strings appear in every successful response regardless of content. The "claude hook dispatches to claude handler" case would pass even if the handler injected completely wrong context — hookSpecificOutput is just a struct key.
To actually verify dispatch, unmarshal the output into the typed struct and assert on real content — e.g. check that additionalContext contains "hook test context" from the fixture AGENTS.yaml, or that permissionDecision is "allow". That lines up with the project's "every test represents a real user scenario" philosophy.
internal/adapter/claude.go line 88, pi.go line 100 — silent write error discard
_, _ = fmt.Fprintln(errOut, w)The blank identifiers swallow write errors on the new errOut writer. Warnings are best-effort so this is probably fine in practice, but a short comment like // best-effort; write failures non-fatal would save the next reader from wondering if it's an oversight.
…t-effort comments on errOut writes
|
Addressed both requested changes:
The three informational notes (unused Dev Ghost metricsTotal duration: 2m 43s
|
Fixes #77
Problem
cmdHook— the function that runs every single time an agent triggers a hook — had zero test coverage. The individual handlers (HandleClaudeHook,HandlePiHook) were well-tested, but the dispatch logic connecting them was a blind spot. A regression inIsPiHookdetection could silently misroute all input and we'd never know until a user hit it.Approach
Thread
io.Reader/io.Writerparams through the full call chain:cmdHook->HandleClaudeHook/HandlePiHook. This is Approach B from the issue discussion.Every other cmd function (
cmdContext,cmdDecisions,cmdValidate,cmdInit) already acceptsio.Writerparams. The adapter handlers were the odd ones out, writing directly toos.Stdout/os.Stderr. Now they're consistent with everything else.With explicit writers, testing
cmdHookdispatch is justbytes.NewReaderfor input andbytes.Bufferfor output. No pipe gymnastics, noos.Stdoutswapping. The existingcaptureStdouthelper (which did pipe redirection) is gone — all ~24 adapter tests now use buffers too.Why not the smaller approaches
Approach A (only refactor
cmdHook, leave handlers alone) would've gotten dispatch coverage but left the handlers inconsistent — still writing toos.Stdoutdirectly while every cmd function uses injected writers. Half the job.Approach C (pipe-based tests, no prod changes) works but pipe manipulation in tests is fragile and harder to read. The existing
captureStdouthelper was already a code smell — it swapped a global, which is inherently racy even if the tests happen to pass today.New tests
TestCmdHookcovers the dispatch paths that were previously untested:"source": "pi"with Claude-shaped fields -> still routes to Pi handlerDev Ghost metrics
Total duration: 9m 30s
Turns: 125
Tool calls: 94
Tokens: 2,222,208 input / 21,350 output
Resolves #77