4 — Additions: Bridges to the Outside
Colibri is a closed system with a three-axis physics, a four-tier social hierarchy, and a locked execution pipeline. But it lives in a world full of other systems: Git, Obsidian, Claude API, developer editors, human messaging tools. The system must integrate with these external realities without allowing them to corrupt internal invariants. This is what ν Integrations does.
The Integration Pattern
Nothing enters or exits the world without passing through the α chain and leaving a ζ record. External systems are not trusted — they are mediated.
Pattern: The α-ζ Invariant
Every external call follows a schema:
invoke(context, #contract) → Record
- context: the current state (which task, which round, which identity)
- #contract: a schema that validates what an external system can and cannot do
- Record: a ζ thought record added to the decision trail, timestamped and hashed
Stages:
- Audit-enter (α.3): The call enters the middleware chain. The contract is loaded.
- Schema-validate (α.2): The external request is mapped to the contract schema. Invalid requests are rejected.
- Dispatch: The external system is called with the validated request.
- Audit-exit (α.4): The response is logged and added to the ζ decision trail.
- Record-finalize (ζ): The record is hash-chained to the previous decision in the trail.
If any stage fails, the entire operation is aborted. The external system never sees a half-baked mutation.
Example: GitHub commit via the GitHub Desktop bridge (Phase 0)
- Task
P0.3.2completes in a worktree - Executor calls
git commit -m "feat(tasks): ..." - Audit-enter: the executor’s session is checked (is it running in a valid worktree?)
- Schema-validate: the commit message is parsed. Forbidden patterns are rejected. Max message length is enforced.
- Dispatch:
git commitis run via the GitHub Desktop MCP - Audit-exit: the commit SHA is logged, the branch name is verified as
feature/<task-slug> - Record-finalize: a ζ record is added:
{"event": "vcs_commit", "branch": "feature/p0.3.2", "sha": "abc123...", "timestamp": "2026-04-13T10:22:45Z"}
If the commit fails (e.g., non-fast-forward), the stage 5 error is propagated back, and no ζ record is created.
Phase 0 Integrations (Implemented or Near-Ready)
Git (GitHub Desktop, never manual CLI)
Why not manual CLI? The Phase 0 Git interface is GitHub Desktop only. Direct CLI access (git push) is forbidden from T3 executor sessions. This prevents accidental force-pushes to main.
Contract: Per CLAUDE.md §3 (worktree rule):
git fetch originallowed (read-only)git worktree add .worktrees/claude/<task-slug> -b feature/<task-slug> origin/mainallowed (creates worktree)git commitonfeature/<task-slug>allowed (local changes)git pushforbidden (human authorizes via GitHub Desktop / PR merge)- Force-push (
git push -f) forbidden on all branches - Deletion of
feature/<task-slug>before merge forbidden
Bridge: GitHub Desktop MCP (not yet connected in Phase 0, manual until P0.9)
Records: Every commit, branch creation, and push attempt is logged to mcp_vcs_events.
Obsidian (Pull-based sync via robocopy)
Why pull-based? Obsidian is a human workspace. It is read-only for code. Changes made in the vault (Obsidian Vault/Colibri/docs/) are never synced back to the repo. This prevents accidental overwrite of canonical specs.
Contract:
docs/→ Obsidian vault: full mirror, updated viarobocopyor thecolibri-docs-syncskill- Obsidian
_vault/→ repo: never. Human planning lives here, is never committed. - Merge strategy:
docs/always wins. If a file exists in both places, the repo copy is canonical.
Direction: One-way, docs → vault. If the human edits a file in the vault that also exists under docs/, those edits are local-only (not pushed).
Sync timing: Manual skill execution (Phase 0), or scheduled (Phase 1+)
Excluded from sync: .git, _vault, .worktrees, node_modules, temp/
Records: Every sync operation logs a ν_obsidian_sync record with file count, conflict resolution strategy, timestamp.
Claude API (Anthropic SDK, Phase 0.5+)
Why separate from Colibri server? Phase 0 is Claude-only, but the language model is external to the server. When a task dispatcher (T2 PM or T3 executor) needs to call Claude, it goes through the router (δ).
Contract:
- Request schema:
{task_id, context, max_tokens, temperature, model} - Response schema:
{tokens_in, tokens_out, model_used, stop_reason, completion} - No system prompt injection:
systemis fixed per phase - Latency budget: 60 seconds per call (P0), 120 seconds (later phases with reasoning)
Bridge: Claude API wrapper (src/domains/router/call.ts, P0.5.2)
Records: Every API call logs mcp_model_calls with routing decision, model, tokens, latency, completion reason.
Forbidden:
- Streaming responses (Phase 0 is one-shot only)
- Vision (deferred to Phase 1)
- Batch processing (deferred to Phase 1)
Integration Architecture (ν domains)
The integrations layer lives in src/domains/integrations/ (Phase 0.9 target). It is organized by external system:
src/domains/integrations/
├── github/
│ ├── contracts.ts # what GitHub APIs can be called
│ ├── client.ts # GitHub Desktop MCP wrapper
│ └── events.ts # vcs_* record schemas
│
├── obsidian/
│ ├── contracts.ts # what paths can be synced
│ ├── sync.ts # robocopy wrapper + strategy
│ └── events.ts # obsidian_sync record schema
│
├── anthropic/
│ ├── contracts.ts # API request/response schemas
│ ├── client.ts # SDK wrapper
│ └── events.ts # model_calls record schema
│
└── index.ts # adapter dispatcher
Every adapter follows the same pattern:
- contracts.ts: Zod schemas for request/response
- client.ts: MCP tool wrapper or HTTP client
- events.ts: ζ record schema
- index.ts: registration in the dispatcher
Failure Handling
External systems fail. Networks go down. APIs return 5xx. The integration pattern isolates failures.
Failure modes:
| Failure | Stage | Behavior |
|---|---|---|
| Invalid request | Schema-validate | Rejected before dispatch. ζ record: {status: "rejected", reason: "schema_error"} |
| Network timeout | Dispatch | Task is retried 3 times, then marked deferred (Phase 1+) or escalated (Phase 0) |
| API error (4xx) | Audit-exit | Logged as-is. No ζ record (auth failures) or ζ record with error (business logic failure) |
| API error (5xx) | Audit-exit | Retried with exponential backoff. Max 5 retries. Then escalated to T2 PM |
| Partial success | Audit-exit | Depends on operation. Commits are atomic (all-or-nothing). Syncs are idempotent. |
Key principle: If ζ record is written, the operation is committed. If ζ record is not written, the operation must be retried or escalated.
Phase 0.9: ν Additions in Action
P0.9 lands in round R80 (the final Phase 0 round). By then:
- GitHub Desktop integration is connected (PR creation + merge workflow)
- Obsidian sync is automated via a scheduled skill
- Claude API calls are logged and routed through the decision trail
- All integration records are validated and added to ζ
At Phase 0 seal, the system has:
- 256 task-level ζ records (one per task, plus routing + API calls)
- ≈50 vcs records (commits, branch creates, PRs)
- ≈8 obsidian_sync records (end of each round)
- Hundreds of model_calls records (every executor session)
All are Merkle-sealed into the session root hash.
Future Integrations (Phase 1+)
| Phase | Bridge | What it adds |
|---|---|---|
| P1 | Editor tools (VS Code, JetBrains) | Live diagnostics, task-aware linting |
| P1 | Slack / Discord | Status updates, notifications |
| P1+ | Plugin system | User-defined adapters, worker thread isolation |
| P7 | CRDT/OT sync | Real-time vault collaboration via Yjs + WebSocket |
| P7 | AI intelligence suite | Semantic cache, query optimizer, pattern recognizer (24 sub-modules) |
Every new integration:
- Defines a contract schema
- Implements an adapter in
src/domains/integrations/<system>/ - Registers itself in the dispatcher
- Logs its output as ζ records
No integration can read or modify the main database. All mutations go through the α middleware chain.
The Core Guarantee
Nothing enters or exits the world without passing through the α chain and leaving a ζ record.
This is not a performance optimization. It is a security invariant. Every external connection is mediated, validated, logged, and sealed into the proof tree. At Phase 0 seal, the system has a complete, auditable log of every external interaction it ever had. The proof tree roots this log cryptographically. Trust is not a feature — it is a consequence of architecture.
Integration Failure Contract
Every integration adapter must answer the same four questions the same way: what does a transient failure look like, what does a permanent failure look like, how many times do I retry, and where does the proof go? This section specifies the universal contract; per-integration sections above already describe their own schemas and bridges.
Per-integration failure semantics
GitHub Desktop MCP — if not connected, ν_github_* tools return:
{
"ok": false,
"error": {
"code": "INTEGRATION_UNAVAILABLE",
"message": "github-desktop MCP not connected"
}
}
The task layer retries up to 3 times with exponential backoff (200ms, 1s, 5s) before escalating to T2 PM. Permanent auth errors (e.g., GitHub token revoked) skip the retry loop and escalate immediately.
Obsidian sync bridge — if temp/sync-full.bat fails (robocopy exit code > 3), the failure is logged to mcp_integrations_log with the robocopy exit code and the first 512 bytes of stderr. Vault drift is acceptable and non-blocking: the Obsidian vault is a human workspace, not a runtime dependency. PM (T2) runs the sync manually on the next round seal if the automated retry didn’t recover.
Claude API (Anthropic SDK) — 5xx errors retry with exponential backoff (1s, 4s, 15s, 60s). 4xx errors (except 429 rate-limit) do not retry. 429 retries use the retry-after header if present; otherwise it falls back to a 30-second floor.
Generic retry semantics
- Transient (network drop, timeout, 5xx, 429 rate-limit, lock contention) — retry with exponential backoff, 3 attempts by default.
- Permanent (auth failure, schema mismatch, 4xx other than 429) — fail fast, log the error, escalate to T0 via session seal notes.
- Unknown — treat as transient once; if the second attempt reproduces the same error code, reclassify as permanent.
Logging shape
Every adapter writes to mcp_integrations_log (Phase 1 target table; Phase 0 stashes this in mcp_vcs_events / mcp_model_calls per domain) using the same record shape:
{
"timestamp": "2026-04-16T14:30:02Z",
"integration_id": "github-desktop",
"operation": "commit",
"result": "SUCCESS" ,
"attempt_number": 1,
"error_code": null,
"latency_ms": 412
}
result is one of SUCCESS | RETRY | FAIL. RETRY rows are emitted per attempt so that a failing operation produces N-1 RETRY rows followed by a terminal FAIL row. SUCCESS after RETRYs is permitted and expected.
Cross-refs
../3-world/execution/decision-trail.md— ζ record shape; every finalSUCCESS/FAILrow also lands here.../guides/troubleshoot.md§integrations — operator recovery playbook when the escalation reaches T0.
See Also
- α System Core — middleware chain
- ζ Decision Trail — records and hashing
- ν Integrations
- CLAUDE.md §3 — worktree rule (Git contract)
- Surfaces — four surfaces