Asoba Asoba Open Source

Database

Nehanda CLI persists all session state in a local SQLite database. You own this data — no cloud dependency for persistence. The database uses WAL (Write-Ahead Logging) mode for concurrent read performance.

Location

Setting Value
Default path ~/.config/nehanda/ona-session.db
Override AGENT_SDLC_DB environment variable

Database Characteristics

Schema Reference

schema_meta

Key-value store for schema metadata.

Column Type Description
key TEXT PK Metadata key (e.g. schema_version)
value TEXT Metadata value

conversations

One row per conversation. Tracks the active SDLC phase and project root.

Column Type Description
id TEXT PK Conversation UUID
project_dir TEXT Working directory path
created_at TEXT ISO timestamp
last_active TEXT ISO timestamp (updated on each turn)
phase TEXT Current SDLC phase (default: idle)

sessions

One row per session (a session is a single runUserTurn invocation). Multiple sessions can belong to one conversation.

Column Type Description
session_id TEXT PK Session UUID
conversation_id TEXT FK Parent conversation
started_at TEXT ISO timestamp

transcript_entries

The complete audit trail. Every user message, assistant response, tool call, and tool result is stored here as a sequence.

Column Type Description
id INTEGER PK Auto-increment
session_id TEXT FK Parent session
sequence INTEGER Order within session (unique with session_id)
parent_entry_id INTEGER FK Self-referential (for threading)
entry_type TEXT user, assistant, or tool_result
payload_json TEXT Full message content as JSON
tool_use_id TEXT Links tool_result to its tool_use
created_at TEXT ISO timestamp

plans

SDLC plans created during the planning phase. Only approved plans are used.

Column Type Description
id INTEGER PK Auto-increment
conversation_id TEXT Parent conversation
file_path TEXT Optional file path reference
content TEXT Full plan text
hash TEXT Content hash for deduplication
status TEXT draft or approved
created_at TEXT ISO timestamp
approved_at TEXT ISO timestamp (set on approval)
completed_at TEXT ISO timestamp

events

SDLC milestones, subagent events, and task outputs.

Column Type Description
id INTEGER PK Auto-increment
conversation_id TEXT Parent conversation
session_id TEXT Session that triggered the event
timestamp TEXT ISO timestamp
event_type TEXT Event name (e.g. subagent_start, task_output, CwdChanged)
detail TEXT Event-specific detail (often JSON)

state

Key-value store for per-conversation state (todos, worktree info, etc.).

Column Type Description
conversation_id TEXT Part of composite PK
key TEXT Part of composite PK (e.g. todo:item-1)
value TEXT JSON-encoded value
updated_at TEXT ISO timestamp

memories + memories_fts

Long-term memory storage with full-text search. The FTS5 virtual table indexes title, content, keywords, and anticipated_queries using Porter stemming with Unicode 6.1 support.

This table is the canonical node store for the Jev-Mem memory architecture. Each row represents one observation (user turn, tool result, or assistant response) with overlapping type scores across four memory types.

Column Type Description
id TEXT PK Memory UUID
type TEXT Memory type classifier (jev_observation, etc.)
title TEXT Short title
content TEXT Full memory content
keywords TEXT Search keywords
anticipated_queries TEXT Queries this memory should match
concept_tags TEXT Concept classification tags
project_scope TEXT Project scope boundary
correction_count INTEGER Times this memory was corrected (default: 1)
created_at INTEGER Unix timestamp
updated_at INTEGER Unix timestamp
last_accessed INTEGER Unix timestamp
access_count INTEGER Number of accesses (default: 0)
attention_score REAL Relevance score (default: 0.5)
session_id TEXT Session that created this observation
conversation_id TEXT Parent conversation
provenance TEXT Source of observation (hot_path, manual, etc.)
entities_json TEXT JSON-encoded entity tags
t_episodic REAL Episodic type score (0–1)
t_semantic REAL Semantic type score (0–1)
t_procedural REAL Procedural type score (0–1)
t_preference REAL Preference type score (0–1)
source_entry_id INTEGER FK to transcript_entries
observation_ts INTEGER Unix timestamp of original observation

memory_edges

Multi-relational graph edges for the Jev-Mem memory graph. The same node pair may have independent edges of different relation types.

Column Type Description
id INTEGER PK Auto-increment
src_id TEXT Source memory node ID
dst_id TEXT Destination memory node ID
relation TEXT Edge type: semantic, temporal, causal, or entity
weight REAL Edge weight (probability from Laya relation judgment)
meta_json TEXT Additional edge metadata (JSON)
created_at INTEGER Unix timestamp

laya_jev_state

System-1 canonical session control block. One row per session, updated on every turn by the Laya control plane.

Column Type Description
session_id TEXT PK Session identifier
task_status TEXT Current task state: investigating, modifying_code, awaiting_user, verifying, blocked, or idle
file_target TEXT Primary file being modified (null if none)
escalation_risk INTEGER 0 or 1 — whether Laya flagged escalation risk
confidence_score REAL Laya confidence in current state assessment (0–1)
state_json TEXT Full state snapshot as JSON
updated_at TEXT ISO timestamp

pinned_context

Session-scoped domain invariants that survive context compaction unchanged. Used to persist ODSE schema mappings, asset capacity limits, simulation bounds, and other constants that must not be distilled or discarded during long sessions.

Unlike memories, pinned blocks are never passed to the distillation summariser. They are reattached verbatim at the start of every System-2 prompt, before the canonical Jev-Mem header and retrieved evidence.

Column Type Description
id INTEGER PK Auto-increment
session_id TEXT Parent session
key TEXT Unique string key (e.g. odse_schema, asset_spec)
content TEXT Invariant content (verbatim)
created_at INTEGER Unix timestamp

(session_id, key) is unique — upserts replace existing content for the same key.

hook_invocations

Complete log of every hook execution. Every hook that fires (whether it matched, skipped, or ran) is recorded.

Column Type Description
id INTEGER PK Auto-increment
session_id TEXT Parent session
conversation_id TEXT Parent conversation
hook_event TEXT Event name (e.g. PreToolUse)
hook_ordinal INTEGER Order within the event’s hook chain
matcher TEXT The matcher string used
command TEXT The shell command that was run
tool_use_id TEXT Related tool call ID (for tool events)
tool_name TEXT Related tool name (for tool events)
input_json TEXT Full JSON input sent to the hook via stdin
exit_code INTEGER Hook’s exit code (null if skipped)
stdout_text TEXT Hook’s stdout (capped at 4 MB)
stderr_text TEXT Hook’s stderr (capped at 4 MB)
started_at TEXT ISO timestamp
completed_at TEXT ISO timestamp
skipped_reason TEXT Why the hook was skipped (null if ran)

tool_permission_log

Every permission decision, regardless of outcome.

Column Type Description
id INTEGER PK Auto-increment
session_id TEXT Parent session
tool_use_id TEXT Tool call ID
tool_name TEXT Tool name
decision TEXT allow, deny, or ask
reason_json TEXT Additional context
created_at TEXT ISO timestamp

settings_snapshot

Effective settings after merge. Updated by /config commands and on bootstrap.

Column Type Description
scope TEXT PK Always 'effective'
json TEXT Full settings JSON
updated_at TEXT ISO timestamp

summaries

Conversation summaries for context compaction.

Column Type Description
conversation_id TEXT PK Parent conversation
content TEXT Summary text
word_count INTEGER Summary length
created_at TEXT ISO timestamp

task_ratings

User ratings of task outcomes.

Column Type Description
id INTEGER PK Auto-increment
conversation_id TEXT Parent conversation
rating INTEGER User rating
objective TEXT Task objective
timestamp TEXT ISO timestamp

Useful Queries

Recent conversation turns

SELECT entry_type, 
       json_extract(payload_json, '$.content') AS preview,
       created_at
FROM transcript_entries
WHERE session_id = '<session-id>'
ORDER BY sequence DESC
LIMIT 20;

Tool calls in a session

SELECT json_extract(payload_json, '$.content[0].name') AS tool,
       json_extract(payload_json, '$.content[0].input') AS input,
       created_at
FROM transcript_entries
WHERE session_id = '<session-id>'
  AND entry_type = 'assistant'
  AND payload_json LIKE '%tool_use%'
ORDER BY sequence;

Permission audit

SELECT tool_name, decision, created_at
FROM tool_permission_log
ORDER BY created_at DESC
LIMIT 50;

Hook execution log

SELECT hook_event, matcher, command, exit_code, 
       substr(stdout_text, 1, 200) AS stdout_preview,
       skipped_reason
FROM hook_invocations
ORDER BY id DESC
LIMIT 50;

Full-text search memories

SELECT title, content, rank
FROM memories_fts
WHERE memories_fts MATCH 'error handling'
ORDER BY rank;