Files
AirCoding/AirPlan/docs/architecture/db-schema-v1.md
AirCoding 33a76a1ebc Move project from external drive to local NVMe
迁移路径: /run/media/airlongdian/EasyU/AirCoding -> /home/airlongdian/DataDevices/AirWorkSpace/AirCoding

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-02 09:51:49 +08:00

14 KiB
Executable File

AirCoding Session DB Schema V1

Date: 2026-05-26 Status: Canonical schema baseline for V1.0.0 Alpha skeleton

This document defines the first implementation-facing SQLite schema for per-session state.

Session DB path:

<project>/.air/local/sessions/<session-id>/session.db

Project-level DBs remain outside this session schema:

<project>/.air/local/debug-records.db
<project>/.air/local/learned-memory.db

1. SQLite Runtime Settings

PRAGMA journal_mode = WAL;
PRAGMA synchronous = NORMAL;
PRAGMA foreign_keys = OFF;

Rationale:

  • WAL supports concurrent read/write patterns needed by runtime and TUI projection.
  • NORMAL is sufficient for local session state and faster than FULL.
  • Foreign keys are disabled in MVP to reduce migration/recovery complexity. Application-level consistency checks handle references. This can be revisited after schema stabilizes.

Transaction rules:

  • A durable event insert and its corresponding domain table update must be in the same transaction.
  • Artifact file writes use temp file → atomic rename → DB record.
  • ui_state is flushed periodically and on normal exit.

2. schema_meta

CREATE TABLE schema_meta (
  key TEXT PRIMARY KEY,
  value TEXT NOT NULL
);

Initial keys:

schema_version = 1
created_by = aircoding
created_at = <ISO time>
aircoding_version_created = <version>
aircoding_version_last_opened = <version>

3. sessions

CREATE TABLE sessions (
  id TEXT PRIMARY KEY,
  project_id TEXT NOT NULL,
  project_root TEXT NOT NULL,
  title TEXT,
  status TEXT NOT NULL,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL,
  exited_at TEXT,
  model_provider_id TEXT,
  model_id TEXT,
  metadata_json TEXT
);

Status values:

active | archived | deleted

4. messages

CREATE TABLE messages (
  id TEXT PRIMARY KEY,
  session_id TEXT NOT NULL,
  role TEXT NOT NULL,
  canonical_format TEXT NOT NULL,
  content_json TEXT NOT NULL,
  parent_message_id TEXT,
  route_json TEXT,
  created_at TEXT NOT NULL,
  token_estimate INTEGER,
  metadata_json TEXT
);

CREATE INDEX idx_messages_session_created
ON messages(session_id, created_at);

canonical_format is anthropic in V1.

5. message_drafts

CREATE TABLE message_drafts (
  message_id TEXT PRIMARY KEY,
  session_id TEXT NOT NULL,
  role TEXT NOT NULL,
  canonical_format TEXT NOT NULL,
  partial_content_json TEXT NOT NULL,
  status TEXT NOT NULL,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL,
  metadata_json TEXT
);

CREATE INDEX idx_drafts_session_status
ON message_drafts(session_id, status);

Drafts are deleted after the completed message is written to messages.

Status values:

streaming | interrupted | error

6. events

CREATE TABLE events (
  id TEXT PRIMARY KEY,
  session_id TEXT NOT NULL,
  type TEXT NOT NULL,
  version INTEGER NOT NULL,
  timestamp TEXT NOT NULL,

  source_kind TEXT NOT NULL,
  source_id TEXT,
  agent_type TEXT,

  task_id TEXT,
  agent_id TEXT,
  tool_run_id TEXT,
  command_run_id TEXT,

  route_json TEXT NOT NULL,
  route_text TEXT NOT NULL,

  payload_json TEXT NOT NULL
);

CREATE INDEX idx_events_session_type_time
ON events(session_id, type, timestamp);

CREATE INDEX idx_events_task_time
ON events(task_id, timestamp);

CREATE INDEX idx_events_agent_time
ON events(agent_id, timestamp);

CREATE INDEX idx_events_route_text
ON events(route_text);

7. tasks

CREATE TABLE tasks (
  id TEXT PRIMARY KEY,
  session_id TEXT NOT NULL,
  type TEXT NOT NULL,
  status TEXT NOT NULL,
  title TEXT NOT NULL,

  task_spec_json TEXT NOT NULL,
  worker_result_json TEXT,

  assigned_agent_id TEXT,
  workspace_id TEXT,

  retry_count INTEGER NOT NULL DEFAULT 0,

  created_at TEXT NOT NULL,
  started_at TEXT,
  completed_at TEXT,
  heartbeat_at TEXT,

  metadata_json TEXT
);

CREATE INDEX idx_tasks_session_status
ON tasks(session_id, status);

Task status values:

pending | running | completed | failed | blocked | cancelled | interrupted

8. task_dependencies

CREATE TABLE task_dependencies (
  id TEXT PRIMARY KEY,
  session_id TEXT NOT NULL,
  task_id TEXT NOT NULL,
  depends_on_task_id TEXT NOT NULL,
  dependency_type TEXT NOT NULL,
  reason TEXT,
  created_at TEXT NOT NULL
);

CREATE INDEX idx_task_deps_task
ON task_dependencies(task_id);

CREATE INDEX idx_task_deps_depends_on
ON task_dependencies(depends_on_task_id);

CREATE INDEX idx_task_deps_session_type
ON task_dependencies(session_id, dependency_type);

Dependency types:

hard | soft | conflict | serialization

9. task_attempts

CREATE TABLE task_attempts (
  id TEXT PRIMARY KEY,
  session_id TEXT NOT NULL,
  task_id TEXT NOT NULL,
  attempt_index INTEGER NOT NULL,

  agent_id TEXT,
  status TEXT NOT NULL,

  failure_signature TEXT,
  failure_summary TEXT,

  started_at TEXT NOT NULL,
  completed_at TEXT,

  worker_result_json TEXT,
  metadata_json TEXT
);

CREATE INDEX idx_task_attempts_task
ON task_attempts(task_id, attempt_index);

CREATE INDEX idx_task_attempts_failure_signature
ON task_attempts(failure_signature);

10. agents

CREATE TABLE agents (
  id TEXT PRIMARY KEY,
  session_id TEXT NOT NULL,
  type TEXT NOT NULL,
  status TEXT NOT NULL,

  pid INTEGER,
  task_id TEXT,

  model_provider_id TEXT,
  model_id TEXT,

  started_at TEXT NOT NULL,
  completed_at TEXT,
  last_heartbeat_at TEXT,

  metadata_json TEXT
);

CREATE INDEX idx_agents_session_status
ON agents(session_id, status);

CREATE INDEX idx_agents_task
ON agents(task_id);

Agent status values:

starting | running | completed | failed | lost | cancelled

11. tool_runs

CREATE TABLE tool_runs (
  id TEXT PRIMARY KEY,
  session_id TEXT NOT NULL,

  task_id TEXT,
  agent_id TEXT,
  origin_message_id TEXT,

  tool_name TEXT NOT NULL,
  status TEXT NOT NULL,

  input_json TEXT NOT NULL,
  output_json TEXT,
  error_json TEXT,

  started_at TEXT NOT NULL,
  completed_at TEXT,
  duration_ms INTEGER,

  artifacts_json TEXT,
  evidence_refs_json TEXT,
  metadata_json TEXT
);

CREATE INDEX idx_tool_runs_origin_message
ON tool_runs(origin_message_id);

CREATE INDEX idx_tool_runs_session_time
ON tool_runs(session_id, started_at);

CREATE INDEX idx_tool_runs_task_time
ON tool_runs(task_id, started_at);

CREATE INDEX idx_tool_runs_agent_time
ON tool_runs(agent_id, started_at);

Status values:

running | ok | error | cancelled

12. command_runs

CREATE TABLE command_runs (
  id TEXT PRIMARY KEY,
  session_id TEXT NOT NULL,

  task_id TEXT,
  agent_id TEXT,
  origin_message_id TEXT,
  tool_run_id TEXT,

  command TEXT NOT NULL,
  cwd TEXT NOT NULL,

  exit_code INTEGER,

  stdout_artifact_id TEXT,
  stderr_artifact_id TEXT,
  combined_artifact_id TEXT,

  started_at TEXT NOT NULL,
  completed_at TEXT,
  duration_ms INTEGER,

  parsed_diagnostics_json TEXT,
  metadata_json TEXT
);

CREATE INDEX idx_command_runs_origin_message
ON command_runs(origin_message_id);

CREATE INDEX idx_command_runs_session_time
ON command_runs(session_id, started_at);

CREATE INDEX idx_command_runs_task_time
ON command_runs(task_id, started_at);

CREATE INDEX idx_command_runs_agent_time
ON command_runs(agent_id, started_at);

13. artifacts

CREATE TABLE artifacts (
  id TEXT PRIMARY KEY,
  session_id TEXT NOT NULL,
  type TEXT NOT NULL,

  uri TEXT NOT NULL,
  path TEXT NOT NULL,
  original_name TEXT,

  size_bytes INTEGER,
  sha256 TEXT,

  task_id TEXT,
  agent_id TEXT,
  tool_run_id TEXT,
  command_run_id TEXT,

  associated_entity_type TEXT,
  associated_entity_id TEXT,

  created_at TEXT NOT NULL,
  metadata_json TEXT
);

CREATE INDEX idx_artifacts_session_type_time
ON artifacts(session_id, type, created_at);

CREATE INDEX idx_artifacts_task
ON artifacts(task_id);

CREATE INDEX idx_artifacts_agent
ON artifacts(agent_id);

CREATE INDEX idx_artifacts_tool_run
ON artifacts(tool_run_id);

CREATE INDEX idx_artifacts_command_run
ON artifacts(command_run_id);

14. diagnostics

CREATE TABLE diagnostics (
  id TEXT PRIMARY KEY,
  session_id TEXT NOT NULL,

  task_id TEXT,
  agent_id TEXT,
  command_run_id TEXT,
  artifact_id TEXT,

  language TEXT,
  toolchain TEXT,
  severity TEXT,

  file TEXT,
  line INTEGER,
  column INTEGER,
  code TEXT,

  message TEXT NOT NULL,
  semantic_signature TEXT NOT NULL,

  created_at TEXT NOT NULL,
  metadata_json TEXT
);

CREATE INDEX idx_diagnostics_signature
ON diagnostics(semantic_signature);

CREATE INDEX idx_diagnostics_file
ON diagnostics(file);

CREATE INDEX idx_diagnostics_command
ON diagnostics(command_run_id);

CREATE INDEX idx_diagnostics_task
ON diagnostics(task_id);

15. evidence_refs

CREATE TABLE evidence_refs (
  id TEXT PRIMARY KEY,
  session_id TEXT NOT NULL,

  task_id TEXT,
  agent_id TEXT,
  tool_run_id TEXT,
  command_run_id TEXT,
  artifact_id TEXT,
  diagnostic_id TEXT,
  message_id TEXT,

  kind TEXT NOT NULL,
  ref TEXT NOT NULL,
  location_json TEXT,
  claim TEXT NOT NULL,

  created_at TEXT NOT NULL
);

CREATE INDEX idx_evidence_task
ON evidence_refs(task_id);

CREATE INDEX idx_evidence_artifact
ON evidence_refs(artifact_id);

CREATE INDEX idx_evidence_diagnostic
ON evidence_refs(diagnostic_id);

16. workspaces

CREATE TABLE workspaces (
  id TEXT PRIMARY KEY,
  session_id TEXT NOT NULL,

  task_id TEXT,
  agent_id TEXT,

  path TEXT NOT NULL,
  strategy TEXT NOT NULL,
  status TEXT NOT NULL,

  base_ref TEXT,
  branch_name TEXT,

  created_at TEXT NOT NULL,
  merged_at TEXT,

  metadata_json TEXT
);

CREATE INDEX idx_workspaces_task
ON workspaces(task_id);

CREATE INDEX idx_workspaces_status
ON workspaces(session_id, status);

Workspace strategy values:

main | worktree | isolated_copy

Workspace status values:

active | merged | conflicted | abandoned | cleaned

17. summaries

CREATE TABLE summaries (
  id TEXT PRIMARY KEY,
  session_id TEXT NOT NULL,

  type TEXT NOT NULL,
  range_start_message_id TEXT,
  range_end_message_id TEXT,

  content_json TEXT NOT NULL,

  created_at TEXT NOT NULL,
  metadata_json TEXT
);

18. ui_state

CREATE TABLE ui_state (
  id TEXT PRIMARY KEY,
  session_id TEXT NOT NULL,
  scope TEXT NOT NULL,
  key TEXT NOT NULL,
  value_json TEXT NOT NULL,
  updated_at TEXT NOT NULL
);

CREATE UNIQUE INDEX idx_ui_state_session_scope_key
ON ui_state(session_id, scope, key);

ui_state is not a source of truth for runtime state. It stores route, active panel, layout, scroll, collapse state, selected tab, and HUD preset.

19. V1 Summary

Frozen decisions:

  1. Session DB is project-local and per-session.
  2. WAL + synchronous NORMAL + foreign_keys OFF.
  3. No message_parts source-of-truth table in V1.0.0 Alpha.
  4. Canonical messages are Anthropic content JSON.
  5. Draft messages exist only during streaming/incomplete assistant output.
  6. Domain tables are scheduling/recovery/query source of truth.
  7. JSON columns preserve full object fidelity; frequently queried relationships are extracted into columns and indexes.
  8. Durable event + domain update must be transactional.
  9. Artifact files are written temp → rename → DB record.
  10. UI state is flushed periodically and on normal exit.

20. Project-Level DBs

Two project-level databases live under <project>/.air/local/:

20.1 debug-records.db

PRAGMA journal_mode = WAL;
PRAGMA synchronous = NORMAL;
PRAGMA foreign_keys = OFF;

CREATE TABLE debug_records (
  id TEXT PRIMARY KEY,
  task_id TEXT,
  failure_signature TEXT NOT NULL,
  summary TEXT NOT NULL,
  root_cause TEXT,
  fix_ref TEXT,
  evidence_json TEXT,
  verification_json TEXT,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL,
  metadata_json TEXT
);

CREATE INDEX idx_debug_records_signature
ON debug_records(failure_signature);

CREATE INDEX idx_debug_records_task
ON debug_records(task_id);

20.2 learned-memory.db

PRAGMA journal_mode = WAL;
PRAGMA synchronous = NORMAL;
PRAGMA foreign_keys = OFF;

CREATE TABLE learned_memories (
  id TEXT PRIMARY KEY,
  memory_type TEXT NOT NULL,
  summary TEXT NOT NULL,
  content TEXT,
  source_entity_type TEXT,
  source_entity_id TEXT,
  status TEXT NOT NULL,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL,
  metadata_json TEXT
);

CREATE INDEX idx_learned_memories_type
ON learned_memories(memory_type);

CREATE INDEX idx_learned_memories_status
ON learned_memories(status);

21. Closed Enum Inventory

The following TEXT columns use closed value sets. Implementations must validate on insert/update.

Table Column Valid values
sessions status active, archived, deleted
messages role user, assistant, system, tool
messages canonical_format anthropic
tasks type execute, review, debug, compact, mine_experience, docs
tasks status pending, running, completed, failed, blocked, cancelled, interrupted
task_dependencies dependency_type hard, soft, conflict, serialization
task_attempts status pending, running, completed, failed, cancelled
agents status starting, running, completed, failed, lost, cancelled
tool_runs status running, ok, error, cancelled
artifacts type log, diff, screenshot, pcap, report, diagnostic, bundle, other
diagnostics severity error, warning, info, hint
evidence_refs kind build_output, test_output, log, screenshot, diff, metric, other
workspaces strategy main, worktree, isolated_copy
workspaces status active, merged, conflicted, abandoned, cleaned
summaries type compaction, checkpoint, review, other
message_drafts status streaming, interrupted, error
learned_memories memory_type project_rule, toolchain_rule, skill_update, debug_experience
learned_memories status candidate, promoted, archived, rejected