Domain: Context — Function Reference
State fork domain (ι concept). Provides immutable roadmap context snapshots for audit trail. Each snapshot captures the roadmap’s nodes, connections, and phases at a point in time; a SHA-256 hash (excluding timestamp) ensures integrity. Supports change detection between snapshots and auto-creation when roadmap content changes.
MCP Tools Exposed
Exposed through unified controller. Key tool names: context_create, context_get, context_latest, context_history, context_verify, context_ensure, context_compare.
| Tool Name | Description | Key Inputs | Returns |
|---|---|---|---|
context_create |
Create a context snapshot | roadmapId: string, metadata?: object |
{ success, context, summary: { roadmapId, nodeCount, contentHash (truncated) } } |
context_get |
Get context by ID | contextId: number |
{ success, context } |
context_latest |
Get latest context for roadmap | roadmapId: string |
{ success, context\|null, message? } |
context_history |
List context history | roadmapId, limit?: 1-100 (default 10) |
{ success, roadmapId, count, contexts[] } |
context_verify |
Verify context hash integrity | contextId: number |
{ success, valid, contextId, storedHash, recalculatedHash, createdAt } |
context_ensure |
Auto-create if roadmap changed | roadmapId, metadata? |
{ success, context, isExisting: boolean, summary? } |
context_compare |
Diff two context snapshots | contextId1, contextId2?: defaults to latest |
{ success, totalChanges, differences } |
Core Functions
createContext(roadmapId, metadata)
Purpose: Snapshot the current roadmap state (nodes, connections, phases) and store with a content hash.
Parameters: roadmapId: string, metadata?: object|null
Returns: Promise<{ success, context, summary: { roadmapId, nodeCount, contentHash } }>
Side effects: Reads roadmap data from filesystem via getRoadmap and getRoadmapNodes; writes context row to DB.
Notes for rewrite: Hash is computed BEFORE adding capturedAt timestamp so identical content always produces identical hash regardless of when it’s captured.
getContext(contextId)
Purpose: Fetch a stored context by its integer ID.
Parameters: contextId: number (positive integer)
Returns: Promise<{ success, context }>
Side effects: Throws if not found.
getLatestContext(roadmapId)
Purpose: Get the most recently created context for a roadmap.
Parameters: roadmapId: string
Returns: Promise<{ success, context\|null, message? }>
listContextHistory(roadmapId, limit)
Purpose: List context snapshots for a roadmap, newest first, with content hashes truncated.
Parameters: roadmapId: string, limit: 1-100 (default 10)
Returns: Promise<{ success, roadmapId, count, contexts[{ contextId, contentHash (truncated), createdAt, metadata }] }>
verifyContext(contextId)
Purpose: Re-hash the stored snapshot data (minus timestamp) and compare to stored hash.
Parameters: contextId: number
Returns: Promise<{ success, valid, contextId, storedHash (truncated), recalculatedHash (truncated), createdAt }>
Notes for rewrite: Uses { capturedAt, ...rest } = snapshot destructuring to exclude timestamp. isValid = SHA256(JSON.stringify(rest)) === contentHash.
ensureContext(roadmapId, metadata)
Purpose: Return existing context if current; create new if roadmap changed or no context exists.
Parameters: roadmapId: string, metadata?: object|null
Returns: Promise<{ success, context, isExisting: boolean, summary? }>
Side effects: If roadmap changed, calls dbPruneRagContextDocuments(roadmapId, newContextId) to clean up stale RAG data.
Notes for rewrite: This is the primary call path for auto-context management in orchestration.
compareContexts(contextId1, contextId2)
Purpose: Compute a structural diff between two context snapshots.
Parameters: contextId1: number, contextId2?: number|null (defaults to latest for same roadmap)
Returns: Promise<{ success, totalChanges, differences }>
Notes for rewrite: See diff structure below.
Database Operations
| Operation | Query Pattern | Tables Used |
|---|---|---|
| Create context | INSERT with hash and JSON snapshot | contexts |
| Get context by ID | SELECT by contextId | contexts |
| Get latest context | SELECT latest by roadmapId | contexts |
| List contexts | SELECT with LIMIT | contexts |
| Prune RAG documents | DELETE stale RAG docs | rag_documents |
Key Algorithms
Content Hash (excluding timestamp)
snapshotData = { title, nodes[], connections, phases } // no capturedAt
contentHash = SHA256(JSON.stringify(snapshotData))
// stored snapshot = { ...snapshotData, capturedAt: ISO8601 }
Node Snapshot Shape
{ id, label, scope, phase, dependencies[], dependents[] }
Context Diff (compareContexts)
diff = {
roadmapId, contextId1, contextId2, createdAt1, createdAt2,
titleChanged: boolean,
title: { old, new },
nodes: compareNodes(snapshot1.nodes, snapshot2.nodes),
connections: compareArrays(snapshot1.connections, snapshot2.connections, "id"),
phases: compareArrays(snapshot1.phases, snapshot2.phases, "id")
}
totalChanges = (titleChanged?1:0) + nodes.added + nodes.removed + nodes.modified + connections.added + connections.removed
compareNodes
added = nodes in snapshot2 not in snapshot1 (by id)
removed = nodes in snapshot1 not in snapshot2
modified = nodes in both where label/scope/phase/dependencies/dependents changed
compareArrays(arr1, arr2, keyField)
added = arr2 items where keyField not in arr1
removed = arr1 items where keyField not in arr2
Validation Schemas Used
CreateContextSchema=RoadmapIdSchema(string matching roadmap ID pattern)GetContextSchema=z.number().int().positive()ListContextHistorySchema={ roadmapId: RoadmapIdSchema, limit: 1-100, default 10 }CompareContextsSchema={ contextId1: positive int, contextId2?: positive int }
buildSnapshotFromRoadmap (internal helper)
roadmap = getRoadmap(roadmapId) // throws with domain-specific error if fails
{ nodes, connections, phases } = getRoadmapNodes(roadmapId)
snapshotData = { title: roadmap.title, nodes: nodes.map(compact), connections, phases }
contentHash = SHA256(JSON.stringify(snapshotData))
return { snapshotData, contentHash }
This helper is shared between createContext and ensureContext to eliminate duplication.