Files
clawmates/handoff/realtime/events.schema.json
T
Omar SobhandClaude Opus 4.8 39bacbd1d2 World page: live WebGL Gource-style visualization (Phases A+B)
Replaces the static React-Flow world forest with a real-time WebGL view of the
swarm working, plus the live event contract that feeds it.

Phase A — the live contract + feed:
- frontend/src/lib/live/taxonomy.ts — the 13-event Clawmates Event Taxonomy as
  typed TS (the shared World/Observe contract).
- frontend/src/lib/live/useClawmatesLive.ts — native shared-singleton live client
  (EventSource to /api/world/live, typed fan-out, replay-of-last-state to late
  subscribers, refcounted, synthetic fallback so views are always alive).
- crates/cm-api/src/routes/world.rs — GET /api/world/live, authed + workspace-
  scoped SSE emitting the taxonomy (real agent.status from live-container state,
  a topology.update of the workspace's agents, telemetry with real doorsPending),
  mirroring run_events_sse. normalize() seam documented for run_events->world.touch.

Phase B — the WebGL engine:
- frontend/src/components/world/engine.ts — Gource-inspired force-directed model:
  org/company/team tree (sibling repulsion + parent spring + friction), agent
  pawns that converge on the touched node and beam it, world nodes that glow with
  heat and fade when idle. Framework-agnostic (renderer-independent) state+math.
- frontend/src/components/world/WorldCanvas.tsx — three.js scene (ortho cam,
  UnrealBloom), render loop syncing engine state, camera auto-fit, HTML labels,
  raycast click->select, Hierarchy/Flat/Live formation switch.
- Dashboard.tsx: swap <WorldFlow/> -> <WorldCanvas/> at the world-tier seam
  (shared claw-tier pieces untouched; WorldFlow.tsx kept for now).
- Adds three (+ @types/three).

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-23 21:23:34 -07:00

200 lines
6.7 KiB
JSON

{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://clawmates.work/schemas/events.schema.json",
"title": "Clawmates Event Taxonomy",
"description": "Normalized real-time events emitted by the live bridge and consumed by the visualizations. Each SSE frame is `event: <type>` + `data: <object matching the matching definition>`.",
"type": "object",
"oneOf": [
{ "$ref": "#/definitions/agent.status" },
{ "$ref": "#/definitions/agent.task.update" },
{ "$ref": "#/definitions/agent.reasoning.delta" },
{ "$ref": "#/definitions/agent.computer.frame" },
{ "$ref": "#/definitions/agent.tool.call" },
{ "$ref": "#/definitions/door.request" },
{ "$ref": "#/definitions/door.resolve" },
{ "$ref": "#/definitions/agent.message" },
{ "$ref": "#/definitions/world.touch" },
{ "$ref": "#/definitions/node.activity" },
{ "$ref": "#/definitions/topology.update" },
{ "$ref": "#/definitions/telemetry" },
{ "$ref": "#/definitions/routine.update" }
],
"definitions": {
"agent.status": {
"type": "object",
"required": ["agentId", "status"],
"properties": {
"agentId": { "type": "string" },
"status": { "enum": ["online", "working", "idle", "offline"] },
"role": { "type": "string" }
}
},
"agent.task.update": {
"type": "object",
"required": ["agentId", "taskId", "title"],
"properties": {
"agentId": { "type": "string" },
"taskId": { "type": "string" },
"title": { "type": "string" },
"elapsedMs": { "type": "integer", "minimum": 0 },
"steps": {
"type": "array",
"items": {
"type": "object",
"required": ["label", "state"],
"properties": {
"label": { "type": "string" },
"state": { "enum": ["done", "active", "pending"] }
}
}
}
}
},
"agent.reasoning.delta": {
"type": "object",
"required": ["agentId", "text"],
"properties": {
"agentId": { "type": "string" },
"text": { "type": "string", "description": "Token chunk to APPEND to the reasoning stream." },
"channel": { "enum": ["think", "say", "tool"], "default": "think" }
}
},
"agent.computer.frame": {
"type": "object",
"required": ["agentId", "app"],
"properties": {
"agentId": { "type": "string" },
"app": { "enum": ["browser", "terminal", "slack", "claw-chat"] },
"url": { "type": "string" },
"lines": {
"type": "array",
"items": {
"type": "object",
"required": ["text"],
"properties": {
"text": { "type": "string" },
"kind": { "enum": ["plain", "add", "del", "ok", "warn", "cursor"], "default": "plain" }
}
}
}
}
},
"agent.tool.call": {
"type": "object",
"required": ["agentId", "tool"],
"properties": {
"agentId": { "type": "string" },
"tool": { "type": "string" },
"target": { "type": "string" },
"doorRequired": { "type": "boolean", "default": false }
}
},
"door.request": {
"type": "object",
"required": ["doorId", "agentId", "action"],
"properties": {
"doorId": { "type": "string" },
"agentId": { "type": "string" },
"action": { "type": "string", "description": "e.g. github.review.comment" },
"target": { "type": "string" },
"summary": { "type": "string" }
}
},
"door.resolve": {
"type": "object",
"required": ["doorId", "decision"],
"properties": {
"doorId": { "type": "string" },
"decision": { "enum": ["approve", "deny"] },
"by": { "type": "string" }
}
},
"agent.message": {
"type": "object",
"required": ["fromAgentId", "toAgentId", "text"],
"properties": {
"fromAgentId": { "type": "string" },
"toAgentId": { "type": "string" },
"text": { "type": "string" },
"ts": { "type": "string", "format": "date-time" }
}
},
"world.touch": {
"type": "object",
"description": "An agent is converging on a project/service/event node (Gource). Drives the Live canvas retarget + beam.",
"required": ["agentId", "nodeId"],
"properties": {
"agentId": { "type": "string" },
"nodeId": { "type": "string" },
"kind": { "enum": ["service", "event"], "default": "service" },
"weight": { "type": "number", "minimum": 0, "maximum": 1, "default": 1 }
}
},
"node.activity": {
"type": "object",
"required": ["nodeId"],
"properties": {
"nodeId": { "type": "string" },
"label": { "type": "string" },
"kind": { "enum": ["service", "event"] },
"heat": { "type": "number", "minimum": 0, "maximum": 1 }
}
},
"topology.update": {
"type": "object",
"description": "Full or partial re-layout of the world graph.",
"required": ["formation"],
"properties": {
"formation": { "enum": ["hierarchy", "flat", "live"] },
"nodes": {
"type": "array",
"items": {
"type": "object",
"required": ["id", "tier"],
"properties": {
"id": { "type": "string" },
"tier": { "enum": ["org", "company", "team", "agent", "service", "event"] },
"label": { "type": "string" },
"parentId": { "type": "string" }
}
}
},
"edges": {
"type": "array",
"items": {
"type": "object",
"required": ["from", "to"],
"properties": {
"from": { "type": "string" },
"to": { "type": "string" },
"kind": { "enum": ["parent", "peer", "flow"], "default": "parent" }
}
}
}
}
},
"telemetry": {
"type": "object",
"properties": {
"tokensPerMin": { "type": "number" },
"costPerHr": { "type": "number" },
"loops": { "type": "integer" },
"doorsPending": { "type": "integer" }
}
},
"routine.update": {
"type": "object",
"required": ["routineId", "name", "kind"],
"properties": {
"routineId": { "type": "string" },
"name": { "type": "string" },
"kind": { "enum": ["cron", "loop"] },
"owner": { "type": "string" },
"schedule": { "type": "string", "description": "cron expr or next-run hint" },
"progress": { "type": "number", "minimum": 0, "maximum": 1 },
"state": { "enum": ["running", "scheduled", "done", "failed", "door"] }
}
}
}
}