mit einem Klick
database
Database skill for the ikigai project
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Menü
Database skill for the ikigai project
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Basierend auf der SOC-Berufsklassifikation
Automated quality check loops with escalation and fix sub-agents
JSON-based end-to-end test format, runner, and mock provider
Jujutsu (jj) skill for the ikigai project
How to write effective Ralph goals for Ikigai-driven workflows
Create and manage Ralph goals from Ikigai using the real ralph-pipeline scripts
Create repositories using the real ralph-pipeline repo-create script
| name | database |
| description | Database skill for the ikigai project |
PostgreSQL-backed event stream architecture with agent registry, session management, message persistence, inter-agent mail, and conversation replay using talloc-based memory management.
Tracks applied migrations for incremental schema updates.
| Column | Type | Constraints | Description |
|---|---|---|---|
| schema_version | INTEGER | PRIMARY KEY | Current schema version number |
Current version: 5
Groups messages by conversation session with persistent state across app launches.
| Column | Type | Constraints | Description |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | Session identifier |
| started_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | Session start timestamp |
| ended_at | TIMESTAMPTZ | NULL | Session end timestamp (NULL = active) |
| title | TEXT | NULL | Optional user-defined session title |
Indexes:
idx_sessions_started: started_at DESC for recent session lookupEvent stream storage for conversation timeline with support for replay, rollback, and agent attribution.
| Column | Type | Constraints | Description |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | Message identifier |
| session_id | BIGINT | NOT NULL, FK sessions(id) ON DELETE CASCADE | Parent session |
| kind | TEXT | NOT NULL | Event type discriminator |
| content | TEXT | NULL | Message text (NULL for clear) |
| data | JSONB | NULL | Event metadata (LLM params, etc.) |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | Event timestamp |
| agent_uuid | TEXT | NULL, FK agents(uuid) | Agent that created this message |
Event Kinds:
clear: Context reset (session start or /clear command)system: System prompt messageuser: User input messageassistant: LLM response messagetool_call: Tool invocation requesttool_result: Tool execution resultmark: Checkpoint created by /mark commandrewind: Rollback operation created by /rewind commandagent_killed: Agent termination eventcommand: Slash command output for persistence across restartsfork: Fork event recorded in both parent and child historiesusage: Token usage tracking eventIndexes:
idx_messages_session: (session_id, created_at) for chronological event stream processingidx_messages_search: GIN index on to_tsvector('english', content) for full-text searchidx_messages_agent: (agent_uuid, id) for efficient agent-based range queriesAgent registry tracking agent lifecycle, parent-child relationships, and status transitions.
| Column | Type | Constraints | Description |
|---|---|---|---|
| uuid | TEXT | PRIMARY KEY | Base64url agent UUID (22 chars) |
| name | TEXT | NULL | Optional human-friendly name |
| parent_uuid | TEXT | NULL, FK agents(uuid) ON DELETE RESTRICT | Parent agent (NULL for root) |
| fork_message_id | BIGINT | NULL | Message ID at fork point |
| status | agent_status | NOT NULL, DEFAULT 'running' | Agent status (running/dead) |
| created_at | BIGINT | NOT NULL | Unix epoch timestamp (seconds) |
| ended_at | BIGINT | NULL | Unix epoch timestamp (NULL if running) |
| provider | TEXT | NULL | LLM provider (anthropic, openai, etc.) |
| model | TEXT | NULL | Model identifier (claude-opus-4.5, etc.) |
| thinking_level | TEXT | NULL | Thinking budget/level for extended thinking |
Enum Types:
agent_status: 'running', 'dead'Indexes:
idx_agents_parent: parent_uuid for child queriesidx_agents_status: status for running agent queriesConstraints:
parent_uuid=NULLInter-agent messaging table for Erlang-style message passing between agents.
| Column | Type | Constraints | Description |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | Mail message identifier |
| session_id | BIGINT | NOT NULL, FK sessions(id) ON DELETE CASCADE | Parent session |
| from_uuid | TEXT | NOT NULL | Sender agent UUID |
| to_uuid | TEXT | NOT NULL | Recipient agent UUID |
| body | TEXT | NOT NULL | Message body |
| timestamp | BIGINT | NOT NULL | Unix epoch timestamp (seconds) |
| read | INTEGER | NOT NULL, DEFAULT 0 | Read status (0=unread, 1=read) |
Indexes:
idx_mail_recipient: (session_id, to_uuid, read) for inbox queriesDesign notes:
Database context managing PostgreSQL connection lifecycle.
typedef struct {
PGconn *conn; // PostgreSQL connection handle
} ik_db_ctx_t;
PQfinish() on conntalloc_free() on parent releases everythingCanonical message structure representing a single event.
typedef struct {
int64_t id; // DB row ID (0 if not from DB)
char *kind; // Message kind discriminator
char *content; // Message text content or human-readable summary
char *data_json; // Structured data for tool messages (NULL for text messages)
} ik_msg_t;
Conversation kinds (included in LLM context):
system, user, assistant, tool_call, tool_result, toolMetadata kinds (not included in LLM context):
clear, mark, rewind, agent_killed, command, fork, usageCheckpoint information for conversation rollback.
typedef struct {
int64_t message_id; // ID of the mark event
char *label; // User label or NULL
size_t context_idx; // Position in context array when mark was created
} ik_replay_mark_t;
Dynamic array of checkpoint marks.
typedef struct {
ik_replay_mark_t *marks; // Dynamic array of marks
size_t count; // Number of marks
size_t capacity; // Allocated capacity
} ik_replay_mark_stack_t;
Dynamic array of messages representing conversation state with mark stack for rollback.
typedef struct {
ik_msg_t **messages; // Dynamic array of message pointers (unified type)
size_t count; // Number of messages in context
size_t capacity; // Allocated capacity
ik_replay_mark_stack_t mark_stack; // Stack of checkpoint marks
} ik_replay_context_t;
Defines a subset of messages to query for agent-based replay.
typedef struct {
char *agent_uuid; // Which agent's messages to query
int64_t start_id; // Start AFTER this message ID (0 = from beginning)
int64_t end_id; // End AT this message ID (0 = no limit, i.e., leaf)
} ik_replay_range_t;
Semantics:
start_id is exclusive (query messages AFTER this ID)end_id is inclusive (query messages up to and including this ID)end_id = 0 means "no upper limit" (used for leaf agent)Agent row structure for query results.
typedef struct {
char *uuid;
char *name;
char *parent_uuid;
char *fork_message_id;
char *status;
int64_t created_at;
int64_t ended_at; // 0 if still running
char *provider; // LLM provider (nullable)
char *model; // Model identifier (nullable)
char *thinking_level; // Thinking budget/level (nullable)
} ik_db_agent_row_t;
Mail message structure for inter-agent messaging.
typedef struct ik_mail_msg {
int64_t id;
char *from_uuid;
char *to_uuid;
char *body;
int64_t timestamp;
bool read;
} ik_mail_msg_t;
Wrapper for PGresult with automatic cleanup via talloc destructor.
typedef struct {
PGresult *pg_result;
} ik_pg_result_wrapper_t;
PQclear() when talloc context is freedInitialize database connection with default migrations directory.
res_t ik_db_init(TALLOC_CTX *ctx, const char *conn_str, ik_db_ctx_t **out_ctx);
ctx: Talloc context for allocations (must not be NULL)conn_str: PostgreSQL connection string (e.g., postgresql://user:pass@host:port/dbname)out_ctx: Output parameter for database context (must not be NULL)OK with db_ctx on success, ERR on failureERR_INVALID_ARG, ERR_DB_CONNECT, ERR_DB_MIGRATE./share/ikigai/migrations/Initialize database connection with custom migrations directory.
res_t ik_db_init_with_migrations(TALLOC_CTX *ctx, const char *conn_str,
const char *migrations_dir, ik_db_ctx_t **out_ctx);
ctx: Talloc context for allocations (must not be NULL)conn_str: PostgreSQL connection string (must not be NULL or empty)migrations_dir: Path to migrations directory (must not be NULL)out_ctx: Output parameter for database context (must not be NULL)OK with db_ctx on success, ERR on failureERR_INVALID_ARG, ERR_DB_CONNECT, ERR_DB_MIGRATE, ERR_IOBegin transaction.
res_t ik_db_begin(ik_db_ctx_t *db_ctx);
db_ctx: Database context (must not be NULL)OK on success, ERR on failureCommit transaction.
res_t ik_db_commit(ik_db_ctx_t *db_ctx);
db_ctx: Database context (must not be NULL)OK on success, ERR on failureRollback transaction.
res_t ik_db_rollback(ik_db_ctx_t *db_ctx);
db_ctx: Database context (must not be NULL)OK on success, ERR on failureCreate a new session with started_at=NOW() and ended_at=NULL.
res_t ik_db_session_create(ik_db_ctx_t *db_ctx, int64_t *session_id_out);
db_ctx: Database context (must not be NULL)session_id_out: Output parameter for new session ID (must not be NULL)OK with session_id on success, ERR on failureGet the most recent active session (ended_at IS NULL).
res_t ik_db_session_get_active(ik_db_ctx_t *db_ctx, int64_t *session_id_out);
db_ctx: Database context (must not be NULL)session_id_out: Output parameter for session ID (must not be NULL)OK with session_id (0 if none found), ERR on database failureEnd a session by setting ended_at=NOW().
res_t ik_db_session_end(ik_db_ctx_t *db_ctx, int64_t session_id);
db_ctx: Database context (must not be NULL)session_id: Session ID to end (must be > 0)OK on success, ERR on failureget_activeInsert a message event into the database.
res_t ik_db_message_insert(ik_db_ctx_t *db,
int64_t session_id,
const char *agent_uuid,
const char *kind,
const char *content,
const char *data_json);
db: Database connection context (must not be NULL)session_id: Session ID (must be positive, references sessions.id)agent_uuid: Agent UUID (may be NULL for backward compatibility)kind: Event kind string (must be valid kind)content: Message content (may be NULL for clear events, empty string allowed)data_json: JSONB data as JSON string (may be NULL)OK on success, ERR on failure (invalid params or database error)Validate that a kind string is one of the allowed event kinds.
bool ik_db_message_is_valid_kind(const char *kind);
kind: The kind string to validate (may be NULL)Create a canonical tool result message with kind="tool_result".
ik_msg_t *ik_msg_create_tool_result(void *parent,
const char *tool_call_id,
const char *name,
const char *output,
bool success,
const char *content);
parent: Talloc context for allocation (can be NULL for root)tool_call_id: Unique tool call ID (e.g., "call_abc123")name: Tool name (e.g., "glob", "file_read")output: Tool output string (can be empty string)success: Whether the tool executed successfully (true/false)content: Human-readable summary for the message (e.g., "3 files found")ik_msg_t struct (owned by parent), or NULL on OOMtalloc_free() releases allCheck if a message kind should be included in LLM conversation context.
bool ik_msg_is_conversation_kind(const char *kind);
kind: Message kind string (e.g., "user", "assistant", "clear")Insert agent into registry.
res_t ik_db_agent_insert(ik_db_ctx_t *db_ctx, const ik_agent_ctx_t *agent);
db_ctx: Database context (must not be NULL)agent: Agent context with uuid, parent_uuid, created_at set (must not be NULL)OK on success, ERR on failureMark agent as dead.
res_t ik_db_agent_mark_dead(ik_db_ctx_t *db_ctx, const char *uuid);
db_ctx: Database context (must not be NULL)uuid: Agent UUID to update (must not be NULL)OK on success, ERR on failureLookup agent by UUID.
res_t ik_db_agent_get(ik_db_ctx_t *db_ctx, TALLOC_CTX *ctx,
const char *uuid, ik_db_agent_row_t **out);
db_ctx: Database context (must not be NULL)ctx: Talloc context for result allocation (must not be NULL)uuid: Agent UUID to lookup (must not be NULL)out: Output parameter for agent row (must not be NULL)OK with agent row on success, ERR if not found or on failureList all running agents.
res_t ik_db_agent_list_running(ik_db_ctx_t *db_ctx, TALLOC_CTX *ctx,
ik_db_agent_row_t ***out, size_t *count);
db_ctx: Database context (must not be NULL)ctx: Talloc context for result allocation (must not be NULL)out: Output parameter for array of agent row pointers (must not be NULL)count: Output parameter for array size (must not be NULL)OK with agent rows on success, ERR on failureGet children of an agent.
res_t ik_db_agent_get_children(ik_db_ctx_t *db_ctx, TALLOC_CTX *ctx,
const char *parent_uuid,
ik_db_agent_row_t ***out, size_t *count);
db_ctx: Database context (must not be NULL)ctx: Talloc context for result allocation (must not be NULL)parent_uuid: Parent agent UUID (must not be NULL)out: Output parameter for array of agent row pointers (must not be NULL)count: Output parameter for array size (must not be NULL)OK with agent rows on success, ERR on failureGet parent agent.
res_t ik_db_agent_get_parent(ik_db_ctx_t *db_ctx, TALLOC_CTX *ctx,
const char *uuid, ik_db_agent_row_t **out);
db_ctx: Database context (must not be NULL)ctx: Talloc context for result allocation (must not be NULL)uuid: Child agent UUID (must not be NULL)out: Output parameter for parent agent row (must not be NULL)OK with parent row (or NULL for root) on success, ERR on failureEnsure Agent 0 exists in registry.
res_t ik_db_ensure_agent_zero(ik_db_ctx_t *db, char **out_uuid);
db: Database context (must not be NULL)out_uuid: Output parameter for Agent 0's UUID (must not be NULL)OK with UUID on success, ERR on failureGet the last message ID for an agent.
res_t ik_db_agent_get_last_message_id(ik_db_ctx_t *db_ctx, const char *agent_uuid,
int64_t *out_message_id);
db_ctx: Database context (must not be NULL)agent_uuid: Agent UUID (must not be NULL)out_message_id: Output parameter for last message ID (must not be NULL)OK on success, ERR on failureUpdate agent provider configuration.
res_t ik_db_agent_update_provider(ik_db_ctx_t *db_ctx, const char *uuid,
const char *provider, const char *model,
const char *thinking_level);
db_ctx: Database context (must not be NULL)uuid: Agent UUID to update (must not be NULL)provider: Provider name (may be NULL)model: Model identifier (may be NULL)thinking_level: Thinking budget/level (may be NULL)OK on success, ERR_DB_CONNECT on database errorInsert mail message (sets msg->id on success).
res_t ik_db_mail_insert(ik_db_ctx_t *db, int64_t session_id,
ik_mail_msg_t *msg);
db: Database context (must not be NULL)session_id: Session ID (must be positive)msg: Mail message (must not be NULL)OK on success, ERR on failureGet inbox for agent (unread first, then by timestamp desc).
res_t ik_db_mail_inbox(ik_db_ctx_t *db, TALLOC_CTX *ctx,
int64_t session_id, const char *to_uuid,
ik_mail_msg_t ***out, size_t *count);
db: Database context (must not be NULL)ctx: Talloc context for result allocation (must not be NULL)session_id: Session ID (must be positive)to_uuid: Recipient agent UUID (must not be NULL)out: Output parameter for array of mail message pointers (must not be NULL)count: Output parameter for array size (must not be NULL)OK on success, ERR on failureGet filtered inbox by sender (unread first, then by timestamp desc).
res_t ik_db_mail_inbox_filtered(ik_db_ctx_t *db, TALLOC_CTX *ctx,
int64_t session_id, const char *to_uuid,
const char *from_uuid,
ik_mail_msg_t ***out, size_t *count);
db: Database context (must not be NULL)ctx: Talloc context for result allocation (must not be NULL)session_id: Session ID (must be positive)to_uuid: Recipient agent UUID (must not be NULL)from_uuid: Sender agent UUID filter (must not be NULL)out: Output parameter for array of mail message pointers (must not be NULL)count: Output parameter for array size (must not be NULL)OK on success, ERR on failureMark message as read.
res_t ik_db_mail_mark_read(ik_db_ctx_t *db, int64_t mail_id);
db: Database context (must not be NULL)mail_id: Mail message ID (must be positive)OK on success, ERR on failureDelete message (validates recipient owns the message).
res_t ik_db_mail_delete(ik_db_ctx_t *db, int64_t mail_id,
const char *recipient_uuid);
db: Database context (must not be NULL)mail_id: Mail message ID (must be positive)recipient_uuid: Recipient agent UUID (must not be NULL)OK on success, ERR on failureCreate a mail message structure.
ik_mail_msg_t *ik_mail_msg_create(TALLOC_CTX *ctx,
const char *from_uuid,
const char *to_uuid,
const char *body);
ctx: Talloc context for allocationfrom_uuid: Sender agent UUIDto_uuid: Recipient agent UUIDbody: Message bodyLoad messages from database and replay to build conversation context (TEST-ONLY).
res_t ik_db_messages_load(TALLOC_CTX *ctx, ik_db_ctx_t *db_ctx, int64_t session_id, ik_logger_t *logger);
ctx: Talloc context for allocations (must not be NULL)db_ctx: Database connection context (must not be NULL)session_id: Session ID to load messages for (must be positive)logger: Logger instance (may be NULL)OK with ik_replay_context_t* on success, ERR on failureik_agent_replay_history() insteadcreated_atclear: Empty context (set count = 0)system/user/assistant/tool_call/tool_result: Append to context arraymark: Append to context and push mark onto mark stackrewind: Truncate context to target mark's position, append rewind eventFind most recent clear event for an agent.
res_t ik_agent_find_clear(ik_db_ctx_t *db_ctx, TALLOC_CTX *ctx,
const char *agent_uuid, int64_t max_id,
int64_t *clear_id_out);
db_ctx: Database context (must not be NULL)ctx: Talloc context for error allocation (must not be NULL)agent_uuid: Agent UUID to search (must not be NULL)max_id: Maximum message ID to consider (0 = no limit)clear_id_out: Output for clear message ID (0 if not found)OK on success, ERR on database failureBuild replay ranges by walking ancestor chain.
res_t ik_agent_build_replay_ranges(ik_db_ctx_t *db_ctx, TALLOC_CTX *ctx,
const char *agent_uuid,
ik_replay_range_t **ranges_out,
size_t *count_out);
db_ctx: Database context (must not be NULL)ctx: Talloc context for result allocation (must not be NULL)agent_uuid: Leaf agent UUID to start from (must not be NULL)ranges_out: Output for array of replay ranges (must not be NULL)count_out: Output for number of ranges (must not be NULL)OK on success, ERR on failureQuery messages for a single replay range.
res_t ik_agent_query_range(ik_db_ctx_t *db_ctx, TALLOC_CTX *ctx,
const ik_replay_range_t *range,
ik_msg_t ***messages_out,
size_t *count_out);
db_ctx: Database context (must not be NULL)ctx: Talloc context for result allocation (must not be NULL)range: Replay range specification (must not be NULL)messages_out: Output for array of message pointers (must not be NULL)count_out: Output for number of messages (must not be NULL)OK on success, ERR on failureWHERE agent_uuid=$1 AND id>$2 AND ($3=0 OR id<=$3)Replay history for an agent using range-based algorithm.
res_t ik_agent_replay_history(ik_db_ctx_t *db_ctx, TALLOC_CTX *ctx,
const char *agent_uuid,
ik_replay_context_t **ctx_out);
db_ctx: Database context (must not be NULL)ctx: Talloc context for result allocation (must not be NULL)agent_uuid: Agent UUID to replay (must not be NULL)ctx_out: Output for replay context (must not be NULL)OK on success, ERR on failurebuild_replay_ranges and query_range to reconstruct agent's full conversation context on startupApply all pending database migrations from specified directory.
res_t ik_db_migrate(ik_db_ctx_t *db_ctx, const char *migrations_dir);
db_ctx: Database context (must not be NULL)migrations_dir: Path to migrations directory (must not be NULL)OK on success, ERR on failureERR_INVALID_ARG, ERR_IO, ERR_DB_MIGRATEschema_metadata table (0 if table doesn't exist).sql files001-initial-schema.sql → 1)PQexec() within transactionNNN-description.sql (e.g., 001-initial-schema.sql, 002-agents-table.sql)BEGIN/COMMIT for atomicityschema_metadata.schema_versionschema_metadata, sessions, and messages tables with indexesagents table with agent_status enum, parent_uuid FK, and indexesagent_uuid column to messages table with FK and indexmail table for inter-agent messaging with indexesprovider, model, and thinking_level columns to agents table for multi-provider support; truncates all tables for clean slateCRITICAL: NEVER call PQclear() manually. Always wrap with ik_db_wrap_pg_result().
Wrap PGresult with automatic cleanup via talloc destructor.
ik_pg_result_wrapper_t *ik_db_wrap_pg_result(TALLOC_CTX *ctx, PGresult *pg_res);
ctx: Parent talloc contextpg_res: PGresult to wrap (may be NULL)PQexec() and PQexecParams() results to prevent leaksPQclear() when parent talloc context is freedUsage pattern:
// Wrap immediately after PQexec/PQexecParams
ik_pg_result_wrapper_t *wrapper = ik_db_wrap_pg_result(tmp_ctx, PQexec(conn, query));
PGresult *res = wrapper->pg_result;
// Use normally - no manual cleanup needed
if (PQresultStatus(res) != PGRES_TUPLES_OK) {
talloc_free(tmp_ctx); // Destructor calls PQclear() automatically
return ERR(...);
}
This integrates PGresult (malloc-based) with talloc's hierarchical memory model.
Most tests use transaction isolation for speed:
static const char *DB_NAME;
static ik_db_ctx_t *db;
static TALLOC_CTX *test_ctx;
// Suite setup (once per file)
DB_NAME = ik_test_db_name(NULL, __FILE__);
ik_test_db_create(DB_NAME);
ik_test_db_migrate(NULL, DB_NAME);
// Per-test setup
test_ctx = talloc_new(NULL);
ik_test_db_connect(test_ctx, DB_NAME, &db);
ik_test_db_begin(db);
// Per-test teardown
ik_test_db_rollback(db);
talloc_free(test_ctx);
// Suite teardown (once per file)
ik_test_db_destroy(DB_NAME);
Rolemodel: tests/unit/repl/repl_actions_db_basic_test.c
Key benefits:
Migration tests use empty database without migrations:
DB_NAME = ik_test_db_name(NULL, __FILE__);
ik_test_db_create(DB_NAME); // No migrate call
// ... test migration logic ...
ik_test_db_destroy(DB_NAME);
Derive database name from source file path.
const char *ik_test_db_name(TALLOC_CTX *ctx, const char *file_path);
tests/unit/db/session_test.c → ikigai_test_session_testCreate test database (drops if exists).
res_t ik_test_db_create(const char *db_name);
Run migrations on test database from ./share/ikigai/migrations/ directory.
res_t ik_test_db_migrate(TALLOC_CTX *ctx, const char *db_name);
Open connection to test database (no migrations).
res_t ik_test_db_connect(TALLOC_CTX *ctx, const char *db_name, ik_db_ctx_t **out);
Begin transaction for test isolation.
res_t ik_test_db_begin(ik_db_ctx_t *db);
Rollback transaction to discard test changes.
res_t ik_test_db_rollback(ik_db_ctx_t *db);
Truncate all application tables (for non-transactional tests).
res_t ik_test_db_truncate_all(ik_db_ctx_t *db);
TRUNCATE TABLE messages, sessions, agents, mail RESTART IDENTITY CASCADEDrop test database completely.
res_t ik_test_db_destroy(const char *db_name);
Fixed configuration - hardcoded in tests/test_utils.c:
ikigaiikigailocalhost (override with PGHOST environment variable)postgres (for CREATE/DROP DATABASE operations)ikigai_test_<basename>Connection strings:
ADMIN_DB_URL = "postgresql://ikigai:ikigai@localhost/postgres"
TEST_DB_URL_PREFIX = "postgresql://ikigai:ikigai@localhost/"
Database setup requirements:
ikigai with password ikigai created| Variable | Purpose |
|---|---|
DATABASE_URL | Production connection string |
PGHOST | Override PostgreSQL host (default: localhost) |
SKIP_LIVE_DB_TESTS | Set to 1 to skip DB tests |
| File | Purpose |
|---|---|
share/ikigai/migrations/001-initial-schema.sql | Initial database schema with sessions and messages tables |
share/ikigai/migrations/002-agents-table.sql | Agent registry table with parent-child relationships |
share/ikigai/migrations/003-messages-agent-uuid.sql | Add agent_uuid column to messages table |
share/ikigai/migrations/004-mail-table.sql | Inter-agent mail table for message passing |
share/ikigai/migrations/005-multi-provider.sql | Add provider, model, thinking_level to agents table |
src/db/connection.h | Database connection API (init, destructor, transactions) |
src/db/connection.c | Connection implementation with validation and migration runner |
src/db/session.h | Session CRUD API (create, get_active, end) |
src/db/session.c | Session implementation with parameterized queries |
src/db/message.h | Message insertion API and tool result helpers |
src/db/message.c | Message implementation with kind validation and yyjson |
src/db/agent.h | Agent registry API (insert, mark_dead, queries, update_provider) |
src/db/agent.c | Agent implementation with parent-child queries |
src/db/agent_row.h | Agent row parsing helper API |
src/db/agent_row.c | Agent row parsing from PGresult |
src/db/agent_zero.h | Agent 0 (root agent) creation API |
src/db/agent_zero.c | Agent 0 creation and orphan message adoption |
src/db/mail.h | Mail API (insert, inbox, mark_read, delete) |
src/db/mail.c | Mail implementation with inbox filtering |
src/db/replay.h | Replay context structures and message loading API |
src/db/replay.c | Event stream replay algorithm with mark/rewind support |
src/db/agent_replay.h | Agent-based replay API (find_clear, build_ranges, query_range) |
src/db/agent_replay.c | Agent replay implementation with ancestry chain walking |
src/db/migration.h | Migration system API |
src/db/migration.c | Migration scanner, parser, and executor |
src/db/pg_result.h | PGresult wrapper API |
src/db/pg_result.c | PGresult wrapper implementation with talloc destructor |
src/msg.h | Canonical message structure and kind validation |
src/mail/msg.h | Mail message structure |
tests/test_utils.h | Database test utilities header |
tests/test_utils.c | Database test utilities implementation |
tests/unit/test_utils/db_test.c | DB test utilities tests |
memory - talloc-based memory management and ownership ruleserrors - Result types with OK()/ERR() patternssource-code - Map of all src/*.c files by functional area