session package

Reviewed against commit 8a2cb42ad on 2026-10-23.

Reference: generated package page orchestrata_ultimate.session (63 modules, 14,958 lines of code); key modules controller, context, graph_store, kg_sync, cli. Sessions, the session CLI and the gateway's session.* methods are explained as part of the whole in the orchestrata overview; the graph it syncs into is described on knowledge_graph, and the plan parser behind goals on planning.

The story

Orchestrata's work does not happen in one sitting. Development unfolds across many discrete sessions — a human or an agent begins work, logs what was done, records decisions and file artifacts, and hands off to whoever picks the project up next. orchestrata_ultimate.session (spec 006, SPEC-023 for goals) exists to make that continuity durable and auditable. It is a fresh implementation of session management built around a dual-storage architecture: Redis holds hot, low-latency session state (RedisSessionStore), the operational graph (orchkg on orchgraph, a Memgraph fork) holds the cold, permanent archive (GraphSessionStore in graph_store.py; it was Neo4jSessionStore until Neo4j was retired on 2026-07-27), and SessionSync flushes the former into the latter. Alongside the databases sits the humble, human-readable layer everyone actually interacts with: a context.md/context.json pair in the project root, owned by ContextFileManager and rendered through Jinja2 templates.

The central actor is SessionController, composed in controller/_core.py from four responsibility mixins — GoalMixin (SPEC-023 goal-driven sessions with exit criteria), GitOpsMixin (commit/push/tag), ChangelogMixin (CHANGELOG.md categorization and splicing), and TestStateMixin (pytest collection and run state). It holds three things: the project root, the resolved ai_model name, and a ContextFileManager (ctx) — with the currently open session guarded behind a threading.Lock. A typical flow starts when a session begins — via the Click CLI (cli/lifecycle.py), an MCP tool call (mcp_tools.py), or automatically through the session_auto_start_hook. As work proceeds, log_work, log_artifact, and log_choice accumulate as Pydantic models (SessionRecord, WorkItem, LogEntry, FileArtifact, TechChoice in models.py) inside ContextData. In parallel, FactEmitter turns session activity into Fact objects, writes them hot in Redis and optionally cold in the graph, and keeps the Prolog engine synchronized as the logical source of truth through PrologSessionInterface and PrologFactBridge. When the session closes, validate_and_end runs checklist validation (raising ChecklistError/SessionStartError on failure) to enforce that tests pass and git is clean, and HandoverManager, WorkCarryoverManager, and SessionArchiver prepare the next session's starting point.

Durability is a first-class concern, because context.json is written by several independent OS processes (the session_cli.py invocations the agent makes, the SessionStart hook, and the in-process SessionEnd hook). ContextFileManager therefore writes atomically (temp file → fsync → os.replace), guards every read-modify-write with a cross-process fcntl.flock on a sidecar .context.lock, and self-heals corrupt reads by salvaging the valid JSON prefix or restoring a .bak — the defense against the recurring "Extra data" corruption. verify_history_integrity and recover_from_git provide a further safety net, reconstructing lost sessions from git tags and history when needed.

Beyond a single session, the package tells the knowledge graph the whole project's story. KnowledgeGraphSyncer (kg_sync/) runs a staged pipeline into orchkg. sync_all runs seven stages (project, directory tree, AST-extracted classes/functions, specs, traces, docs/statistics, file traceability), and nine when it is given a session number (session and session files are added); its docstring still says 8. Meanwhile kg_context.py is the read side, pulling relevant graph nodes back out for context injection. PortfolioController lifts the same model to multi-project coordination. The package collaborates widely with its neighbors: it builds on core (graph/Redis client factories, traceability decorators, the tracing scanner), drives orchestrator's PipelineRunner from the cli/pipeline.py commands (run/resume/approve/reject agent pipelines), wraps the controller in EventEmittingSessionController so lifecycle events reach the kernel's event bus, and exposes the MCP tools of an external integration (fireflies_tools.py). Three Claude Code hooks (hooks/) close the loop with the editing workflow itself: auto-starting sessions, extracting facts from tool calls, and gating session close.

Key responsibilities

Class diagram

Controller and context files

SessionController is the façade: it composes four responsibility mixins and owns a single ContextFileManager for all file I/O.

Diagram projects-orchestrata-ultimate-modules-session-1

Facts and dual storage

FactEmitter fans every fact out to three backends; SessionSync reconciles the hot Redis store into the cold graph archive (GraphSessionStore).

Diagram projects-orchestrata-ultimate-modules-session-2

Domain models

The persisted shape of a session. ContextData is the root object serialized to context.json; a SessionRecord nests the log, artifacts, choices and handoff for one session.

Diagram projects-orchestrata-ultimate-modules-session-3

Continuity, recovery, portfolio and KG sync

The helpers that carry state across sessions and out to the knowledge graph. The three file-based managers each own a ContextFileManager; RecoveryManager checkpoints through Redis; KnowledgeGraphSyncer runs the 8-stage sync into orchkg.

Diagram projects-orchestrata-ultimate-modules-session-4

Notes

Class attributes and method signatures above were extracted from the live source via the AST toolkit; all four mermaid blocks are render-verified.

Class map (generated)

Generated from the live source AST by scripts/gen-module-class-diagrams.py — do not hand-edit. Abstract classes have a green border; members listed are those defined on the class itself (inherited members excluded). Solid empty-triangle arrows = in-package inheritance; dashed arrows into dashed boxes = external/stdlib/cross-package bases; filled diamond = composition (constructed in __init__); open diamond = aggregation (annotated/injected reference); diamond edge labels name the owning attribute.

session class map