Skip to content

feat: extract clash_hooks library and unify agent protocol path#411

Open
akesling wants to merge 2 commits intomainfrom
akesling/init
Open

feat: extract clash_hooks library and unify agent protocol path#411
akesling wants to merge 2 commits intomainfrom
akesling/init

Conversation

@akesling
Copy link
Copy Markdown
Collaborator

Summary

  • Extracts clash_hooks as a standalone crate (serde, serde_json, thiserror — zero heavy deps) providing typed deserialization of all 22+ Claude Code hook events, cached tool-input accessors, and opaque response construction
  • Unifies the agent output path — all agents (including Claude) now go through HookProtocol trait methods (format_decision, format_session_start, format_post_tool_use, format_permission_response), eliminating if agent == Claude branches in cmd/hooks.rs
  • Introduces PolicyDecision (Allow/Deny/Ask/Pass) as the single boundary type between the policy engine and protocol output, replacing the old ToolUseHookInput + check_permission_legacy path
  • Disambiguates namingmatch_tree::DecisionMatchVerdict, ir::PolicyDecisionPolicyEvaluation, trace::PolicyDecisionTraceDecision
  • Removes dead legacy codeToolUseHookInput, check_permission_legacy, duplicated display/ui formatting functions

Test plan

  • cargo test --workspace — 1,113 tests pass (0 failures)
  • cargo clippy --workspace — clean
  • Verified no remaining references to ToolUseHookInput, check_permission_legacy, or AgentKind::Claude branches in cmd/hooks.rs
  • clash_hooks has 16 unit tests + 23 integration tests + 1 doctest covering all hook event types
  • Edge-case coverage for tool_response: None in network_hints and sandbox_hints

…ent architecture

Extract clash_hooks as a standalone crate with two-phase deserialization,
per-event field structs (CommonFields + XxxFields), OnceLock-cached typed
tool input accessors, and opaque Response builders.

- 22+ hook event types with typed response constructors
- No RawInput god-object — each event holds only its own fields
- parse_payload() macro for concise event dispatch
- debug_assert on Response builders to catch silent no-ops
- Re-export CommonFields from lib.rs
- Migrate clash crate to use clash_hooks types
- Unify Claude output through HookProtocol trait: all agents (including
  Claude) go through format_decision/format_session_start/etc. with no
  AgentKind::Claude branches in cmd/hooks.rs
- Introduce PolicyDecision enum as the boundary type between policy
  engine and protocol output, replacing HookOutput-based returns from
  check_permission
- Delete ToolUseHookInput, SessionStartHookInput, StopHookInput, and
  check_permission_legacy — all input handling uses clash_hooks typed
  events via recv_from_value
- Add recv_from_value to clash_hooks for non-Claude agent protocol
  normalization
- Rename Decision → MatchVerdict, ir::PolicyDecision → PolicyEvaluation,
  trace::PolicyDecision → TraceDecision to eliminate naming collisions
- Eliminate duplicated display/ui formatting: delete print_tool_header,
  print_decision, print_sandbox_summary from ui.rs; cmd/explain.rs now
  uses display:: formatters like all other callers
- Thread agent through handle_permission_request for consistent
  check_permission calls
- Restore dropped edge-case tests for tool_response: None path
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants