Menu

#316 docs: document the shared shape of Doberman host adapters

closed
nobody
None
2026-08-11
2026-08-09
Anonymous
No

Originally created by: AshSgDe29071999

Summary

Adds docs/ADAPTER_GUIDE.md so a third host-adapter author does not have to reverse-engineer both existing integrations.

Covered

  1. Hook lifecycle — pre-call gating for both adapters; Claude Code post-call output scan; OpenClaw pre-only limitation.
  2. Normalization — host tool call → (canonical, args)spine.evaluate_actionSecurityObject (models.py fields, normalize() as the single constructor).
  3. Verdict enforcement — PASS / AUTH / BLOCK mapped to Claude Code permissionDecision and OpenClaw BeforeToolCallResult (allow / requireApproval / block), including fail-closed transport behavior in adapters/openclaw/index.js.

Concrete citations

  • claude_code.py: to_normalize_input, evaluate_pre, evaluate_post, _resolve_auth, _deny
  • openclaw.py: to_normalize_input, evaluate_before_tool_call, _verdict_auth, _verdict_block
  • adapters/openclaw/index.js: askDoberman, toHookResult, failClosed
  • hosthooks/spine.py: evaluate_action
  • models.py: SecurityObject, Verdict, Decision

Out of scope (per issue)

  • No adapter code changes.
  • No third adapter.

Validation

Read-only cross-check of each claim against claude_code.py, openclaw.py, adapters/openclaw/index.js, and models.py. Existing tests unchanged.

Fixes [#189]

Related

Tickets: #189

Discussion

  • Anonymous

    Anonymous - 2026-08-10

    Originally posted by: fu351

    This is an unusually accurate docs PR. On a close read, almost every cited symbol, field, and mapping traces to the exact line in source and holds up: the fail-closed transport constants, the SecurityObject field table, and both verdict-mapping tables (PASS/AUTH/BLOCK → Claude Code permissionDecision, and OpenClaw allow/requireApproval/block). Those are the hard part of an adapter guide, and a third integrator won't have to reverse-engineer them now.

    One fix before merge: the "Shared spine" section says the spine is the only place that builds a SecurityObject and runs the engine. The Claude Code PostToolUse path (evaluate_post plus the history recording) actually calls normalize + decide directly, over a synthetic SecurityObject built from tool output. That's correct by design, so the line just needs scoping to the pre-call gate. Small one too: Bash maps to the canonical bash, not shell.

    Fix those and it's ready to go.

     
  • Anonymous

    Anonymous - 2026-08-11

    Ticket changed by: fu351

    • status: open --> closed
     
  • Anonymous

    Anonymous - 2026-08-11

    Originally posted by: fu351

    This is the doc I wish had existed before the second adapter got written. I checked every symbol you cited against the source before merging — all of them exact, down to the field names in the OpenClaw verdict table — which means the next adapter author can actually grep their way through it. And you documented the pre/post asymmetry honestly instead of smoothing it over, which is exactly the right instinct for this repo.

    Two wording fixes I pushed to your branch before merging (6d582ea), so you know what changed and why. The guide said the spine is the only place a SecurityObject gets built. That's true on the pre-call path, but the post-call output scan builds its own outside spine.evaluate_action, and anyone adding a post-call scan to a new adapter would have followed the doc down the wrong path — the section now says which path the claim covers and points at the post-call precedent. Also, "two shipping integrations" quietly left out the experimental Codex adapter, so a parenthetical names it now.

    Since you've now mapped both adapters end to end, [#244] (level-5) — the research memo on Cursor and Codex CLI interception surfaces — is a natural next one. It's the same close reading you just did, aimed at what we haven't finished fronting yet.

     

    Related

    Tickets: #244


Log in to post a comment.