feat(ui): surface review readiness and blockers

Add readiness hints, blocker summaries, and progress cues across
the dataset review workspace to clarify partial recovery and
launch gating states.

Highlight read-only preview snapshots, pending semantic review,
clarification queue status, and unresolved validation blockers to
guide the next recommended action.

Document known limitations in backend test doubles so permission,
task dispatch, and uncovered persistence branches are explicit.
This commit is contained in:
2026-03-21 15:48:28 +03:00
parent ce9980829e
commit ea4f41c996
13 changed files with 323 additions and 15 deletions

View File

@@ -6,8 +6,10 @@
class FakeQuery:
"""Shared chainable query stub for route tests.
Warning: predicate arguments passed to filter() are recorded only for inspection
and are not evaluated; result sets remain predicate-blind.
WARNING: filter() is predicate-blind — all ownership and permission filters are
ignored. Tests using FakeQuery cannot verify scoped data access. This is a
known limitation; do not use for permission-sensitive test paths without a
spec-guarded replacement.
"""
def __init__(self, rows):

View File

@@ -256,6 +256,11 @@ def _make_us2_session():
# [DEF:_make_us3_session:Function]
# @RELATION: BINDS_TO -> DatasetReviewApiTests
def _make_us3_session():
"""Fake session factory for US3 flow tests.
`imported_filter` and `template_variable` are bare MagicMocks without spec;
ORM attribute access is unchecked.
"""
now = datetime.now(timezone.utc)
session = _make_session()
session.readiness_state = ReadinessState.MAPPING_REVIEW_NEEDED
@@ -587,6 +592,8 @@ def test_orchestrator_start_session_preserves_partial_recovery(
orchestrator = DatasetReviewOrchestrator(
repository=repository,
config_manager=dataset_review_api_dependencies["config_manager"],
# WARNING: task_manager=None — all async task dispatch paths are bypassed.
# Task dispatch failures are invisible to this test.
task_manager=None,
)
@@ -653,6 +660,8 @@ def test_orchestrator_start_session_bootstraps_recovery_state(
orchestrator = DatasetReviewOrchestrator(
repository=repository,
config_manager=dataset_review_api_dependencies["config_manager"],
# WARNING: task_manager=None — all async task dispatch paths are bypassed.
# Task dispatch failures are invisible to this test.
task_manager=None,
)
@@ -1255,6 +1264,8 @@ def test_execution_snapshot_includes_recovered_imported_filters_without_template
orchestrator = DatasetReviewOrchestrator(
repository=repository,
config_manager=dataset_review_api_dependencies["config_manager"],
# WARNING: task_manager=None — all async task dispatch paths are bypassed.
# Task dispatch failures are invisible to this test.
task_manager=None,
)
session = _make_preview_ready_session()
@@ -1326,6 +1337,8 @@ def test_execution_snapshot_preserves_mapped_template_variables_and_filter_conte
orchestrator = DatasetReviewOrchestrator(
repository=repository,
config_manager=dataset_review_api_dependencies["config_manager"],
# WARNING: task_manager=None — all async task dispatch paths are bypassed.
# Task dispatch failures are invisible to this test.
task_manager=None,
)
session = _make_preview_ready_session()
@@ -1363,6 +1376,8 @@ def test_execution_snapshot_skips_partial_imported_filters_without_values(
orchestrator = DatasetReviewOrchestrator(
repository=repository,
config_manager=dataset_review_api_dependencies["config_manager"],
# WARNING: task_manager=None — all async task dispatch paths are bypassed.
# Task dispatch failures are invisible to this test.
task_manager=None,
)
session = _make_preview_ready_session()

View File

@@ -31,6 +31,10 @@ mock_user.roles.append(admin_role)
@pytest.fixture(autouse=True)
def mock_deps():
"""Bare MagicMock — no spec guards. All service method calls succeed silently.
Authorization, data integrity, and error paths are invisible to this fixture.
"""
# @INVARIANT: unconstrained mock — no spec= enforced; attribute typos will silently pass
config_manager = MagicMock()
# @INVARIANT: unconstrained mock — no spec= enforced; attribute typos will silently pass

View File

@@ -117,6 +117,12 @@ async def test_dashboard_validation_plugin_persists_task_and_environment_ids(
# @PURPOSE: Deterministic LLM client double returning canonical analysis payload for persistence-path assertions.
# @INVARIANT: analyze_dashboard is side-effect free and returns schema-compatible PASS result.
class _FakeLLMClient:
"""Fake LLM client for persistence tests.
Always returns PASS status. FAIL and UNKNOWN persistence branches are NOT
covered by this fake — see coverage-planner findings.
"""
def __init__(self, **_kwargs):
return None