Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""add showcase_workspace run_config column

Revision ID: b7c1d9e3f204
Revises: d45cf40dfe47
Create Date: 2026-06-13 12:00:00.000000

E4 of the showcase-completion initiative (umbrella #406, epic #410). Adds a
single nullable JSONB ``run_config`` column to ``showcase_workspace`` -- a
REPLAY-INPUT column in the same class as ``seed`` / ``scenario`` / ``reset`` /
``skip_seed`` (NOT an E1 story slot; see docs/_base/DOMAIN_MODEL.md D1). It
records the start-frame model set + backtest config a ``preservation="keep"``
run was launched with, so Load/Replay can reproduce it verbatim. NULL when the
run used default config. No index (the read path is by ``workspace_id``; the
column is a display/replay payload). Forward-only.
"""

from collections.abc import Sequence

import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

from alembic import op

# revision identifiers, used by Alembic.
revision: str = "b7c1d9e3f204"
down_revision: str | None = "d45cf40dfe47"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None


def upgrade() -> None:
"""Add the nullable ``run_config`` JSONB column."""
op.add_column(
"showcase_workspace",
sa.Column("run_config", postgresql.JSONB(astext_type=sa.Text()), nullable=True),
)


def downgrade() -> None:
"""Drop the ``run_config`` column."""
op.drop_column("showcase_workspace", "run_config")
9 changes: 9 additions & 0 deletions app/features/demo/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class ShowcaseWorkspace(TimestampMixin, Base):
date_end: Seeded data window end; NULL when unknown.
created_objects: Soft-reference ids of everything the run created (JSONB).
result_summary: Winner / WAPE / wall-clock display payload (JSONB).
run_config: Replay-input run config -- model set + backtest knobs (E4 #410); NULL on defaults.
archived: Operator curation flag -- archived rows still list in E1.
pinned: Operator curation flag -- no behavioral semantics in E1.
notes: Free-text operator annotation (capped at the Pydantic boundary).
Expand Down Expand Up @@ -102,6 +103,14 @@ class ShowcaseWorkspace(TimestampMixin, Base):
)
# winner_model_type / winner_wape / wall_clock_s -- display payload.
result_summary: Mapped[dict[str, Any] | None] = mapped_column(JSONB, nullable=True)
# E4 (#410) -- replay-input run config (NOT an E1 story slot; see
# DOMAIN_MODEL.md D1). Shape: {"train_model_types": [...], "backtest": {...}}
# via model_dump(mode="json"); NULL when the run used default config.
# Written by create_workspace at insert time (a replay input known before
# step 1, like seed/scenario); consumed by Load/Replay. config_schema_version
# is deliberately NOT bumped -- it versions the STORY-SLOT schema; run_config
# presence is NULL-detectable and carries its own documented shape.
run_config: Mapped[dict[str, Any] | None] = mapped_column(JSONB, nullable=True)

# ── E1 (#407) — lifecycle metadata ────────────────────────────────────
# Orthogonal to ``status`` (which the pipeline owns): archive/pin are
Expand Down
Loading