The app is light shadcn; GraphView was hardcoded dark-Bauhaus and clashed. Re-theme to shadcn tokens (var(--card)/--foreground/--muted-foreground/ --border, var(--primary) for active) so the panel is theme-aware (light now, follows dark mode if toggled) and native to the command-center. Node-kind encoding kept (shapes + light-readable hues); labels are sentence-case. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
4.0 KiB
Continual-Learning Graph Spec
Owner: graph data + visualization. Status: demo-backed (live
team_modelreads land later). Satisfies the documentation-first gate for thebackend/src/graph/*andfrontend/src/components/GraphView.tsxfiles.
What this is (and is NOT)
PodMan's visible "it learned" surface. The graph is a render of the per-pod
team_model — who owns / edits which files, where work collides, and what
PodMan learned from accepted interventions (the learned_from edges). It is the
continual-learning loop made legible in 10 seconds: "PodMan now knows Karti owns auth."
It is not a generic analytics dashboard (judges down-rank dashboard-as-product). It is a secondary view behind the pods list — opened from a header toggle — that exists to make the self-improving loop visible during the demo. The landing surface stays the pods list.
Data model — graph as a view of team_model
The graph lives in two places, both keyed by podId:
-
Embedded (served to the viz): the
team_modeldocument carries agraphfield:// team_model doc (one per pod, unique index { podId: 1 }) { podId, graph: PodGraph, updatedAt }GET /api/pods/:podId/graphreturnsteam_model.graph, or a demo graph when none exists yet. -
Normalized (for traversal): the same nodes/edges are mirrored into two collections so the model can be walked with MongoDB
$graphLookup(the graph-database pattern):Collection Doc shape ( shared/src/graph.ts)Index graph_nodesGraphNodeDoc=PodGraphNode+podId{ podId: 1, id: 1 }uniquegraph_edgesGraphEdgeDoc=PodGraphEdge+podId{ podId: 1, source: 1 }
Node kinds: engineer · feature · file · collision · intervention.
Edge kinds: owns · editing · touches · collides · warns · learned_from.
The learned_from edges are the continual-learning signal — derived from accepted
interventions / outcomes (ownership PodMan retains across sessions).
Traversal ($graphLookup)
Walk the directed edge chain from any node (e.g. engineer → file → collision → intervention):
db.collection('graph_edges').aggregate([
{ $match: { podId, source: startNodeId } },
{
$graphLookup: {
from: 'graph_edges',
startWith: '$target',
connectFromField: 'target',
connectToField: 'source',
as: 'reaches',
restrictSearchWithMatch: { podId },
},
},
]);
This answers "what does this engineer's edit reach?" — the risk path PodMan lights up.
API
| Method | Route | Returns |
|---|---|---|
GET |
/api/pods/:podId/graph |
PodGraph (live team_model, demo fallback) |
GET |
/api/pods/:podId/graph/reach/:id |
$graphLookup reachability from node :id |
Additive routes in backend/src/server.ts (shared file — additive only).
Files
shared/src/graph.ts—PodGraph,PodGraphNode/Edge/Metric,GraphNodeDoc,GraphEdgeDocbackend/src/graph/demo.ts—createDemoPodGraph(podId)(grounded in the demo-pod crew)backend/src/graph/store.ts—loadPodGraph,seedGraph,reachFrom($graphLookup)backend/src/graph/seed.ts—pnpm graph:seed(writes demo intoteam_model+ graph collections)frontend/src/lib/graph.ts—fetchPodGraph(podId)frontend/src/components/GraphView.tsx— shadcn-themed SVG graph (theme-aware; toggle fromApp.tsx)
Demo-first plan
- Serve
createDemoPodGraph()from the route (demo-stable, no DB dependency on the demo path). pnpm graph:seedwrites the same graph into Mongo so$graphLookupis real, not a mock.- Swap
loadPodGraphto read liveteam_model.graphonce the ingest pipeline populates it.