# Session Context Pattern ## Problem **Context Fragmentation in Multi-Agent Orchestration** When orchestrating complex features across multiple agents (TaskManager → CoderAgent → TestEngineer), each agent is stateless and loses context between delegations: - **TaskManager** creates subtasks but doesn't know what ContextScout discovered - **CoderAgent** doesn't see what ArchitectureAnalyzer decided - **TestEngineer** doesn't know what files CoderAgent created - **Orchestrator** has to manually pass context in every delegation This leads to: - ❌ Repeated context discovery (inefficient) - ❌ Inconsistent decisions (agents don't see previous choices) - ❌ Lost architectural context (bounded contexts, contracts, ADRs) - ❌ Manual context passing (error-prone, verbose) ## Solution **Persistent Session Context File** Create a single `context.md` file that all agents read and update throughout the feature lifecycle: ``` .tmp/sessions/{session-id}/context.md ``` This file acts as the **shared memory** for the entire orchestration session. ## Architecture ### Session Lifecycle ``` 1. Orchestrator creates session → context.md initialized 2. ContextScout updates → adds context_files 3. ArchitectureAnalyzer updates → adds bounded_context, module 4. TaskManager reads context → creates subtasks with full context 5. CoderAgent reads context → knows all decisions, files, contracts 6. TestEngineer reads context → knows what to test 7. Orchestrator marks complete → session archived ``` ### Context.md Structure ```markdown # Task Context: {Feature Name} Session ID: {session-id} Created: {timestamp} Status: in_progress | completed | blocked ## Current Request {Original user request - what we're building} ## Context Files to Load - {Standards paths - coding conventions, patterns, security rules} ## Reference Files - {Source material - existing project files to look at} ## Architecture - Bounded Context: {DDD context from ArchitectureAnalyzer} - Module: {Package/module name} - Vertical Slice: {Feature slice from StoryMapper} ## User Stories - {Story 1 from StoryMapper} - {Story 2} ## Priorities - RICE Score: {score from PrioritizationEngine} - WSJF Score: {score} - Release Slice: {v1.0.0, Q1-2026, MVP} ## Contracts - {type}: {name} ({status}) Path: {contract file path} ## Architectural Decision Records - {ADR-ID}: {title} Path: {adr file path} ## Progress Current Stage: {Stage N: Name} Completed Stages: - {Stage 0: Context Loading} - {Stage 1: Planning} Stage Outputs: - {Stage 0}: - {Output 1} - {Output 2} ## Key Decisions - [{timestamp}] {decision} Rationale: {why this choice was made} ## Files Created - {file path 1} - {file path 2} ## Exit Criteria - [ ] {criterion 1} - [ ] {criterion 2} - [x] {completed criterion} ``` ## When to Use ### Use Session Context When: ✅ **Multi-agent orchestration** - Feature requires 3+ agents working sequentially ✅ **Complex features** - Needs architecture analysis, contracts, ADRs ✅ **Stateful workflows** - Later agents need to know what earlier agents did ✅ **Context-heavy tasks** - Lots of standards, patterns, decisions to track ### Don't Use Session Context When: ❌ **Single agent tasks** - Simple subtask execution (CoderAgent alone) ❌ **Stateless operations** - Each task is independent ❌ **Quick fixes** - Bug fixes, small updates ## Usage by Agent Type ### Orchestrator (MetaAgent) **Stage 0: Initialize Session** ```typescript import { createSession } from '.opencode/skill/task-management/scripts/session-context-manager'; const result = createSession(feature, request, { contextFiles: [], // Will be populated by ContextScout referenceFiles: [], exitCriteria: [ 'All subtasks completed', 'Tests passing', 'Documentation updated' ] }); const sessionId = result.sessionId; // Pass sessionId to all subsequent agents ``` **Between Stages: Update Context** ```typescript import { updateSession, markStageComplete } from './session-context-manager'; // After ContextScout completes updateSession(sessionId, { contextFiles: [ '.opencode/context/core/standards/code-quality.md', '.opencode/context/core/standards/security-patterns.md' ] }); // After ArchitectureAnalyzer completes updateSession(sessionId, { architecture: { boundedContext: 'authentication', module: '@app/auth' } }); // Mark stage complete markStageComplete(sessionId, 'Stage 1: Planning', [ '.tmp/tasks/auth-system/task.json', '.tmp/tasks/auth-system/subtask_01.json' ]); ``` **Final Stage: Complete Session** ```typescript updateSession(sessionId, { status: 'completed' }); ``` ### TaskManager **Stage 0: Load Session Context** ```typescript import { loadSession } from '.opencode/skill/task-management/scripts/session-context-manager'; const result = loadSession(sessionId); if (!result.success) { throw new Error(`Session not found: ${sessionId}`); } const session = result.session; // Use session context for task planning const contextFiles = session.contextFiles; // Standards to follow const referenceFiles = session.referenceFiles; // Source files to look at const architecture = session.architecture; // Bounded context, module const contracts = session.contracts; // API contracts const adrs = session.adrs; // Architectural decisions ``` **Stage 2: Create Tasks with Full Context** ```json { "id": "auth-system", "name": "Authentication System", "context_files": ["...from session.contextFiles..."], "reference_files": ["...from session.referenceFiles..."], "bounded_context": "...from session.architecture.boundedContext...", "module": "...from session.architecture.module...", "contracts": ["...from session.contracts..."], "related_adrs": ["...from session.adrs..."] } ``` **Stage 3: Update Progress** ```typescript import { addDecision } from './session-context-manager'; addDecision(sessionId, { decision: 'Split authentication into 3 subtasks: schema, service, middleware', rationale: 'Each subtask is atomic (1-2 hours) and has clear dependencies' }); ``` ### CoderAgent **Before Coding: Load Session Context** ```typescript import { loadSession } from '.opencode/skill/task-management/scripts/session-context-manager'; const result = loadSession(sessionId); const session = result.session; // Read context files (standards) session.contextFiles.forEach(file => { // Load coding standards, security patterns }); // Read reference files (existing code) session.referenceFiles.forEach(file => { // Study existing patterns }); // Check architectural constraints const boundedContext = session.architecture?.boundedContext; const contracts = session.contracts; // API contracts to implement const adrs = session.adrs; // Architectural decisions to follow ``` **After Coding: Track Files Created** ```typescript import { addFile } from './session-context-manager'; addFile(sessionId, 'src/auth/jwt.service.ts'); addFile(sessionId, 'src/auth/jwt.service.test.ts'); ``` ### ContextScout **After Discovery: Update Session** ```typescript import { updateSession } from './session-context-manager'; updateSession(sessionId, { contextFiles: [ '.opencode/context/core/standards/code-quality.md', '.opencode/context/core/standards/security-patterns.md', '(example: .opencode/context/core/standards/naming-conventions.md)' ], referenceFiles: [ 'src/middleware/auth.middleware.ts', 'src/config/jwt.config.ts' ] }); ``` ### ArchitectureAnalyzer **After Analysis: Update Session** ```typescript import { updateSession, addDecision } from './session-context-manager'; updateSession(sessionId, { architecture: { boundedContext: 'authentication', module: '@app/auth', verticalSlice: 'user-login' } }); addDecision(sessionId, { decision: 'Place authentication in separate bounded context', rationale: 'Auth is a core domain with clear boundaries, used by multiple features' }); ``` ### ContractManager **After Contract Definition: Update Session** ```typescript import { updateSession } from './session-context-manager'; updateSession(sessionId, { contracts: [ { type: 'api', name: 'AuthAPI', path: 'src/api/auth.contract.ts', status: 'defined' }, { type: 'interface', name: 'JWTService', path: 'src/auth/jwt.service.ts', status: 'draft' } ] }); ``` ## API Reference ### createSession(feature, request, options) Initialize a new session with context.md file. **Parameters:** - `feature` (string) - Feature name (kebab-case) - `request` (string) - Original user request - `options` (object) - Optional configuration - `contextFiles` (string[]) - Standards paths - `referenceFiles` (string[]) - Source file paths - `exitCriteria` (string[]) - Completion criteria - `architecture` (object) - Bounded context, module, vertical slice - `stories` (string[]) - User stories - `priorities` (object) - RICE/WSJF scores, release slice - `contracts` (array) - API/interface contracts - `adrs` (array) - Architectural decision records **Returns:** ```typescript { success: boolean; sessionId?: string; error?: string } ``` **Example:** ```typescript const result = createSession('auth-system', 'Implement JWT authentication', { exitCriteria: ['All tests passing', 'JWT tokens signed with RS256'] }); // result.sessionId = "auth-system-2026-02-15T10-30-00-000Z" ``` ### loadSession(sessionId) Read session context from context.md. **Parameters:** - `sessionId` (string) - Session identifier **Returns:** ```typescript { success: boolean; session?: SessionContext; error?: string } ``` **Example:** ```typescript const result = loadSession('auth-system-2026-02-15T10-30-00-000Z'); if (result.success) { const contextFiles = result.session.contextFiles; const architecture = result.session.architecture; } ``` ### updateSession(sessionId, updates) Append new information to session context. **Parameters:** - `sessionId` (string) - Session identifier - `updates` (object) - Fields to update - `status` - 'in_progress' | 'completed' | 'blocked' - `contextFiles` - Add standards paths (merged with existing) - `referenceFiles` - Add source file paths (merged with existing) - `architecture` - Update bounded context, module, vertical slice - `stories` - Add user stories - `priorities` - Update RICE/WSJF scores - `contracts` - Add contracts - `adrs` - Add ADRs **Returns:** ```typescript { success: boolean; error?: string } ``` **Example:** ```typescript updateSession(sessionId, { architecture: { boundedContext: 'authentication', module: '@app/auth' }, contracts: [ { type: 'api', name: 'AuthAPI', path: 'src/api/auth.contract.ts', status: 'defined' } ] }); ``` ### markStageComplete(sessionId, stage, outputs) Mark a workflow stage as complete and record outputs. **Parameters:** - `sessionId` (string) - Session identifier - `stage` (string) - Stage name (e.g., "Stage 1: Planning") - `outputs` (string[]) - Files/artifacts created in this stage **Returns:** ```typescript { success: boolean; error?: string } ``` **Example:** ```typescript markStageComplete(sessionId, 'Stage 1: Planning', [ '.tmp/tasks/auth-system/task.json', '.tmp/tasks/auth-system/subtask_01.json', '.tmp/tasks/auth-system/subtask_02.json' ]); ``` ### addDecision(sessionId, decision) Log a key decision with rationale. **Parameters:** - `sessionId` (string) - Session identifier - `decision` (object) - `decision` (string) - What was decided - `rationale` (string) - Why this choice was made **Returns:** ```typescript { success: boolean; error?: string } ``` **Example:** ```typescript addDecision(sessionId, { decision: 'Use RS256 for JWT signing instead of HS256', rationale: 'RS256 (asymmetric) is more secure for distributed systems where tokens are verified by multiple services' }); ``` ### addFile(sessionId, filePath) Track a file created during the session. **Parameters:** - `sessionId` (string) - Session identifier - `filePath` (string) - Path to created file **Returns:** ```typescript { success: boolean; error?: string } ``` **Example:** ```typescript addFile(sessionId, 'src/auth/jwt.service.ts'); addFile(sessionId, 'src/auth/jwt.service.test.ts'); ``` ### getSessionSummary(sessionId) Get current session state summary. **Parameters:** - `sessionId` (string) - Session identifier **Returns:** ```typescript { success: boolean; summary?: { sessionId: string; feature: string; status: string; currentStage: string; completedStages: number; totalDecisions: number; filesCreated: number; exitCriteriaMet: number; exitCriteriaTotal: number; }; error?: string; } ``` **Example:** ```typescript const result = getSessionSummary(sessionId); console.log(`Progress: ${result.summary.completedStages} stages complete`); console.log(`Files: ${result.summary.filesCreated} created`); console.log(`Exit Criteria: ${result.summary.exitCriteriaMet}/${result.summary.exitCriteriaTotal}`); ``` ## CLI Usage ```bash # Create session npx ts-node session-context-manager.ts create auth-system "Implement JWT authentication" # Load session npx ts-node session-context-manager.ts load auth-system-2026-02-15T10-30-00-000Z # Show summary npx ts-node session-context-manager.ts summary auth-system-2026-02-15T10-30-00-000Z ``` ## Benefits ✅ **No context loss** - All agents see the full picture ✅ **Consistent decisions** - Architectural choices tracked and visible ✅ **Efficient** - Context discovered once, used by all agents ✅ **Auditable** - Complete history of decisions and progress ✅ **Self-documenting** - context.md is human-readable ✅ **Resumable** - Can pause and resume orchestration ## Best Practices ### 1. Initialize Early Create session at the start of orchestration, before any agent work begins. ### 2. Update After Each Stage Every agent that completes work should update the session context. ### 3. Read Before Acting Every agent should load session context before starting work. ### 4. Track Decisions Use `addDecision()` for any architectural or design choice. ### 5. Track Files Use `addFile()` for every file created (helps with cleanup, rollback). ### 6. Use Exit Criteria Define clear, binary exit criteria at session creation. ## Example: Full Orchestration Flow ```typescript // Orchestrator: Initialize const { sessionId } = createSession('auth-system', 'Implement JWT authentication', { exitCriteria: ['All tests passing', 'JWT tokens signed with RS256'] }); // Stage 0: ContextScout discovers context updateSession(sessionId, { contextFiles: ['.opencode/context/core/standards/code-quality.md'], referenceFiles: ['src/middleware/auth.middleware.ts'] }); markStageComplete(sessionId, 'Stage 0: Context Loading', []); // Stage 1: ArchitectureAnalyzer analyzes updateSession(sessionId, { architecture: { boundedContext: 'authentication', module: '@app/auth' } }); addDecision(sessionId, { decision: 'Separate bounded context for auth', rationale: 'Core domain with clear boundaries' }); markStageComplete(sessionId, 'Stage 1: Architecture Analysis', []); // Stage 2: TaskManager creates tasks const { session } = loadSession(sessionId); // Use session.contextFiles, session.architecture in task.json markStageComplete(sessionId, 'Stage 2: Task Planning', [ '.tmp/tasks/auth-system/task.json' ]); // Stage 3: CoderAgent implements const { session } = loadSession(sessionId); // Read session.contextFiles, session.contracts addFile(sessionId, 'src/auth/jwt.service.ts'); markStageComplete(sessionId, 'Stage 3: Implementation', [ 'src/auth/jwt.service.ts' ]); // Stage 4: Complete updateSession(sessionId, { status: 'completed' }); ``` ## Related - `.opencode/skill/task-management/scripts/session-context-manager.ts` - Implementation - `.opencode/context/core/task-management/standards/task-schema.md` - Task JSON schema - `.opencode/context/core/workflows/task-delegation.md` - Multi-agent orchestration - `.tmp/sessions/test-task-manager/context.md` - Example session context