4.5 KiB
MongoDB Atlas Integration Spec
MongoDB Atlas is PodMan's shared memory. It stores live engineer state, the ownership map that enables continual learning, coordination events, and nudge history.
Collections
engineer_states
Latest context per engineer. Two writers, one collection — vision pipeline upserts vision fields, git watcher script upserts git fields independently. Hermes reads the merged document for event detection.
{
_id: string, // engineerId (stable across sessions)
podId: string,
name: string, // display name
// --- Vision fields (written by Hermes via POST /ingest) ---
currentFile: string | null, // active file inferred from screen
inferredTask: string | null, // what engineer appears to be doing
terminalVisible: boolean,
recentTerminalOutput: string | null,
confidence: number, // Gemini Vision confidence (0–1)
visionUpdatedAt: Date,
// --- Git fields (written directly by scripts/podman-agent.mjs) ---
changedFiles: string[], // files with uncommitted changes (git status)
diffStat: string | null, // e.g. "auth/middleware.ts | 24 +++++"
recentCommit: string | null, // most recent commit message
branch: string | null, // current branch name
gitUpdatedAt: Date,
// --- Shared ---
updatedAt: Date // most recent write from either source
}
Index: { podId: 1, updatedAt: -1 }
Two writers, no conflict: vision upsert uses $set on vision fields only; git upsert uses $set on git fields only. MongoDB upsert semantics merge them cleanly.
Usage: Hermes reads all documents for a given podId after each update to run event detection. Both vision and git context are available in the same document — changedFiles provides ground truth, currentFile provides screen context.
ownership_map
Tracks who works on which files. Built up over the session. Persists across sessions — this is the continual learning artifact.
{
_id: string, // `${podId}:${file}`
podId: string,
file: string,
primaryOwner: string, // engineerId with most recent activity on this file
contributors: string[], // all engineerIds observed on this file
observationCount: number, // total frames where this file was seen
lastSeenAt: Date
}
Index: { podId: 1, file: 1 } (unique)
Upsert logic:
- On each context update where
currentFileis non-null:- Increment
observationCount - Update
primaryOwnerto the engineer with the most recentlastSeenAton this file - Add engineerId to
contributorsif not present - Update
lastSeenAt
- Increment
Continual learning: Hermes loads this collection on startup for the pod. If history exists, it pre-populates the in-memory ownership cache before the first frame arrives.
events
Every coordination event detected by Hermes.
{
_id: ObjectId,
podId: string,
type: 'DEPENDENCY_READY' | 'BLOCKER_DETECTED' | 'DUPLICATE_WORK',
involvedEngineers: string[],
file: string | null,
reason: string, // 1-sentence explanation from Gemini
nudgeSent: boolean, // false if suppressed by cooldown
detectedAt: Date
}
Index: { podId: 1, detectedAt: -1 }
nudges
Every voice nudge sent to the room.
{
_id: ObjectId,
podId: string,
eventId: ObjectId, // ref to events collection
targetEngineers: string[],
message: string, // the spoken text
sentAt: Date
}
Index: { podId: 1, sentAt: -1 }
Cooldown check: before sending a nudge, Hermes queries this collection for any nudge in the last 3 minutes for the same podId. If found, suppresses the new nudge and marks the event as nudgeSent: false.
Hermes startup sequence
1. Connect to Atlas using MONGODB_URI
2. Load ownership_map for this podId
3. Build in-memory cache: Map<file, { primaryOwner, contributors }>
4. Begin accepting /ingest requests
Atlas configuration
- Cluster tier: M0 (free) is sufficient for hackathon scale
- Region: same as DigitalOcean deployment (e.g. NYC1)
- Auth: connection string in
MONGODB_URIenv var - Collections created automatically on first write (no schema migration needed)
What MongoDB does NOT store
- Raw screenshot frames (too large — frames are processed in-memory by Hermes and discarded)
- Full Gemini response objects (only extracted fields are stored)
- Session recordings