4.3 KiB
External rereview: hook public surface hardening
1. Result: approve
Approve. The previous blocker is fixed: the public pre-tool hook action surface no longer exposes a no-result skip action, and public deny still maps to a synthetic error result.
2. Summary of rereviewed changes
The follow-up commit a4e30e2 fix: remove public hook skip action narrowed HookPreToolAction by removing the Skip variant and its conversion to llm_worker::interceptor::PreToolAction::Skip. The public pre-tool actions are now Continue, Deny(String), Abort(String), and Pause.
HookPreToolAction::Deny still converts internally to PreToolAction::SyntheticResult(ToolResult::error(call_id, reason)), preserving the fail-closed/synthetic-result path needed by manifest permissions and future public hooks.
3. Requirement-by-requirement assessment
- Previous blocker fixed: satisfied.
HookPreToolAction::Skipis gone, and grep found noHookPreToolAction::Skip,PreToolAction::Skip, or standaloneSkipusage undercrates/pod/src. - Public pre-tool deny maps to synthetic error result: satisfied.
HookPreToolAction::Denyconverts toPreToolAction::SyntheticResult(ToolResult::error(...)); existing interceptor tests also assert the synthetic result has the expected call id, summary, no content, andis_error = true. - Public Hook API exposes no no-result skip: satisfied. The only no-result skip capability remains in the lower-level
llm_workerinterceptor model; it is no longer reachable through the publicpod::hook::HookPreToolActionsurface. - Public Hook API exposes no raw
Iteminjection: satisfied.PreLlmRequestandOnTurnEnduse safe public action types rather than rawPreRequestAction::ContinueWith(Vec<Item>)orTurnEndAction::ContinueWithMessages(Vec<Item>)as hook outputs. - Public Hook API exposes no arbitrary
ToolResultconstruction: satisfied for action outputs. Public pre-tool hooks provide only a denial message; Pod constructs the synthetic error result internally. - Internal capabilities remain internal: satisfied. Internal Pod/Worker code still uses richer
llm_worker::Interceptoractions where needed, including durable host-owned prompt append paths and compact/internal mechanisms. - Tests cover the fixed path sufficiently: satisfied. The added
public_pre_tool_hook_actions_cannot_emit_internal_no_result_skipunit test verifies the available public pre-tool conversions and asserts public deny produces a synthetic result. The existingpublic_pre_tool_hook_deny_becomes_synthetic_error_and_short_circuitsintegration-style interceptor test covers bridge behavior and ordering.
4. Blockers
None.
5. Non-blockers / follow-ups
- As noted in the original review,
ToolResultSummarystill exposesllm_worker::tool::ToolOutputas public hook input. This is not a blocker because it does not allow output rewriting or arbitraryToolResultconstruction, but the future plugin/feature registry may still want a Pod-owned summary type before freezing a public API boundary.
6. Validation assessed or rerun
Rerun/read-only checks from /home/hare/Projects/yoi/.worktree/hook-public-surface-hardening:
git rev-parse HEADreporteda4e30e292abf5c640b923e3307a75eded366351a.git status --shortwas clean.git diff --check develop...HEADpassed.cargo fmt --checkpassed../tickets.sh doctorpassed.git grep -n -E 'HookPreToolAction::Skip|PreToolAction::Skip|pub (use|type).*\b(PreRequestAction|TurnEndAction|PreToolAction|PostToolAction|ToolResult|Item)\b' crates/pod/srcproduced no matches.
Assessed by source review:
- Follow-up commit
a4e30e2diff. - Full diff
develop...HEADforcrates/pod/src/hook.rs,crates/pod/src/ipc/interceptor.rs,crates/pod/src/permission.rs, andcrates/pod/src/pod.rs. - Relevant lower-level
llm-workerpre-tool handling to confirm internal skip remains lower-level only.
I did not run cargo test, cargo check, or nix build; those commands would write build artifacts outside this review artifact scope. The fixed-path tests were assessed from source.
7. Residual risk
No merge-blocking residual risk found. The remaining risk is API polish for the future feature/plugin registry, especially whether all hook input summary types should become Pod-owned wrapper types before being treated as a stable plugin boundary.