feat(ui): add chat-driven dataset review flow
Move dataset review clarification into the assistant workspace and rework the review page into a chat-centric layout with execution rails. Add session-scoped assistant actions for mappings, semantic fields, and SQL preview generation. Introduce optimistic locking for dataset review mutations, propagate session versions through API responses, and mask imported filter values before assistant exposure. Refresh tests, i18n, and spec artifacts to match the new workflow. BREAKING CHANGE: dataset review mutation endpoints now require the X-Session-Version header, and clarification is no longer handled through ClarificationDialog-based flows
This commit is contained in:
@@ -467,6 +467,90 @@ def _ensure_filter_source_enum_values(bind_engine):
|
||||
# [/DEF:_ensure_filter_source_enum_values:Function]
|
||||
|
||||
|
||||
# [DEF:_ensure_dataset_review_session_columns:Function]
|
||||
# @COMPLEXITY: 4
|
||||
# @PURPOSE: Apply additive schema upgrades for dataset review persistence required by optimistic-lock and recovery metadata semantics.
|
||||
# @PRE: bind_engine points to the application database where dataset review tables are stored.
|
||||
# @POST: Missing additive columns across legacy dataset review tables are created without removing existing data.
|
||||
# @SIDE_EFFECT: Executes ALTER TABLE statements against dataset review tables in the application database.
|
||||
# @RELATION: [DEPENDS_ON] ->[DatasetReviewSession]
|
||||
# @RELATION: [DEPENDS_ON] ->[ImportedFilter]
|
||||
def _ensure_dataset_review_session_columns(bind_engine):
|
||||
with belief_scope("_ensure_dataset_review_session_columns"):
|
||||
inspector = inspect(bind_engine)
|
||||
existing_tables = set(inspector.get_table_names())
|
||||
migration_plan = {
|
||||
"dataset_review_sessions": [
|
||||
(
|
||||
"version",
|
||||
"ALTER TABLE dataset_review_sessions "
|
||||
"ADD COLUMN version INTEGER NOT NULL DEFAULT 0",
|
||||
)
|
||||
],
|
||||
"imported_filters": [
|
||||
(
|
||||
"raw_value_masked",
|
||||
"ALTER TABLE imported_filters "
|
||||
"ADD COLUMN raw_value_masked BOOLEAN NOT NULL DEFAULT FALSE",
|
||||
)
|
||||
],
|
||||
}
|
||||
|
||||
for table_name, planned_columns in migration_plan.items():
|
||||
if table_name not in existing_tables:
|
||||
logger.reason(
|
||||
"Dataset review table does not exist yet; skipping additive schema migration",
|
||||
extra={"table": table_name},
|
||||
)
|
||||
continue
|
||||
|
||||
existing_columns = {
|
||||
str(column.get("name") or "").strip()
|
||||
for column in inspector.get_columns(table_name)
|
||||
}
|
||||
alter_statements = [
|
||||
statement
|
||||
for column_name, statement in planned_columns
|
||||
if column_name not in existing_columns
|
||||
]
|
||||
|
||||
if not alter_statements:
|
||||
logger.reason(
|
||||
"Dataset review table schema already up to date",
|
||||
extra={"table": table_name, "columns": sorted(existing_columns)},
|
||||
)
|
||||
continue
|
||||
|
||||
logger.reason(
|
||||
"Applying additive dataset review schema migration",
|
||||
extra={"table": table_name, "statements": alter_statements},
|
||||
)
|
||||
|
||||
try:
|
||||
with bind_engine.begin() as connection:
|
||||
for statement in alter_statements:
|
||||
connection.execute(text(statement))
|
||||
logger.reflect(
|
||||
"Dataset review additive schema migration completed",
|
||||
extra={
|
||||
"table": table_name,
|
||||
"added_columns": [
|
||||
stmt.split(" ADD COLUMN ", 1)[1].split()[0]
|
||||
for stmt in alter_statements
|
||||
],
|
||||
},
|
||||
)
|
||||
except Exception as migration_error:
|
||||
logger.explore(
|
||||
"Dataset review additive schema migration failed",
|
||||
extra={"table": table_name, "error": str(migration_error)},
|
||||
)
|
||||
raise
|
||||
|
||||
|
||||
# [/DEF:_ensure_dataset_review_session_columns:Function]
|
||||
|
||||
|
||||
# [DEF:init_db:Function]
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Initializes the database by creating all tables.
|
||||
@@ -475,6 +559,7 @@ def _ensure_filter_source_enum_values(bind_engine):
|
||||
# @SIDE_EFFECT: Creates physical database files if they don't exist.
|
||||
# @RELATION: [CALLS] ->[ensure_connection_configs_table]
|
||||
# @RELATION: [CALLS] ->[_ensure_filter_source_enum_values]
|
||||
# @RELATION: [CALLS] ->[_ensure_dataset_review_session_columns]
|
||||
def init_db():
|
||||
with belief_scope("init_db"):
|
||||
Base.metadata.create_all(bind=engine)
|
||||
@@ -487,6 +572,7 @@ def init_db():
|
||||
_ensure_auth_users_columns(auth_engine)
|
||||
ensure_connection_configs_table(engine)
|
||||
_ensure_filter_source_enum_values(engine)
|
||||
_ensure_dataset_review_session_columns(engine)
|
||||
|
||||
|
||||
# [/DEF:init_db:Function]
|
||||
|
||||
Reference in New Issue
Block a user