Files
the-matrix/INTEGRATION.md
Perplexity Computer 22daaade36 docs: INTEGRATION.md v2 — Replit fork coordination + economy protocol
- Added Fork Coordination section documenting replit/the-matrix changes
- Acknowledged Replit resolved issues #1 (Vite), #2 (agent-defs), #6 (UUID)
- Updated architecture diagram to reflect Vite + ES module structure
- Documented Replit's module exports for each file
- Aligned field names to camelCase (matching Replit's codebase)
- Updated Phase 2 ownership: Replit primary, Perplexity review
- Added coordination strategy: code flows replit→canonical, docs stay canonical
- Resolved WS path decision (#10): VITE_WS_URL env var
2026-03-18 23:54:13 +00:00

450 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Integration Plan: The Matrix × Timmy Time
**Date:** 2026-03-18 (v2 — updated against live codebase + Replit fork)
**Author:** Perplexity Computer
**Status:** Active — cross-referenced with issues across all three repos
---
## Overview
The Matrix is a standalone 3D world that visualizes and commands the Timmy Time agent swarm. It currently runs on a `MockWebSocket`. This document defines how it integrates with the two other systems:
1. **Timmy Dashboard** — FastAPI/HTMX mission control (`rockachopa/Timmy-time-dashboard`)
2. **Token-Gated Economy** — Lightning-based agent economy (`replit/token-gated-economy`)
The Matrix does not replace either system. It is a third interface — spatial, persistent, iPad-native.
### Related Issues
| Repo | Key Issues |
|---|---|
| `perplexity/the-matrix` | #1#17 (full backlog) |
| `replit/token-gated-economy` | #1 (EPIC), #2 (WebSocket), #3 (SSE), #7 (3D env), #9 (chat UI) |
| `rockachopa/Timmy-time-dashboard` | #325 (cognitive state → Matrix), #326 (Timmy hands), #324 (three-phase loop) |
---
## Fork Coordination: `perplexity/the-matrix` ↔ `replit/the-matrix`
Replit forked the canonical repo and is actively developing on branch `feat/vite-build-agent-defs`. This creates a two-track development model:
### What Replit Has Done (as of 2026-03-18)
| Change | Addresses Issue | Details |
|---|---|---|
| Vite build system | #1 | `package.json` + `vite.config.js`, Three.js as npm dep (`0.171.0`) |
| Consolidated agent defs | #2 | New `js/agent-defs.js` — single source of truth for agent id/color/role/position |
| `crypto.randomUUID()` | #6 | Used in `websocket.js` subscribe handshake |
| ES module refactor | — | All files use `import/export`, Three.js via npm not CDN |
| CSS inlined | — | Styles moved into `index.html <style>`, `style.css` removed |
| `PROTOCOL.md` removed | — | Working from clean slate on their fork |
| `INTEGRATION.md` removed | — | Working from clean slate on their fork |
| Simplified interaction | — | `OrbitControls` via `three/addons`, much cleaner |
| WS URL via env var | #7 partial | `import.meta.env.VITE_WS_URL` — configurable at build time |
### Coordination Strategy
**Replit = upstream for code.** Their Vite refactor is a clean break. The canonical `perplexity/the-matrix` keeps docs (`PROTOCOL.md`, `INTEGRATION.md`) and the issue tracker. Replit's code will be the production codebase.
**Workflow:**
1. Replit develops features on their fork (`replit/the-matrix`)
2. Replit opens PRs to canonical (`perplexity/the-matrix`) when features are stable
3. Perplexity (this account) reviews, tests, and merges upstream
4. Issues stay on the canonical repo — both teams reference them
5. `INTEGRATION.md` and `PROTOCOL.md` live in canonical only — Replit reads them here
**Sync cadence:** Replit syncs their fork from canonical before starting new work. Cross-fork PRs merge at feature boundaries, not every commit.
### Issues Resolved by Replit's Branch
When the `feat/vite-build-agent-defs` branch is merged upstream, the following issues can be closed:
- **#1** — Build system: Vite replaces esm.sh CDN ✓
- **#2** — Agent definition consolidation ✓
- **#6** — `crypto.randomUUID()`
- **#11/#12** — partially addressed (commit mentions them, needs verification)
---
## Architecture (Current State)
```
┌─── Timmy Tower (FastAPI + SQLite + Ollama) ──────────────────────┐
│ │
│ src/dashboard/ → HTMX pages, WebSocket live feeds │
│ src/timmy/ → Agent core, agentic loop, memory │
│ src/timmy/adapters/ → gitea_adapter, time_adapter (NEW) │
│ src/infrastructure/ → EventBus (async, SQLite-backed, │
│ wildcard subscriptions, replay) │
│ src/dashboard/routes/chat_api_v1.py → SSE chat, v1 API (NEW) │
│ │
└───────────────────────────────────────────────────────────────────┘
┌─── Token Economy (Express + PostgreSQL + LNbits) ─────────────────┐
│ │
│ artifacts/api-server/src/routes/ │
│ jobs.ts → eval invoice → work invoice → execute → refund │
│ sessions.ts → deposit → macaroon auth → balance management │
│ ui.ts → Timmy chat interface │
│ lib/ │
│ pricing.ts → cost-based pricing, BTC oracle, model rates │
│ lnbits.ts → Lightning invoices (stub mode available) │
│ agent.ts → Anthropic eval + work execution │
│ event-bus.ts → typed EventEmitter (job:*, session:*) │
│ stream-registry.ts → SSE stream management (PR #20) │
│ │
└────────────────────────────────────────────────────────────────────┘
┌─── The Matrix (Three.js + Vite + WebSocket) ─────────────────────┐
│ │
│ js/agent-defs.js → AGENT_DEFS single source of truth (NEW) │
│ js/websocket.js → WS client, VITE_WS_URL env var │
│ js/agents.js → Agent class, 3D avatars, connection lines │
│ js/ui.js → HUD, agent list, chat panel │
│ js/effects.js → Matrix rain particles, starfield │
│ js/interaction.js → OrbitControls (three/addons) │
│ js/main.js → Init + render loop │
│ js/world.js → Scene, camera, renderer, grid │
│ vite.config.js → Build config (esnext target) │
│ package.json → three@0.171.0, vite@^5.4.0 │
│ │
│ Docs (canonical repo only): │
│ PROTOCOL.md → WebSocket message spec │
│ INTEGRATION.md → This document │
│ │
└────────────────────────────────────────────────────────────────────┘
```
### Module Structure (Replit's Vite Refactor)
```
js/
agent-defs.js → exports: AGENT_DEFS[], colorToCss()
agents.js → exports: initAgents(), updateAgents(), setAgentState(),
getAgentCount(), getAgentDefs()
effects.js → exports: initEffects(), updateEffects()
interaction.js → exports: initInteraction(), updateControls()
main.js → entry point, imports all modules, runs animate loop
ui.js → exports: initUI(), updateUI(), appendChatMessage()
websocket.js → exports: initWebSocket(), getConnectionState(), getJobCount()
world.js → exports: initWorld(), onWindowResize()
```
Key design: `agent-defs.js` is the single source of truth. To add an agent, append one entry to `AGENT_DEFS`. No other file needs editing. WebSocket handler maps `msg.agentId` → agent defs for state and chat rendering.
---
## The Hard Problem: Two Payment Models
> Tracked in: `the-matrix#9`
The Matrix protocol currently assumes simple state transitions:
```
agent_state → idle | active
job_started → increment counter
job_completed → decrement counter
```
The Token Economy has a multi-step payment flow:
```
POST /api/jobs → eval invoice (10 sats)
→ pay eval invoice → Timmy evaluates
→ work invoice (variable sats, cost-based)
→ pay work invoice → Timmy executes
→ honest accounting → refund if overpaid
```
### Resolution: Extend WebSocket message types
The Matrix message handler (`websocket.js handleMessage()`) currently handles: `agent_state`, `job_started`, `job_completed`, `chat`, `agent_count`. New message types needed:
| Economy State | New WS message type | Matrix behavior |
|---|---|---|
| `created` | `invoice_request` (type=eval) | Show eval cost in chat panel |
| `evaluating` | `agent_state` (state=active) | Agent glows active |
| `awaiting_work_payment` | `invoice_request` (type=work) | Show work cost + pay button |
| `work_paid` | `invoice_settled` | Log in chat, start work animation |
| `completed` | `job_completed` (extended) | Show result + actual cost + refund |
| `rejected` | `job_completed` (with error) | Log rejection |
New message schemas for `PROTOCOL.md`:
```jsonc
// Server → Client: invoice for operator to pay
{
"type": "invoice_request",
"jobId": "...",
"invoiceType": "eval" | "work",
"paymentRequest": "lnbc...", // BOLT11
"amountSats": 500,
"description": "Work fee for: analyze sentiment..."
}
// Server → Client: payment confirmed
{
"type": "invoice_settled",
"jobId": "...",
"invoiceType": "eval" | "work"
}
// Server → Client: job completed with accounting
{
"type": "job_completed",
"jobId": "...",
"agentId": "alpha",
"result": "...",
"actualCostSats": 380,
"estimatedCostSats": 500,
"refundSats": 120
}
```
Note: field names use camelCase to match Replit's refactored code (`agentId`, not `agent_id`).
---
## WebSocket Path Alignment
> Tracked in: `the-matrix#10`
Three systems, three WS paths:
- Matrix (Replit refactor): `import.meta.env.VITE_WS_URL` — fully configurable
- Economy PR #20: SSE on HTTP (no WS path yet); issue #2/#15 track WS
- Dashboard: `ws://tower:8080/ws`
**Resolved:** Replit's refactor uses `VITE_WS_URL` env var. No hardcoded path. Set it at build/dev time:
```bash
VITE_WS_URL=ws://tower:8080/ws/matrix npm run dev
```
If empty, the Matrix runs disconnected (no mock — just shows OFFLINE).
---
## Phase 1: WebSocket Gateway
> Tracked in: `the-matrix#8`, `dashboard#325`
**Owner:** Dashboard team (Kimi or Claude)
**Effort:** 23 days
The dashboard's `infrastructure/events/bus.py` already provides:
- Typed `Event` dataclass with source, type, data, timestamp
- Async pub/sub with wildcard matching (`agent.task.*`)
- SQLite persistence + replay
- Existing subscribers: gitea_adapter, time_adapter
What's needed: A WebSocket endpoint that bridges the EventBus to Matrix clients.
```python
# src/infrastructure/ws_gateway/matrix_handler.py
@router.websocket("/ws/matrix")
async def matrix_ws(websocket: WebSocket):
await websocket.accept()
# Send agent registry on connect
await websocket.send_json({
"type": "connection",
"status": "connected",
"agents": get_agent_registry()
})
# Subscribe to relevant bus events
@bus.subscribe("agent.*")
async def on_agent_event(event: Event):
await websocket.send_json(translate_to_matrix(event))
@bus.subscribe("task.*")
async def on_task_event(event: Event):
await websocket.send_json(translate_to_matrix(event))
# Handle inbound Matrix messages
async for msg in websocket.iter_json():
await handle_matrix_message(msg)
```
The `translate_to_matrix()` function maps EventBus events → Matrix protocol messages (using the camelCase field names from Replit's codebase). The `handle_matrix_message()` function routes Matrix commands → internal APIs.
### Cognitive State Signal
Dashboard issue #325 asks for Timmy's cognitive state to drive his 3D avatar behavior. This feeds into the gateway:
```jsonc
// New event on the bus: timmy.cognitive_state
{
"type": "agent_state",
"agentId": "timmy",
"state": "deep_focus",
"focusTopic": "analyzing PR #315",
"engagement": 0.9,
"coherence": 0.85
}
```
---
## Phase 2: Frontend Integration
> Tracked in: `the-matrix#7`
**Owner:** Replit (primary), Perplexity (review)
**Effort:** 12 days
**Blocked on:** Phase 1 (need a real WS endpoint to connect to)
Replit's refactor already handles most of this:
- `websocket.js` connects to `VITE_WS_URL` with auto-reconnect
- `handleMessage()` dispatches by `msg.type`
- `setAgentState()` drives 3D avatar glow/animation
What remains:
- Add `invoice_request` / `invoice_settled` / extended `job_completed` handlers to `handleMessage()`
- Expose economy data to `ui.js` for payment UI
- Add connection handshake → populate agent registry from server (not just `AGENT_DEFS`)
---
## Phase 3: Economy Display
> Tracked in: `the-matrix#15`, `#17`
**Owner:** Perplexity (this repo) or Replit
**Effort:** 23 days
**Blocked on:** Phase 1 (need real data)
### Status Panel — Economy Section
Extend `ui.js updateUI()` to show economy data when available:
```
┌─────────────────────────────────────────┐
│ BALANCE ⚡ 15,420 sats │
│ EARNED TODAY ⚡ 8,500 │
│ SPENT TODAY ⚡ 3,200 │
│ DAILY LIMIT ⚡ 50,000 │
│ PENDING 2 invoices │
└─────────────────────────────────────────┘
```
### Chat Panel — Payment Flow
Payment events render in the existing chat panel via `appendChatMessage()`:
```
[SYS] JOB a4f2... eval invoice: ⚡10 sats
[SYS] JOB a4f2... eval paid — evaluating...
[ALPHA] Task looks feasible. Work cost: ⚡500 sats
[SYS] JOB a4f2... work invoice: ⚡500 sats [PAY]
[SYS] JOB a4f2... work paid — executing...
[ALPHA] Analysis complete. Actual cost: ⚡380 sats, refund: ⚡120 sats
```
### Core Panel — Treasury
New DOM element in `index.html`, rendered by `ui.js`:
```
┌─────────────────────────────────────────┐
│ TREASURY ⚡ 142,800 sats │
│ DAILY BURN ⚡ 12,400 │
│ NET TODAY +⚡ 5,800 │
│ SESSION BALANCE ⚡ 2,340 │
└─────────────────────────────────────────┘
```
---
## Phase 4: 3D Economy Visuals
> Tracked in: `the-matrix#13`, `#15`
**Owner:** Perplexity or Replit
**Effort:** 23 days
**Blocked on:** Phase 3
### Budget Stress Glow
In `agents.js` — the Agent class `update()` method already blends `emissiveIntensity` based on state. Extend to include `budgetStress` (0.01.0):
- 0.0: normal agent color
- 0.5: shifts toward warning orange
- 1.0: emergency red
### Sat Flow Particles
On `invoice_settled` events, animate particles along connection lines from payer → payee. Small glowing dots traveling the path. Use `effects.js` pattern (BufferGeometry + Points).
### Dynamic Agent Hot-Add (#12)
When `agent_joined` fires via WS, create a new Agent instance from the message data and call `scene.add()`. The `AGENT_DEFS` array becomes the default set; live agents can extend it.
---
## Phase 5: Session Mode
> Maps to: `economy/sessions.ts`
**Owner:** Both repos
**Effort:** 23 days
**Blocked on:** Phase 2
The economy supports session mode: deposit sats upfront, get a macaroon, chat freely until balance runs out. This is the iPad-native experience.
### Flow in The Matrix
1. First connection: "Deposit ⚡10010,000 sats to start a session" prompt
2. Show Lightning invoice QR (render in chat panel or overlay)
3. On payment: session activates, macaroon stored in localStorage
4. Chat freely — each message deducts from session balance
5. Balance display in status panel, warning at minimum threshold
6. Session expiry countdown
---
## File Changes Summary
### Matrix repo (`replit/the-matrix` → merged to `perplexity/the-matrix`)
| File | Change | Phase | Issue |
|---|---|---|---|
| `js/websocket.js` | Add economy message handlers | 2 | #7, #9 |
| `js/ui.js` | Economy rows, payment chat, treasury panel | 3 | #15, #17 |
| `js/agents.js` | Budget stress glow, dynamic hot-add | 4 | #12, #13, #15 |
| `js/effects.js` | Sat flow particles | 4 | #13 |
| `js/agent-defs.js` | May become runtime-extensible for hot-add | 4 | #12 |
| `index.html` | Treasury DOM, PWA manifest link | 3 | #5, #17 |
| `PROTOCOL.md` | Add economy message types, cognitive state | 2 | #9 |
### Dashboard repo (`rockachopa/Timmy-time-dashboard`)
| File | Change | Phase |
|---|---|---|
| `src/infrastructure/ws_gateway/` | New — Matrix protocol bridge | 1 |
| `src/timmy/cognitive_state.py` | New — observable cognitive state | 1 |
### Economy repo (`replit/token-gated-economy`)
| File | Change | Phase |
|---|---|---|
| WebSocket endpoint | New — payment events over WS | 1 |
| `lib/event-bus.ts` | Emit to Matrix-format WS channel | 1 |
---
## Open Decisions
| # | Question | Options | Status |
|---|---|---|---|
| 1 | WS path | `VITE_WS_URL` env var — resolved | ✓ Resolved by Replit |
| 2 | Auth | Token param for now, L402 later | Proposed in #11 |
| 3 | Which backend? | Dashboard (Tower) or Economy (Replit) | Depends on deployment |
| 4 | Multi-operator | Defer to v2 | — |
| 5 | Agent hot-add | Backend pushes `agent_joined` event | Tracked in #12 |
| 6 | Session vs per-task | Support both, session default on iPad | Phase 5 |
| 7 | Fork merge cadence | Feature-boundary PRs, not every commit | Proposed above |
---
*This document lives in `perplexity/the-matrix` (canonical) and is the source of truth for how the three systems connect. Replit's fork reads this doc; code PRs flow from `replit/the-matrix` → `perplexity/the-matrix`. Backend tasks are cross-referenced to their respective repos via issue numbers.*