Adds the team_model graph layer (the "it learned" view) and its visualization,
per docs/graph.md. Demo-backed first; built on origin/main conventions.
- shared: PodGraph / node / edge / metric types + GraphNodeDoc / GraphEdgeDoc
- backend/src/graph: demo graph data; Mongo store (loadPodGraph w/ demo
fallback, seedGraph, reachFrom via $graphLookup); graph:seed script
- backend/src/server.ts: additive GET /api/pods/:id/graph + /graph/reach/:node
- frontend: dark-Bauhaus GraphView + fetch helper, reachable from a
"Team memory" toggle in App.tsx
- docs/graph.md: spec (data model, $graphLookup, API, demo-first plan)
Demo-backed: the route serves a grounded demo graph when team_model has no
graph yet; graph:seed writes team_model + graph_nodes/graph_edges so the
$graphLookup traversal is real. Swap loadPodGraph to live team_model later.
Known follow-ups before merge: branch is based on 65a0791; origin/main is now
at 1294b84, so this needs a rebase + App.tsx conflict resolution (teammate
rewrote App.tsx with live room view / one-click join).
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— dark-Bauhaus SVG graph (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.