Status: Accepted Date: 2026-04-20 Deciders: cyre (diazMelgarejo)
AlphaClaw (diazMelgarejo/AlphaClaw) is a macOS ARM64 port of chrysb/alphaclaw — an active upstream. The system must evolve to support Claude Code, Xcode 26 mcpbridge, Ollama, and LM Studio agents co-managing AlphaClaw installations, while keeping the fork clean and upstreamable.
Two companion repos exist (Perplexity-Tools → renamed Perpetua-Tools, ultrathink-system → renamed orama-system) that accumulated orchestration logic in conflict with each other. The previous contract had gateway routing split between PT and orama, direct Python patching of the AlphaClaw npm package, and no stable interface boundary.
Forces at play:
- AlphaClaw tracks an active upstream (
chrysb/alphaclaw). Every internal import creates a merge conflict surface. - orama-system must remain a stateless execution layer — it must not re-own gateway decisions.
- Local agents (Ollama, LM Studio) need a unified client that works offline and survives backend failures.
- MCP protocol requires a standalone stdio server process — not an HTTP endpoint inside AlphaClaw.
- The rename from Perplexity-Tools eliminates trademark risk (
Perplexityis an active AI company, copyright infringement not intended).
Adopt a three-repo layered architecture where PT drives AlphaClaw exclusively through its CLI and HTTP surface — never via require() or direct file patching at runtime.
AlphaClaw (Layer 1 — infrastructure / managed dependency)
│ node bin/alphaclaw.js + GET /health, /api/status, etc.
▼
Perpetua-Tools (Layer 2 — middleware / adapters / tooling)
│ typed adapter contract (docs/adapter-interface-contract.md)
▼
orama-system (Layer 3 — orchestration / meta-intelligence / delegate runtime)
PT is the single authoritative control plane for: gateway discovery, route choice, lifecycle (start/stop/restart), LM Studio routing, and local agent dispatch. orama only applies PT-resolved config and exposes execution interfaces.
PT spawns node bin/alphaclaw.js start and communicates via GET /health, GET /api/status, POST /api/gateway/restart, etc. The AlphaClaw MCP server (packages/alphaclaw-adapter/src/mcp/server.js) is a standalone stdio process managed by PT.
| Dimension | Assessment |
|---|---|
| Upstream coupling | Low — zero imports from AlphaClaw internals |
| Latency | Slightly higher (HTTP round-trip) but irrelevant at human-interaction timescales |
| Crash isolation | High — AlphaClaw crash doesn't kill PT or MCP server |
| Testability | High — adapter can be tested with mock HTTP server |
| Upstreamability | High — AlphaClaw stays a clean fork, PRs mergeable |
Pros: Zero coupling to upstream internals; adapter absorbs churn from upstream merges; MCP server survives AlphaClaw restarts; strangler-fig lets us migrate incrementally. Cons: Slightly more ceremony to add new capabilities (must add HTTP endpoint + adapter method).
PT imports AlphaClaw internals via require() or calls openclaw_bootstrap.py methods directly.
| Dimension | Assessment |
|---|---|
| Upstream coupling | High — every upstream merge is a potential breaking change |
| Crash isolation | Low — tight process coupling |
| Testability | Low — requires AlphaClaw's full dependency tree |
| Upstreamability | Low — fork diverges, upstream PRs rejected |
Rejected. Identified in old contract as the source of gateway decision authority being split.
Mount an /mcp HTTP route in AlphaClaw that speaks JSON-RPC 2.0 over HTTP.
| Dimension | Assessment |
|---|---|
| Upstream coupling | High — MCP logic lands in AlphaClaw |
| Crash isolation | None — AlphaClaw crash kills MCP |
| Upstreamability | Low — violates "no PT code in AlphaClaw" invariant |
Rejected immediately. Violates the core invariant.
Key trade-off accepted: HTTP adapter adds a layer of indirection. In exchange, we get zero upstream coupling — when chrysb/alphaclaw merges a breaking change, only docs/adapter-interface-contract.md and packages/alphaclaw-adapter/src/index.js need updating, not orama or any consumer of PT's API.
Resolved tension — macOS patching vs lifecycle management: setup_macos.py in orama applies 6 idempotent patches to the AlphaClaw npm binary at OS-install time (one-time, macOS-only). This is OS-level setup, not lifecycle management. PT's adapter then calls the already-patched binary. These are complementary, not competing.
Resolved tension — Python control plane vs Node.js packages: Python orchestrator/ in PT owns PT's own orchestration decisions (model routing, cost guard, LAN discovery, autoresearch). Node.js packages/ owns MCP protocol + AlphaClaw HTTP communication. Both coexist in PT with no conflict.
All three old-contract concerns resolved before Gate 1 work begins:
| Concern | Status | Evidence |
|---|---|---|
bin/agents/orchestrator/orchestrator_logic.py empty |
✅ Resolved | Full implementation: create_task_state(), advance_stage(), stage machine |
tests/test_orchestrator.py stale imports |
✅ Resolved | Already uses bin/shared + bin/agents/orchestrator; pythonpath=["."] in pyproject.toml |
| orama orchestrator tests passing | ✅ 19/19 PASS | Verified in sandbox against live code |
| Gateway decision authority split | ✅ Resolved by architecture | PT is sole authority; orama delegates |
What becomes easier:
- AlphaClaw upstream merges: diff
adapter-interface-contract.md, update one adapter file - Testing PT without running AlphaClaw: mock the HTTP surface
- Adding new MCP tools: add to
packages/alphaclaw-adapter/src/mcp/server.js, no AlphaClaw change needed - orama stays stateless: it reads PT-resolved config, never makes gateway decisions
What becomes harder:
- Adding a capability that has no AlphaClaw HTTP endpoint requires either: (a) adding the endpoint upstream, or (b) using the CLI surface
- Debugging requires understanding two process boundaries (PT ↔ AlphaClaw)
What we'll need to revisit:
- Gate 1: full
packages/alphaclaw-adapter/src/index.js— implementstatus(),login(),gatewayStatus(),restartGateway(),tailLogs() - Gate 2:
start.shin orama → thin PT delegator;openclaw_bootstrap.py→ apply-config only - Gate 3:
openclaw_bridge.pyin orama routes through PT adapter instead of direct AlphaClaw calls ALPHACLAW_ROOTenv var must be set correctly when PT and AlphaClaw are not siblings
- Scaffold
packages/alphaclaw-adapter/,packages/local-agents/,packages/mcpb-agents/ - Copy AlphaClaw MCP server + local agent client + orchestrator to PT packages/
- Update import paths in PT test file (
../../lib/agents/→../src/) - Write
docs/adapter-interface-contract.mdwith verified HTTP endpoints - Update CLAUDE.md in PT and orama with new identities
- Verify orama 19/19 tests pass
- Copy
install-gstack.shandfix-xcode-claude.shto PT scripts/
- Implement full
packages/alphaclaw-adapter/src/index.jsHTTP client - Register MCP server:
claude mcp add --transport stdio alphaclaw -- node packages/alphaclaw-adapter/src/mcp/server.js - Smoke-test all 11 MCP tools against live AlphaClaw
- Reduce orama
start.shto PT delegator - Scope
openclaw_bootstrap.pyto apply-config only - Tag
lib/mcp/+lib/agents/in AlphaClaw for removal (do not delete yet)
-
packages/mcpb-agents/:ollama-agent.mcpb,lmstudio-agent.mcpb - Wire PT
orchestrator.pyas idempotent lifecycle entrypoint - Move gstack install + Xcode scripts from AlphaClaw to PT (scripts already copied)
- Remove
lib/mcp/+lib/agents/from AlphaClawfeature/MacOS-post-install
docs/MIGRATION.md— full migration sequencedocs/adapter-interface-contract.md— living HTTP contractdocs/system-design-three-repo-architecture.md— architecture diagram + milestone gatesdocs/plan-review-migration-plan-3.md— critique and steelmanorama-system/.claude/lessons/Perplexity-Orama-Consolidation.md— lessons from prior workdocs/wiki/08-macos-alphaclaw-compat.md— macOS patching lessons