Files
cleveragents-core/docs/reference/database_schema.md
T
freemo da8e5f716d
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
CI / security (push) Waiting to run
CI / quality (push) Waiting to run
CI / unit_tests (push) Waiting to run
CI / integration_tests (push) Waiting to run
CI / coverage (push) Blocked by required conditions
CI / build (push) Waiting to run
CI / docker (push) Blocked by required conditions
CI / lint (pull_request) Successful in 15s
CI / typecheck (pull_request) Successful in 26s
CI / security (pull_request) Successful in 21s
CI / quality (pull_request) Successful in 15s
CI / integration_tests (pull_request) Successful in 4m16s
CI / build (pull_request) Successful in 16s
CI / unit_tests (pull_request) Successful in 8m37s
CI / coverage (pull_request) Successful in 6m40s
CI / docker (pull_request) Successful in 38s
feat(db): add resource registry tables
2026-02-13 22:46:03 -05:00

18 KiB

Database Schema Reference

This document describes the spec-aligned database tables created by the A5.alpha migrations (a5_003_spec_aligned_actions and a5_004_spec_aligned_plans).

These tables replace the legacy actions_v3 and lifecycle_plans tables with a normalized schema using namespaced names as action identity and child tables for arguments, invariants, and project links.

Migration Chain

Revision Description
a5_003_spec_aligned_actions Drops lifecycle_plans and actions_v3; creates actions, action_invariants, action_arguments
a5_004_spec_aligned_plans Creates v3_plans, plan_projects, plan_arguments, plan_invariants

Table: actions

The primary action definition table. Each row represents a reusable action template identified by its namespaced name.

Primary Key: namespaced_name

Column Type Nullable Default Description
namespaced_name String(255) No -- PK. Full namespaced name (e.g. local/code-review)
namespace String(100) No -- Extracted namespace component
name String(150) No -- Extracted short name component
description Text No -- Short description
long_description Text Yes NULL Detailed description
definition_of_done Text No -- Explicit testable completion criteria
strategy_actor String(255) No -- Actor for Strategize phase
execution_actor String(255) No -- Actor for Execute phase
review_actor String(255) Yes NULL Actor for reviewing results
apply_actor String(255) Yes NULL Actor for Apply phase
estimation_actor String(255) Yes NULL Actor for cost estimation
invariant_actor String(255) Yes NULL Actor for invariant reconciliation
automation_profile String(255) Yes NULL Default automation profile name
reusable Boolean No 1 Whether action persists after use
read_only Boolean No 0 Read-only mode
inputs_schema_json Text Yes NULL JSON Schema dict for input validation
state String(20) No 'available' available or archived
created_by String(255) Yes NULL Creator identifier
tags_json Text No '[]' JSON array of tag strings
created_at String(30) No -- ISO-8601 creation timestamp
updated_at String(30) No -- ISO-8601 last-update timestamp

Check Constraints:

  • ck_actions_state: state IN ('available', 'archived')

Indexes:

  • ix_actions_namespace on namespace
  • ix_actions_state on state
  • ix_actions_name on name

Table: action_invariants

Ordered invariant constraints attached to an action. Cascades on action delete.

Primary Key: id (auto-increment)

Column Type Nullable Default Description
id Integer No auto Surrogate PK
action_name String(255) No -- FK to actions.namespaced_name (CASCADE)
invariant_text Text No -- The invariant constraint text
position Integer No -- Display ordering
created_at String(30) No -- ISO-8601 timestamp

Foreign Keys:

  • fk_action_invariants_action: action_name -> actions.namespaced_name ON DELETE CASCADE

Indexes:

  • ix_action_invariants_action on action_name
  • ix_action_invariants_position on (action_name, position)

Table: action_arguments

Typed argument definitions for an action. Cascades on action delete.

Primary Key: id (auto-increment)

Column Type Nullable Default Description
id Integer No auto Surrogate PK
action_name String(255) No -- FK to actions.namespaced_name (CASCADE)
name String(100) No -- Argument identifier
arg_type String(20) No 'string' string, integer, float, boolean, list
requirement String(20) No 'required' required or optional
description Text Yes NULL Human-readable description
default_value_json Text Yes NULL JSON-encoded default value
min_value Float Yes NULL Min bound for numeric types
max_value Float Yes NULL Max bound for numeric types
validation_pattern String(500) Yes NULL Regex pattern for string validation
position Integer No -- Display ordering

Foreign Keys:

  • fk_action_arguments_action: action_name -> actions.namespaced_name ON DELETE CASCADE

Unique Constraints:

  • uq_action_arguments_name on (action_name, name)

Check Constraints:

  • ck_action_arguments_type: arg_type IN ('string', 'integer', 'float', 'boolean', 'list')
  • ck_action_arguments_requirement: requirement IN ('required', 'optional')

Indexes:

  • ix_action_arguments_action on action_name
  • ix_action_arguments_position on (action_name, position)

Table: v3_plans

The primary plan table. Each row is a plan instance created from an action, identified by a ULID. Plans reference actions by namespaced name and support hierarchical subplan trees via self-referencing foreign keys.

Primary Key: plan_id (ULID, String(26))

Column Type Nullable Default Description
plan_id String(26) No -- ULID primary key
parent_plan_id String(26) Yes NULL FK to v3_plans.plan_id (SET NULL)
root_plan_id String(26) Yes NULL FK to v3_plans.plan_id (SET NULL)
action_name String(255) No -- FK to actions.namespaced_name (RESTRICT)
namespaced_name String(255) No -- Plan's own namespaced name
namespace String(100) No -- Extracted namespace
phase String(20) No 'strategize' Current lifecycle phase
processing_state String(20) No 'queued' Current processing state
attempt Integer No 1 Retry attempt counter
description Text No -- Rendered description (from action template + args)
definition_of_done Text Yes NULL Rendered completion criteria
strategy_actor String(255) Yes NULL Strategize phase actor
execution_actor String(255) Yes NULL Execute phase actor
review_actor String(255) Yes NULL Review actor
apply_actor String(255) Yes NULL Apply phase actor
estimation_actor String(255) Yes NULL Estimation actor
invariant_actor String(255) Yes NULL Invariant reconciliation actor
automation_profile String(255) Yes NULL Resolved automation profile name
automation_level String(30) No 'manual' manual, review_before_apply, full_automation
reusable Boolean No 1 Copied from action
read_only Boolean No 0 Copied from action
inputs_schema_json Text Yes NULL JSON Schema dict (copied from action)
changeset_id String(26) Yes NULL Changeset ULID from Execute phase
sandbox_refs_json Text Yes NULL JSON sandbox references
validation_summary_json Text Yes NULL JSON validation summary
decision_root_id String(26) Yes NULL Root decision tree ULID
error_message Text Yes NULL Error message if errored
error_details_json Text Yes NULL JSON error details dict
cost_estimate_usd Float Yes NULL Estimated cost in USD
cost_actual_usd Float Yes NULL Actual cost in USD
token_count_input Integer Yes 0 Input token count
token_count_output Integer Yes 0 Output token count
created_by String(255) Yes NULL Creator identifier
tags_json Text No '[]' JSON array of tag strings
created_at String(30) No -- ISO-8601 creation timestamp
updated_at String(30) No -- ISO-8601 last-update timestamp
completed_at String(30) Yes NULL ISO-8601 completion timestamp
strategize_started_at String(30) Yes NULL Strategize phase start
strategize_completed_at String(30) Yes NULL Strategize phase end
execute_started_at String(30) Yes NULL Execute phase start
execute_completed_at String(30) Yes NULL Execute phase end
apply_started_at String(30) Yes NULL Apply phase start
applied_at String(30) Yes NULL Terminal apply timestamp

Foreign Keys:

  • fk_v3_plans_parent: parent_plan_id -> v3_plans.plan_id ON DELETE SET NULL
  • fk_v3_plans_root: root_plan_id -> v3_plans.plan_id ON DELETE SET NULL
  • fk_v3_plans_action: action_name -> actions.namespaced_name ON DELETE RESTRICT

Check Constraints:

  • ck_v3_plans_phase: phase IN ('strategize', 'execute', 'apply', 'applied')
  • ck_v3_plans_state: processing_state IN ('queued', 'processing', 'errored', 'complete', 'cancelled')
  • ck_v3_plans_automation: automation_level IN ('manual', 'review_before_apply', 'full_automation')

Indexes:

  • ix_v3_plans_phase on phase
  • ix_v3_plans_state on processing_state
  • ix_v3_plans_parent on parent_plan_id
  • ix_v3_plans_root on root_plan_id
  • ix_v3_plans_created on created_at
  • ix_v3_plans_action on action_name
  • ix_v3_plans_namespace on namespace
  • ix_v3_plans_phase_state on (phase, processing_state) (composite)

Table: plan_projects

Links plans to target projects. Composite primary key. Cascades on plan delete.

Primary Key: (plan_id, project_name)

Column Type Nullable Default Description
plan_id String(26) No -- FK to v3_plans.plan_id (CASCADE)
project_name String(255) No -- Target project namespaced name
alias String(100) Yes NULL Short alias for plan context
read_only Boolean No 0 Whether project is read-only for this plan
created_at String(30) No -- ISO-8601 timestamp

Foreign Keys:

  • fk_plan_projects_plan: plan_id -> v3_plans.plan_id ON DELETE CASCADE

Indexes:

  • ix_plan_projects_project on project_name

Table: plan_arguments

Resolved argument values for a plan instance. Cascades on plan delete.

Primary Key: id (auto-increment)

Column Type Nullable Default Description
id Integer No auto Surrogate PK
plan_id String(26) No -- FK to v3_plans.plan_id (CASCADE)
name String(100) No -- Argument name
value_json Text Yes NULL JSON-encoded argument value
value_type String(20) No 'string' Value type hint
position Integer No -- Display ordering

Foreign Keys:

  • fk_plan_arguments_plan: plan_id -> v3_plans.plan_id ON DELETE CASCADE

Unique Constraints:

  • uq_plan_arguments_name on (plan_id, name)

Indexes:

  • ix_plan_arguments_plan on plan_id
  • ix_plan_arguments_position on (plan_id, position)

Table: plan_invariants

Plan-level invariant constraints with scope provenance. Cascades on plan delete.

Primary Key: id (auto-increment)

Column Type Nullable Default Description
id Integer No auto Surrogate PK
plan_id String(26) No -- FK to v3_plans.plan_id (CASCADE)
invariant_text Text No -- The invariant constraint text
source_scope String(20) No 'plan' Origin scope: global, project, action, plan
source_name String(255) Yes NULL Name of the source entity
position Integer No -- Display ordering
created_at String(30) No -- ISO-8601 timestamp

Foreign Keys:

  • fk_plan_invariants_plan: plan_id -> v3_plans.plan_id ON DELETE CASCADE

Unique Constraints:

  • uq_plan_invariants_text on (plan_id, invariant_text)

Check Constraints:

  • ck_plan_invariants_scope: source_scope IN ('global', 'project', 'action', 'plan')

Indexes:

  • ix_plan_invariants_plan on plan_id
  • ix_plan_invariants_position on (plan_id, position)


Table: resource_types

Schema-level definitions that constrain categories of resources. Built-in types (e.g. builtin/git-checkout) are registered at startup; custom types are loaded from YAML configuration files.

Primary Key: name

Column Type Nullable Default Description
name String(255) No -- PK. Namespaced type name (e.g. builtin/git-checkout)
namespace String(100) No -- Extracted namespace component
description Text Yes NULL Human-readable description
resource_kind String(20) No -- physical or virtual
sandbox_strategy String(50) Yes NULL Default sandbox strategy for instances
user_addable Boolean No 0 Whether users can add instances via CLI
handler_ref String(500) Yes NULL Handler implementation reference
args_schema_json Text Yes NULL JSON: CLI argument definitions
allowed_parent_types_json Text Yes NULL JSON: allowed parent type names
allowed_child_types_json Text Yes NULL JSON: allowed child type definitions
auto_discover_json Text Yes NULL JSON: auto-discovery configuration
capabilities_json Text Yes NULL JSON: capability flags
equivalence_json Text Yes NULL JSON: equivalence criteria (virtual types)
source String(500) Yes NULL builtin or path to YAML config
created_at String(30) No -- ISO-8601 creation timestamp
updated_at String(30) No -- ISO-8601 last-update timestamp

Check Constraints:

  • ck_resource_types_kind: resource_kind IN ('physical', 'virtual')

Indexes:

  • ix_resource_types_namespace on namespace
  • ix_resource_types_kind on resource_kind
  • ix_resource_types_user_addable on user_addable

Table: resources

Independently registered resources representing anything that can be read, written, or queried. Each resource has a ULID primary key and an optional namespaced name (auto-discovered children have no name).

Primary Key: resource_id (ULID, String(26))

Column Type Nullable Default Description
resource_id String(26) No -- ULID primary key
namespaced_name String(255) Yes NULL Optional namespaced name (unique when non-null)
namespace String(100) Yes NULL Extracted namespace component
type_name String(255) No -- FK to resource_types.name (RESTRICT)
resource_kind String(20) No -- physical or virtual (denormalized from type)
location Text Yes NULL Physical location (path, URL, etc.)
description Text Yes NULL Human-readable description
read_only Boolean No 0 Read-only flag
auto_discovered Boolean No 0 Whether auto-discovered (not user-registered)
sandbox_strategy String(50) Yes NULL Per-resource sandbox strategy override
content_hash String(128) Yes NULL Content hash for equivalence tracking
properties_json Text Yes NULL JSON: type-specific properties
metadata_json Text Yes NULL JSON: type-specific metadata
created_at String(30) No -- ISO-8601 creation timestamp
updated_at String(30) No -- ISO-8601 last-update timestamp

Foreign Keys:

  • fk_resources_type: type_name -> resource_types.name ON DELETE RESTRICT

Check Constraints:

  • ck_resources_kind: resource_kind IN ('physical', 'virtual')

Indexes:

  • ix_resources_name on namespaced_name (unique, partial - non-null only)
  • ix_resources_namespace on namespace
  • ix_resources_type on type_name
  • ix_resources_kind on resource_kind
  • ix_resources_content_hash on content_hash

Table: resource_edges

DAG edges representing parent-child relationships between resources. A resource can have multiple parents and multiple children, subject to type constraints.

Primary Key: (parent_id, child_id) (composite)

Column Type Nullable Default Description
parent_id String(26) No -- FK to resources.resource_id (CASCADE)
child_id String(26) No -- FK to resources.resource_id (CASCADE)
link_type String(30) No 'contains' contains, references, or derived_from
auto_discovered Boolean No 0 Whether auto-discovered (vs manually linked)
created_at String(30) No -- ISO-8601 timestamp

Foreign Keys:

  • fk_resource_edges_parent: parent_id -> resources.resource_id ON DELETE CASCADE
  • fk_resource_edges_child: child_id -> resources.resource_id ON DELETE CASCADE

Check Constraints:

  • ck_resource_edges_no_self_loop: parent_id != child_id
  • ck_resource_edges_link_type: link_type IN ('contains', 'references', 'derived_from')

Indexes:

  • ix_resource_edges_child on child_id
  • ix_resource_edges_link_type on link_type

Entity Relationship Diagram

actions (PK: namespaced_name)
  |-- 1:N --> action_invariants (FK: action_name)
  |-- 1:N --> action_arguments  (FK: action_name)
  |-- 1:N --> v3_plans          (FK: action_name, RESTRICT)

v3_plans (PK: plan_id)
  |-- self --> parent_plan_id   (SET NULL)
  |-- self --> root_plan_id     (SET NULL)
  |-- 1:N --> plan_projects     (FK: plan_id, CASCADE)
  |-- 1:N --> plan_arguments    (FK: plan_id, CASCADE)
  |-- 1:N --> plan_invariants   (FK: plan_id, CASCADE)

resource_types (PK: name)
  |-- 1:N --> resources         (FK: type_name, RESTRICT)

resources (PK: resource_id)
  |-- N:M --> resource_edges    (FK: parent_id/child_id, CASCADE)

Migration Chain

Revision Description
a5_003_spec_aligned_actions Drops lifecycle_plans and actions_v3; creates actions, action_invariants, action_arguments
a5_004_spec_aligned_plans Creates v3_plans, plan_projects, plan_arguments, plan_invariants
b1_001_resource_registry Creates resource_types, resources, resource_edges

Source Location

  • Migration (actions): alembic/versions/a5_003_spec_aligned_actions.py
  • Migration (plans): alembic/versions/a5_004_spec_aligned_plans.py
  • Migration (resources): alembic/versions/b1_001_resource_registry_tables.py
  • ORM models: src/cleveragents/infrastructure/database/models.py
  • Repositories: src/cleveragents/infrastructure/database/repositories.py