Skip to content

Claude adapter + registry + Hub.Ingest / Handler - #1

Merged
kareemaly merged 1 commit into
mainfrom
feat/claude-adapter-hub-ingest
Apr 20, 2026
Merged

kareemaly merged 1 commit into
mainfrom
feat/claude-adapter-hub-ingest

Conversation

@kareemaly

Copy link
Copy Markdown
Owner

Summary

  • Wires the first real adapter end-to-end: POST /hook/claudeEvent on Hub.Events().
  • Adds Adapter + registry, Hub.Ingest/Handler/ServeHTTP, and Signal.RawEvent.Raw plumbing.
  • Claude adapter covers every row in specs/design.md's mapping table; install/uninstall stubbed for the next ticket (Skipped: true).
  • Subagent identity follows the official Claude schema: SessionID = agent_id, ParentSessionID = session_id.

Test plan

  • go vet ./...
  • go test -race ./... (registry, claude map per row, full HTTP integration including 1000-concurrent ingest)
  • golangci-lint run
  • Manual: curl -X POST -d @testdata/claude/stop.json http://localhost:9090/hook/claude produces Event{Status: idle} on the stream.

Follow-up flagged

Per the official Claude hooks reference, agent_id is added to every hook fired inside a subagent (not just SubagentStart/SubagentStop). Today we only remap session ids on those two events. To match design.md's "subagents are independent sessions" model, the remap (SessionID = agent_id, ParentSessionID = session_id) should be promoted to a default rule whenever agent_id is non-empty. Deliberately deferred to its own ticket so this PR stays scoped to the design table.

Wire the first real adapter end-to-end. POSTing a Claude hook body to
/hook/claude now produces an Event on Hub.Events().

Core
- Signal.Raw + Event.Raw plumbing (decision.go, hub.go, design.md).
- Adapter struct, RegisterAdapter, Adapters, lookupAdapter, InstallConfig,
  InstallResult, AllAgents, ErrUnknownAgent (adapter.go).
- Hub.Ingest, Hub.Handler (POST /hook/{agent}, 202/400/404/405/413/500),
  Hub.ServeHTTP, 1 MiB body cap (hub.go).

Claude adapter
- Self-registers from init(); MapHookEvent covers every row in
  design.md's Claude table. Install/uninstall stubbed pending next ticket.
- Subagent identity follows the official schema: SessionID = agent_id,
  ParentSessionID = session_id (Claude fires Subagent* under the parent).

Tests
- adapters/claude/map_test.go: per-row mapping + timestamp + tolerance.
- adapter_test.go: registry duplicate / empty / sorted snapshot / concurrent.
- hub_ingest_test.go: E2E HTTP — happy path, 404/400/413/405, unknown
  event drop, PreCompact drop, subagent flow, 1000-concurrent ingest.
- testdata/claude/*.json fixtures mirror real Claude payload shape.
@kareemaly
kareemaly merged commit 0c0bad8 into main Apr 20, 2026
2 checks passed
@kareemaly
kareemaly deleted the feat/claude-adapter-hub-ingest branch April 20, 2026 12:40
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.

1 participant