Portability audit — all platform-specific concerns moved to adapter layer:
- Gate Approval UX (Resolved Mechanics): rewritten as platform-agnostic.
Core: runner writes gate_pending, calls notify_adapter.send(), polls
blackboard for gate_approved. Universal path: agency CLI writes directly
to blackboard. Adapter handles its own inbound response bridge internally.
- pending_gates.json removed from core directory structure and runner
responsibilities — adapter-internal state, not a core concern.
- 'User → Hans → team_runner.start()' → 'User → team_runner.start()'
Core has no dependency on a specific caller.
- 'notify_adapter.send(...to Andrew via Hans)' → 'notify_adapter.send()'
throughout design.md and buildspec.md.
- anthropic.py description: 'via OpenClaw or direct API' → 'direct API'
(anthropic adapter never goes via OpenClaw)
- Output/review decision: 'Hans messages Andrew' → 'notify_adapter.send()'
- Run visibility decision: 'Andrew via Hans' → 'via notify_adapter.send()'
- Decisions log: gate approval and visibility entries rewritten accordingly
Adapter layer correctly unchanged:
adapters/notify/openclaw.py — OpenClaw-specific, owns its inbound bridge
adapters/runtime/openclaw.py — OpenClaw sessions_spawn, correctly isolated
team.yaml example config — adapter selection is config, not core