docs: document the shared shape of Doberman host adapters
Your AI's guard dog to stop it from going rogue.
Brought to you by:
doberman
Originally created by: AshSgDe29071999
Adds docs/ADAPTER_GUIDE.md so a third host-adapter author does not have to reverse-engineer both existing integrations.
(canonical, args) → spine.evaluate_action → SecurityObject (models.py fields, normalize() as the single constructor).permissionDecision and OpenClaw BeforeToolCallResult (allow / requireApproval / block), including fail-closed transport behavior in adapters/openclaw/index.js.claude_code.py: to_normalize_input, evaluate_pre, evaluate_post, _resolve_auth, _denyopenclaw.py: to_normalize_input, evaluate_before_tool_call, _verdict_auth, _verdict_blockadapters/openclaw/index.js: askDoberman, toHookResult, failClosedhosthooks/spine.py: evaluate_actionmodels.py: SecurityObject, Verdict, DecisionRead-only cross-check of each claim against claude_code.py, openclaw.py, adapters/openclaw/index.js, and models.py. Existing tests unchanged.
Fixes [#189]
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
SecurityObjectfield table, and both verdict-mapping tables (PASS/AUTH/BLOCK → Claude CodepermissionDecision, and OpenClawallow/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
SecurityObjectand runs the engine. The Claude Code PostToolUse path (evaluate_postplus the history recording) actually callsnormalize+decidedirectly, over a syntheticSecurityObjectbuilt from tool output. That's correct by design, so the line just needs scoping to the pre-call gate. Small one too:Bashmaps to the canonicalbash, notshell.Fix those and it's ready to go.
Ticket changed by: fu351
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
SecurityObjectgets built. That's true on the pre-call path, but the post-call output scan builds its own outsidespine.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