From cc8d79026299068fd4bdf390ca439f66ddd16a32 Mon Sep 17 00:00:00 2001 From: Lucas Israel Date: Mon, 27 Jul 2026 09:20:15 -0300 Subject: [PATCH] docs: design isolated Devin Claude bridge --- .../plans/2026-07-27-devin-claude-bridge.md | 108 ++++++++++++++++++ .../2026-07-27-devin-claude-bridge-design.md | 60 ++++++++++ 2 files changed, 168 insertions(+) create mode 100644 docs/superpowers/plans/2026-07-27-devin-claude-bridge.md create mode 100644 docs/superpowers/specs/2026-07-27-devin-claude-bridge-design.md diff --git a/docs/superpowers/plans/2026-07-27-devin-claude-bridge.md b/docs/superpowers/plans/2026-07-27-devin-claude-bridge.md new file mode 100644 index 0000000000..c32d39f3c4 --- /dev/null +++ b/docs/superpowers/plans/2026-07-27-devin-claude-bridge.md @@ -0,0 +1,108 @@ +# Devin Claude Bridge Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Build a fail-closed `devin-cli-agentic` provider that serves local Anthropic Messages requests through Devin CLI ACP stdio while preserving Claude Code tool-use semantics. + +**Architecture:** Add a separate Claude-format provider and executor instead of changing the existing OpenAI-format `devin-cli` summarizer. Keep parsing, prompt serialization, Anthropic response rendering, and ACP process handling in focused files under `open-sse/executors/devin-agentic/`, then wire them into the existing provider and executor registries. + +**Tech Stack:** TypeScript ES modules, Node child process stdio, Anthropic Messages JSON/SSE, JSON-RPC 2.0 ACP, Node test runner. + +--- + +### Task 1: Agentic Bridge Core + +**Files:** +- Create: `open-sse/executors/devin-agentic/types.ts` +- Create: `open-sse/executors/devin-agentic/serializer.ts` +- Create: `open-sse/executors/devin-agentic/toolParser.ts` +- Create: `open-sse/executors/devin-agentic/anthropicResponse.ts` +- Test: `tests/unit/executor-devin-cli-agentic-core.test.ts` + +- [ ] **Implement and prove serialization, parsing, validation, and Anthropic rendering** + +Interfaces: + +```ts +export function serializeAnthropicForDevin(body: unknown): DevinPrompt; +export function parseDevinToolRequest(text: string, tools: AnthropicTool[]): ParsedToolRequest | null; +export function buildClaudeTextResponse(args: ClaudeResponseArgs): Record; +export function buildClaudeToolUseResponse(args: ClaudeToolUseArgs): Record; +export function buildClaudeSseFrames(message: Record): string; +``` + +Invariants: + +- Preserve `text`, `tool_use`, `tool_result`, `thinking`, and `redacted_thinking`. +- Reject `image` with a clear error. +- Reject unknown content block types. +- Allow only one tool request per model turn. +- Validate tool arguments against object JSON Schema with `required`, `type`, `properties`, `additionalProperties`, `enum`, `items`, and scalar types. +- Generate deterministic ids from tool name and canonicalized arguments. + +Run: `node --import tsx/esm --test tests/unit/executor-devin-cli-agentic-core.test.ts` +Expected: core tests pass after dependencies are installed. + +### Task 2: ACP Executor And Provider Wiring + +**Files:** +- Create: `open-sse/executors/devin-cli-agentic.ts` +- Modify: `open-sse/executors/index.ts` +- Create: `open-sse/config/providers/registry/devin-cli-agentic/index.ts` +- Modify: `open-sse/config/providers/index.ts` +- Test: `tests/unit/executor-devin-cli-agentic-acp.test.ts` + +- [ ] **Implement and prove fail-closed ACP execution** + +Behavior: + +- `buildUrl()` returns `devin://acp/stdio`. +- `buildHeaders()` returns `{}`. +- `execute()` spawns only `devin acp` by default or the explicit `CLI_DEVIN_AGENTIC_BIN`/`CLI_DEVIN_BIN` override. +- The child environment removes Anthropic and Claude routing credentials before spawn. +- The executor sends `initialize`, `session/new`, and `session/prompt`. +- The executor collects `agent_message_chunk` text and `session/prompt` final result. +- Non-streaming Claude clients receive native Anthropic JSON. +- Streaming Claude clients receive native Anthropic SSE lifecycle frames. +- Spawn failure, ACP error, timeout, and early exit produce non-2xx responses with sanitized messages. + +Run: `node --import tsx/esm --test tests/unit/executor-devin-cli-agentic-acp.test.ts` +Expected: ACP mock tests pass after dependencies are installed. + +### Task 3: Isolation Scripts And Documentation + +**Files:** +- Create: `scripts/devin-bridge/verify-anthropic-isolation` +- Create: `scripts/devin-bridge/test-unit` +- Create: `scripts/devin-bridge/launch` +- Create: `docs/DEVIN_CLAUDE_BRIDGE.md` +- Modify: `.gitignore` + +- [ ] **Implement offline guardrails and operator docs** + +Behavior: + +- `verify-anthropic-isolation` fails if `CLAUDE_CONFIG_DIR` is missing, points outside an isolated path, or if Anthropic routing env vars are present. +- `test-unit` runs the focused unit tests. +- `launch` refuses to start unless `ENABLE_LIVE_DEVIN_TESTS=1` for live Devin or `DEVIN_BRIDGE_OFFLINE=1` for offline mock mode. +- Documentation distinguishes tested offline behavior from live Devin opt-in behavior. + +Run: `./scripts/devin-bridge/verify-anthropic-isolation` with explicit isolated env. +Expected: exits 0 with isolated env and non-zero without it. + +### Task 4: Verification + +**Files:** +- No additional source files. + +- [ ] **Run proportional checks and capture real output** + +Commands: + +```bash +./scripts/devin-bridge/test-unit +npm test +``` + +Expected in this workspace before installing dependencies: both commands fail with `ERR_MODULE_NOT_FOUND` for `tsx`. Expected after `npm install`: focused tests pass; `npm test` outcome must be reported from real output. + diff --git a/docs/superpowers/specs/2026-07-27-devin-claude-bridge-design.md b/docs/superpowers/specs/2026-07-27-devin-claude-bridge-design.md new file mode 100644 index 0000000000..81a3689cd6 --- /dev/null +++ b/docs/superpowers/specs/2026-07-27-devin-claude-bridge-design.md @@ -0,0 +1,60 @@ +# Devin Claude Bridge Design + +## Baseline + +- Branch: `release/v3.8.49` +- HEAD: `ed7db3ee5f89a144b2d931d8605534522f83de30` +- Package version: `3.8.49` +- Node: `v26.0.0` +- npm: `11.12.1` +- Pre-existing worktree state: `.tug/` untracked +- Dependency state: `node_modules` is absent; the first focused test run failed before loading tests because `tsx` was not installed. +- Tugline state: `tug` exists, but `tug search` failed with MCP connection closed and `tug doctor` hung; it was interrupted. +- Upstream check: `git ls-remote` failed because GitHub DNS was unavailable. Web search of the public repository showed the existing `devin-cli` summarizer provider, but no evidence of `devin-cli-agentic`. + +## Source Anchors + +- `/v1/messages`: `src/app/api/v1/messages/route.ts` +- Existing Devin provider: `open-sse/config/providers/registry/devin-cli/index.ts` +- Existing Devin executor: `open-sse/executors/devin-cli.ts` +- Executor registry: `open-sse/executors/index.ts` +- Provider registry: `open-sse/config/providers/index.ts` +- Format detection: `open-sse/services/provider.ts` +- Claude non-streaming response conversion: `open-sse/handlers/responseTranslator.ts` +- Existing Devin ACP unit test: `tests/unit/executor-devin-cli-acp-protocol-8406.test.ts` + +## Findings + +The existing `devin-cli` provider is intentionally OpenAI-format and summarizer-oriented. Its executor spawns `devin acp --agent-type summarizer`, flattens the message history into a single text prompt, and emits OpenAI SSE text chunks. It does not preserve Anthropic `tool_use` and `tool_result` blocks. + +The safest implementation is a new provider id, `devin-cli-agentic`, with a separate executor. This leaves `devin-cli`, Anthropic OAuth, Claude OAuth, Claude Web, and all host Claude configuration code untouched. The new provider is fail-closed: it only resolves to `devin://acp/stdio`, uses the official Devin CLI ACP stdio path, and has no fallback provider. + +## Architecture + +Claude Code sends Anthropic Messages requests to local OmniRoute. OmniRoute resolves model ids prefixed with `devin-cli-agentic/` to a new Claude-format provider. The new executor translates the complete Anthropic request into an explicit text prompt for Devin ACP, including system text, structured message history, tool schemas, and prior tool results. + +Devin remains a model backend. It must request tool execution by emitting a strict XML-wrapped JSON block: + +```xml + +{"name":"Read","arguments":{"file_path":"src/index.ts"}} + +``` + +The bridge parses exactly one tool request per model turn, validates that the tool name was supplied in the incoming request, validates arguments against a minimal JSON Schema validator, generates a stable `tool_devin_...` id, and returns a native Anthropic `tool_use` block. If no valid tool request is present, the bridge returns text with `stop_reason: "end_turn"`. + +## Error And Safety Rules + +- Unsupported Anthropic content blocks fail explicitly; images are rejected. +- Unknown tools fail explicitly. +- Invalid tool arguments fail explicitly. +- Invalid tool XML/JSON fails explicitly. +- Narrative claims that a tool was executed are returned as text, not actions. +- ACP spawn, timeout, early exit, and stderr-only failures return explicit Devin errors. +- The executor never reads `~/.claude`, `~/.claude.json`, macOS Keychain paths, or host Claude config. +- Live Devin is outside normal tests and remains opt-in via `ENABLE_LIVE_DEVIN_TESTS=1`. + +## Test Strategy + +Focused unit tests cover serialization, tool parsing, validation, Anthropic JSON, Anthropic SSE, malformed tool output, unknown tools, invalid arguments, image rejection, timeout, and spawn failure. Environment scripts provide an offline isolation verifier without reading host Claude credentials. +