// AXIOM Doc Generator — Generated docs
// Format: doxygen  Mode: grace  Contracts: 3195
// Usage: run through `jsdoc --pedantic` or `doxygen -W` for validation

// --- SrcRoot (backend/src/__init__.py)
/**!
 * @brief Canonical backend package root for application, scripts, and tests.
 */

// --- src.api (backend/src/api/__init__.py)
/**!
 * @brief Backend API package root.
 */

// --- AuthApi (backend/src/api/auth.py)
/**!
 * @brief Authentication API endpoints.
 * @complexity 5
 * @data_contract Input -> OAuth2PasswordRequestForm -> Token, User
 * @invariant All auth endpoints must return consistent error codes.
 * @layer API
 * @post FastAPI app instance with auth routes registered.
 * @pre Python environment and dependencies installed; database available.
 * @side_effect Registers API routes; configures OAuth and CORS middleware.
 */

// --- login_for_access_token (backend/src/api/auth.py)
/**!
 * @brief Authenticates a user and returns a JWT access token.
 * @complexity 4
 * @post Returns a Token object on success.
 * @pre form_data contains username and password.
 * @side_effect DB read/write for auth session; writes security event log.
 */

// --- read_users_me (backend/src/api/auth.py)
/**!
 * @brief Retrieves the profile of the currently authenticated user.
 * @complexity 4
 * @post Returns the current user's data.
 * @pre Valid JWT token provided.
 * @side_effect Reads current user from DB via auth middleware; writes security event log.
 */

// --- logout (backend/src/api/auth.py)
/**!
 * @brief Logs out the current user (placeholder for session revocation).
 * @complexity 4
 * @post Returns success message.
 * @pre Valid JWT token provided.
 * @side_effect Writes security event LOGOUT event.
 */

// --- login_adfs (backend/src/api/auth.py)
/**!
 * @brief Initiates the ADFS OIDC login flow.
 * @complexity 4
 * @post Redirects the user to ADFS.
 * @side_effect Redirects user to ADFS external OIDC provider.
 */

// --- auth_callback_adfs (backend/src/api/auth.py)
/**!
 * @brief Handles the callback from ADFS after successful authentication.
 * @complexity 4
 * @post Provisions user JIT and returns session token.
 * @side_effect Provisions user in DB, creates auth session, writes security event log.
 */

// --- ApiRoutesModule (backend/src/api/routes/__init__.py)
/**!
 * @brief Provide lazy route module loading to avoid heavyweight imports during tests.
 * @complexity 5
 * @invariant Only names listed in __all__ are importable via __getattr__.
 * @layer API
 * @post Route modules are lazily loadable via __getattr__
 * @pre FastAPI app initialized, route modules available in package
 */

// --- Route_Group_Contracts (backend/src/api/routes/__init__.py)
/**!
 * @brief Declare the canonical route-module registry used by lazy imports and app router inclusion.
 * @complexity 3
 * @data_contract Package -> RouterModule mapping
 * @side_effect Registers route group imports via __getattr__
 */

// --- ApiRoutesGetAttr (backend/src/api/routes/__init__.py)
/**!
 * @brief Lazily import route module by attribute name.
 * @complexity 3
 * @post Returns imported submodule or raises AttributeError.
 * @pre name is module candidate exposed in __all__.
 */

// --- RoutesTestsConftest (backend/src/api/routes/__tests__/conftest.py)
/**!
 * @brief Shared low-fidelity test doubles for API route test modules.
 * @complexity 1
 */

// --- AssistantApiTests (backend/src/api/routes/__tests__/test_assistant_api.py)
/**!
 * @brief Validate assistant API endpoint logic via direct async handler invocation.
 * @complexity 3
 * @invariant Every test clears assistant in-memory state before execution.
 */

// --- _dataset_review_session (backend/src/api/routes/__tests__/test_assistant_api.py)
/**!
 * @brief Build minimal owned dataset-review session fixture for assistant scoped routing tests.
 * @complexity 1
 */

// --- _await_none (backend/src/api/routes/__tests__/test_assistant_api.py)
/**!
 * @brief Async helper returning None for planner fallback tests.
 * @complexity 1
 */

// --- test_unknown_command_returns_needs_clarification (backend/src/api/routes/__tests__/test_assistant_api.py)
/**!
 * @brief Unknown command should return clarification state and unknown intent.
 */

// --- test_capabilities_question_returns_successful_help (backend/src/api/routes/__tests__/test_assistant_api.py)
/**!
 * @brief Capability query should return deterministic help response.
 */

// --- test_assistant_message_request_accepts_dataset_review_session_binding (backend/src/api/routes/__tests__/test_assistant_api.py)
/**!
 * @brief Assistant request schema should accept active dataset review session binding for scoped orchestration.
 */

// --- test_dataset_review_scoped_message_uses_masked_filter_context (backend/src/api/routes/__tests__/test_assistant_api.py)
/**!
 * @brief Session-scoped assistant context should mask imported-filter raw values before assistant-visible metadata is persisted.
 */

// --- test_dataset_review_scoped_command_returns_confirmation_for_mapping_approval (backend/src/api/routes/__tests__/test_assistant_api.py)
/**!
 * @brief Session-scoped assistant commands should route dataset-review mapping approvals into confirmation workflow with bound session metadata.
 */

// --- test_dataset_review_scoped_command_routes_field_semantics_update (backend/src/api/routes/__tests__/test_assistant_api.py)
/**!
 * @brief Session-scoped assistant commands should route semantic field updates through explicit confirmation metadata.
 */

// --- TestAssistantAuthz (backend/src/api/routes/__tests__/test_assistant_authz.py)
/**!
 * @brief Verify assistant confirmation ownership, expiration, and deny behavior for restricted users.
 * @complexity 3
 * @invariant Security-sensitive flows fail closed for unauthorized actors.
 * @layer API
 */

// --- _run_async (backend/src/api/routes/__tests__/test_assistant_authz.py)
/**!
 * @brief Execute async endpoint handler in synchronous test context.
 * @complexity 1
 * @post Returns coroutine result or raises propagated exception.
 * @pre coroutine is awaitable endpoint invocation.
 */

// --- _FakeTask (backend/src/api/routes/__tests__/test_assistant_authz.py)
/**!
 * @brief Lightweight task model used for assistant authz tests.
 * @complexity 1
 * @post Returns task with provided id, status, and user_id accessible as attributes.
 * @pre task_id is non-empty string.
 */

// --- _FakeConfigManager (backend/src/api/routes/__tests__/test_assistant_authz.py)
/**!
 * @brief Provide deterministic environment aliases required by intent parsing.
 * @complexity 1
 * @invariant get_config() is absent; only get_environments() is emulated. Safe only for routes that do not invoke get_config() on the injected ConfigManager — verify against assistant.py route handler code before adding new test cases that use this fake.
 * @post get_environments() returns two deterministic SimpleNamespace stubs with id/name.
 * @pre No external config or DB state is required.
 */

// --- _other_admin_user (backend/src/api/routes/__tests__/test_assistant_authz.py)
/**!
 * @brief Build second admin principal fixture for ownership tests.
 * @complexity 1
 * @post Returns alternate admin-like user stub.
 * @pre Ownership mismatch scenario needs distinct authenticated actor.
 */

// --- _limited_user (backend/src/api/routes/__tests__/test_assistant_authz.py)
/**!
 * @brief Build limited principal without required assistant execution privileges.
 * @complexity 1
 * @post Returns restricted user stub.
 * @pre Permission denial scenario needs non-admin actor.
 */

// --- _FakeDb (backend/src/api/routes/__tests__/test_assistant_authz.py)
/**!
 * @brief In-memory DB session double constrained to assistant message/confirmation/audit persistence paths.
 * @complexity 2
 * @invariant query/add/merge are intentionally narrow and must not claim full SQLAlchemy Session semantics.
 */

// --- _clear_assistant_state (backend/src/api/routes/__tests__/test_assistant_authz.py)
/**!
 * @brief Reset assistant process-local state between test cases.
 * @complexity 1
 * @post Assistant in-memory state dictionaries are cleared.
 * @pre Assistant globals may contain state from prior tests.
 */

// --- test_confirmation_owner_mismatch_returns_403 (backend/src/api/routes/__tests__/test_assistant_authz.py)
/**!
 * @brief Confirm endpoint should reject requests from user that does not own the confirmation token.
 * @post Second actor receives 403 on confirm operation.
 * @pre Confirmation token is created by first admin actor.
 */

// --- test_expired_confirmation_cannot_be_confirmed (backend/src/api/routes/__tests__/test_assistant_authz.py)
/**!
 * @brief Expired confirmation token should be rejected and not create task.
 * @post Confirm endpoint raises 400 and no task is created.
 * @pre Confirmation token exists and is manually expired before confirm request.
 */

// --- test_limited_user_cannot_launch_restricted_operation (backend/src/api/routes/__tests__/test_assistant_authz.py)
/**!
 * @brief Limited user should receive denied state for privileged operation.
 * @post Assistant returns denied state and does not execute operation.
 * @pre Restricted user attempts dangerous deploy command.
 */

// --- TestCleanReleaseApi (backend/src/api/routes/__tests__/test_clean_release_api.py)
/**!
 * @brief Contract tests for clean release checks and reports endpoints.
 * @complexity 3
 * @invariant API returns deterministic payload shapes for checks and reports.
 * @layer Domain
 */

// --- test_start_check_and_get_status_contract (backend/src/api/routes/__tests__/test_clean_release_api.py)
/**!
 * @brief Validate checks start endpoint returns expected identifiers and status endpoint reflects the same run.
 */

// --- test_get_report_not_found_returns_404 (backend/src/api/routes/__tests__/test_clean_release_api.py)
/**!
 * @brief Validate reports endpoint returns 404 for an unknown report identifier.
 */

// --- test_get_report_success (backend/src/api/routes/__tests__/test_clean_release_api.py)
/**!
 * @brief Validate reports endpoint returns persisted report payload for an existing report identifier.
 */

// --- test_prepare_candidate_api_success (backend/src/api/routes/__tests__/test_clean_release_api.py)
/**!
 * @brief Validate candidate preparation endpoint returns prepared status and manifest identifier on valid input.
 */

// --- TestCleanReleaseLegacyCompat (backend/src/api/routes/__tests__/test_clean_release_legacy_compat.py)
/**!
 * @brief Compatibility tests for legacy clean-release API paths retained during v2 migration.
 * @complexity 3
 * @layer Tests
 */

// --- _seed_legacy_repo (backend/src/api/routes/__tests__/test_clean_release_legacy_compat.py)
/**!
 * @brief Seed in-memory repository with minimum trusted data for legacy endpoint contracts.
 * @post Candidate, policy, registry and manifest are available for legacy checks flow.
 * @pre Repository is empty.
 */

// --- test_legacy_prepare_endpoint_still_available (backend/src/api/routes/__tests__/test_clean_release_legacy_compat.py)
/**!
 * @brief Verify legacy prepare endpoint remains reachable and returns a status payload.
 */

// --- test_legacy_checks_endpoints_still_available (backend/src/api/routes/__tests__/test_clean_release_legacy_compat.py)
/**!
 * @brief Verify legacy checks start/status endpoints remain available during v2 transition.
 */

// --- TestCleanReleaseSourcePolicy (backend/src/api/routes/__tests__/test_clean_release_source_policy.py)
/**!
 * @brief Validate API behavior for source isolation violations in clean release preparation.
 * @complexity 3
 * @invariant External endpoints must produce blocking violation entries.
 * @layer Domain
 */

// --- _repo_with_seed_data (backend/src/api/routes/__tests__/test_clean_release_source_policy.py)
/**!
 * @brief Seed repository with candidate, registry, and active policy for source isolation test flow.
 */

// --- test_prepare_candidate_blocks_external_source (backend/src/api/routes/__tests__/test_clean_release_source_policy.py)
/**!
 * @brief Verify candidate preparation is blocked when at least one source host is external to the trusted registry.
 */

// --- CleanReleaseV2ApiTests (backend/src/api/routes/__tests__/test_clean_release_v2_api.py)
/**!
 * @brief API contract tests for redesigned clean release endpoints.
 * @complexity 3
 * @layer Domain
 */

// --- test_candidate_registration_contract (backend/src/api/routes/__tests__/test_clean_release_v2_api.py)
/**!
 * @brief Validate candidate registration endpoint creates a draft candidate with expected identifier contract.
 */

// --- test_artifact_import_contract (backend/src/api/routes/__tests__/test_clean_release_v2_api.py)
/**!
 * @brief Validate artifact import endpoint accepts candidate artifacts and returns success status payload.
 */

// --- test_manifest_build_contract (backend/src/api/routes/__tests__/test_clean_release_v2_api.py)
/**!
 * @brief Validate manifest build endpoint produces manifest payload linked to the target candidate.
 */

// --- CleanReleaseV2ReleaseApiTests (backend/src/api/routes/__tests__/test_clean_release_v2_release_api.py)
/**!
 * @brief API contract test scaffolding for clean release approval and publication endpoints.
 * @complexity 3
 * @layer Domain
 */

// --- _seed_candidate_and_passed_report (backend/src/api/routes/__tests__/test_clean_release_v2_release_api.py)
/**!
 * @brief Seed repository with approvable candidate and passed report for release endpoint contracts.
 */

// --- test_release_approve_and_publish_revoke_contract (backend/src/api/routes/__tests__/test_clean_release_v2_release_api.py)
/**!
 * @brief Verify approve, publish, and revoke endpoints preserve expected release lifecycle contract.
 */

// --- test_release_reject_contract (backend/src/api/routes/__tests__/test_clean_release_v2_release_api.py)
/**!
 * @brief Verify reject endpoint returns successful rejection decision payload.
 */

// --- DashboardsApiTests (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Unit tests for dashboards API endpoints.
 * @complexity 3
 * @layer API
 */

// --- test_get_dashboards_success (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Validate dashboards listing returns a populated response that satisfies the schema contract.
 * @post Response matches DashboardsResponse schema
 * @pre env_id exists
 * @test GET /api/dashboards returns 200 and valid schema
 * @test_fixture dashboard_list_happy -> {"id": 1, "title": "Main Revenue"}
 */

// --- test_get_dashboards_with_search (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Validate dashboards listing applies the search filter and returns only matching rows.
 * @post Filtered result count must match search
 * @pre search parameter provided
 * @test GET /api/dashboards filters by search term
 */

// --- test_get_dashboards_empty (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Validate dashboards listing returns an empty payload for an environment without dashboards.
 * @test_edge empty_dashboards -> {env_id: 'empty_env', expected_total: 0}
 */

// --- test_get_dashboards_superset_failure (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Validate dashboards listing surfaces a 503 contract when Superset access fails.
 * @test_edge external_superset_failure -> {env_id: 'bad_conn', status: 503}
 */

// --- test_get_dashboards_env_not_found (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Validate dashboards listing returns 404 when the requested environment does not exist.
 * @post Returns 404 error
 * @pre env_id does not exist
 * @test GET /api/dashboards returns 404 if env_id missing
 */

// --- test_get_dashboards_invalid_pagination (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Validate dashboards listing rejects invalid pagination parameters with 400 responses.
 * @post Returns 400 error
 * @pre page < 1 or page_size > 100
 * @test GET /api/dashboards returns 400 for invalid page/page_size
 */

// --- test_get_dashboard_detail_success (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Validate dashboard detail returns charts and datasets for an existing dashboard.
 * @test GET /api/dashboards/{id} returns dashboard detail with charts and datasets
 */

// --- test_get_dashboard_detail_env_not_found (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Validate dashboard detail returns 404 when the requested environment is missing.
 * @test GET /api/dashboards/{id} returns 404 for missing environment
 */

// --- test_migrate_dashboards_success (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Validate dashboard migration request creates an async task and returns its identifier.
 * @post Returns task_id and create_task was called





















@POST/@SIDE_EFFECT: create_task was called
 * @pre Valid source_env_id, target_env_id, dashboard_ids
 * @test POST /api/dashboards/migrate creates migration task
 */

// --- test_migrate_dashboards_no_ids (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Validate dashboard migration rejects empty dashboard identifier lists.
 * @post Returns 400 error
 * @pre dashboard_ids is empty
 * @test POST /api/dashboards/migrate returns 400 for empty dashboard_ids
 */

// --- test_migrate_dashboards_env_not_found (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Validate migration creation returns 404 when the source environment cannot be resolved.
 * @pre source_env_id and target_env_id are valid environment IDs
 */

// --- test_backup_dashboards_success (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Validate dashboard backup request creates an async backup task and returns its identifier.
 * @post Returns task_id and create_task was called














@POST/@SIDE_EFFECT: create_task was called
 * @pre Valid env_id, dashboard_ids
 * @test POST /api/dashboards/backup creates backup task
 */

// --- test_backup_dashboards_env_not_found (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Validate backup task creation returns 404 when the target environment is missing.
 * @pre env_id is a valid environment ID
 */

// --- test_get_database_mappings_success (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Validate database mapping suggestions are returned for valid source and target environments.
 * @post Returns list of database mappings
 * @pre Valid source_env_id, target_env_id
 * @test GET /api/dashboards/db-mappings returns mapping suggestions
 */

// --- test_get_database_mappings_env_not_found (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Validate database mapping suggestions return 404 when either environment is missing.
 * @pre source_env_id and target_env_id are valid environment IDs
 */

// --- test_get_dashboard_tasks_history_filters_success (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Validate dashboard task history returns only related backup and LLM tasks.
 * @test GET /api/dashboards/{id}/tasks returns backup and llm tasks for dashboard
 */

// --- test_get_dashboard_thumbnail_success (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Validate dashboard thumbnail endpoint proxies image bytes and content type from Superset.
 * @test GET /api/dashboards/{id}/thumbnail proxies image bytes from Superset
 */

// --- _build_profile_preference_stub (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Creates profile preference payload stub for dashboards filter contract tests.
 * @post Returns object compatible with ProfileService.get_my_preference contract.
 * @pre username can be empty; enabled indicates profile-default toggle state.
 */

// --- _matches_actor_case_insensitive (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Applies trim + case-insensitive owners OR modified_by matching used by route contract tests.
 * @post Returns True when bound username matches any owner or modified_by.
 * @pre owners can be None or list-like values.
 */

// --- test_get_dashboards_profile_filter_contract_owners_or_modified_by (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Validate profile-default filtering matches owner and modifier aliases using normalized Superset actor values.
 * @post Response includes only matching dashboards and effective_profile_filter metadata.
 * @pre Current user has enabled profile-default preference and bound username.
 * @test GET /api/dashboards applies profile-default filter with owners OR modified_by trim+case-insensitive semantics.
 */

// --- test_get_dashboards_override_show_all_contract (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Validate override_show_all bypasses profile-default filtering without changing dashboard list semantics.
 * @post Response remains unfiltered and effective_profile_filter.applied is false.
 * @pre Profile-default preference exists but override_show_all=true query is provided.
 * @test GET /api/dashboards honors override_show_all and disables profile-default filter for current page.
 */

// --- test_get_dashboards_profile_filter_no_match_results_contract (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Validate profile-default filtering returns an empty dashboard page when no actor aliases match the bound user.
 * @post Response total is 0 with deterministic pagination and active effective_profile_filter metadata.
 * @pre Profile-default preference is enabled with bound username and all dashboards are non-matching.
 * @test GET /api/dashboards returns empty result set when profile-default filter is active and no dashboard actors match.
 */

// --- test_get_dashboards_page_context_other_disables_profile_default (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Validate non-dashboard page contexts suppress profile-default filtering and preserve unfiltered results.
 * @post Response remains unfiltered and metadata reflects source_page=other.
 * @pre Profile-default preference exists but page_context=other query is provided.
 * @test GET /api/dashboards does not auto-apply profile-default filter outside dashboards_main page context.
 */

// --- test_get_dashboards_profile_filter_matches_display_alias_without_detail_fanout (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Validate profile-default filtering reuses resolved Superset display aliases without triggering per-dashboard detail fanout.
 * @post Route matches by alias (`Superset Admin`) and does not call `SupersetClient.get_dashboard` in list filter path.
 * @pre Profile-default filter is active, bound username is `admin`, dashboard actors contain display labels.
 * @test GET /api/dashboards resolves Superset display-name alias once and filters without per-dashboard detail calls.
 */

// --- test_get_dashboards_profile_filter_matches_owner_object_payload_contract (backend/src/api/routes/__tests__/test_dashboards.py)
/**!
 * @brief Validate profile-default filtering accepts owner object payloads once aliases resolve to the bound Superset username.
 * @post Response keeps dashboards where owner object resolves to bound username alias.
 * @pre Profile-default preference is enabled and owners list contains dict payloads.
 * @test GET /api/dashboards profile-default filter matches Superset owner object payloads.
 */

// --- DatasetReviewApiTests (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 * @brief Verify backend US1 dataset review lifecycle, export, parsing, and dictionary-resolution contracts.
 * @complexity 3
 * @layer API
 */

// --- _make_user (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 */

// --- _make_config_manager (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 */

// --- _make_session (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 */

// --- _make_us2_session (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 */

// --- _make_us3_session (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 */

// --- _make_preview_ready_session (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 */

// --- dataset_review_api_dependencies (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 */

// --- test_parse_superset_link_dashboard_partial_recovery (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 * @brief Verify dashboard links recover dataset context and preserve explicit partial-recovery markers.
 */

// --- test_parse_superset_link_dashboard_slug_recovery (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 * @brief Verify dashboard slug links resolve through dashboard detail endpoints and recover dataset context.
 */

// --- test_parse_superset_link_dashboard_permalink_partial_recovery (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 * @brief Verify dashboard permalink links no longer fail parsing and preserve permalink filter state for partial recovery.
 */

// --- test_parse_superset_link_dashboard_permalink_recovers_dataset_from_nested_dashboard_state (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 * @brief Verify permalink state with nested dashboard id recovers dataset binding and keeps imported filters.
 */

// --- test_resolve_from_dictionary_prefers_exact_match (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 * @brief Verify trusted dictionary exact matches outrank fuzzy candidates and unresolved fields stay explicit.
 */

// --- test_orchestrator_start_session_preserves_partial_recovery (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 * @brief Verify session start persists usable recovery-required state when Superset intake is partial.
 */

// --- test_orchestrator_start_session_bootstraps_recovery_state (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 * @brief Verify session start persists recovered filters, template variables, and initial execution mappings for review workspace bootstrap.
 */

// --- test_start_session_endpoint_returns_created_summary (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 * @brief Verify POST session lifecycle endpoint returns a persisted ownership-scoped summary.
 */

// --- test_get_session_detail_export_and_lifecycle_endpoints (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 * @brief Verify lifecycle get/patch/delete plus documentation and validation exports remain ownership-scoped and usable.
 */

// --- test_get_clarification_state_returns_empty_payload_when_session_has_no_record (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 * @brief Clarification state endpoint should return a non-blocking empty payload when the session has no clarification aggregate yet.
 */

// --- test_us2_clarification_endpoints_persist_answer_and_feedback (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 * @brief Clarification endpoints should expose one current question, persist the answer before advancement, and store feedback on the answer audit record.
 */

// --- test_us2_field_semantic_override_lock_unlock_and_feedback (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 * @brief Semantic field endpoints should apply manual overrides with lock/provenance invariants and persist feedback independently.
 */

// --- test_us3_mapping_patch_approval_preview_and_launch_endpoints (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 * @brief US3 execution endpoints should persist manual overrides, preserve explicit approval semantics, return contract-shaped preview truth, and expose audited launch handoff.
 */

// --- test_us3_preview_response_propagates_refreshed_session_version_for_launch_follow_up (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 * @brief Preview response should expose the refreshed session version so the normal preview-then-launch UI flow can satisfy optimistic locking without a forced full reload.
 */

// --- test_us3_preview_endpoint_returns_failed_preview_without_false_dashboard_not_found_contract_drift (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 * @brief Preview endpoint should preserve API contract and surface generic upstream preview failures without fabricating dashboard-not-found semantics for non-dashboard 404s.
 */

// --- test_mutation_endpoints_surface_session_version_conflict_payload (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 * @brief Dataset review mutation endpoints should return deterministic 409 conflict semantics when optimistic-lock versions are stale.
 */

// --- test_update_session_surfaces_commit_time_session_version_conflict_payload (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 * @brief Session lifecycle mutation should return deterministic 409 conflict semantics when commit-time optimistic locking rejects a stale write.
 */

// --- test_execution_snapshot_includes_recovered_imported_filters_without_template_mapping (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 * @brief Recovered imported filters with values should flow into preview filter context even when no template variable mapping exists.
 */

// --- test_execution_snapshot_preserves_mapped_template_variables_and_filter_context (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 * @brief Mapped template variables should still populate template params while contributing their effective filter context.
 */

// --- test_execution_snapshot_skips_partial_imported_filters_without_values (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 * @brief Partial imported filters without raw or normalized values must not emit bogus active preview filters.
 */

// --- test_us3_launch_endpoint_requires_launch_permission (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 * @brief Launch endpoint should enforce the contract RBAC permission instead of the generic session-manage permission.
 */

// --- test_semantic_source_version_propagation_preserves_locked_fields (backend/src/api/routes/__tests__/test_dataset_review_api.py)
/**!
 * @brief Updated semantic source versions should mark unlocked fields reviewable while preserving locked manual values.
 */

// --- DatasetsApiTests (backend/src/api/routes/__tests__/test_datasets.py)
/**!
 * @brief Unit tests for datasets API endpoints.
 * @complexity 3
 * @invariant Endpoint contracts remain stable for success and validation failure paths.
 * @layer API
 */

// --- test_get_datasets_success (backend/src/api/routes/__tests__/test_datasets.py)
/**!
 * @brief Validate successful datasets listing contract for an existing environment.
 * @post Response matches DatasetsResponse schema
 * @pre env_id exists
 * @test GET /api/datasets returns 200 and valid schema
 */

// --- test_get_datasets_env_not_found (backend/src/api/routes/__tests__/test_datasets.py)
/**!
 * @brief Validate datasets listing returns 404 when the requested environment does not exist.
 * @post Returns 404 error
 * @pre env_id does not exist
 * @test GET /api/datasets returns 404 if env_id missing
 */

// --- test_get_datasets_invalid_pagination (backend/src/api/routes/__tests__/test_datasets.py)
/**!
 * @brief Validate datasets listing rejects invalid pagination parameters with 400 responses.
 * @post Returns 400 error
 * @pre page < 1 or page_size > 100
 * @test GET /api/datasets returns 400 for invalid page/page_size
 */

// --- test_map_columns_success (backend/src/api/routes/__tests__/test_datasets.py)
/**!
 * @brief Validate map-columns request creates an async mapping task and returns its identifier.
 * @post Returns task_id
 * @pre Valid env_id, dataset_ids, source_type (sqllab)
 * @test POST /api/datasets/map-columns creates mapping task
 */

// --- test_map_columns_invalid_source_type (backend/src/api/routes/__tests__/test_datasets.py)
/**!
 * @brief Validate map-columns rejects unsupported source types with a 400 contract response.
 * @post Returns 400 error
 * @pre source_type is not 'sqllab' or 'xlsx'
 * @test POST /api/datasets/map-columns returns 400 for invalid source_type
 */

// --- test_generate_docs_success (backend/src/api/routes/__tests__/test_datasets.py)
/**!
 * @brief Validate generate-docs request creates an async documentation task and returns its identifier.
 * @post Returns task_id
 * @pre Valid env_id, dataset_ids, llm_provider
 * @test POST /api/datasets/generate-docs creates doc generation task
 */

// --- test_map_columns_empty_ids (backend/src/api/routes/__tests__/test_datasets.py)
/**!
 * @brief Validate map-columns rejects empty dataset identifier lists.
 * @post Returns 400 error
 * @pre dataset_ids is empty
 * @test POST /api/datasets/map-columns returns 400 for empty dataset_ids
 */

// --- test_map_columns_missing_database_id (backend/src/api/routes/__tests__/test_datasets.py)
/**!
 * @brief Validate map-columns rejects sqllab source without database_id.
 * @post Returns 400 error
 * @test POST /api/datasets/map-columns returns 400 for sqllab without database_id
 */

// --- test_generate_docs_empty_ids (backend/src/api/routes/__tests__/test_datasets.py)
/**!
 * @brief Validate generate-docs rejects empty dataset identifier lists.
 * @post Returns 400 error
 * @pre dataset_ids is empty
 * @test POST /api/datasets/generate-docs returns 400 for empty dataset_ids
 */

// --- test_generate_docs_env_not_found (backend/src/api/routes/__tests__/test_datasets.py)
/**!
 * @brief Validate generate-docs returns 404 when the requested environment cannot be resolved.
 * @post Returns 404 error
 * @pre env_id does not exist
 * @test POST /api/datasets/generate-docs returns 404 for missing env
 */

// --- test_get_datasets_superset_failure (backend/src/api/routes/__tests__/test_datasets.py)
/**!
 * @brief Validate datasets listing surfaces a 503 contract when Superset access fails.
 * @post Returns 503 with stable error detail when upstream dataset fetch fails.
 * @test_edge external_superset_failure -> {status: 503}
 */

// --- TestGitApi (backend/src/api/routes/__tests__/test_git_api.py)
/**!
 * @brief API tests for Git configurations and repository operations.
 * @complexity 3
 */

// --- DbMock (backend/src/api/routes/__tests__/test_git_api.py)
/**!
 * @brief In-memory session double for git route tests with minimal query/filter persistence semantics.
 * @complexity 2
 * @invariant Supports only the SQLAlchemy-like operations exercised by this test module.
 */

// --- test_get_git_configs_masks_pat (backend/src/api/routes/__tests__/test_git_api.py)
/**!
 * @brief Validate listing git configs masks stored PAT values in API-facing responses.
 */

// --- test_create_git_config_persists_config (backend/src/api/routes/__tests__/test_git_api.py)
/**!
 * @brief Validate creating git config persists supplied server attributes in backing session.
 */

// --- test_update_git_config_modifies_record (backend/src/api/routes/__tests__/test_git_api.py)
/**!
 * @brief Validate updating git config modifies mutable fields while preserving masked PAT semantics.
 */

// --- SingleConfigDbMock (backend/src/api/routes/__tests__/test_git_api.py)
/**!
 */

// --- test_update_git_config_raises_404_if_not_found (backend/src/api/routes/__tests__/test_git_api.py)
/**!
 * @brief Validate updating non-existent git config raises HTTP 404 contract response.
 */

// --- test_delete_git_config_removes_record (backend/src/api/routes/__tests__/test_git_api.py)
/**!
 * @brief Validate deleting existing git config removes record and returns success payload.
 */

// --- test_test_git_config_validates_connection_successfully (backend/src/api/routes/__tests__/test_git_api.py)
/**!
 * @brief Validate test-connection endpoint returns success when provider connectivity check passes.
 */

// --- MockGitService (backend/src/api/routes/__tests__/test_git_api.py)
/**!
 */

// --- test_test_git_config_fails_validation (backend/src/api/routes/__tests__/test_git_api.py)
/**!
 * @brief Validate test-connection endpoint raises HTTP 400 when provider connectivity check fails.
 */

// --- test_list_gitea_repositories_returns_payload (backend/src/api/routes/__tests__/test_git_api.py)
/**!
 * @brief Validate gitea repositories endpoint returns normalized list for GITEA provider configs.
 */

// --- test_list_gitea_repositories_rejects_non_gitea (backend/src/api/routes/__tests__/test_git_api.py)
/**!
 * @brief Validate gitea repositories endpoint rejects non-GITEA providers with HTTP 400.
 */

// --- test_create_remote_repository_creates_provider_repo (backend/src/api/routes/__tests__/test_git_api.py)
/**!
 * @brief Validate remote repository creation endpoint maps provider response into normalized payload.
 */

// --- test_init_repository_initializes_and_saves_binding (backend/src/api/routes/__tests__/test_git_api.py)
/**!
 * @brief Validate repository initialization endpoint creates local repo and persists dashboard binding.
 */

// --- TestGitStatusRoute (backend/src/api/routes/__tests__/test_git_status_route.py)
/**!
 * @brief Validate status endpoint behavior for missing and error repository states.
 * @complexity 3
 * @layer Domain
 */

// --- test_get_repository_status_returns_no_repo_payload_for_missing_repo (backend/src/api/routes/__tests__/test_git_status_route.py)
/**!
 * @brief Ensure missing local repository is represented as NO_REPO payload instead of an API error.
 * @post Route returns a deterministic NO_REPO status payload.
 * @pre GitService.get_status raises HTTPException(404).
 */

// --- test_get_repository_status_propagates_non_404_http_exception (backend/src/api/routes/__tests__/test_git_status_route.py)
/**!
 * @brief Ensure HTTP exceptions other than 404 are not masked.
 * @post Raised exception preserves original status and detail.
 * @pre GitService.get_status raises HTTPException with non-404 status.
 */

// --- test_get_repository_diff_propagates_http_exception (backend/src/api/routes/__tests__/test_git_status_route.py)
/**!
 * @brief Ensure diff endpoint preserves domain HTTP errors from GitService.
 * @post Endpoint raises same HTTPException values.
 * @pre GitService.get_diff raises HTTPException.
 */

// --- test_get_history_wraps_unexpected_error_as_500 (backend/src/api/routes/__tests__/test_git_status_route.py)
/**!
 * @brief Ensure non-HTTP exceptions in history endpoint become deterministic 500 errors.
 * @post Endpoint returns HTTPException with status 500 and route context.
 * @pre GitService.get_commit_history raises ValueError.
 */

// --- test_commit_changes_wraps_unexpected_error_as_500 (backend/src/api/routes/__tests__/test_git_status_route.py)
/**!
 * @brief Ensure commit endpoint does not leak unexpected errors as 400.
 * @post Endpoint raises HTTPException(500) with route context.
 * @pre GitService.commit_changes raises RuntimeError.
 */

// --- test_get_repository_status_batch_returns_mixed_statuses (backend/src/api/routes/__tests__/test_git_status_route.py)
/**!
 * @brief Ensure batch endpoint returns per-dashboard statuses in one response.
 * @post Returned map includes resolved status for each requested dashboard ID.
 * @pre Some repositories are missing and some are initialized.
 */

// --- test_get_repository_status_batch_marks_item_as_error_on_service_failure (backend/src/api/routes/__tests__/test_git_status_route.py)
/**!
 * @brief Ensure batch endpoint marks failed items as ERROR without failing entire request.
 * @post Failed dashboard status is marked as ERROR.
 * @pre GitService raises non-HTTP exception for one dashboard.
 */

// --- test_get_repository_status_batch_deduplicates_and_truncates_ids (backend/src/api/routes/__tests__/test_git_status_route.py)
/**!
 * @brief Ensure batch endpoint protects server from oversized payloads.
 * @post Result contains unique IDs up to configured cap.
 * @pre request includes duplicate IDs and more than MAX_REPOSITORY_STATUS_BATCH entries.
 */

// --- test_commit_changes_applies_profile_identity_before_commit (backend/src/api/routes/__tests__/test_git_status_route.py)
/**!
 * @brief Ensure commit route configures repository identity from profile preferences before commit call.
 * @post git_service.configure_identity receives resolved identity and commit proceeds.
 * @pre Profile preference contains git_username/git_email for current user.
 */

// --- test_pull_changes_applies_profile_identity_before_pull (backend/src/api/routes/__tests__/test_git_status_route.py)
/**!
 * @brief Ensure pull route configures repository identity from profile preferences before pull call.
 * @post git_service.configure_identity receives resolved identity and pull proceeds.
 * @pre Profile preference contains git_username/git_email for current user.
 */

// --- test_get_merge_status_returns_service_payload (backend/src/api/routes/__tests__/test_git_status_route.py)
/**!
 * @brief Ensure merge status route returns service payload as-is.
 * @post Route response contains has_unfinished_merge=True.
 * @pre git_service.get_merge_status returns unfinished merge payload.
 */

// --- test_resolve_merge_conflicts_passes_resolution_items_to_service (backend/src/api/routes/__tests__/test_git_status_route.py)
/**!
 * @brief Ensure merge resolve route forwards parsed resolutions to service.
 * @post Service receives normalized list and route returns resolved files.
 * @pre resolve_data has one file strategy.
 */

// --- test_abort_merge_calls_service_and_returns_result (backend/src/api/routes/__tests__/test_git_status_route.py)
/**!
 * @brief Ensure abort route delegates to service.
 * @post Route returns aborted status.
 * @pre Service abort_merge returns aborted status.
 */

// --- test_continue_merge_passes_message_and_returns_commit (backend/src/api/routes/__tests__/test_git_status_route.py)
/**!
 * @brief Ensure continue route passes commit message to service.
 * @post Route returns committed status and hash.
 * @pre continue_data.message is provided.
 */

// --- TestMigrationRoutes (backend/src/api/routes/__tests__/test_migration_routes.py)
/**!
 * @brief Unit tests for migration API route handlers.
 * @complexity 3
 * @layer API
 */

// --- _mock_env (backend/src/api/routes/__tests__/test_migration_routes.py)
/**!
 */

// --- _make_sync_config_manager (backend/src/api/routes/__tests__/test_migration_routes.py)
/**!
 */

// --- TestProfileApi (backend/src/api/routes/__tests__/test_profile_api.py)
/**!
 * @brief Verifies profile API route contracts for preference read/update and Superset account lookup.
 * @complexity 3
 * @layer API
 */

// --- mock_profile_route_dependencies (backend/src/api/routes/__tests__/test_profile_api.py)
/**!
 * @brief Provides deterministic dependency overrides for profile route tests.
 * @post Dependencies are overridden for current test and restored afterward.
 * @pre App instance is initialized.
 */

// --- profile_route_deps_fixture (backend/src/api/routes/__tests__/test_profile_api.py)
/**!
 * @brief Pytest fixture wrapper for profile route dependency overrides.
 * @post Yields overridden dependencies and clears overrides after test.
 * @pre None.
 */

// --- _build_preference_response (backend/src/api/routes/__tests__/test_profile_api.py)
/**!
 * @brief Builds stable profile preference response payload for route tests.
 * @post Returns ProfilePreferenceResponse object with deterministic timestamps.
 * @pre user_id is provided.
 */

// --- test_get_profile_preferences_returns_self_payload (backend/src/api/routes/__tests__/test_profile_api.py)
/**!
 * @brief Verifies GET /api/profile/preferences returns stable self-scoped payload.
 * @post Response status is 200 and payload contains current user preference.
 * @pre Authenticated user context is available.
 */

// --- test_patch_profile_preferences_success (backend/src/api/routes/__tests__/test_profile_api.py)
/**!
 * @brief Verifies PATCH /api/profile/preferences persists valid payload through route mapping.
 * @post Response status is 200 with saved preference payload.
 * @pre Valid request payload and authenticated user.
 */

// --- test_patch_profile_preferences_validation_error (backend/src/api/routes/__tests__/test_profile_api.py)
/**!
 * @brief Verifies route maps domain validation failure to HTTP 422 with actionable details.
 * @post Response status is 422 and includes validation messages.
 * @pre Service raises ProfileValidationError.
 */

// --- test_patch_profile_preferences_cross_user_denied (backend/src/api/routes/__tests__/test_profile_api.py)
/**!
 * @brief Verifies route maps domain authorization guard failure to HTTP 403.
 * @post Response status is 403 with denial message.
 * @pre Service raises ProfileAuthorizationError.
 */

// --- test_lookup_superset_accounts_success (backend/src/api/routes/__tests__/test_profile_api.py)
/**!
 * @brief Verifies lookup route returns success payload with normalized candidates.
 * @post Response status is 200 and items list is returned.
 * @pre Valid environment_id and service success response.
 */

// --- test_lookup_superset_accounts_env_not_found (backend/src/api/routes/__tests__/test_profile_api.py)
/**!
 * @brief Verifies lookup route maps missing environment to HTTP 404.
 * @post Response status is 404 with explicit message.
 * @pre Service raises EnvironmentNotFoundError.
 */

// --- TestReportsApi (backend/src/api/routes/__tests__/test_reports_api.py)
/**!
 * @brief Contract tests for GET /api/reports defaults, pagination, and filtering behavior.
 * @complexity 3
 * @debt Divergent _FakeTaskManager definition. Canonical version should be in conftest.py. Authz variant is missing get_all_tasks().
 * @invariant API response contract contains {items,total,page,page_size,has_next,applied_filters}.
 * @layer Domain
 */

// --- _make_task (backend/src/api/routes/__tests__/test_reports_api.py)
/**!
 * @brief Build Task fixture with controlled timestamps/status for reports list/detail normalization.
 */

// --- test_get_reports_default_pagination_contract (backend/src/api/routes/__tests__/test_reports_api.py)
/**!
 * @brief Validate reports list endpoint default pagination and contract keys for mixed task statuses.
 */

// --- test_get_reports_filter_and_pagination (backend/src/api/routes/__tests__/test_reports_api.py)
/**!
 * @brief Validate reports list endpoint applies task-type/status filters and pagination boundaries.
 */

// --- test_get_reports_handles_mixed_naive_and_aware_datetimes (backend/src/api/routes/__tests__/test_reports_api.py)
/**!
 * @brief Validate reports sorting remains stable when task timestamps mix naive and timezone-aware datetimes.
 */

// --- test_get_reports_invalid_filter_returns_400 (backend/src/api/routes/__tests__/test_reports_api.py)
/**!
 * @brief Validate reports list endpoint rejects unsupported task type filters with HTTP 400.
 */

// --- TestReportsDetailApi (backend/src/api/routes/__tests__/test_reports_detail_api.py)
/**!
 * @brief Contract tests for GET /api/reports/{report_id} detail endpoint behavior.
 * @complexity 3
 * @debt Divergent _FakeTaskManager definition. Canonical version should be in conftest.py. Authz variant is missing get_all_tasks().
 * @invariant Detail endpoint tests must keep deterministic assertions for success and not-found contracts.
 * @layer Domain
 */

// --- test_get_report_detail_success (backend/src/api/routes/__tests__/test_reports_detail_api.py)
/**!
 * @brief Validate report detail endpoint returns report body with diagnostics and next actions for existing task.
 */

// --- test_get_report_detail_not_found (backend/src/api/routes/__tests__/test_reports_detail_api.py)
/**!
 * @brief Validate report detail endpoint returns 404 when requested report identifier is absent.
 */

// --- TestReportsOpenapiConformance (backend/src/api/routes/__tests__/test_reports_openapi_conformance.py)
/**!
 * @brief Validate implemented reports payload shape against OpenAPI-required top-level contract fields.
 * @complexity 3
 * @invariant List and detail payloads include required contract keys.
 * @layer Domain
 */

// --- _FakeTaskManager (backend/src/api/routes/__tests__/test_reports_openapi_conformance.py)
/**!
 * @brief Minimal task-manager fake exposing static task list for OpenAPI conformance checks.
 * @complexity 1
 * @invariant get_all_tasks returns seeded tasks unchanged.
 */

// --- _admin_user (backend/src/api/routes/__tests__/test_reports_openapi_conformance.py)
/**!
 * @brief Provide admin principal fixture required by reports routes in conformance tests.
 */

// --- _task (backend/src/api/routes/__tests__/test_reports_openapi_conformance.py)
/**!
 * @brief Construct deterministic task fixture consumed by reports list/detail payload assertions.
 */

// --- test_reports_list_openapi_required_keys (backend/src/api/routes/__tests__/test_reports_openapi_conformance.py)
/**!
 * @brief Verify reports list endpoint includes all required OpenAPI top-level keys.
 */

// --- test_reports_detail_openapi_required_keys (backend/src/api/routes/__tests__/test_reports_openapi_conformance.py)
/**!
 * @brief Verify reports detail endpoint returns payload containing the report object key.
 */

// --- test_tasks_logs_module (backend/src/api/routes/__tests__/test_tasks_logs.py)
/**!
 * @brief Contract testing for task logs API endpoints.
 * @complexity 2
 * @layer Domain
 * @test_fixture mock_app
 */

// --- test_get_task_logs_success (backend/src/api/routes/__tests__/test_tasks_logs.py)
/**!
 * @brief Validate task logs endpoint returns filtered logs for an existing task.
 */

// --- test_get_task_logs_not_found (backend/src/api/routes/__tests__/test_tasks_logs.py)
/**!
 * @brief Validate task logs endpoint returns 404 when the task identifier is missing.
 * @test_edge invalid_limit
 */

// --- test_get_task_logs_invalid_limit (backend/src/api/routes/__tests__/test_tasks_logs.py)
/**!
 * @brief Validate task logs endpoint enforces query validation for limit lower bound.
 */

// --- test_get_task_log_stats_success (backend/src/api/routes/__tests__/test_tasks_logs.py)
/**!
 * @brief Validate log stats endpoint returns success payload for an existing task.
 */

// --- AdminApi (backend/src/api/routes/admin.py)
/**!
 * @brief Admin API endpoints for user and role management.
 * @complexity 5
 * @invariant All endpoints in this module require 'Admin' role or 'admin' scope.
 * @layer API
 */

// --- list_users (backend/src/api/routes/admin.py)
/**!
 * @brief Lists all registered users.
 * @complexity 3
 * @post Returns a list of UserSchema objects.
 * @pre Current user has 'Admin' role.
 */

// --- create_user (backend/src/api/routes/admin.py)
/**!
 * @brief Creates a new local user.
 * @complexity 3
 * @post New user is created in the database.
 * @pre Current user has 'Admin' role.
 */

// --- update_user (backend/src/api/routes/admin.py)
/**!
 * @brief Updates an existing user.
 * @complexity 3
 * @post User record is updated in the database.
 * @pre Current user has 'Admin' role.
 */

// --- delete_user (backend/src/api/routes/admin.py)
/**!
 * @brief Deletes a user.
 * @complexity 3
 * @post User record is removed from the database.
 * @pre Current user has 'Admin' role.
 */

// --- list_roles (backend/src/api/routes/admin.py)
/**!
 * @brief Lists all available roles.
 * @complexity 3
 */

// --- create_role (backend/src/api/routes/admin.py)
/**!
 * @brief Creates a new system role with associated permissions.
 * @complexity 3
 * @post New Role record is created in auth.db.
 * @pre Role name must be unique.
 * @side_effect Commits new role and associations to auth.db.
 */

// --- update_role (backend/src/api/routes/admin.py)
/**!
 * @brief Updates an existing role's metadata and permissions.
 * @complexity 3
 * @post Role record is updated in auth.db.
 * @pre role_id must be a valid existing role UUID.
 * @side_effect Commits updates to auth.db.
 */

// --- delete_role (backend/src/api/routes/admin.py)
/**!
 * @brief Removes a role from the system.
 * @complexity 3
 * @post Role record is removed from auth.db.
 * @pre role_id must be a valid existing role UUID.
 * @side_effect Deletes record from auth.db and commits.
 */

// --- list_ad_mappings (backend/src/api/routes/admin.py)
/**!
 * @brief Lists all AD Group to Role mappings.
 * @complexity 3
 */

// --- create_ad_mapping (backend/src/api/routes/admin.py)
/**!
 * @brief Creates a new AD Group mapping.
 * @complexity 2
 */

// --- AdminApiKeyRoutes (backend/src/api/routes/admin_api_keys.py)
/**!
 * @brief Admin API endpoints for API key management — list, generate (one-time reveal), and revoke.
 * @complexity 3
 * @invariant DELETE /api/admin/api-keys/{id} soft-deletes (active=False), preserves row for audit.
 * @layer API
 */

// --- ApiKeyCreateRequest (backend/src/api/routes/admin_api_keys.py)
/**!
 * @complexity 1
 */

// --- ApiKeyCreateResponse (backend/src/api/routes/admin_api_keys.py)
/**!
 * @complexity 1
 */

// --- ApiKeyListItem (backend/src/api/routes/admin_api_keys.py)
/**!
 * @complexity 1
 */

// --- ApiKeyRevokeResponse (backend/src/api/routes/admin_api_keys.py)
/**!
 * @complexity 1
 */

// --- list_api_keys (backend/src/api/routes/admin_api_keys.py)
/**!
 * @brief List all API keys — NEVER returns key_hash or raw_key.
 * @complexity 2
 * @post Returns list of ApiKeyListItem without sensitive fields.
 * @pre Requires admin:settings WRITE permission.
 */

// --- create_api_key (backend/src/api/routes/admin_api_keys.py)
/**!
 * @brief Generate a new API key — returns raw key ONCE, never stored or retrievable again.
 * @complexity 3
 * @post Creates APIKey row with SHA-256 hash. Returns raw key in response.
 * @pre Requires admin:settings WRITE permission. name is required, at least one permission.
 * @side_effect Generates cryptographically random key, stores hash in DB.
 */

// --- revoke_api_key (backend/src/api/routes/admin_api_keys.py)
/**!
 * @brief Revoke an API key by setting active=False. Preserves row for audit.
 * @complexity 2
 * @post Sets active=False on the key. Returns 404 if already revoked or not found.
 * @pre Requires admin:settings WRITE permission.
 */

// --- AssistantAdminRoutes (backend/src/api/routes/assistant/_admin_routes.py)
/**!
 * @brief FastAPI route handlers for assistant admin operations — conversation listing, deletion, history, audit.
 * @complexity 5
 * @invariant Audit endpoint requires tasks:READ permission.
 * @layer API
 */

// --- list_conversations (backend/src/api/routes/assistant/_admin_routes.py)
/**!
 * @brief Return paginated conversation list for current user with archived flag and last message preview.
 * @complexity 2
 * @post Conversations are grouped by conversation_id sorted by latest activity descending.
 * @pre Authenticated user context and valid pagination params.
 */

// --- delete_conversation (backend/src/api/routes/assistant/_admin_routes.py)
/**!
 * @brief Soft-delete or hard-delete a conversation and clear its in-memory trace.
 * @complexity 2
 * @post Conversation records are removed from DB and CONVERSATIONS cache.
 * @pre conversation_id belongs to current_user.
 */

// --- get_history (backend/src/api/routes/assistant/_admin_routes.py)
/**!
 * @brief Retrieve paginated assistant conversation history for current user.
 * @post Returns persistent messages and mirrored in-memory snapshot for diagnostics.
 * @pre Authenticated user is available and page params are valid.
 */

// --- get_assistant_audit (backend/src/api/routes/assistant/_admin_routes.py)
/**!
 * @brief Return assistant audit decisions for current user from persistent and in-memory stores.
 * @post Audit payload is returned in reverse chronological order from DB.
 * @pre User has tasks:READ permission.
 */

// --- AssistantCommandParser (backend/src/api/routes/assistant/_command_parser.py)
/**!
 * @brief Deterministic RU/EN command text parser that converts user messages into intent payloads.
 * @complexity 4
 * @invariant Every return path includes domain, operation, entities, confidence, risk_level, requires_confirmation.
 * @layer API
 */

// --- _parse_command (backend/src/api/routes/assistant/_command_parser.py)
/**!
 * @brief Deterministically parse RU/EN command text into intent payload.
 * @complexity 4
 * @data_contract Input[message:str, config_manager:ConfigManager] -> Output[Dict[str,Any]{domain,operation,entities,confidence,risk_level,requires_confirmation}]
 * @invariant every return path includes domain, operation, entities, confidence, risk_level, requires_confirmation.
 * @post Returns intent dict with domain/operation/entities/confidence/risk fields.
 * @pre message contains raw user text and config manager resolves environments.
 * @side_effect None (pure parsing logic).
 */

// --- AssistantDatasetReview (backend/src/api/routes/assistant/_dataset_review.py)
/**!
 * @brief Dataset review context loading and intent planning for the assistant API.
 * @complexity 4
 * @invariant Dataset review operations are always scoped to the owner's session.
 * @layer API
 */

// --- _serialize_dataset_review_context (backend/src/api/routes/assistant/_dataset_review.py)
/**!
 * @brief Build assistant-safe dataset-review context snapshot with masked imported-filter payloads for session-scoped assistant routing.
 * @complexity 4
 * @post Returns a serializable dictionary containing the complete review context.
 * @pre session_id is a valid active review session identifier.
 * @side_effect Reads session data from the database.
 */

// --- _load_dataset_review_context (backend/src/api/routes/assistant/_dataset_review.py)
/**!
 * @brief Load owner-scoped dataset-review context for assistant planning and grounded response generation.
 * @complexity 4
 * @post Returns a loaded context object with session data and findings.
 * @pre session_id is a valid active review session identifier.
 * @side_effect Reads session data from the database.
 */

// --- _extract_dataset_review_target (backend/src/api/routes/assistant/_dataset_review.py)
/**!
 * @brief Extract structured dataset-review focus target hints embedded in assistant prompts.
 * @complexity 2
 */

// --- _match_dataset_review_field (backend/src/api/routes/assistant/_dataset_review.py)
/**!
 * @brief Resolve one semantic field from assistant-visible context by id or user-visible label.
 * @complexity 2
 */

// --- _extract_quoted_segment (backend/src/api/routes/assistant/_dataset_review.py)
/**!
 * @brief Extract one quoted assistant command segment after a label token.
 * @complexity 2
 */

// --- _plan_dataset_review_intent (backend/src/api/routes/assistant/_dataset_review.py)
/**!
 * @brief Parse session-scoped dataset-review assistant commands before falling back to generic assistant tool routing.
 * @complexity 3
 */

// --- AssistantDatasetReviewDispatch (backend/src/api/routes/assistant/_dataset_review_dispatch.py)
/**!
 * @brief Dispatch and confirmation handling for dataset-review assistant intents.
 * @complexity 4
 * @invariant Dataset review dispatch requires valid session version for write operations.
 * @layer API
 */

// --- _dataset_review_conflict_http_exception (backend/src/api/routes/assistant/_dataset_review_dispatch.py)
/**!
 * @brief Convert dataset-review optimistic-lock conflicts into shared 409 assistant semantics.
 * @complexity 2
 */

// --- _dispatch_dataset_review_intent (backend/src/api/routes/assistant/_dataset_review_dispatch.py)
/**!
 * @brief Route confirmed dataset-review assistant intents through existing backend dataset-review APIs and orchestration boundaries.
 * @complexity 4
 * @post Returns a structured response with planned actions and confirmations.
 * @pre context contains valid session data and user intent.
 * @side_effect May update session state and enqueue tasks.
 */

// --- AssistantDispatch (backend/src/api/routes/assistant/_dispatch.py)
/**!
 * @brief Intent dispatch engine, confirmation summary, and clarification text for the assistant API.
 * @complexity 5
 * @invariant Unsupported operations are rejected via HTTPException(400).
 * @layer API
 */

// --- _clarification_text_for_intent (backend/src/api/routes/assistant/_dispatch.py)
/**!
 * @brief Convert technical missing-parameter errors into user-facing clarification prompts.
 * @complexity 2
 * @post Returned text is human-readable and actionable for target operation.
 * @pre state was classified as needs_clarification for current intent/error combination.
 */

// --- _async_confirmation_summary (backend/src/api/routes/assistant/_dispatch.py)
/**!
 * @brief Build human-readable confirmation prompt for an intent before execution.
 * @complexity 4
 * @post Returns a formatted summary string suitable for display to the user.
 * @pre actions is a non-empty list of planned review actions.
 * @side_effect None - pure formatting function.
 */

// --- _dispatch_intent (backend/src/api/routes/assistant/_dispatch.py)
/**!
 * @brief Execute parsed assistant intent via existing task/plugin/git services.
 * @complexity 5
 * @data_contract Input[intent,current_user,task_manager,config_manager,db] -> Output[Tuple[text:str,task_id:Optional[str],actions:List[AssistantAction]]]
 * @invariant unsupported operations are rejected via HTTPException(400).
 * @post Returns response text, optional task id, and UI actions for follow-up.
 * @pre intent operation is known and actor permissions are validated per operation.
 * @side_effect May enqueue tasks, invoke git operations, and query/update external service state.
 */

// --- AssistantHistory (backend/src/api/routes/assistant/_history.py)
/**!
 * @brief Conversation history, audit trail, and confirmation persistence helpers for the assistant API.
 * @complexity 2
 * @invariant Failed persistence attempts always rollback before returning.
 * @layer API
 */

// --- _append_history (backend/src/api/routes/assistant/_history.py)
/**!
 * @brief Append conversation message to in-memory history buffer.
 * @complexity 2
 * @data_contract Input[user_id,conversation_id,role,text,state?,task_id?,confirmation_id?] -> Output[None]
 * @invariant every appended entry includes generated message_id and created_at timestamp.
 * @post Message entry is appended to CONVERSATIONS key list.
 * @pre user_id and conversation_id identify target conversation bucket.
 * @side_effect Mutates in-memory CONVERSATIONS store for user conversation history.
 */

// --- _persist_message (backend/src/api/routes/assistant/_history.py)
/**!
 * @brief Persist assistant/user message record to database.
 * @complexity 2
 * @data_contract Input[Session,user_id,conversation_id,role,text,state?,task_id?,confirmation_id?,metadata?] -> Output[None]
 * @invariant failed persistence attempts always rollback before returning.
 * @post Message row is committed or persistence failure is logged.
 * @pre db session is writable and message payload is serializable.
 * @side_effect Writes AssistantMessageRecord rows and commits or rollbacks the DB session.
 */

// --- _audit (backend/src/api/routes/assistant/_history.py)
/**!
 * @brief Append in-memory audit record for assistant decision trace.
 * @complexity 2
 * @data_contract Input[user_id,payload:Dict[str,Any]] -> Output[None]
 * @invariant persisted in-memory audit entry always contains created_at in ISO format.
 * @post ASSISTANT_AUDIT list for user contains new timestamped entry.
 * @pre payload describes decision/outcome fields.
 * @side_effect Mutates in-memory ASSISTANT_AUDIT store and emits structured log event.
 */

// --- _persist_audit (backend/src/api/routes/assistant/_history.py)
/**!
 * @brief Persist structured assistant audit payload in database.
 * @complexity 2
 * @post Audit row is committed or failure is logged with rollback.
 * @pre db session is writable and payload is JSON-serializable.
 */

// --- _persist_confirmation (backend/src/api/routes/assistant/_history.py)
/**!
 * @brief Persist confirmation token record to database.
 * @complexity 2
 * @post Confirmation row exists in persistent storage.
 * @pre record contains id/user/intent/dispatch/expiry fields.
 */

// --- _update_confirmation_state (backend/src/api/routes/assistant/_history.py)
/**!
 * @brief Update persistent confirmation token lifecycle state.
 * @complexity 2
 * @post State and consumed_at fields are updated when applicable.
 * @pre confirmation_id references existing row.
 */

// --- _load_confirmation_from_db (backend/src/api/routes/assistant/_history.py)
/**!
 * @brief Load confirmation token from database into in-memory model.
 * @complexity 2
 * @post Returns ConfirmationRecord when found, otherwise None.
 * @pre confirmation_id may or may not exist in storage.
 */

// --- _ensure_conversation (backend/src/api/routes/assistant/_history.py)
/**!
 * @brief Resolve active conversation id in memory or create a new one.
 * @complexity 2
 * @post Returns stable conversation id and updates USER_ACTIVE_CONVERSATION.
 * @pre user_id identifies current actor.
 */

// --- _resolve_or_create_conversation (backend/src/api/routes/assistant/_history.py)
/**!
 * @brief Resolve active conversation using explicit id, memory cache, or persisted history.
 * @complexity 2
 * @post Returns conversation id and updates USER_ACTIVE_CONVERSATION cache.
 * @pre user_id and db session are available.
 */

// --- _cleanup_history_ttl (backend/src/api/routes/assistant/_history.py)
/**!
 * @brief Enforce assistant message retention window by deleting expired rows and in-memory records.
 * @complexity 2
 * @post Messages older than ASSISTANT_MESSAGE_TTL_DAYS are removed from persistence and memory mirrors.
 * @pre db session is available and user_id references current actor scope.
 */

// --- _is_conversation_archived (backend/src/api/routes/assistant/_history.py)
/**!
 * @brief Determine archived state for a conversation based on last update timestamp.
 * @complexity 2
 * @post Returns True when conversation inactivity exceeds archive threshold.
 * @pre updated_at can be null for empty conversations.
 */

// --- _coerce_query_bool (backend/src/api/routes/assistant/_history.py)
/**!
 * @brief Normalize bool-like query values for compatibility in direct handler invocations/tests.
 * @complexity 2
 * @post Returns deterministic boolean flag.
 * @pre value may be bool, string, or FastAPI Query metadata object.
 */

// --- AssistantLlmPlanner (backend/src/api/routes/assistant/_llm_planner.py)
/**!
 * @brief LLM-based intent planning, tool catalog construction, and authorization for the assistant API.
 * @complexity 5
 * @data_contract UserPermissions -> ToolCatalog
 * @invariant Tool catalog is filtered by user permissions before being sent to LLM.
 * @layer API
 * @post LLM tool catalog filtered and returned
 * @pre Assistant routes initialized, user authenticated
 * @side_effect Filters tool catalog by user permissions
 */

// --- _check_any_permission (backend/src/api/routes/assistant/_llm_planner.py)
/**!
 * @brief Validate user against alternative permission checks (logical OR).
 * @complexity 2
 * @post Returns on first successful permission; raises 403-like HTTPException otherwise.
 * @pre checks list contains resource-action tuples.
 */

// --- _has_any_permission (backend/src/api/routes/assistant/_llm_planner.py)
/**!
 * @brief Check whether user has at least one permission tuple from the provided list.
 * @complexity 2
 * @post Returns True when at least one permission check passes.
 * @pre current_user and checks list are valid.
 */

// --- _build_tool_catalog (backend/src/api/routes/assistant/_llm_planner.py)
/**!
 * @brief Build current-user tool catalog for LLM planner with operation contracts and defaults.
 * @complexity 3
 * @post Returns list of executable tools filtered by permission and runtime availability.
 * @pre current_user is authenticated; config/db are available.
 */

// --- _coerce_intent_entities (backend/src/api/routes/assistant/_llm_planner.py)
/**!
 * @brief Normalize intent entity value types from LLM output to route-compatible values.
 * @complexity 2
 * @post Returned intent has numeric ids coerced where possible and string values stripped.
 * @pre intent contains entities dict or missing entities.
 */

// --- AssistantLlmPlannerIntent (backend/src/api/routes/assistant/_llm_planner_intent.py)
/**!
 * @brief LLM-based intent planning and authorization for the assistant API — separated from tool catalog.
 * @complexity 5
 * @data_contract UserIntent -> PlannedAction
 * @invariant Production deployments always require confirmation.
 * @layer API
 * @post Intent planning registered with confirmation gate
 * @pre Assistant routes initialized, user authenticated
 * @side_effect Registers intent planning routes
 */

// --- _plan_intent_with_llm (backend/src/api/routes/assistant/_llm_planner_intent.py)
/**!
 * @brief Use active LLM provider to select best tool/operation from dynamic catalog.
 * @complexity 2
 * @post Returns normalized intent dict when planning succeeds; otherwise None.
 * @pre tools list contains allowed operations for current user.
 */

// --- _authorize_intent (backend/src/api/routes/assistant/_llm_planner_intent.py)
/**!
 * @brief Validate user permissions for parsed intent before confirmation/dispatch.
 * @complexity 2
 * @post Returns if authorized; raises HTTPException(403) when denied.
 * @pre intent.operation is present for known assistant command domains.
 */

// --- AssistantResolvers (backend/src/api/routes/assistant/_resolvers.py)
/**!
 * @brief Environment, dashboard, provider, and task resolution utilities for the assistant API.
 * @complexity 2
 * @invariant Resolution functions never raise; they return None on failure.
 * @layer API
 */

// --- _extract_id (backend/src/api/routes/assistant/_resolvers.py)
/**!
 * @brief Extract first regex match group from text by ordered pattern list.
 * @complexity 2
 * @post Returns first matched token or None.
 * @pre patterns contain at least one capture group.
 */

// --- _resolve_env_id (backend/src/api/routes/assistant/_resolvers.py)
/**!
 * @brief Resolve environment identifier/name token to canonical environment id.
 * @complexity 2
 * @post Returns matched environment id or None.
 * @pre config_manager provides environment list.
 */

// --- _is_production_env (backend/src/api/routes/assistant/_resolvers.py)
/**!
 * @brief Determine whether environment token resolves to production-like target.
 * @complexity 2
 * @post Returns True for production/prod synonyms, else False.
 * @pre config_manager provides environments or token text is provided.
 */

// --- _resolve_provider_id (backend/src/api/routes/assistant/_resolvers.py)
/**!
 * @brief Resolve provider token to provider id with active/default fallback.
 * @complexity 2
 * @post Returns provider id or None when no providers configured.
 * @pre db session can load provider list through LLMProviderService.
 */

// --- _get_default_environment_id (backend/src/api/routes/assistant/_resolvers.py)
/**!
 * @brief Resolve default environment id from settings or first configured environment.
 * @complexity 2
 * @post Returns default environment id or None when environment list is empty.
 * @pre config_manager returns environments list.
 */

// --- _resolve_dashboard_id_by_ref (backend/src/api/routes/assistant/_resolvers.py)
/**!
 * @brief Resolve dashboard id by title or slug reference in selected environment.
 * @complexity 2
 * @post Returns dashboard id when uniquely matched, otherwise None.
 * @pre dashboard_ref is a non-empty string-like token.
 */

// --- _resolve_dashboard_id_entity (backend/src/api/routes/assistant/_resolvers.py)
/**!
 * @brief Resolve dashboard id from intent entities using numeric id or dashboard_ref fallback.
 * @complexity 2
 * @post Returns resolved dashboard id or None when ambiguous/unresolvable.
 * @pre entities may contain dashboard_id as int/str and optional dashboard_ref.
 */

// --- _get_environment_name_by_id (backend/src/api/routes/assistant/_resolvers.py)
/**!
 * @brief Resolve human-readable environment name by id.
 * @complexity 2
 * @post Returns matching environment name or fallback id.
 * @pre environment id may be None.
 */

// --- _extract_result_deep_links (backend/src/api/routes/assistant/_resolvers.py)
/**!
 * @brief Build deep-link actions to verify task result from assistant chat.
 * @complexity 2
 * @post Returns zero or more assistant actions for dashboard open/diff.
 * @pre task object is available.
 */

// --- _build_task_observability_summary (backend/src/api/routes/assistant/_resolvers.py)
/**!
 * @brief Build compact textual summary for completed tasks to reduce "black box" effect.
 * @complexity 2
 * @post Returns non-empty summary line for known task types or empty string fallback.
 * @pre task may contain plugin-specific result payload.
 */

// --- AssistantRoutes (backend/src/api/routes/assistant/_routes.py)
/**!
 * @brief FastAPI route handlers for the assistant API — message sending, confirmation, conversation management.
 * @complexity 5
 * @invariant Risky operations are never executed without valid confirmation token.
 * @layer API
 */

// --- send_message (backend/src/api/routes/assistant/_routes.py)
/**!
 * @brief Parse assistant command, enforce safety gates, and dispatch executable intent.
 * @complexity 5
 * @data_contract Input[AssistantMessageRequest,User,TaskManager,ConfigManager,Session] -> Output[AssistantMessageResponse]
 * @invariant non-safe operations are gated with confirmation before execution from this endpoint.
 * @post Response state is one of clarification/confirmation/started/success/denied/failed.
 * @pre Authenticated user is available and message text is non-empty.
 * @side_effect Persists chat/audit state, mutates in-memory conversation and confirmation stores, and may create confirmation records.
 */

// --- confirm_operation (backend/src/api/routes/assistant/_routes.py)
/**!
 * @brief Execute previously requested risky operation after explicit user confirmation.
 * @complexity 2
 * @post Confirmation state becomes consumed and operation result is persisted in history.
 * @pre confirmation_id exists, belongs to current user, is pending, and not expired.
 */

// --- cancel_operation (backend/src/api/routes/assistant/_routes.py)
/**!
 * @brief Cancel pending risky operation and mark confirmation token as cancelled.
 * @complexity 2
 * @post Confirmation becomes cancelled and cannot be executed anymore.
 * @pre confirmation_id exists, belongs to current user, and is still pending.
 */

// --- AssistantSchemas (backend/src/api/routes/assistant/_schemas.py)
/**!
 * @brief Pydantic models, in-memory stores, and permission mappings for the assistant API.
 * @complexity 2
 * @invariant In-memory stores are module-level singletons shared across the assistant package.
 * @layer API
 * @rationale In-memory stores documented with NOTE about restart loss. ASSISTANT_ARCHIVE_AFTER_DAYS and ASSISTANT_MESSAGE_TTL_DAYS kept as module-level constants with TODO for config migration — Pydantic schemas module should not depend on ConfigManager for architectural purity.
 */

// --- AssistantMessageRequest (backend/src/api/routes/assistant/_schemas.py)
/**!
 * @brief Input payload for assistant message endpoint.
 * @complexity 1
 * @data_contract Input[conversation_id?:str, message:str(1..4000)] -> Output[AssistantMessageRequest]
 * @invariant message is always non-empty and no longer than 4000 characters.
 * @post Request object provides message text and optional conversation binding.
 * @pre message length is within accepted bounds.
 * @side_effect None (schema declaration only).
 */

// --- AssistantAction (backend/src/api/routes/assistant/_schemas.py)
/**!
 * @brief UI action descriptor returned with assistant responses.
 * @complexity 1
 * @data_contract Input[type:str, label:str, target?:str] -> Output[AssistantAction]
 * @invariant type and label are required for every UI action.
 * @post Action can be rendered as button on frontend.
 * @pre type and label are provided by orchestration logic.
 * @side_effect None (schema declaration only).
 */

// --- AssistantMessageResponse (backend/src/api/routes/assistant/_schemas.py)
/**!
 * @brief Output payload contract for assistant interaction endpoints.
 * @complexity 1
 * @data_contract Input[conversation_id,response_id,state,text,intent?,confirmation_id?,task_id?,actions[],created_at] -> Output[AssistantMessageResponse]
 * @invariant created_at and state are always present in endpoint responses.
 * @post Payload may include task_id/confirmation_id/actions for UI follow-up.
 * @pre Response includes deterministic state and text.
 * @side_effect None (schema declaration only).
 */

// --- ConfirmationRecord (backend/src/api/routes/assistant/_schemas.py)
/**!
 * @brief In-memory confirmation token model for risky operation dispatch.
 * @complexity 1
 * @data_contract Input[id,user_id,conversation_id,intent,dispatch,expires_at,state?,created_at] -> Output[ConfirmationRecord]
 * @invariant state defaults to "pending" and expires_at bounds confirmation validity.
 * @post Record tracks lifecycle state and expiry timestamp.
 * @pre intent/dispatch/user_id are populated at confirmation request time.
 * @side_effect None (schema declaration only).
 */

// --- CONVERSATIONS (backend/src/api/routes/assistant/_schemas.py)
/**!
 * @brief In-memory conversation history store: {(user_id, conversation_id) -> [message_records]}
 * @complexity 1
 */

// --- ASSISTANT_AUDIT (backend/src/api/routes/assistant/_schemas.py)
/**!
 * @brief In-memory assistant audit trail: {user_id -> [audit_records]}. Volatile — lost on restart.
 * @complexity 1
 */

// --- CleanReleaseApi (backend/src/api/routes/clean_release.py)
/**!
 * @brief Expose clean release endpoints for candidate preparation and subsequent compliance flow.
 * @complexity 4
 * @invariant API never reports prepared status if preparation errors are present.
 * @layer API
 * @post Candidate preparation, manifest, and compliance routes expose deterministic API payloads without reporting prepared state on failed preparation.
 * @pre Clean release repository and preparation service dependencies are configured for the current request scope.
 * @side_effect Persists candidate/compliance lifecycle state and triggers clean-release orchestration services.
 */

// --- PrepareCandidateRequest (backend/src/api/routes/clean_release.py)
/**!
 * @brief Request schema for candidate preparation endpoint.
 */

// --- StartCheckRequest (backend/src/api/routes/clean_release.py)
/**!
 * @brief Request schema for clean compliance check run startup.
 */

// --- RegisterCandidateRequest (backend/src/api/routes/clean_release.py)
/**!
 * @brief Request schema for candidate registration endpoint.
 */

// --- ImportArtifactsRequest (backend/src/api/routes/clean_release.py)
/**!
 * @brief Request schema for candidate artifact import endpoint.
 */

// --- BuildManifestRequest (backend/src/api/routes/clean_release.py)
/**!
 * @brief Request schema for manifest build endpoint.
 */

// --- CreateComplianceRunRequest (backend/src/api/routes/clean_release.py)
/**!
 * @brief Request schema for compliance run creation with optional manifest pinning.
 */

// --- register_candidate_v2_endpoint (backend/src/api/routes/clean_release.py)
/**!
 * @brief Register a clean-release candidate for headless lifecycle.
 * @post Candidate is persisted in DRAFT status.
 * @pre Candidate identifier is unique.
 */

// --- import_candidate_artifacts_v2_endpoint (backend/src/api/routes/clean_release.py)
/**!
 * @brief Import candidate artifacts in headless flow.
 * @post Artifacts are persisted and candidate advances to PREPARED if it was DRAFT.
 * @pre Candidate exists and artifacts array is non-empty.
 */

// --- build_candidate_manifest_v2_endpoint (backend/src/api/routes/clean_release.py)
/**!
 * @brief Build immutable manifest snapshot for prepared candidate.
 * @post Returns created ManifestDTO with incremented version.
 * @pre Candidate exists and has imported artifacts.
 */

// --- get_candidate_overview_v2_endpoint (backend/src/api/routes/clean_release.py)
/**!
 * @brief Return expanded candidate overview DTO for headless lifecycle visibility.
 * @post Returns CandidateOverviewDTO built from the same repository state used by headless US1 endpoints.
 * @pre Candidate exists.
 */

// --- prepare_candidate_endpoint (backend/src/api/routes/clean_release.py)
/**!
 * @brief Prepare candidate with policy evaluation and deterministic manifest generation.
 * @post Returns preparation result including manifest reference and violations.
 * @pre Candidate and active policy exist in repository.
 */

// --- start_check (backend/src/api/routes/clean_release.py)
/**!
 * @brief Start and finalize a clean compliance check run and persist report artifacts.
 * @post Returns accepted payload with check_run_id and started_at.
 * @pre Active policy and candidate exist.
 */

// --- get_check_status (backend/src/api/routes/clean_release.py)
/**!
 * @brief Return terminal/intermediate status payload for a check run.
 * @post Deterministic payload shape includes checks and violations arrays.
 * @pre check_run_id references an existing run.
 */

// --- get_report (backend/src/api/routes/clean_release.py)
/**!
 * @brief Return persisted compliance report by report_id.
 * @post Returns serialized report object.
 * @pre report_id references an existing report.
 */

// --- CleanReleaseV2Api (backend/src/api/routes/clean_release_v2.py)
/**!
 * @brief Redesigned clean release API for headless candidate lifecycle.
 * @complexity 4
 * @layer API
 * @post Candidate registration, approval, publication, and revocation routes are registered without behavior changes.
 * @pre Clean release repository dependency is available for candidate lifecycle endpoints.
 * @side_effect Persists candidate lifecycle state through clean release services and repository adapters.
 */

// --- ApprovalRequest (backend/src/api/routes/clean_release_v2.py)
/**!
 * @brief Schema for approval request payload.
 * @complexity 1
 */

// --- PublishRequest (backend/src/api/routes/clean_release_v2.py)
/**!
 * @brief Schema for publication request payload.
 * @complexity 1
 */

// --- RevokeRequest (backend/src/api/routes/clean_release_v2.py)
/**!
 * @brief Schema for revocation request payload.
 * @complexity 1
 */

// --- register_candidate (backend/src/api/routes/clean_release_v2.py)
/**!
 * @brief Register a new release candidate.
 * @complexity 3
 * @post Candidate is saved in repository.
 * @pre Payload contains required fields (id, version, source_snapshot_ref, created_by).
 */

// --- import_artifacts (backend/src/api/routes/clean_release_v2.py)
/**!
 * @brief Associate artifacts with a release candidate.
 * @complexity 3
 * @post Artifacts are processed (placeholder).
 * @pre Candidate exists.
 */

// --- build_manifest (backend/src/api/routes/clean_release_v2.py)
/**!
 * @brief Generate distribution manifest for a candidate.
 * @complexity 3
 * @post Manifest is created and saved.
 * @pre Candidate exists.
 */

// --- approve_candidate_endpoint (backend/src/api/routes/clean_release_v2.py)
/**!
 * @brief Endpoint to record candidate approval.
 * @complexity 3
 */

// --- reject_candidate_endpoint (backend/src/api/routes/clean_release_v2.py)
/**!
 * @brief Endpoint to record candidate rejection.
 * @complexity 3
 */

// --- publish_candidate_endpoint (backend/src/api/routes/clean_release_v2.py)
/**!
 * @brief Endpoint to publish an approved candidate.
 * @complexity 3
 */

// --- revoke_publication_endpoint (backend/src/api/routes/clean_release_v2.py)
/**!
 * @brief Endpoint to revoke a previous publication.
 * @complexity 3
 */

// --- DashboardsApi (backend/src/api/routes/dashboards/__init__.py)
/**!
 * @brief API endpoints for the Dashboard Hub - listing dashboards with Git and task status
 * @complexity 5
 * @data_contract Input(env_id, filters) -> Output(DashboardsResponse)
 * @invariant All dashboard responses include git_status and last_task metadata
 * @layer API
 * @post Dashboard responses are projected into DashboardsResponse DTO.
 * @pre Valid environment configurations exist in ConfigManager.
 * @side_effect Performs external calls to Superset API and potentially Git providers.
 * @test_contract DashboardsAPI -> {
 */

// --- DashboardActionRoutes (backend/src/api/routes/dashboards/_action_routes.py)
/**!
 * @brief Dashboard action route handlers — migrate, backup.
 * @complexity 2
 * @layer API
 */

// --- migrate_dashboards (backend/src/api/routes/dashboards/_action_routes.py)
/**!
 * @brief Trigger bulk migration of dashboards from source to target environment
 * @complexity 2
 * @post Task is created and queued for execution
 * @pre dashboard_ids is a non-empty list
 */

// --- backup_dashboards (backend/src/api/routes/dashboards/_action_routes.py)
/**!
 * @brief Trigger bulk backup of dashboards with optional cron schedule
 * @complexity 2
 * @post If schedule is provided, a scheduled task is created
 * @pre dashboard_ids is a non-empty list
 */

// --- DashboardDetailRoutes (backend/src/api/routes/dashboards/_detail_routes.py)
/**!
 * @brief Dashboard detail, db-mappings, task history, thumbnail route handlers.
 * @complexity 3
 * @layer API
 */

// --- get_database_mappings (backend/src/api/routes/dashboards/_detail_routes.py)
/**!
 * @brief Get database mapping suggestions between source and target environments
 * @complexity 2
 * @post Returns list of suggested database mappings with confidence scores
 * @pre source_env_id and target_env_id are valid environment IDs
 */

// --- get_dashboard_detail (backend/src/api/routes/dashboards/_detail_routes.py)
/**!
 * @brief Fetch detailed dashboard info with related charts and datasets
 * @complexity 2
 * @post Returns dashboard detail payload for overview page
 * @pre env_id must be valid and dashboard ref (slug or id) must exist
 */

// --- get_dashboard_tasks_history (backend/src/api/routes/dashboards/_detail_routes.py)
/**!
 * @brief Returns history of backup and LLM validation tasks for a dashboard.
 * @complexity 2
 * @post Response contains sorted task history (newest first).
 * @pre dashboard ref (slug or id) is valid.
 */

// --- get_dashboard_thumbnail (backend/src/api/routes/dashboards/_detail_routes.py)
/**!
 * @brief Proxies Superset dashboard thumbnail with cache support.
 * @complexity 3
 * @post Returns image bytes or 202 when thumbnail is being prepared by Superset.
 * @pre env_id must exist.
 */

// --- DashboardHelpers (backend/src/api/routes/dashboards/_helpers.py)
/**!
 * @brief Basic helper functions for dashboard route handlers — slug resolution, filter normalization.
 * @complexity 2
 * @layer Infrastructure
 */

// --- _find_dashboard_id_by_slug (backend/src/api/routes/dashboards/_helpers.py)
/**!
 * @brief Resolve dashboard numeric ID by slug using Superset list endpoint.
 * @complexity 2
 * @post Returns dashboard ID when found, otherwise None.
 * @pre `dashboard_slug` is non-empty.
 */

// --- _resolve_dashboard_id_from_ref (backend/src/api/routes/dashboards/_helpers.py)
/**!
 * @brief Resolve dashboard ID from slug-first reference with numeric fallback.
 * @complexity 2
 * @post Returns a valid dashboard ID or raises HTTPException(404).
 * @pre `dashboard_ref` is provided in route path.
 */

// --- _find_dashboard_id_by_slug_async (backend/src/api/routes/dashboards/_helpers.py)
/**!
 * @brief Resolve dashboard numeric ID by slug using async Superset list endpoint.
 * @complexity 2
 * @post Returns dashboard ID when found, otherwise None.
 * @pre dashboard_slug is non-empty.
 */

// --- _resolve_dashboard_id_from_ref_async (backend/src/api/routes/dashboards/_helpers.py)
/**!
 * @brief Resolve dashboard ID from slug-first reference using async Superset client.
 * @complexity 2
 * @post Returns valid dashboard ID or raises HTTPException(404).
 * @pre dashboard_ref is provided in route path.
 */

// --- _normalize_filter_values (backend/src/api/routes/dashboards/_helpers.py)
/**!
 * @brief Normalize query filter values to lower-cased non-empty tokens.
 * @complexity 2
 * @post Returns trimmed normalized list preserving input order.
 * @pre values may be None or list of strings.
 */

// --- _dashboard_git_filter_value (backend/src/api/routes/dashboards/_helpers.py)
/**!
 * @brief Build comparable git status token for dashboards filtering.
 * @complexity 2
 * @post Returns one of ok|diff|no_repo|error|pending.
 * @pre dashboard payload may contain git_status or None.
 */

// --- DashboardListingRoutes (backend/src/api/routes/dashboards/_listing_routes.py)
/**!
 * @brief Dashboard listing route handler for Dashboard Hub.
 * @complexity 4
 * @layer API
 */

// --- get_dashboards (backend/src/api/routes/dashboards/_listing_routes.py)
/**!
 * @brief Fetch list of dashboards from a specific environment with Git status and last task status
 * @complexity 3
 * @post Response includes effective profile filter metadata for main dashboards page context
 * @pre page_size must be between 1 and 100 if provided
 */

// --- DashboardProjection (backend/src/api/routes/dashboards/_projection.py)
/**!
 * @brief Dashboard response projection and profile-filter helpers for Dashboard Hub routes.
 * @complexity 2
 * @layer Infrastructure
 */

// --- _normalize_actor_alias_token (backend/src/api/routes/dashboards/_projection.py)
/**!
 * @brief Normalize actor alias token to comparable trim+lower text.
 * @complexity 2
 */

// --- _normalize_owner_display_token (backend/src/api/routes/dashboards/_projection.py)
/**!
 * @brief Project owner payload value into stable display string for API response contracts.
 * @complexity 2
 */

// --- _normalize_dashboard_owner_values (backend/src/api/routes/dashboards/_projection.py)
/**!
 * @brief Normalize dashboard owners payload to optional list of display strings.
 * @complexity 2
 */

// --- _project_dashboard_response_items (backend/src/api/routes/dashboards/_projection.py)
/**!
 * @brief Project dashboard payloads to response-contract-safe shape.
 * @complexity 2
 */

// --- _get_profile_filter_binding (backend/src/api/routes/dashboards/_projection.py)
/**!
 * @brief Resolve dashboard profile-filter binding through current or legacy profile service contracts.
 * @complexity 2
 */

// --- _resolve_profile_actor_aliases (backend/src/api/routes/dashboards/_projection.py)
/**!
 * @brief Resolve stable actor aliases for profile filtering without per-dashboard detail fan-out.
 * @complexity 2
 * @side_effect Performs at most one Superset users-lookup request.
 */

// --- _matches_dashboard_actor_aliases (backend/src/api/routes/dashboards/_projection.py)
/**!
 * @brief Apply profile actor matching against multiple aliases (username + optional display name).
 * @complexity 2
 */

// --- _task_matches_dashboard (backend/src/api/routes/dashboards/_projection.py)
/**!
 * @brief Checks whether task params are tied to a specific dashboard and environment.
 * @complexity 2
 */

// --- DashboardsRouter (backend/src/api/routes/dashboards/_router.py)
/**!
 * @brief Single APIRouter instance for all dashboard endpoints.
 * @complexity 1
 */

// --- DashboardSchemas (backend/src/api/routes/dashboards/_schemas.py)
/**!
 * @brief DTO classes for the Dashboard Hub API.
 * @complexity 1
 * @layer Infrastructure
 */

// --- GitStatus (backend/src/api/routes/dashboards/_schemas.py)
/**!
 * @brief DTO for dashboard Git synchronization status.
 * @complexity 1
 */

// --- DashboardItem (backend/src/api/routes/dashboards/_schemas.py)
/**!
 * @brief DTO representing a single dashboard with projected metadata.
 * @complexity 1
 */

// --- EffectiveProfileFilter (backend/src/api/routes/dashboards/_schemas.py)
/**!
 * @brief Metadata about applied profile filters for UI context.
 * @complexity 1
 */

// --- DashboardsResponse (backend/src/api/routes/dashboards/_schemas.py)
/**!
 * @brief Envelope DTO for paginated dashboards list.
 * @complexity 1
 */

// --- DashboardChartItem (backend/src/api/routes/dashboards/_schemas.py)
/**!
 * @brief DTO for a chart linked to a dashboard.
 * @complexity 1
 */

// --- DashboardDatasetItem (backend/src/api/routes/dashboards/_schemas.py)
/**!
 * @brief DTO for a dataset associated with a dashboard.
 * @complexity 1
 */

// --- DashboardDetailResponse (backend/src/api/routes/dashboards/_schemas.py)
/**!
 * @brief Detailed dashboard metadata including children.
 * @complexity 1
 */

// --- DashboardTaskHistoryItem (backend/src/api/routes/dashboards/_schemas.py)
/**!
 * @brief Individual history record entry.
 * @complexity 1
 */

// --- DashboardTaskHistoryResponse (backend/src/api/routes/dashboards/_schemas.py)
/**!
 * @brief Collection DTO for task history.
 * @complexity 1
 */

// --- DatabaseMapping (backend/src/api/routes/dashboards/_schemas.py)
/**!
 * @brief DTO for cross-environment database ID mapping.
 * @complexity 2
 */

// --- DatabaseMappingsResponse (backend/src/api/routes/dashboards/_schemas.py)
/**!
 * @brief Wrapper for database mappings.
 * @complexity 1
 */

// --- MigrateRequest (backend/src/api/routes/dashboards/_schemas.py)
/**!
 * @brief DTO for dashboard migration requests.
 * @complexity 1
 */

// --- BackupRequest (backend/src/api/routes/dashboards/_schemas.py)
/**!
 * @brief DTO for dashboard backup requests.
 * @complexity 1
 */

// --- DatasetReviewDependencies (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Dependency injection, serialization helpers, and feature-flag guards for dataset review endpoints.
 * @complexity 2
 * @layer API
 */

// --- StartSessionRequest (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Request DTO for starting one dataset review session.
 * @complexity 1
 */

// --- UpdateSessionRequest (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Request DTO for lifecycle state updates on an existing session.
 * @complexity 1
 */

// --- SessionCollectionResponse (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Paginated session collection response.
 * @complexity 1
 */

// --- ExportArtifactResponse (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Inline export response for documentation or validation outputs.
 * @complexity 1
 */

// --- FieldSemanticUpdateRequest (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Request DTO for field-level semantic candidate acceptance or manual override.
 * @complexity 1
 */

// --- FeedbackRequest (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Request DTO for thumbs up/down feedback.
 * @complexity 1
 */

// --- ClarificationAnswerRequest (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Request DTO for submitting one clarification answer.
 * @complexity 1
 */

// --- ClarificationSessionSummaryResponse (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Summary DTO for current clarification session state.
 * @complexity 1
 */

// --- ClarificationStateResponse (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Response DTO for current clarification state and active question payload.
 * @complexity 1
 */

// --- ClarificationAnswerResultResponse (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Response DTO for one clarification answer mutation result.
 * @complexity 1
 */

// --- FeedbackResponse (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Minimal response DTO for persisted AI feedback actions.
 * @complexity 1
 */

// --- ApproveMappingRequest (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Optional request DTO for explicit mapping approval audit notes.
 * @complexity 1
 */

// --- BatchApproveSemanticItemRequest (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Request DTO for one batch semantic-approval item.
 * @complexity 1
 */

// --- BatchApproveSemanticRequest (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Request DTO for explicit batch semantic approvals.
 * @complexity 1
 */

// --- BatchApproveMappingRequest (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Request DTO for explicit batch mapping approvals.
 * @complexity 1
 */

// --- PreviewEnqueueResultResponse (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Async preview trigger response exposing only enqueue state.
 * @complexity 1
 */

// --- MappingCollectionResponse (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Wrapper for execution mapping list responses.
 * @complexity 1
 */

// --- UpdateExecutionMappingRequest (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Request DTO for one manual execution-mapping override update.
 * @complexity 1
 */

// --- LaunchDatasetResponse (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Launch result exposing audited run context and SQL Lab redirect target.
 * @complexity 1
 */

// --- _require_auto_review_flag (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Guard US1 dataset review endpoints behind the configured feature flag.
 * @complexity 2
 */

// --- _require_clarification_flag (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Guard clarification-specific US2 endpoints behind the configured feature flag.
 * @complexity 2
 */

// --- _require_execution_flag (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Guard US3 execution endpoints behind the configured feature flag.
 * @complexity 2
 */

// --- _get_repository (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Build repository dependency.
 * @complexity 1
 */

// --- _get_orchestrator (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Build orchestrator dependency.
 * @complexity 1
 */

// --- _get_clarification_engine (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Build clarification engine dependency.
 * @complexity 1
 */

// --- _serialize_session_summary (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Map session aggregate into stable API summary DTO.
 * @complexity 1
 */

// --- _serialize_session_detail (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Map session aggregate into stable API detail DTO.
 * @complexity 1
 */

// --- _require_session_version_header (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Read the optimistic-lock session version header.
 * @complexity 1
 */

// --- _build_session_version_conflict_http_exception (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Normalize optimistic-lock conflict errors into HTTP 409 responses.
 * @complexity 1
 */

// --- _enforce_session_version (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Convert repository optimistic-lock conflicts into deterministic HTTP 409 responses.
 * @complexity 3
 */

// --- _get_owned_session_or_404 (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Resolve one session for current user or collaborator scope, returning 404 when inaccessible.
 * @complexity 3
 */

// --- _require_owner_mutation_scope (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Enforce owner-only mutation scope.
 * @complexity 2
 */

// --- _prepare_owned_session_mutation (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Resolve owner-scoped mutation session and enforce optimistic-lock version.
 * @complexity 3
 */

// --- _commit_owned_session_mutation (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Centralize session version bumping and commit semantics.
 * @complexity 3
 */

// --- _record_session_event (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Persist one explicit audit event for an owned mutation endpoint.
 * @complexity 1
 */

// --- _serialize_semantic_field (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Map one semantic field into stable DTO.
 * @complexity 1
 */

// --- _serialize_execution_mapping (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Map one execution mapping into stable DTO.
 * @complexity 1
 */

// --- _serialize_preview (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Map one preview into stable DTO.
 * @complexity 1
 */

// --- _serialize_run_context (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Map one run context into stable DTO.
 * @complexity 1
 */

// --- _serialize_clarification_question_payload (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Convert clarification engine payload into API DTO.
 * @complexity 1
 */

// --- _serialize_clarification_state (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Convert clarification engine state into API response.
 * @complexity 1
 */

// --- _serialize_empty_clarification_state (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Return empty clarification payload.
 * @complexity 1
 */

// --- _get_latest_clarification_session_or_404 (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Resolve the latest clarification aggregate or raise.
 * @complexity 1
 */

// --- _get_owned_mapping_or_404 (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Resolve one execution mapping inside one owned session.
 * @complexity 2
 */

// --- _get_owned_field_or_404 (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Resolve a semantic field inside one owned session.
 * @complexity 2
 */

// --- _map_candidate_provenance (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Translate accepted semantic candidate type into stable field provenance.
 * @complexity 1
 */

// --- _resolve_candidate_source_version (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Resolve the semantic source version for one accepted candidate.
 * @complexity 1
 */

// --- _update_semantic_field_state (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Apply field-level semantic manual override or candidate acceptance.
 * @complexity 3
 * @post Manual overrides always set manual provenance plus lock.
 */

// --- _build_sql_lab_redirect_url (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Build SQL Lab redirect URL.
 * @complexity 1
 */

// --- _build_documentation_export (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Produce session documentation export content.
 * @complexity 2
 */

// --- _build_validation_export (backend/src/api/routes/dataset_review_pkg/_dependencies.py)
/**!
 * @brief Produce validation-focused export content.
 * @complexity 2
 */

// --- DatasetReviewRoutes (backend/src/api/routes/dataset_review_pkg/_routes.py)
/**!
 * @brief Persist thumbs up/down feedback for clarification question/answer content.
 * @complexity 3
 */

// --- list_sessions (backend/src/api/routes/dataset_review_pkg/_routes.py)
/**!
 * @brief List resumable dataset review sessions for the current user.
 * @complexity 3
 */

// --- start_session (backend/src/api/routes/dataset_review_pkg/_routes.py)
/**!
 * @brief Start a new dataset review session from a Superset link or dataset selection.
 * @complexity 4
 */

// --- get_session_detail (backend/src/api/routes/dataset_review_pkg/_routes.py)
/**!
 * @brief Return the full accessible dataset review session aggregate.
 * @complexity 3
 */

// --- update_session (backend/src/api/routes/dataset_review_pkg/_routes.py)
/**!
 * @brief Update resumable lifecycle status for an owned session.
 * @complexity 3
 */

// --- delete_session (backend/src/api/routes/dataset_review_pkg/_routes.py)
/**!
 * @brief Archive or hard-delete a session owned by the current user.
 * @complexity 3
 */

// --- export_documentation (backend/src/api/routes/dataset_review_pkg/_routes.py)
/**!
 * @brief Export documentation output for the current session.
 * @complexity 3
 */

// --- export_validation (backend/src/api/routes/dataset_review_pkg/_routes.py)
/**!
 * @brief Export validation findings for the current session.
 * @complexity 3
 */

// --- get_clarification_state (backend/src/api/routes/dataset_review_pkg/_routes.py)
/**!
 * @brief Return the current clarification session summary and active question payload.
 * @complexity 3
 */

// --- resume_clarification (backend/src/api/routes/dataset_review_pkg/_routes.py)
/**!
 * @brief Resume clarification mode on the highest-priority unresolved question.
 * @complexity 3
 */

// --- record_clarification_answer (backend/src/api/routes/dataset_review_pkg/_routes.py)
/**!
 * @brief Persist one clarification answer before advancing the active pointer.
 * @complexity 3
 */

// --- update_field_semantic (backend/src/api/routes/dataset_review_pkg/_routes.py)
/**!
 * @brief Apply one field-level semantic candidate decision or manual override.
 * @complexity 3
 */

// --- lock_field_semantic (backend/src/api/routes/dataset_review_pkg/_routes.py)
/**!
 * @brief Lock one semantic field against later automatic overwrite.
 * @complexity 3
 */

// --- unlock_field_semantic (backend/src/api/routes/dataset_review_pkg/_routes.py)
/**!
 * @brief Unlock one semantic field so later automated candidate application may replace it.
 * @complexity 3
 */

// --- approve_batch_semantic_fields (backend/src/api/routes/dataset_review_pkg/_routes.py)
/**!
 * @brief Approve multiple semantic candidate decisions in one batch.
 * @complexity 3
 */

// --- list_execution_mappings (backend/src/api/routes/dataset_review_pkg/_routes.py)
/**!
 * @brief Return the current mapping-review set for one accessible session.
 * @complexity 3
 */

// --- update_execution_mapping (backend/src/api/routes/dataset_review_pkg/_routes.py)
/**!
 * @brief Persist one owner-authorized execution-mapping effective value override.
 * @complexity 3
 */

// --- approve_execution_mapping (backend/src/api/routes/dataset_review_pkg/_routes.py)
/**!
 * @brief Explicitly approve a warning-sensitive mapping transformation.
 * @complexity 3
 */

// --- approve_batch_execution_mappings (backend/src/api/routes/dataset_review_pkg/_routes.py)
/**!
 * @brief Approve multiple warning-sensitive execution mappings in one batch.
 * @complexity 3
 */

// --- trigger_preview_generation (backend/src/api/routes/dataset_review_pkg/_routes.py)
/**!
 * @brief Trigger Superset-side preview compilation for the current owned execution context.
 * @complexity 3
 */

// --- launch_dataset (backend/src/api/routes/dataset_review_pkg/_routes.py)
/**!
 * @brief Execute the current owned session launch handoff and return audited SQL Lab run context.
 * @complexity 3
 */

// --- record_field_feedback (backend/src/api/routes/dataset_review_pkg/_routes.py)
/**!
 * @brief Persist thumbs up/down feedback for AI-assisted semantic field content.
 * @complexity 3
 */

// --- record_clarification_feedback (backend/src/api/routes/dataset_review_pkg/_routes.py)
/**!
 * @brief Persist thumbs up/down feedback for clarification question/answer content.
 * @complexity 3
 */

// --- DatasetsApi (backend/src/api/routes/datasets.py)
/**!
 * @brief API endpoints for the Dataset Hub - listing datasets with mapping progress
 * @complexity 5
 * @data_contract Input -> DatasetQuery, Output -> DatasetsResponse, DatasetDetailResponse
 * @invariant All dataset responses include last_task metadata
 * @layer API
 * @post Returns dataset metadata with mapping status.
 * @pre SupersetClient is available; env_id is valid.
 * @side_effect Reads from Superset API and task manager.
 */

// --- MappedFields (backend/src/api/routes/datasets.py)
/**!
 * @brief DTO for dataset mapping progress statistics
 * @complexity 1
 */

// --- LastTask (backend/src/api/routes/datasets.py)
/**!
 * @brief DTO for the most recent task associated with a dataset
 * @complexity 1
 */

// --- DatasetItem (backend/src/api/routes/datasets.py)
/**!
 * @brief Summary DTO for a dataset in the hub listing
 * @complexity 1
 */

// --- LinkedDashboard (backend/src/api/routes/datasets.py)
/**!
 * @brief DTO for a dashboard linked to a dataset
 * @complexity 1
 */

// --- DatasetColumn (backend/src/api/routes/datasets.py)
/**!
 * @brief DTO for a single dataset column's metadata
 * @complexity 1
 */

// --- MetricItem (backend/src/api/routes/datasets.py)
/**!
 * @brief Pydantic DTO for a dataset metric — carries Superset metric metadata.
 * @complexity 1
 */

// --- DatasetDetailResponse (backend/src/api/routes/datasets.py)
/**!
 * @brief Detailed DTO for a dataset including columns, linked dashboards, and metrics.
 * @complexity 2
 */

// --- StatsCounts (backend/src/api/routes/datasets.py)
/**!
 * @brief Aggregate statistics for the Stats Bar — computed from full dataset list.
 * @complexity 1
 */

// --- DatasetsResponse (backend/src/api/routes/datasets.py)
/**!
 * @brief Paginated response DTO for dataset listings with stats.
 * @complexity 2
 */

// --- TaskResponse (backend/src/api/routes/datasets.py)
/**!
 * @brief Response DTO containing a task ID for tracking
 * @complexity 1
 */

// --- ColumnDescriptionUpdate (backend/src/api/routes/datasets.py)
/**!
 * @brief Request DTO for inline-edit of a column description.
 * @complexity 1
 */

// --- MetricDescriptionUpdate (backend/src/api/routes/datasets.py)
/**!
 * @brief Request DTO for inline-edit of a metric description.
 * @complexity 1
 */

// --- get_dataset_ids (backend/src/api/routes/datasets.py)
/**!
 * @brief Fetch list of all dataset IDs from a specific environment (without pagination)
 * @complexity 4
 * @post Returns a list of all dataset IDs
 * @pre env_id must be a valid environment ID
 */

// --- get_datasets (backend/src/api/routes/datasets.py)
/**!
 * @brief Fetch list of datasets from a specific environment with mapping progress and stats.
 * @complexity 4
 * @post Response includes pagination metadata (page, page_size, total, total_pages) and stats object.
 * @pre page_size must be between 1 and 100 if provided
 * @rationale Stats counts returned in the same response as datasets to avoid an extra API call for the Stats Bar (FR-022).
 */

// --- MapColumnsRequest (backend/src/api/routes/datasets.py)
/**!
 * @brief Request DTO for initiating column mapping
 * @complexity 1
 */

// --- map_columns (backend/src/api/routes/datasets.py)
/**!
 * @brief Trigger bulk column mapping for datasets
 * @complexity 4
 * @post Task is created and queued for execution
 * @pre dataset_ids is a non-empty list
 */

// --- GenerateDocsRequest (backend/src/api/routes/datasets.py)
/**!
 * @brief Request DTO for initiating documentation generation
 * @complexity 1
 */

// --- generate_docs (backend/src/api/routes/datasets.py)
/**!
 * @brief Trigger bulk documentation generation for datasets
 * @complexity 4
 * @post Task is created and queued for execution
 * @pre dataset_ids is a non-empty list
 */

// --- get_dataset_detail (backend/src/api/routes/datasets.py)
/**!
 * @brief Get detailed dataset information including columns and linked dashboards
 * @complexity 4
 * @post Returns detailed dataset info with columns and linked dashboards
 * @pre dataset_id is a valid dataset ID
 */

// --- _strip_html_tags (backend/src/api/routes/datasets.py)
/**!
 * @brief Detect and strip HTML tags from a text string. Uses simple regex <[^>]*>.
 * @complexity 2
 */

// --- update_column_description (backend/src/api/routes/datasets.py)
/**!
 * @brief Save description for a single dataset column. Internal: GET full dataset from Superset, modify one column's description, PUT back.
 * @complexity 4
 * @error 400 — description exceeds max length or contains non-plaintext content. 404 — dataset_id or column_id not found. 502 — Superset upstream failure (GET or PUT).
 * @post Column description in Superset is updated. Response confirms success.
 * @pre dataset_id and column_id must exist in the target environment.
 * @rationale Must perform GET→modify→PUT because Superset has no PATCH for individual columns — only full object PUT with override_columns=false.
 * @rejected Direct PUT from frontend — rejected because frontend would need to handle full Superset payload structure.
 * @side_effect Mutates dataset metadata in upstream Superset instance via PUT.
 * @validation description — string, max 2000 chars, plain text only (HTML stripped), may be empty string to clear description, no trimming applied. 404 if dataset or column not found. 502 if Superset upstream fails.
 */

// --- update_metric_description (backend/src/api/routes/datasets.py)
/**!
 * @brief Save description for a single dataset metric. Mirror of update_column_description for metrics.
 * @complexity 4
 * @error 400 — description exceeds max length or contains non-plaintext content. 404 — dataset_id or metric_id not found. 502 — Superset upstream failure (GET or PUT).
 * @post Metric description in Superset is updated.
 * @pre dataset_id and metric_id must exist in the target environment.
 * @side_effect Mutates dataset metadata in upstream Superset instance via PUT.
 * @validation description — string, max 2000 chars, plain text only (HTML stripped), may be empty string to clear description, no trimming applied. 404 if dataset or metric not found. 502 if Superset upstream fails.
 */

// --- EnvironmentsApi (backend/src/api/routes/environments.py)
/**!
 * @brief API endpoints for listing environments and their databases.
 * @complexity 5
 * @invariant Environment IDs must exist in the configuration.
 * @layer API
 */

// --- _normalize_superset_env_url (backend/src/api/routes/environments.py)
/**!
 * @brief Canonicalize Superset environment URL to base host/path without trailing /api/v1.
 * @post Returns normalized base URL.
 * @pre raw_url can be empty.
 */

// --- ScheduleSchema (backend/src/api/routes/environments.py)
/**!
 */

// --- EnvironmentResponse (backend/src/api/routes/environments.py)
/**!
 */

// --- DatabaseResponse (backend/src/api/routes/environments.py)
/**!
 */

// --- update_environment_schedule (backend/src/api/routes/environments.py)
/**!
 * @brief Update backup schedule for an environment.
 * @layer API
 * @post Backup schedule updated and scheduler reloaded.
 * @pre Environment id exists, schedule is valid ScheduleSchema.
 */

// --- get_environment_databases (backend/src/api/routes/environments.py)
/**!
 * @brief Fetch the list of databases from a specific environment.
 * @layer API
 * @post Returns a list of database summaries from the environment.
 * @pre Environment id exists.
 */

// --- GitPackage (backend/src/api/routes/git/__init__.py)
/**!
 * @brief Package root for decomposed git routes. Re-exports all public symbols from submodules.
 * @complexity 5
 * @data_contract GitRequest -> GitResponse
 * @invariant git_service and os are module-level attributes for test monkeypatch compatibility.
 * @layer API
 * @post Git API package exported
 * @pre Git service initialized
 * @side_effect Registers git route submodules
 */

// --- GitConfigRoutes (backend/src/api/routes/git/_config_routes.py)
/**!
 * @brief FastAPI endpoints for Git server configuration CRUD and connection testing.
 * @complexity 2
 * @layer API
 */

// --- get_git_configs (backend/src/api/routes/git/_config_routes.py)
/**!
 * @brief List all configured Git servers.
 * @complexity 2
 */

// --- create_git_config (backend/src/api/routes/git/_config_routes.py)
/**!
 * @brief Register a new Git server configuration.
 * @complexity 2
 */

// --- update_git_config (backend/src/api/routes/git/_config_routes.py)
/**!
 * @brief Update an existing Git server configuration.
 * @complexity 2
 */

// --- delete_git_config (backend/src/api/routes/git/_config_routes.py)
/**!
 * @brief Remove a Git server configuration.
 * @complexity 2
 */

// --- test_git_config (backend/src/api/routes/git/_config_routes.py)
/**!
 * @brief Validate connection to a Git server using provided credentials.
 * @complexity 2
 */

// --- GitDeps (backend/src/api/routes/git/_deps.py)
/**!
 * @brief Shared dependency wiring for monkeypatch-safe git_service access and constants.
 * @complexity 1
 * @invariant get_git_service() resolves from sys.modules at call time so test monkeypatching
 * @layer API
 */

// --- GitEnvironmentRoutes (backend/src/api/routes/git/_environment_routes.py)
/**!
 * @brief FastAPI endpoint for listing deployment environments.
 * @complexity 2
 * @layer API
 */

// --- GitGiteaRoutes (backend/src/api/routes/git/_gitea_routes.py)
/**!
 * @brief FastAPI endpoints for Gitea-specific repository operations.
 * @complexity 2
 * @layer API
 */

// --- list_gitea_repositories (backend/src/api/routes/git/_gitea_routes.py)
/**!
 * @brief List repositories in Gitea for a saved Gitea config.
 * @complexity 2
 */

// --- create_gitea_repository (backend/src/api/routes/git/_gitea_routes.py)
/**!
 * @brief Create a repository in Gitea for a saved Gitea config.
 * @complexity 2
 */

// --- delete_gitea_repository (backend/src/api/routes/git/_gitea_routes.py)
/**!
 * @brief Delete repository in Gitea for a saved Gitea config.
 * @complexity 2
 */

// --- create_remote_repository (backend/src/api/routes/git/_gitea_routes.py)
/**!
 * @brief Create repository on remote Git server using selected provider config.
 * @complexity 2
 */

// --- GitHelpers (backend/src/api/routes/git/_helpers.py)
/**!
 * @brief Shared helper functions for Git route modules.
 * @complexity 3
 * @layer API
 */

// --- _build_no_repo_status_payload (backend/src/api/routes/git/_helpers.py)
/**!
 * @brief Build a consistent status payload for dashboards without initialized repositories.
 * @complexity 1
 * @post Returns a stable payload compatible with frontend repository status parsing.
 */

// --- _handle_unexpected_git_route_error (backend/src/api/routes/git/_helpers.py)
/**!
 * @brief Convert unexpected route-level exceptions to stable 500 API responses.
 * @complexity 1
 * @post Raises HTTPException(500) with route-specific context.
 * @pre `error` is a non-HTTPException instance.
 */

// --- _resolve_repository_status (backend/src/api/routes/git/_helpers.py)
/**!
 * @brief Resolve repository status for one dashboard with graceful NO_REPO semantics.
 * @complexity 2
 * @post Returns standard status payload or `NO_REPO` payload when repository path is absent.
 * @pre `dashboard_id` is a valid integer.
 */

// --- _get_git_config_or_404 (backend/src/api/routes/git/_helpers.py)
/**!
 * @brief Resolve GitServerConfig by id or raise 404.
 * @complexity 2
 */

// --- _resolve_repo_key_from_ref (backend/src/api/routes/git/_helpers.py)
/**!
 * @brief Resolve repository folder key with slug-first strategy and deterministic fallback.
 * @complexity 2
 */

// --- _sanitize_optional_identity_value (backend/src/api/routes/git/_helpers.py)
/**!
 * @brief Normalize optional identity value into trimmed string or None.
 * @complexity 1
 */

// --- _resolve_current_user_git_identity (backend/src/api/routes/git/_helpers.py)
/**!
 * @brief Resolve configured Git username/email from current user's profile preferences.
 * @complexity 2
 */

// --- _apply_git_identity_from_profile (backend/src/api/routes/git/_helpers.py)
/**!
 * @brief Apply user-scoped Git identity to repository-local config before write/pull operations.
 * @complexity 2
 */

// --- GitMergeRoutes (backend/src/api/routes/git/_merge_routes.py)
/**!
 * @brief FastAPI endpoints for merge operations (status, conflicts, resolve, abort, continue).
 * @complexity 3
 * @layer API
 */

// --- get_merge_status (backend/src/api/routes/git/_merge_routes.py)
/**!
 * @brief Return unfinished-merge status for repository (web-only recovery support).
 * @complexity 2
 */

// --- get_merge_conflicts (backend/src/api/routes/git/_merge_routes.py)
/**!
 * @brief Return conflicted files with mine/theirs previews for web conflict resolver.
 * @complexity 2
 */

// --- resolve_merge_conflicts (backend/src/api/routes/git/_merge_routes.py)
/**!
 * @brief Apply mine/theirs/manual conflict resolutions from WebUI and stage files.
 * @complexity 3
 */

// --- abort_merge (backend/src/api/routes/git/_merge_routes.py)
/**!
 * @brief Abort unfinished merge from WebUI flow.
 * @complexity 2
 */

// --- continue_merge (backend/src/api/routes/git/_merge_routes.py)
/**!
 * @brief Finalize unfinished merge from WebUI flow.
 * @complexity 3
 */

// --- GitRepoLifecycleRoutes (backend/src/api/routes/git/_repo_lifecycle_routes.py)
/**!
 * @brief FastAPI endpoints for Git lifecycle operations (sync, promote, deploy).
 * @complexity 3
 * @layer API
 */

// --- sync_dashboard (backend/src/api/routes/git/_repo_lifecycle_routes.py)
/**!
 * @brief Sync dashboard state from Superset to Git using the GitPlugin.
 * @complexity 3
 */

// --- promote_dashboard (backend/src/api/routes/git/_repo_lifecycle_routes.py)
/**!
 * @brief Promote changes between branches via MR or direct merge.
 * @complexity 3
 */

// --- deploy_dashboard (backend/src/api/routes/git/_repo_lifecycle_routes.py)
/**!
 * @brief Deploy dashboard from Git to a target environment.
 * @complexity 3
 */

// --- GitRepoOperationsRoutes (backend/src/api/routes/git/_repo_operations_routes.py)
/**!
 * @brief FastAPI endpoints for Git repository operations (commit, push, pull, status, diff, history).
 * @complexity 3
 * @layer API
 */

// --- commit_changes (backend/src/api/routes/git/_repo_operations_routes.py)
/**!
 * @brief Stage and commit changes in the dashboard's repository.
 * @complexity 2
 */

// --- push_changes (backend/src/api/routes/git/_repo_operations_routes.py)
/**!
 * @brief Push local commits to the remote repository.
 * @complexity 2
 */

// --- pull_changes (backend/src/api/routes/git/_repo_operations_routes.py)
/**!
 * @brief Pull changes from the remote repository.
 * @complexity 3
 */

// --- get_repository_status (backend/src/api/routes/git/_repo_operations_routes.py)
/**!
 * @brief Get current Git status for a dashboard repository.
 * @complexity 2
 */

// --- get_repository_status_batch (backend/src/api/routes/git/_repo_operations_routes.py)
/**!
 * @brief Get Git statuses for multiple dashboard repositories in one request.
 * @complexity 2
 */

// --- get_repository_diff (backend/src/api/routes/git/_repo_operations_routes.py)
/**!
 * @brief Get Git diff for a dashboard repository.
 * @complexity 2
 */

// --- generate_commit_message (backend/src/api/routes/git/_repo_operations_routes.py)
/**!
 * @brief Generate a suggested commit message using LLM.
 * @complexity 3
 */

// --- GitRepoRoutes (backend/src/api/routes/git/_repo_routes.py)
/**!
 * @brief FastAPI endpoints for core Git repository operations (init, binding, branches, checkout).
 * @complexity 3
 * @layer API
 */

// --- init_repository (backend/src/api/routes/git/_repo_routes.py)
/**!
 * @brief Link a dashboard to a Git repository and perform initial clone/init.
 * @complexity 3
 */

// --- get_repository_binding (backend/src/api/routes/git/_repo_routes.py)
/**!
 * @brief Return repository binding with provider metadata for selected dashboard.
 * @complexity 2
 */

// --- delete_repository (backend/src/api/routes/git/_repo_routes.py)
/**!
 * @brief Delete local repository workspace and DB binding for selected dashboard.
 * @complexity 2
 */

// --- get_branches (backend/src/api/routes/git/_repo_routes.py)
/**!
 * @brief List all branches for a dashboard's repository.
 * @complexity 2
 */

// --- create_branch (backend/src/api/routes/git/_repo_routes.py)
/**!
 * @brief Create a new branch in the dashboard's repository.
 * @complexity 2
 */

// --- checkout_branch (backend/src/api/routes/git/_repo_routes.py)
/**!
 * @brief Switch the dashboard's repository to a specific branch.
 * @complexity 2
 */

// --- GitRouter (backend/src/api/routes/git/_router.py)
/**!
 * @brief Shared APIRouter for all Git route modules.
 * @complexity 1
 * @layer API
 */

// --- GitSchemas (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Defines Pydantic models for the Git integration API layer.
 * @complexity 1
 * @invariant All schemas must be compatible with the FastAPI router.
 * @layer API
 */

// --- GitServerConfigBase (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Base schema for Git server configuration attributes.
 * @complexity 1
 */

// --- GitServerConfigUpdate (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Schema for updating an existing Git server configuration.
 */

// --- GitServerConfigCreate (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Schema for creating a new Git server configuration.
 */

// --- GitServerConfigSchema (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Schema for representing a Git server configuration with metadata.
 */

// --- GitRepositorySchema (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Schema for tracking a local Git repository linked to a dashboard.
 */

// --- BranchSchema (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Schema for representing a Git branch metadata.
 */

// --- CommitSchema (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Schema for representing Git commit details.
 */

// --- BranchCreate (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Schema for branch creation requests.
 */

// --- BranchCheckout (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Schema for branch checkout requests.
 */

// --- CommitCreate (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Schema for staging and committing changes.
 */

// --- ConflictResolution (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Schema for resolving merge conflicts.
 */

// --- MergeStatusSchema (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Schema representing unfinished merge status for repository.
 */

// --- MergeConflictFileSchema (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Schema describing one conflicted file with optional side snapshots.
 */

// --- MergeResolveRequest (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Request schema for resolving one or multiple merge conflicts.
 */

// --- MergeContinueRequest (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Request schema for finishing merge with optional explicit commit message.
 */

// --- DeploymentEnvironmentSchema (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Schema for representing a target deployment environment.
 */

// --- DeployRequest (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Schema for dashboard deployment requests.
 */

// --- RepoInitRequest (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Schema for repository initialization requests.
 */

// --- RepositoryBindingSchema (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Schema describing repository-to-config binding and provider metadata.
 */

// --- RepoStatusBatchRequest (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Schema for requesting repository statuses for multiple dashboards in a single call.
 */

// --- RepoStatusBatchResponse (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Schema for returning repository statuses keyed by dashboard ID.
 */

// --- GiteaRepoSchema (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Schema describing a Gitea repository.
 */

// --- GiteaRepoCreateRequest (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Request schema for creating a Gitea repository.
 */

// --- RemoteRepoSchema (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Provider-agnostic remote repository payload.
 */

// --- RemoteRepoCreateRequest (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Provider-agnostic repository creation request.
 */

// --- PromoteRequest (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Request schema for branch promotion workflow.
 */

// --- PromoteResponse (backend/src/api/routes/git_schemas.py)
/**!
 * @brief Response schema for promotion operation result.
 */

// --- health_router (backend/src/api/routes/health.py)
/**!
 * @brief API endpoints for dashboard health monitoring and status aggregation.
 * @complexity 3
 * @layer UI
 */

// --- get_health_summary (backend/src/api/routes/health.py)
/**!
 * @brief Get aggregated health status for all dashboards.
 * @post Returns HealthSummaryResponse.
 * @pre Caller has read permission for dashboard health view.
 */

// --- delete_health_report (backend/src/api/routes/health.py)
/**!
 * @brief Delete one persisted dashboard validation report from health summary.
 * @post Validation record is removed; linked task/logs are cleaned when available.
 * @pre Caller has write permission for tasks/report maintenance.
 */

// --- LlmRoutes (backend/src/api/routes/llm.py)
/**!
 * @brief API routes for LLM provider configuration and management.
 * @complexity 3
 * @layer API
 */

// --- FetchModelsRequest (backend/src/api/routes/llm.py)
/**!
 * @brief Pydantic request model for the fetch-models endpoint.
 * @complexity 1
 */

// --- router (backend/src/api/routes/llm.py)
/**!
 * @brief APIRouter instance for LLM routes.
 * @complexity 1
 */

// --- _is_valid_runtime_api_key (backend/src/api/routes/llm.py)
/**!
 * @brief Validate decrypted runtime API key presence/shape.
 * @complexity 4
 * @post Returns True only for non-placeholder key.
 * @pre value can be None.
 */

// --- get_providers (backend/src/api/routes/llm.py)
/**!
 * @brief Retrieve all LLM provider configurations.
 * @complexity 4
 * @post Returns list of LLMProviderConfig.
 * @pre User is authenticated.
 */

// --- fetch_models (backend/src/api/routes/llm.py)
/**!
 * @brief Fetch available models from an LLM provider by base_url+provider_type, or by provider_id.
 * @complexity 4
 * @post Returns a list of available model IDs.
 * @pre User is authenticated. Either provider_id or base_url+provider_type must be provided.
 */

// --- get_llm_status (backend/src/api/routes/llm.py)
/**!
 * @brief Returns whether LLM runtime is configured for dashboard validation.
 * @complexity 4
 * @post configured=true only when an active provider with valid decrypted key exists.
 * @pre User is authenticated.
 */

// --- create_provider (backend/src/api/routes/llm.py)
/**!
 * @brief Create a new LLM provider configuration.
 * @complexity 4
 * @post Returns the created LLMProviderConfig.
 * @pre User is authenticated and has admin permissions.
 */

// --- update_provider (backend/src/api/routes/llm.py)
/**!
 * @brief Update an existing LLM provider configuration.
 * @complexity 4
 * @post Returns the updated LLMProviderConfig.
 * @pre User is authenticated and has admin permissions.
 */

// --- delete_provider (backend/src/api/routes/llm.py)
/**!
 * @brief Delete an LLM provider configuration.
 * @complexity 4
 * @post Returns success status.
 * @pre User is authenticated and has admin permissions.
 */

// --- test_connection (backend/src/api/routes/llm.py)
/**!
 * @brief Test connection to an LLM provider.
 * @complexity 4
 * @post Returns success status and message.
 * @pre User is authenticated.
 */

// --- test_provider_config (backend/src/api/routes/llm.py)
/**!
 * @brief Test connection with a provided configuration (not yet saved).
 * @complexity 4
 * @post Returns success status and message.
 * @pre User is authenticated.
 */

// --- MaintenanceRoutesPackage (backend/src/api/routes/maintenance/__init__.py)
/**!
 * @brief Maintenance Banner API route package.
 * @complexity 1
 * @layer API
 */

// --- MaintenanceRouter (backend/src/api/routes/maintenance/_router.py)
/**!
 * @brief FastAPI APIRouter for the Maintenance Banner endpoints.
 * @complexity 3
 * @layer API
 */

// --- MaintenanceRoutesModule (backend/src/api/routes/maintenance/_routes.py)
/**!
 * @brief Route handler stubs for all 7 Maintenance Banner API endpoints with RBAC guards per FR-015.
 * @complexity 3
 * @invariant RBAC enforced per FR-015 matrix via has_permission() dependency.
 * @layer API
 */

// --- list_dashboard_banners (backend/src/api/routes/maintenance/_routes.py)
/**!
 * @brief Get per-dashboard banner state for the Dashboard Hub indicator.
 * @complexity 2
 */

// --- list_events (backend/src/api/routes/maintenance/_routes.py)
/**!
 * @brief Get active and completed maintenance event lists with affected dashboard counts.
 * @complexity 2
 */

// --- start_maintenance (backend/src/api/routes/maintenance/_routes.py)
/**!
 * @brief Start a maintenance event. Validates input, creates event, dispatches TaskManager task.
 * @complexity 3
 */

// --- end_maintenance (backend/src/api/routes/maintenance/_routes.py)
/**!
 * @brief End a specific maintenance event by ID. Removes banners from affected dashboards.
 * @complexity 3
 */

// --- end_all_maintenance (backend/src/api/routes/maintenance/_routes.py)
/**!
 * @brief End all active maintenance events. Removes all banners from all dashboards.
 * @complexity 3
 */

// --- get_maintenance_settings (backend/src/api/routes/maintenance/_routes.py)
/**!
 * @brief Get current maintenance settings configuration.
 * @complexity 2
 */

// --- update_maintenance_settings (backend/src/api/routes/maintenance/_routes.py)
/**!
 * @brief Update maintenance settings. All fields optional for partial update.
 * @complexity 2
 */

// --- MaintenanceSchemasModule (backend/src/api/routes/maintenance/_schemas.py)
/**!
 * @brief Pydantic models for Maintenance Banner API: request/response schemas per data-model.md.
 * @complexity 2
 * @invariant All response schemas use the standard envelope shape: { status, data, error, meta }
 * @layer API
 */

// --- MaintenanceStartRequest (backend/src/api/routes/maintenance/_schemas.py)
/**!
 * @brief POST /api/maintenance/start request body with environment scoping.
 * @complexity 1
 */

// --- MaintenanceSettingsUpdate (backend/src/api/routes/maintenance/_schemas.py)
/**!
 * @brief PUT /api/maintenance/settings request body — all fields optional for partial update.
 * @complexity 1
 */

// --- MaintenanceStartResponse (backend/src/api/routes/maintenance/_schemas.py)
/**!
 * @brief Response for /api/maintenance/start — always 202 with task_id.
 * @complexity 1
 */

// --- MaintenanceDashboardResult (backend/src/api/routes/maintenance/_schemas.py)
/**!
 * @brief Describes a single dashboard affected by a maintenance operation.
 * @complexity 1
 */

// --- MaintenanceFailedDashboard (backend/src/api/routes/maintenance/_schemas.py)
/**!
 * @brief Describes a dashboard that failed during banner apply/removal.
 * @complexity 1
 */

// --- MaintenanceTaskResult (backend/src/api/routes/maintenance/_schemas.py)
/**!
 * @brief Result payload for a completed maintenance start task.
 * @complexity 1
 */

// --- MaintenanceEndResponse (backend/src/api/routes/maintenance/_schemas.py)
/**!
 * @brief Response for /api/maintenance/{id}/end and /api/maintenance/end-all — always 202 with task_id.
 * @complexity 1
 */

// --- MaintenanceEndTaskResult (backend/src/api/routes/maintenance/_schemas.py)
/**!
 * @brief Result payload for a completed end maintenance task.
 * @complexity 1
 */

// --- MaintenanceEndAllTaskResult (backend/src/api/routes/maintenance/_schemas.py)
/**!
 * @brief Result payload for a completed end-all maintenance task.
 * @complexity 1
 */

// --- MaintenanceSettingsResponse (backend/src/api/routes/maintenance/_schemas.py)
/**!
 * @brief Response for GET /api/maintenance/settings.
 * @complexity 1
 */

// --- MaintenanceEventItem (backend/src/api/routes/maintenance/_schemas.py)
/**!
 * @brief Single maintenance event summary for GET /api/maintenance/events.
 * @complexity 1
 */

// --- MaintenanceEventListResponse (backend/src/api/routes/maintenance/_schemas.py)
/**!
 * @brief Response for GET /api/maintenance/events.
 * @complexity 1
 */

// --- MaintenanceDashboardBannerState (backend/src/api/routes/maintenance/_schemas.py)
/**!
 * @brief Per-dashboard banner state for GET /api/maintenance/dashboard-banners.
 * @complexity 1
 */

// --- MaintenanceAlreadyActiveResponse (backend/src/api/routes/maintenance/_schemas.py)
/**!
 * @brief Response for duplicate /start call — idempotency hit.
 * @complexity 1
 */

// --- MappingsApi (backend/src/api/routes/mappings.py)
/**!
 * @brief API endpoints for managing database mappings and getting suggestions.
 * @complexity 3
 * @layer API
 */

// --- MappingCreate (backend/src/api/routes/mappings.py)
/**!
 */

// --- MappingResponse (backend/src/api/routes/mappings.py)
/**!
 */

// --- SuggestRequest (backend/src/api/routes/mappings.py)
/**!
 */

// --- get_mappings (backend/src/api/routes/mappings.py)
/**!
 * @brief List all saved database mappings.
 * @post Returns filtered list of DatabaseMapping records.
 * @pre db session is injected.
 */

// --- create_mapping (backend/src/api/routes/mappings.py)
/**!
 * @brief Create or update a database mapping.
 * @post DatabaseMapping created or updated in database.
 * @pre mapping is valid MappingCreate, db session is injected.
 */

// --- suggest_mappings_api (backend/src/api/routes/mappings.py)
/**!
 * @brief Get suggested mappings based on fuzzy matching.
 * @post Returns mapping suggestions.
 * @pre request is valid SuggestRequest, config_manager is injected.
 */

// --- MigrationApi (backend/src/api/routes/migration.py)
/**!
 * @brief HTTP contract layer for migration orchestration, settings, dry-run, and mapping sync endpoints.
 * @complexity 5
 * @data_contract [DashboardSelection | QueryParams] -> [TaskResponse | DryRunResult | MappingSummary]
 * @invariant Migration endpoints never execute with invalid environment references and always return explicit HTTP errors on guard failures.
 * @layer Infrastructure
 * @post Migration tasks are enqueued or dry-run results are computed and returned.
 * @pre Backend core services initialized and Database session available.
 * @side_effect Enqueues long-running tasks, potentially mutates ResourceMapping table, and performs remote Superset API calls.
 * @test_contract [DashboardSelection + configured envs] -> [task_id | dry-run result | sync summary]
 * @test_edge [external_fail] ->[HTTP_500]
 * @test_invariant [EnvironmentValidationBeforeAction] -> VERIFIED_BY: [invalid_environment, valid_execution]
 * @test_scenario [valid_execution] -> [success_payload_with_required_fields]
 */

// --- execute_migration (backend/src/api/routes/migration.py)
/**!
 * @brief Validate migration selection and enqueue asynchronous migration task execution.
 * @complexity 5
 * @data_contract Input[DashboardSelection] -> Output[Dict[str, str]]
 * @invariant Migration task dispatch never occurs before source and target environment ids pass guard validation.
 * @post Returns {"task_id": str, "message": str} when task creation succeeds; emits HTTP_400/HTTP_500 on failure.
 * @pre DashboardSelection payload is valid and both source/target environments exist.
 * @side_effect Reads configuration, writes task record through task manager, and writes operational logs.
 */

// --- dry_run_migration (backend/src/api/routes/migration.py)
/**!
 * @brief Build pre-flight migration diff and risk summary without mutating target systems.
 * @complexity 5
 * @data_contract Input[DashboardSelection] -> Output[Dict[str, Any]]
 * @invariant Dry-run flow remains read-only and rejects identical source/target environments before service execution.
 * @post Returns deterministic dry-run payload; emits HTTP_400 for guard violations and HTTP_500 for orchestrator value errors.
 * @pre DashboardSelection is valid, source and target environments exist, differ, and selected_ids is non-empty.
 * @side_effect Reads local mappings from DB and fetches source/target metadata via Superset API.
 */

// --- get_migration_settings (backend/src/api/routes/migration.py)
/**!
 * @brief Read and return configured migration synchronization cron expression.
 * @complexity 3
 * @data_contract Input[None] -> Output[Dict[str, str]]
 * @post Returns {"cron": str} reflecting current persisted settings value.
 * @pre Configuration store is available and requester has READ permission.
 * @side_effect Reads configuration from config manager.
 */

// --- update_migration_settings (backend/src/api/routes/migration.py)
/**!
 * @brief Validate and persist migration synchronization cron expression update.
 * @complexity 3
 * @data_contract Input[Dict[str, str]] -> Output[Dict[str, str]]
 * @post Returns {"cron": str, "status": "updated"} and persists updated cron value.
 * @pre Payload includes "cron" key and requester has WRITE permission.
 * @side_effect Mutates configuration and writes persisted config through config manager.
 */

// --- get_resource_mappings (backend/src/api/routes/migration.py)
/**!
 * @brief Fetch synchronized resource mappings with optional filters and pagination for migration mappings view.
 * @complexity 3
 * @data_contract Input[QueryParams] -> Output[Dict[str, Any]]
 * @post Returns {"items": [...], "total": int} where items reflect applied filters and pagination.
 * @pre skip>=0, 1<=limit<=500, DB session is active, requester has READ permission.
 * @side_effect Executes database read queries against ResourceMapping table.
 */

// --- trigger_sync_now (backend/src/api/routes/migration.py)
/**!
 * @brief Trigger immediate ID synchronization for every configured environment.
 * @complexity 3
 * @data_contract Input[None] -> Output[Dict[str, Any]]
 * @post Returns sync summary with synced/failed counts after attempting all environments.
 * @pre At least one environment is configured and requester has EXECUTE permission.
 * @side_effect Upserts Environment rows, commits DB transaction, performs network sync calls, and writes logs.
 */

// --- PluginsRouter (backend/src/api/routes/plugins.py)
/**!
 * @brief Defines the FastAPI router for plugin-related endpoints, allowing clients to list available plugins.
 * @complexity 3
 * @layer API
 */

// --- list_plugins (backend/src/api/routes/plugins.py)
/**!
 * @brief Retrieve a list of all available plugins.
 * @post Returns a list of PluginConfig objects.
 * @pre plugin_loader is injected via Depends.
 */

// --- ProfileApiModule (backend/src/api/routes/profile.py)
/**!
 * @brief Exposes self-scoped profile preference endpoints and environment-based Superset account lookup.
 * @complexity 5
 * @invariant Endpoints are self-scoped and never mutate another user preference.
 * @layer API
 * @post Profile endpoints registered
 * @pre Auth middleware configured, database session available
 */

// --- _get_profile_service (backend/src/api/routes/profile.py)
/**!
 * @brief Build profile service for current request scope.
 * @post Returns a ready ProfileService instance.
 * @pre db session and config manager are available.
 */

// --- get_preferences (backend/src/api/routes/profile.py)
/**!
 * @brief Get authenticated user's dashboard filter preference.
 * @post Returns preference payload for current user only.
 * @pre Valid JWT and authenticated user context.
 */

// --- update_preferences (backend/src/api/routes/profile.py)
/**!
 * @brief Update authenticated user's dashboard filter preference.
 * @post Persists normalized preference for current user or raises validation/authorization errors.
 * @pre Valid JWT and valid request payload.
 */

// --- lookup_superset_accounts (backend/src/api/routes/profile.py)
/**!
 * @brief Lookup Superset account candidates in selected environment.
 * @post Returns success or degraded lookup payload with stable shape.
 * @pre Valid JWT, authenticated context, and environment_id query parameter.
 */

// --- ReportsRouter (backend/src/api/routes/reports.py)
/**!
 * @brief FastAPI router for unified task report list and detail retrieval endpoints.
 * @complexity 5
 * @data_contract [ReportQuery] -> [ReportCollection | ReportDetailView]
 * @invariant Endpoints are read-only and do not trigger long-running tasks.
 * @layer API
 * @post Router is configured and endpoints are ready for registration.
 * @pre Reports service and dependencies are initialized.
 * @side_effect None
 */

// --- _parse_csv_enum_list (backend/src/api/routes/reports.py)
/**!
 * @brief Parse comma-separated query value into enum list.
 * @complexity 1
 * @post Returns enum list or raises HTTP 400 with deterministic machine-readable payload.
 * @pre raw may be None/empty or comma-separated values.
 */

// --- list_reports (backend/src/api/routes/reports.py)
/**!
 * @brief Return paginated unified reports list.
 * @complexity 2
 * @post deterministic error payload for invalid filters.
 * @pre authenticated/authorized request and validated query params.
 * @test_contract ListReportsApi ->
 */

// --- get_report_detail (backend/src/api/routes/reports.py)
/**!
 * @brief Return one normalized report detail with diagnostics and next actions.
 * @complexity 2
 * @post returns normalized detail envelope or 404 when report is not found.
 * @pre authenticated/authorized request and existing report_id.
 */

// --- SettingsRouter (backend/src/api/routes/settings.py)
/**!
 * @brief Provides API endpoints for managing application settings and Superset environments.
 * @complexity 5
 * @data_contract Input -> ConfigUpdateRequest, Output -> AppConfig, LoggingConfigResponse
 * @invariant All settings changes must be persisted via ConfigManager.
 * @layer API
 * @post Settings are read or written via ConfigManager.
 * @pre ConfigManager is initialized and accessible.
 * @public_api router
 * @side_effect Persists config changes to disk via ConfigManager.
 */

// --- LoggingConfigResponse (backend/src/api/routes/settings.py)
/**!
 * @brief Response model for logging configuration with current task log level.
 * @complexity 1
 */

// --- _validate_superset_connection_fast (backend/src/api/routes/settings.py)
/**!
 * @brief Run lightweight Superset connectivity validation without full pagination scan.
 * @complexity 2
 * @post Raises on auth/API failures; returns None on success.
 * @pre env contains valid URL and credentials.
 */

// --- get_settings (backend/src/api/routes/settings.py)
/**!
 * @brief Retrieves all application settings.
 * @complexity 2
 * @post Returns masked AppConfig.
 * @pre Config manager is available.
 */

// --- get_features (backend/src/api/routes/settings.py)
/**!
 * @brief Public endpoint returning feature flags for frontend sidebar filtering.
 * @complexity 1
 * @post Returns dict with dataset_review and health_monitor booleans.
 * @pre Config manager is available.
 * @rationale Unauthenticated because sidebar filtering must work for all users, not just admins.
 */

// --- get_storage_settings (backend/src/api/routes/settings.py)
/**!
 * @brief Retrieves storage-specific settings.
 * @complexity 2
 */

// --- update_storage_settings (backend/src/api/routes/settings.py)
/**!
 * @brief Updates storage-specific settings.
 * @complexity 2
 * @post Storage settings are updated and saved.
 */

// --- test_environment_connection (backend/src/api/routes/settings.py)
/**!
 * @brief Tests the connection to a Superset environment.
 * @complexity 2
 * @post Returns success or error status.
 * @pre ID is provided.
 */

// --- get_logging_config (backend/src/api/routes/settings.py)
/**!
 * @brief Retrieves current logging configuration.
 * @complexity 2
 * @post Returns logging configuration.
 * @pre Config manager is available.
 */

// --- update_logging_config (backend/src/api/routes/settings.py)
/**!
 * @brief Updates logging configuration.
 * @complexity 2
 * @post Logging configuration is updated and saved.
 * @pre New logging config is provided.
 */

// --- ConsolidatedSettingsResponse (backend/src/api/routes/settings.py)
/**!
 * @brief Response model for consolidated application settings.
 * @complexity 1
 */

// --- get_consolidated_settings (backend/src/api/routes/settings.py)
/**!
 * @brief Retrieves all settings categories in a single call.
 * @complexity 4
 * @data_contract Input[ConfigManager] -> Output[ConsolidatedSettingsResponse]
 * @post Returns consolidated settings, provider metadata, and persisted notification payload in one stable response.
 * @pre Config manager is available and the caller holds admin settings read permission.
 * @side_effect Opens one database session to read LLM providers and config-backed notification payload, then closes it.
 */

// --- update_consolidated_settings (backend/src/api/routes/settings.py)
/**!
 * @brief Bulk update application settings from the consolidated view.
 * @complexity 2
 * @post Settings are updated and saved via ConfigManager.
 * @pre User has admin permissions, config is valid.
 */

// --- get_validation_policies (backend/src/api/routes/settings.py)
/**!
 * @brief Lists all validation policies.
 * @complexity 2
 */

// --- create_validation_policy (backend/src/api/routes/settings.py)
/**!
 * @brief Creates a new validation policy.
 * @complexity 2
 */

// --- update_validation_policy (backend/src/api/routes/settings.py)
/**!
 * @brief Updates an existing validation policy.
 * @complexity 2
 */

// --- delete_validation_policy (backend/src/api/routes/settings.py)
/**!
 * @brief Deletes a validation policy.
 * @complexity 2
 */

// --- get_translation_schedules (backend/src/api/routes/settings.py)
/**!
 * @brief Lists all translation schedules joined with translation job names.
 * @complexity 2
 */

// --- storage_routes (backend/src/api/routes/storage.py)
/**!
 * @brief API endpoints for file storage management (backups and repositories).
 * @complexity 5
 * @invariant All paths must be validated against path traversal.
 * @layer API
 */

// --- list_files (backend/src/api/routes/storage.py)
/**!
 * @brief List all files and directories in the storage system.
 * @complexity 3
 * @post Returns a list of StoredFile objects.
 * @pre None.
 */

// --- delete_file (backend/src/api/routes/storage.py)
/**!
 * @brief Delete a specific file or directory.
 * @complexity 3
 * @post Item is removed from storage.
 * @pre category must be a valid FileCategory.
 * @side_effect Deletes item from the filesystem.
 */

// --- download_file (backend/src/api/routes/storage.py)
/**!
 * @brief Retrieve a file for download.
 * @complexity 3
 * @post Returns a FileResponse.
 * @pre category must be a valid FileCategory.
 */

// --- get_file_by_path (backend/src/api/routes/storage.py)
/**!
 * @brief Retrieve a file by validated absolute/relative path under storage root.
 * @complexity 3
 * @post Returns a FileResponse for existing files.
 * @pre path must resolve under configured storage root.
 */

// --- TasksRouter (backend/src/api/routes/tasks.py)
/**!
 * @brief Defines the FastAPI router for task-related endpoints, allowing clients to create, list, and get the status of tasks.
 * @complexity 3
 * @layer API
 */

// --- resume_task (backend/src/api/routes/tasks.py)
/**!
 * @brief Resume a task that is awaiting input (e.g., passwords).
 * @complexity 2
 * @post Task resumes execution with provided input.
 * @pre task must be in AWAITING_INPUT status.
 */

// --- TranslateRoutes (backend/src/api/routes/translate/__init__.py)
/**!
 * @brief API routes for LLM-based SQL/dashboard translation management including terminology dictionary CRUD and import.
 * @complexity 4
 * @layer API
 * @post Translation job, run, dictionary, correction, preview, and schedule CRUD operations are executed.
 * @pre API server is running, user is authenticated, database is accessible.
 * @rationale Snapshot isolation — in-progress runs use config snapshot; config edits affect future runs only.
 * @rejected Invalidating in-progress runs on config edit would break scheduled run continuity.
 * @side_effect Creates/modifies DB rows; triggers background translation runs; queries Superset API.
 */

// --- TranslateCorrectionRoutesModule (backend/src/api/routes/translate/_correction_routes.py)
/**!
 * @brief Term correction submission endpoints.
 * @complexity 2
 * @layer API
 */

// --- submit_correction (backend/src/api/routes/translate/_correction_routes.py)
/**!
 * @brief Submit a term correction from a run result review.
 * @complexity 4
 * @post Correction applied with conflict detection.
 * @pre User has translate.dictionary.edit permission.
 * @side_effect Creates/updates DictionaryEntry row; commits.
 */

// --- submit_bulk_corrections (backend/src/api/routes/translate/_correction_routes.py)
/**!
 * @brief Submit multiple term corrections atomically.
 * @complexity 4
 * @post All corrections applied or none with conflict list.
 * @pre User has translate.dictionary.edit permission.
 * @side_effect Creates/updates DictionaryEntry rows; commits once.
 */

// --- TranslateDictionaryRoutesModule (backend/src/api/routes/translate/_dictionary_routes.py)
/**!
 * @brief Terminology Dictionary CRUD, entries management, and import routes.
 * @complexity 3
 * @layer API
 */

// --- list_dictionaries (backend/src/api/routes/translate/_dictionary_routes.py)
/**!
 * @brief List all terminology dictionaries.
 * @complexity 4
 * @post Returns list of dictionaries with total count.
 * @pre User has translate.dictionary.view permission.
 */

// --- get_dictionary (backend/src/api/routes/translate/_dictionary_routes.py)
/**!
 * @brief Get a single terminology dictionary by ID.
 * @complexity 4
 * @post Returns the dictionary with entry_count.
 * @pre User has translate.dictionary.view permission.
 */

// --- create_dictionary (backend/src/api/routes/translate/_dictionary_routes.py)
/**!
 * @brief Create a new terminology dictionary.
 * @complexity 4
 * @post Returns the created dictionary.
 * @pre User has translate.dictionary.create permission.
 */

// --- update_dictionary (backend/src/api/routes/translate/_dictionary_routes.py)
/**!
 * @brief Update an existing terminology dictionary.
 * @complexity 4
 * @post Returns the updated dictionary.
 * @pre User has translate.dictionary.edit permission.
 */

// --- delete_dictionary (backend/src/api/routes/translate/_dictionary_routes.py)
/**!
 * @brief Delete a terminology dictionary, blocked if attached to active/scheduled jobs.
 * @complexity 4
 * @post Dictionary is deleted.
 * @pre User has translate.dictionary.delete permission.
 */

// --- list_dictionary_entries (backend/src/api/routes/translate/_dictionary_routes.py)
/**!
 * @brief List entries for a dictionary, optionally filtered by language pair.
 * @complexity 4
 * @post Returns paginated list of entries with language pair fields.
 * @pre User has translate.dictionary.view permission.
 */

// --- add_dictionary_entry (backend/src/api/routes/translate/_dictionary_routes.py)
/**!
 * @brief Add a new entry to a dictionary.
 * @complexity 4
 * @post Entry is created.
 * @pre User has translate.dictionary.edit permission.
 */

// --- edit_dictionary_entry (backend/src/api/routes/translate/_dictionary_routes.py)
/**!
 * @brief Update an existing dictionary entry.
 * @complexity 4
 * @post Entry is updated.
 * @pre User has translate.dictionary.edit permission.
 */

// --- delete_dictionary_entry (backend/src/api/routes/translate/_dictionary_routes.py)
/**!
 * @brief Delete a dictionary entry.
 * @complexity 4
 * @post Entry is deleted.
 * @pre User has translate.dictionary.edit permission.
 */

// --- import_dictionary_entries (backend/src/api/routes/translate/_dictionary_routes.py)
/**!
 * @brief Import entries into a terminology dictionary from CSV/TSV content.
 * @complexity 4
 * @post Entries are imported per conflict mode.
 * @pre User has translate.dictionary.edit permission.
 */

// --- TranslateHelpersModule (backend/src/api/routes/translate/_helpers.py)
/**!
 * @brief Shared helper functions for translate route handlers.
 * @complexity 2
 * @layer API
 */

// --- _run_to_response (backend/src/api/routes/translate/_helpers.py)
/**!
 * @brief Convert TranslationRun ORM to response dict.
 * @complexity 2
 */

// --- _dict_to_response (backend/src/api/routes/translate/_helpers.py)
/**!
 * @brief Convert a TerminologyDictionary ORM model to a response dict with computed entry_count.
 * @complexity 2
 */

// --- _get_dictionary_entry_counts (backend/src/api/routes/translate/_helpers.py)
/**!
 * @brief Get entry counts for a list of dictionary IDs.
 * @complexity 2
 */

// --- TranslateJobRoutesModule (backend/src/api/routes/translate/_job_routes.py)
/**!
 * @brief Translation Job CRUD and datasource column routes.
 * @complexity 3
 * @layer API
 */

// --- list_jobs (backend/src/api/routes/translate/_job_routes.py)
/**!
 * @brief List all translation jobs.
 * @complexity 4
 * @post Returns list of translation jobs.
 * @pre User has translate.job.view permission.
 */

// --- get_job (backend/src/api/routes/translate/_job_routes.py)
/**!
 * @brief Get a single translation job by ID.
 * @complexity 4
 * @post Returns the translation job.
 * @pre User has translate.job.view permission.
 */

// --- create_job (backend/src/api/routes/translate/_job_routes.py)
/**!
 * @brief Create a new translation job.
 * @complexity 4
 * @post Returns the created translation job.
 * @pre User has translate.job.create permission.
 * @side_effect Validates columns via SupersetClient; caches database_dialect.
 */

// --- update_job (backend/src/api/routes/translate/_job_routes.py)
/**!
 * @brief Update an existing translation job.
 * @complexity 4
 * @post Returns the updated translation job.
 * @pre User has translate.job.edit permission.
 * @side_effect Re-detects database_dialect if datasource changed.
 */

// --- delete_job (backend/src/api/routes/translate/_job_routes.py)
/**!
 * @brief Delete a translation job.
 * @complexity 4
 * @post Job is deleted.
 * @pre User has translate.job.delete permission.
 */

// --- duplicate_job (backend/src/api/routes/translate/_job_routes.py)
/**!
 * @brief Duplicate a translation job.
 * @complexity 4
 * @post Returns the duplicated job with status DRAFT.
 * @pre User has translate.job.create permission.
 */

// --- get_datasource_columns (backend/src/api/routes/translate/_job_routes.py)
/**!
 * @brief Get column metadata and database dialect for a Superset datasource.
 * @complexity 4
 * @post Returns column list with metadata and database_dialect.
 * @pre User has translate.job.view permission.
 * @rationale Dialect detection from Superset connection cached on TranslationJob at save time.
 * @rejected Hardcoding dialect list per database — would drift from actual Superset config.
 * @side_effect Queries Superset API for dataset detail and database info.
 */

// --- check_target_schema (backend/src/api/routes/translate/_job_routes.py)
/**!
 * @brief Проверяет схему целевой таблицы: какие колонки ожидаются, какие есть, каких не хватает.
 * @complexity 3
 * @rationale Позволяет UI показать пользователю подсказку о недостающих колонках
 */

// --- TranslateMetricsRoutesModule (backend/src/api/routes/translate/_metrics_routes.py)
/**!
 * @brief Translation Metrics endpoints.
 * @complexity 2
 * @layer API
 */

// --- get_metrics (backend/src/api/routes/translate/_metrics_routes.py)
/**!
 * @brief Get translation metrics, optionally filtered by job.
 * @complexity 4
 * @post Returns metrics data.
 * @pre User has translate.metrics.view permission.
 */

// --- get_job_metrics (backend/src/api/routes/translate/_metrics_routes.py)
/**!
 * @brief Get aggregated metrics for a specific job.
 * @complexity 4
 * @post Returns metrics dict.
 * @pre User has translate.metrics.view permission.
 */

// --- TranslatePreviewRoutesModule (backend/src/api/routes/translate/_preview_routes.py)
/**!
 * @brief Translation Preview session management routes.
 * @complexity 3
 * @layer API
 */

// --- preview_translation (backend/src/api/routes/translate/_preview_routes.py)
/**!
 * @brief Preview a translation before applying it.
 * @complexity 4
 * @post Returns a preview session with records and cost estimation.
 * @pre User has translate.job.execute permission.
 * @side_effect Fetches sample data from Superset; calls LLM provider; creates DB rows.
 */

// --- update_preview_row (backend/src/api/routes/translate/_preview_routes.py)
/**!
 * @brief Approve, edit, or reject a preview row (optionally per language).
 * @complexity 4
 * @post Preview row status is updated.
 * @pre User has translate.job.execute permission.
 */

// --- accept_preview_session (backend/src/api/routes/translate/_preview_routes.py)
/**!
 * @brief Accept a preview session, marking it as the quality gate for full execution.
 * @complexity 4
 * @post Preview session is marked as APPLIED; full execution can proceed.
 * @pre User has translate.job.execute permission. Job has an ACTIVE preview session.
 */

// --- apply_preview (backend/src/api/routes/translate/_preview_routes.py)
/**!
 * @brief Apply a preview session (alias for accept when accepting at session level).
 * @complexity 4
 * @post Preview is applied.
 * @pre User has translate.job.execute permission.
 */

// --- get_preview_records (backend/src/api/routes/translate/_preview_routes.py)
/**!
 * @brief Get records for a preview session.
 * @complexity 4
 * @post Returns list of preview records.
 * @pre User has translate.job.view permission.
 */

// --- TranslateRouterModule (backend/src/api/routes/translate/_router.py)
/**!
 * @brief APIRouter instance for translate routes.
 * @complexity 1
 * @layer API
 */

// --- translate_router (backend/src/api/routes/translate/_router.py)
/**!
 * @brief APIRouter instance for all translate sub-routes.
 */

// --- TranslateRunListRoutesModule (backend/src/api/routes/translate/_run_list_routes.py)
/**!
 * @brief Translation Run listing, detail, and CSV download routes (cross-job).
 * @complexity 3
 * @layer API
 */

// --- download_skipped_csv (backend/src/api/routes/translate/_run_list_routes.py)
/**!
 * @brief Download a CSV of skipped translation records from a run.
 * @complexity 4
 * @post Returns CSV file of skipped records.
 * @pre User has translate.job.view permission.
 */

// --- TranslateRunRoutesModule (backend/src/api/routes/translate/_run_routes.py)
/**!
 * @brief Translation Run execution, history, status, records and batches routes.
 * @complexity 3
 * @layer API
 */

// --- run_translation (backend/src/api/routes/translate/_run_routes.py)
/**!
 * @brief Execute a translation job (trigger a run).
 * @complexity 4
 * @post Returns the created translation run.
 * @pre User has translate.job.execute permission.
 */

// --- retry_run (backend/src/api/routes/translate/_run_routes.py)
/**!
 * @brief Retry failed batches in a translation run.
 * @complexity 4
 * @post Returns the updated translation run.
 * @pre User has translate.job.execute permission.
 */

// --- retry_insert (backend/src/api/routes/translate/_run_routes.py)
/**!
 * @brief Retry the SQL insert phase for a completed run.
 * @complexity 4
 * @post Returns the updated run.
 * @pre User has translate.job.execute permission.
 */

// --- cancel_run (backend/src/api/routes/translate/_run_routes.py)
/**!
 * @brief Cancel a running translation.
 * @complexity 4
 * @post Run is cancelled.
 * @pre User has translate.job.execute permission.
 */

// --- get_run_history (backend/src/api/routes/translate/_run_routes.py)
/**!
 * @brief Get run history for a translation job.
 * @complexity 4
 * @post Returns list of runs.
 * @pre User has translate.history.view permission.
 */

// --- get_run_status (backend/src/api/routes/translate/_run_routes.py)
/**!
 * @brief Get status and statistics for a translation run.
 * @complexity 4
 * @post Returns run details with statistics.
 * @pre User has translate.history.view permission.
 */

// --- get_run_records (backend/src/api/routes/translate/_run_routes.py)
/**!
 * @brief Get paginated records for a translation run.
 * @complexity 4
 * @post Returns paginated records.
 * @pre User has translate.history.view permission.
 */

// --- get_batches (backend/src/api/routes/translate/_run_routes.py)
/**!
 * @brief Get batches for a translation run.
 * @complexity 4
 * @post Returns list of batches.
 * @pre User has translate.job.view permission.
 */

// --- override_detected_language (backend/src/api/routes/translate/_run_routes.py)
/**!
 * @brief Manually override the detected source language for a specific translation language entry.
 * @complexity 4
 * @post TranslationLanguage.source_language_detected is updated; language_overridden is set to True.
 * @pre User has translate.job.execute permission. Run, record, and language entry exist.
 * @side_effect DB write.
 */

// --- inline_edit_translation (backend/src/api/routes/translate/_run_routes.py)
/**!
 * @brief Apply an inline correction to a translated value on a completed run result.
 * @complexity 4
 * @post TranslationLanguage.final_value and user_edit are updated. Optional dictionary submission.
 * @pre User has translate.job.execute permission. Run, record, and language entry exist.
 */

// --- bulk_find_replace (backend/src/api/routes/translate/_run_routes.py)
/**!
 * @brief Perform bulk find-and-replace on translated values within a run.
 * @complexity 4
 * @post If preview=false, matching translations are updated. Optional dictionary submission.
 * @pre User has translate.job.execute permission. Run exists.
 */

// --- TranslateScheduleRoutesModule (backend/src/api/routes/translate/_schedule_routes.py)
/**!
 * @brief Translation Schedule management routes.
 * @complexity 3
 * @layer API
 */

// --- get_schedule (backend/src/api/routes/translate/_schedule_routes.py)
/**!
 * @brief Get the schedule for a translation job.
 * @complexity 4
 * @post Returns the schedule configuration.
 * @pre User has translate.schedule.view permission.
 */

// --- set_schedule (backend/src/api/routes/translate/_schedule_routes.py)
/**!
 * @brief Set or update the schedule for a translation job.
 * @complexity 4
 * @post Schedule is created or updated.
 * @pre User has translate.schedule.manage permission.
 */

// --- enable_schedule (backend/src/api/routes/translate/_schedule_routes.py)
/**!
 * @brief Enable a schedule for a translation job.
 * @complexity 4
 * @post Schedule is enabled.
 * @pre User has translate.schedule.manage permission.
 */

// --- disable_schedule (backend/src/api/routes/translate/_schedule_routes.py)
/**!
 * @brief Disable a schedule for a translation job.
 * @complexity 4
 * @post Schedule is disabled.
 * @pre User has translate.schedule.manage permission.
 */

// --- delete_schedule (backend/src/api/routes/translate/_schedule_routes.py)
/**!
 * @brief Delete the schedule for a translation job.
 * @complexity 4
 * @post Schedule is removed.
 * @pre User has translate.schedule.manage permission.
 */

// --- get_next_executions (backend/src/api/routes/translate/_schedule_routes.py)
/**!
 * @brief Preview next N executions for a job's schedule.
 * @complexity 4
 * @post Returns next execution times.
 * @pre User has translate.schedule.view permission.
 */

// --- ValidationRoutes (backend/src/api/routes/validation.py)
/**!
 * @brief API routes for validation task management and run history.
 * @complexity 3
 * @layer API
 */

// --- _get_task_service (backend/src/api/routes/validation.py)
/**!
 * @complexity 1
 */

// --- _get_run_service (backend/src/api/routes/validation.py)
/**!
 * @complexity 1
 */

// --- list_tasks (backend/src/api/routes/validation.py)
/**!
 * @complexity 4
 * @rationale Route handler delegates to service with permission check — keeps API layer thin and testable; auth gate happens before any business logic.
 * @rejected Business logic in route handler rejected — would duplicate validation logic and make permission checks harder to audit.
 */

// --- update_task (backend/src/api/routes/validation.py)
/**!
 * @complexity 4
 * @rationale PUT semantics for full resource update — consistent with existing API patterns; Pydantic's exclude_unset handles partial updates while keeping PUT as the endpoint verb.
 * @rejected PATCH semantics rejected — using PUT with exclude_unset provides the same partial-update flexibility without introducing a second HTTP method for the same resource.
 */

// --- delete_task (backend/src/api/routes/validation.py)
/**!
 * @complexity 4
 * @rationale DELETE returns 204 No Content per REST convention — minimizes response payload for delete operations; supports optional delete_runs query param for cascade control.
 * @rejected Returning deleted resource in response body rejected — unnecessary data transfer; 204 with no body is the REST standard for delete operations.
 */

// --- trigger_run (backend/src/api/routes/validation.py)
/**!
 * @complexity 4
 * @rationale Returns spawned task ID so frontend can poll for completion — enables progress tracking without WebSocket. Async spawn is essential since LLM validation can take 30+ seconds.
 * @rejected Blocking until run completes rejected — LLM-based validation is slow (30-120s); synchronous wait would timeout HTTP requests and create terrible UX.
 */

// --- list_runs (backend/src/api/routes/validation.py)
/**!
 * @complexity 4
 * @rationale Exposes 6 query parameters for cross-task run filtering — matches the run service's filter capabilities exactly, enabling flexible history exploration.
 * @rejected Fixed filter set rejected — would limit the history page's debugging use cases; users need to filter by task, status, dashboard, environment, and date range.
 */

// --- get_run_detail (backend/src/api/routes/validation.py)
/**!
 * @complexity 4
 * @rationale Returns full run detail including issues list and raw response for the report view — single endpoint serves the complete detail page without multiple fetches.
 * @rejected Paginated issues endpoint rejected — issues per run are typically < 20 items; pagination overhead is unnecessary for such small collections.
 */

// --- delete_run (backend/src/api/routes/validation.py)
/**!
 * @complexity 3
 * @rationale Returns 404 when run not found — explicit error handling rather than silent success; helps frontend distinguish between successful delete and missing resource.
 * @rejected Silent success on missing run rejected — would mask bugs in the UI that reference already-deleted runs; explicit 404 helps debugging.
 */

// --- ValidationApiTests (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief Unit tests for validation task CRUD and run history API endpoints.
 * @complexity 3
 * @invariant provider_id must reference a multimodal LLM provider for creation
 * @layer API
 * @test_contract [ValidationTaskCreate|Update|RunRequest] -> [ValidationTaskResponse|RunResponse|TriggerRunResponse]
 * @test_edge delete_task_with_runs -> 204 with delete_runs=true flag
 * @test_scenario delete_run -> 204 on success; 404 for nonexistent
 */

// --- test_list_tasks_success (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief GET /validation/tasks returns paginated task list with filters.
 * @complexity 2
 */

// --- test_list_tasks_pagination (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief Pagination query params are validated: page >= 1, page_size 1-100.
 * @complexity 2
 */

// --- test_list_tasks_service_error (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief Service ValueError becomes 400 on list_tasks.
 * @complexity 2
 */

// --- test_create_task_success (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief POST /validation/tasks with valid payload returns 201.
 * @complexity 2
 */

// --- test_create_task_missing_fields (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief POST with missing required fields returns 422.
 * @complexity 2
 */

// --- test_create_task_invalid_provider (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief POST with non-multimodal provider returns 422.
 * @complexity 2
 */

// --- test_get_task_success (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief GET /validation/tasks/{id} returns task with recent_runs.
 * @complexity 2
 */

// --- test_get_task_not_found (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief GET for nonexistent task returns 404.
 * @complexity 2
 */

// --- test_update_task_success (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief PUT /validation/tasks/{id} updates task and returns updated object.
 * @complexity 2
 */

// --- test_update_task_not_found (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief PUT for nonexistent task returns 404.
 * @complexity 2
 */

// --- test_delete_task_success (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief DELETE /validation/tasks/{id} returns 204.
 * @complexity 2
 */

// --- test_delete_task_not_found (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief DELETE for nonexistent task returns 404.
 * @complexity 2
 */

// --- test_delete_task_with_runs_flag (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief DELETE with delete_runs=true passes query param to service.
 * @complexity 2
 */

// --- test_trigger_run_success (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief POST /validation/tasks/{id}/run spawns a validation task.
 * @complexity 2
 */

// --- test_trigger_run_not_found (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief POST for nonexistent task returns 422.
 * @complexity 2
 */

// --- test_trigger_run_no_dashboards (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief Trigger fails with 422 when task has no dashboard IDs.
 * @complexity 2
 */

// --- test_list_runs_success (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief GET /validation/runs returns paginated run list.
 * @complexity 2
 */

// --- test_list_runs_filters (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief All 6 filter query params are accepted and forwarded to service.
 * @complexity 2
 */

// --- test_list_runs_pagination (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief Pagination boundary checks on runs list.
 * @complexity 2
 */

// --- test_list_runs_invalid_status (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief Status is a free string; any value passes through to service.
 * @complexity 2
 */

// --- test_get_run_detail_success (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief GET /validation/runs/{id} returns full detail with issues and raw_response.
 * @complexity 2
 */

// --- test_get_run_detail_not_found (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief GET for nonexistent run returns 404.
 * @complexity 2
 */

// --- test_delete_run_success (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief DELETE /validation/runs/{id} returns 204.
 * @complexity 2
 */

// --- test_delete_run_not_found (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief DELETE for nonexistent run returns 404.
 * @complexity 2
 */

// --- test_endpoints_require_authentication (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief Without current_user dependency, all 9 endpoints return 401.
 * @complexity 2
 */

// --- test_permission_denied_non_admin (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief A non-admin user without validation.* permissions receives 403.
 * @complexity 2
 */

// --- test_permission_denied_all_actions (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief Each action (VIEW, CREATE, EDIT, DELETE, EXECUTE) denied for non-admin.
 * @complexity 2
 */

// --- test_delete_task_runs_default_false (backend/src/api/routes/validation/__tests__/test_validation_api.py)
/**!
 * @brief delete_runs query param defaults to False.
 * @complexity 2
 */

// --- AppModule (backend/src/app.py)
/**!
 * @brief The main entry point for the FastAPI application.
 * @complexity 5
 * @data_contract [HTTP Request | WS Message] -> [HTTP Response | JSON Log Stream]
 * @invariant All WebSocket connections must be properly cleaned up on disconnect.
 * @layer API
 * @post FastAPI app instance is created, middleware configured, and routes registered.
 * @pre Python environment and dependencies installed; configuration database available.
 * @rationale Duplicate @RELATION and @INVARIANT lines removed from header. Import sorting unified via ruff isort (I) rule across src/ — 139 fixes applied.
 * @side_effect Starts background scheduler and binds network ports for HTTP/WS traffic.
 */

// --- FastAPI_App (backend/src/app.py)
/**!
 * @brief Canonical FastAPI application instance for route, middleware, and websocket registration.
 * @complexity 3
 */

// --- ensure_initial_admin_user (backend/src/app.py)
/**!
 * @brief Ensures initial admin user exists when bootstrap env flags are enabled.
 * @complexity 3
 */

// --- startup_event (backend/src/app.py)
/**!
 * @brief Handles application startup tasks, such as starting the scheduler.
 * @complexity 3
 * @post Scheduler is started.
 * @pre None.
 */

// --- shutdown_event (backend/src/app.py)
/**!
 * @brief Handles application shutdown tasks, such as stopping the scheduler.
 * @complexity 3
 * @post Scheduler is stopped.
 * @pre None.
 */

// --- app_middleware (backend/src/app.py)
/**!
 * @brief Configure application-wide middleware (Session, CORS).
 * @rationale CORS allow_origins reads from ALLOWED_ORIGINS env var instead of hardcoded "*".
 */

// --- network_error_handler (backend/src/app.py)
/**!
 * @brief Global exception handler for NetworkError.
 * @complexity 1
 * @post Returns 503 HTTP Exception.
 * @pre request is a FastAPI Request object.
 */

// --- log_requests (backend/src/app.py)
/**!
 * @brief Middleware to log incoming HTTP requests and their response status.
 * @complexity 3
 * @post Logs request and response details.
 * @pre request is a FastAPI Request object.
 */

// --- API_Routes (backend/src/app.py)
/**!
 * @brief Register all FastAPI route groups exposed by the application entrypoint.
 * @complexity 3
 */

// --- api.include_routers (backend/src/app.py)
/**!
 * @brief Registers all API routers with the FastAPI application.
 * @complexity 1
 * @layer API
 */

// --- websocket_endpoint (backend/src/app.py)
/**!
 * @brief Provides a WebSocket endpoint for real-time log streaming of a task with server-side filtering.
 * @complexity 5
 * @data_contract [task_id: str, source: str, level: str] -> [JSON log entry objects]
 * @invariant Every accepted WebSocket subscription is unsubscribed exactly once even when streaming fails or the client disconnects.
 * @post WebSocket connection is managed and logs are streamed until disconnect.
 * @pre task_id must be a valid task ID.
 * @side_effect Subscribes to TaskManager log queue and broadcasts messages over network.
 * @test_contract WebSocketLogStreamApi ->
 * @ux_state Connecting -> Streaming -> (Disconnected)
 */

// --- dataset_websocket_endpoint (backend/src/app.py)
/**!
 * @brief WebSocket endpoint for dataset.updated events — auto-refresh on task completion.
 * @complexity 4
 * @post WebSocket streams dataset.updated events until disconnect.
 * @pre env_id must reference a known environment.
 * @side_effect Subscribes to dataset event queue in task manager lifecycle.
 */

// --- StaticFiles (backend/src/app.py)
/**!
 * @brief Mounts the frontend build directory to serve static assets.
 * @complexity 1
 */

// --- serve_spa (backend/src/app.py)
/**!
 * @brief Serves the SPA frontend for any path not matched by API routes.
 * @complexity 1
 * @post Returns the requested file or index.html.
 * @pre frontend_path exists.
 */

// --- read_root (backend/src/app.py)
/**!
 * @brief A simple root endpoint to confirm that the API is running when frontend is missing.
 * @complexity 1
 * @post Returns a JSON message indicating API status.
 * @pre None.
 */

// --- src.core (backend/src/core/__init__.py)
/**!
 * @brief Backend core services and infrastructure package root.
 */

// --- TestConfigManagerCompat (backend/src/core/__tests__/test_config_manager_compat.py)
/**!
 * @brief Verifies ConfigManager compatibility wrappers preserve legacy payload sections.
 * @complexity 3
 * @layer Domain
 */

// --- test_get_payload_preserves_legacy_sections (backend/src/core/__tests__/test_config_manager_compat.py)
/**!
 * @brief Ensure get_payload merges typed config into raw payload without dropping legacy sections.
 */

// --- test_save_config_accepts_raw_payload_and_keeps_extras (backend/src/core/__tests__/test_config_manager_compat.py)
/**!
 * @brief Ensure save_config accepts raw dict payload, refreshes typed config, and preserves extra sections.
 */

// --- test_save_config_syncs_environment_records_for_fk_backed_flows (backend/src/core/__tests__/test_config_manager_compat.py)
/**!
 * @brief Ensure saving config mirrors typed environments into relational records required by FK-backed session persistence.
 */

// --- _FakeQuery (backend/src/core/__tests__/test_config_manager_compat.py)
/**!
 * @brief Minimal query stub returning hardcoded existing environment record list for sync tests.
 * @complexity 1
 * @invariant all() always returns [existing_record]; no parameterization or filtering.
 */

// --- _FakeSession (backend/src/core/__tests__/test_config_manager_compat.py)
/**!
 * @brief Minimal SQLAlchemy session stub that captures add/delete calls for environment sync assertions.
 * @complexity 1
 * @invariant query() always returns _FakeQuery; no real DB interaction.
 */

// --- test_save_config_syncs_deletions_to_persistence (backend/src/core/__tests__/test_config_manager_compat.py)
/**!
 * @brief Ensure stale environment records are deleted during save (in _delete_stale_environment_records)
 */

// --- _FakeQueryDel (backend/src/core/__tests__/test_config_manager_compat.py)
/**!
 * @brief Minimal query stub for deletion test.
 * @complexity 1
 */

// --- _FakeSessionDel (backend/src/core/__tests__/test_config_manager_compat.py)
/**!
 * @brief Minimal session stub that captures add/delete for deletion assertions.
 * @complexity 1
 */

// --- test_load_config_syncs_environment_records_from_existing_db_payload (backend/src/core/__tests__/test_config_manager_compat.py)
/**!
 * @brief Ensure loading an existing DB-backed config also mirrors environment rows required by FK-backed runtime flows.
 */

// --- NativeFilterExtractionTests (backend/src/core/__tests__/test_native_filters.py)
/**!
 * @brief Verify native filter extraction from permalinks and native_filters_key URLs.
 * @complexity 3
 * @layer Domain
 */

// --- test_extract_native_filters_from_permalink (backend/src/core/__tests__/test_native_filters.py)
/**!
 * @brief Extract native filters from a permalink key.
 */

// --- test_extract_native_filters_from_permalink_direct_response (backend/src/core/__tests__/test_native_filters.py)
/**!
 * @brief Handle permalink response without result wrapper.
 */

// --- test_extract_native_filters_from_key (backend/src/core/__tests__/test_native_filters.py)
/**!
 * @brief Extract native filters from a native_filters_key.
 */

// --- test_extract_native_filters_from_key_single_filter (backend/src/core/__tests__/test_native_filters.py)
/**!
 * @brief Handle single filter format in native filter state.
 */

// --- test_extract_native_filters_from_key_dict_value (backend/src/core/__tests__/test_native_filters.py)
/**!
 * @brief Handle filter state value as dict instead of JSON string.
 */

// --- test_parse_dashboard_url_for_filters_permalink (backend/src/core/__tests__/test_native_filters.py)
/**!
 * @brief Parse permalink URL format.
 */

// --- test_parse_dashboard_url_for_filters_native_key (backend/src/core/__tests__/test_native_filters.py)
/**!
 * @brief Parse native_filters_key URL format with numeric dashboard ID.
 */

// --- test_parse_dashboard_url_for_filters_native_key_slug (backend/src/core/__tests__/test_native_filters.py)
/**!
 * @brief Parse native_filters_key URL format when dashboard reference is a slug, not a numeric ID.
 */

// --- test_parse_dashboard_url_for_filters_native_key_slug_resolution_fails (backend/src/core/__tests__/test_native_filters.py)
/**!
 * @brief Gracefully handle slug resolution failure for native_filters_key URL.
 */

// --- test_parse_dashboard_url_for_filters_native_filters_direct (backend/src/core/__tests__/test_native_filters.py)
/**!
 * @brief Parse native_filters direct query param.
 */

// --- test_parse_dashboard_url_for_filters_no_filters (backend/src/core/__tests__/test_native_filters.py)
/**!
 * @brief Return empty result when no filters present.
 */

// --- test_extra_form_data_merge (backend/src/core/__tests__/test_native_filters.py)
/**!
 * @brief Test ExtraFormDataMerge correctly merges dictionaries.
 */

// --- test_filter_state_model (backend/src/core/__tests__/test_native_filters.py)
/**!
 * @brief Test FilterState Pydantic model.
 */

// --- test_parsed_native_filters_model (backend/src/core/__tests__/test_native_filters.py)
/**!
 * @brief Test ParsedNativeFilters Pydantic model.
 */

// --- test_parsed_native_filters_empty (backend/src/core/__tests__/test_native_filters.py)
/**!
 * @brief Test ParsedNativeFilters with no filters.
 */

// --- test_native_filter_data_mask_model (backend/src/core/__tests__/test_native_filters.py)
/**!
 * @brief Test NativeFilterDataMask model.
 */

// --- test_recover_imported_filters_reconciles_raw_native_filter_ids_to_metadata_names (backend/src/core/__tests__/test_native_filters.py)
/**!
 * @brief Reconcile raw native filter ids from state to canonical metadata filter names.
 */

// --- test_recover_imported_filters_collapses_state_and_metadata_duplicates_into_one_canonical_filter (backend/src/core/__tests__/test_native_filters.py)
/**!
 * @brief Collapse raw-id state entries and metadata entries into one canonical filter.
 */

// --- test_recover_imported_filters_preserves_unmatched_raw_native_filter_ids (backend/src/core/__tests__/test_native_filters.py)
/**!
 * @brief Preserve unmatched raw native filter ids as fallback diagnostics when metadata mapping is unavailable.
 */

// --- test_extract_imported_filters_preserves_clause_level_native_filter_payload_for_preview (backend/src/core/__tests__/test_native_filters.py)
/**!
 * @brief Recovered native filter state should preserve exact Superset clause payload and time extras for preview compilation.
 */

// --- test_sanitize_imported_filter_for_assistant_masks_sensitive_raw_values (backend/src/core/__tests__/test_native_filters.py)
/**!
 * @brief Assistant-facing imported-filter payload should redact likely PII while preserving structure metadata.
 */

// --- SupersetPreviewPipelineTests (backend/src/core/__tests__/test_superset_preview_pipeline.py)
/**!
 * @brief Verify explicit chart-data preview compilation and ensure non-dashboard 404 errors remain generic across sync and async clients.
 * @complexity 3
 * @layer Domain
 */

// --- _make_environment (backend/src/core/__tests__/test_superset_preview_pipeline.py)
/**!
 */

// --- _make_requests_http_error (backend/src/core/__tests__/test_superset_preview_pipeline.py)
/**!
 */

// --- _make_httpx_status_error (backend/src/core/__tests__/test_superset_preview_pipeline.py)
/**!
 */

// --- test_compile_dataset_preview_prefers_legacy_explore_form_data_strategy (backend/src/core/__tests__/test_superset_preview_pipeline.py)
/**!
 * @brief Superset preview compilation should prefer the legacy form_data transport inferred from browser traffic before falling back to chart-data.
 */

// --- test_compile_dataset_preview_falls_back_to_chart_data_after_legacy_failures (backend/src/core/__tests__/test_superset_preview_pipeline.py)
/**!
 * @brief Superset preview compilation should fall back to chart-data when legacy form_data strategies are rejected.
 */

// --- test_build_dataset_preview_query_context_places_recovered_filters_in_chart_style_form_data (backend/src/core/__tests__/test_superset_preview_pipeline.py)
/**!
 * @brief Preview query context should mirror chart-style filter transport so recovered native filters reach Superset compilation.
 */

// --- test_build_dataset_preview_query_context_merges_dataset_template_params_and_preserves_user_values (backend/src/core/__tests__/test_superset_preview_pipeline.py)
/**!
 * @brief Preview query context should merge dataset template params for parity with real dataset definitions while preserving explicit session overrides.
 */

// --- test_build_dataset_preview_query_context_preserves_time_range_from_native_filter_payload (backend/src/core/__tests__/test_superset_preview_pipeline.py)
/**!
 * @brief Preview query context should preserve time-range native filter extras even when dataset defaults differ.
 */

// --- test_build_dataset_preview_legacy_form_data_preserves_native_filter_clauses (backend/src/core/__tests__/test_superset_preview_pipeline.py)
/**!
 * @brief Legacy preview form_data should preserve recovered native filter clauses in browser-style fields without duplicating datasource for QueryObjectFactory.
 */

// --- test_sync_network_404_mapping_keeps_non_dashboard_endpoints_generic (backend/src/core/__tests__/test_superset_preview_pipeline.py)
/**!
 * @brief Sync network client should reserve dashboard-not-found translation for dashboard endpoints only.
 */

// --- test_sync_network_404_mapping_translates_dashboard_endpoints (backend/src/core/__tests__/test_superset_preview_pipeline.py)
/**!
 * @brief Sync network client should still translate dashboard endpoint 404 responses into dashboard-not-found errors.
 */

// --- test_async_network_404_mapping_keeps_non_dashboard_endpoints_generic (backend/src/core/__tests__/test_superset_preview_pipeline.py)
/**!
 * @brief Async network client should reserve dashboard-not-found translation for dashboard endpoints only.
 */

// --- test_async_network_404_mapping_translates_dashboard_endpoints (backend/src/core/__tests__/test_superset_preview_pipeline.py)
/**!
 * @brief Async network client should still translate dashboard endpoint 404 responses into dashboard-not-found errors.
 */

// --- TestSupersetProfileLookup (backend/src/core/__tests__/test_superset_profile_lookup.py)
/**!
 * @brief Verifies Superset profile lookup adapter payload normalization and fallback error precedence.
 * @complexity 3
 * @layer Domain
 */

// --- _RecordingNetworkClient (backend/src/core/__tests__/test_superset_profile_lookup.py)
/**!
 * @brief Records request payloads and returns scripted responses for deterministic adapter tests.
 * @complexity 2
 * @invariant Each request consumes one scripted response in call order and persists call metadata.
 */

// --- test_get_users_page_sends_lowercase_order_direction (backend/src/core/__tests__/test_superset_profile_lookup.py)
/**!
 * @brief Ensures adapter sends lowercase order_direction compatible with Superset rison schema.
 * @post First request query payload contains order_direction='asc' for asc sort.
 * @pre Adapter is initialized with recording network client.
 */

// --- test_get_users_page_preserves_primary_schema_error_over_fallback_auth_error (backend/src/core/__tests__/test_superset_profile_lookup.py)
/**!
 * @brief Ensures fallback auth error does not mask primary schema/query failure.
 * @post Raised exception remains primary SupersetAPIError (non-auth) to preserve root cause.
 * @pre Primary endpoint fails with SupersetAPIError and fallback fails with AuthenticationError.
 */

// --- test_get_users_page_uses_fallback_endpoint_when_primary_fails (backend/src/core/__tests__/test_superset_profile_lookup.py)
/**!
 * @brief Verifies adapter retries second users endpoint and succeeds when fallback is healthy.
 * @post Result status is success and both endpoints were attempted in order.
 * @pre Primary endpoint fails; fallback returns valid users payload.
 */

// --- test_throttled_scheduler (backend/src/core/__tests__/test_throttled_scheduler.py)
/**!
 * @brief Unit tests for ThrottledSchedulerConfigurator distribution logic.
 * @complexity 3
 */

// --- test_calculate_schedule_even_distribution (backend/src/core/__tests__/test_throttled_scheduler.py)
/**!
 * @brief Validate even spacing across a two-hour scheduling window for three tasks.
 */

// --- test_calculate_schedule_midnight_crossing (backend/src/core/__tests__/test_throttled_scheduler.py)
/**!
 * @brief Validate scheduler correctly rolls timestamps into the next day across midnight.
 */

// --- test_calculate_schedule_single_task (backend/src/core/__tests__/test_throttled_scheduler.py)
/**!
 * @brief Validate single-task schedule returns only the window start timestamp.
 */

// --- test_calculate_schedule_empty_list (backend/src/core/__tests__/test_throttled_scheduler.py)
/**!
 * @brief Validate empty dashboard list produces an empty schedule.
 */

// --- test_calculate_schedule_zero_window (backend/src/core/__tests__/test_throttled_scheduler.py)
/**!
 * @brief Validate zero-length window schedules all tasks at identical start timestamp.
 */

// --- test_calculate_schedule_very_small_window (backend/src/core/__tests__/test_throttled_scheduler.py)
/**!
 * @brief Validate sub-second interpolation when task count exceeds near-zero window granularity.
 */

// --- AsyncSupersetClientModule (backend/src/core/async_superset_client.py)
/**!
 * @brief Parse a Superset dashboard URL and extract native filter state asynchronously.
 * @complexity 3
 * @layer Core
 */

// --- AsyncSupersetClient (backend/src/core/async_superset_client.py)
/**!
 * @brief Async sibling of SupersetClient for dashboard read paths.
 * @complexity 3
 */

// --- AsyncSupersetClientInit (backend/src/core/async_superset_client.py)
/**!
 * @brief Initialize async Superset client with AsyncAPIClient transport.
 * @complexity 3
 * @data_contract Input[Environment] -> self.network[AsyncAPIClient]
 * @post Client uses async network transport and inherited projection helpers.
 * @pre env is valid Environment instance.
 */

// --- AsyncSupersetClientClose (backend/src/core/async_superset_client.py)
/**!
 * @brief Close async transport resources.
 * @complexity 3
 * @post Underlying AsyncAPIClient is closed.
 * @side_effect Closes network sockets.
 */

// --- get_dashboards_page_async (backend/src/core/async_superset_client.py)
/**!
 * @brief Fetch one dashboards page asynchronously.
 * @complexity 3
 * @data_contract Input[query: Optional[Dict]] -> Output[Tuple[int, List[Dict]]]
 * @post Returns total count and page result list.
 */

// --- get_dashboard_async (backend/src/core/async_superset_client.py)
/**!
 * @brief Fetch one dashboard payload asynchronously.
 * @complexity 3
 * @data_contract Input[dashboard_id: int] -> Output[Dict]
 * @post Returns raw dashboard payload from Superset API.
 */

// --- get_chart_async (backend/src/core/async_superset_client.py)
/**!
 * @brief Fetch one chart payload asynchronously.
 * @complexity 3
 * @data_contract Input[chart_id: int] -> Output[Dict]
 * @post Returns raw chart payload from Superset API.
 */

// --- get_dashboard_detail_async (backend/src/core/async_superset_client.py)
/**!
 * @brief Fetch dashboard detail asynchronously with concurrent charts/datasets requests.
 * @complexity 3
 * @data_contract Input[dashboard_id: int] -> Output[Dict]
 * @post Returns dashboard detail payload for overview page.
 */

// --- get_dashboard_permalink_state_async (backend/src/core/async_superset_client.py)
/**!
 * @brief Fetch stored dashboard permalink state asynchronously.
 * @complexity 2
 * @data_contract Input[permalink_key: str] -> Output[Dict]
 * @post Returns dashboard permalink state payload from Superset API.
 */

// --- get_native_filter_state_async (backend/src/core/async_superset_client.py)
/**!
 * @brief Fetch stored native filter state asynchronously.
 * @complexity 2
 * @data_contract Input[dashboard_id: Union[int, str], filter_state_key: str] -> Output[Dict]
 * @post Returns native filter state payload from Superset API.
 */

// --- extract_native_filters_from_permalink_async (backend/src/core/async_superset_client.py)
/**!
 * @brief Extract native filters dataMask from a permalink key asynchronously.
 * @complexity 3
 * @data_contract Input[permalink_key: str] -> Output[Dict]
 * @post Returns extracted dataMask with filter states.
 */

// --- extract_native_filters_from_key_async (backend/src/core/async_superset_client.py)
/**!
 * @brief Extract native filters from a native_filters_key URL parameter asynchronously.
 * @complexity 3
 * @data_contract Input[dashboard_id: Union[int, str], filter_state_key: str] -> Output[Dict]
 * @post Returns extracted filter state with extraFormData.
 */

// --- parse_dashboard_url_for_filters_async (backend/src/core/async_superset_client.py)
/**!
 * @brief Parse a Superset dashboard URL and extract native filter state asynchronously.
 * @complexity 3
 * @data_contract Input[url: str] -> Output[Dict]
 * @post Returns extracted filter state or empty dict if no filters found.
 */

// --- AuthPackage (backend/src/core/auth/__init__.py)
/**!
 * @brief Authentication and authorization package root.
 */

// --- test_auth (backend/src/core/auth/__tests__/test_auth.py)
/**!
 * @brief Unit tests for authentication module
 * @complexity 3
 * @layer Domain
 */

// --- test_create_user (backend/src/core/auth/__tests__/test_auth.py)
/**!
 * @brief Verifies that a persisted user can be retrieved with intact credential hash.
 */

// --- test_authenticate_user (backend/src/core/auth/__tests__/test_auth.py)
/**!
 * @brief Validates authentication outcomes for valid, wrong-password, and unknown-user cases.
 */

// --- test_create_session (backend/src/core/auth/__tests__/test_auth.py)
/**!
 * @brief Ensures session creation returns bearer token payload fields.
 */

// --- test_role_permission_association (backend/src/core/auth/__tests__/test_auth.py)
/**!
 * @brief Confirms role-permission many-to-many assignments persist and reload correctly.
 */

// --- test_user_role_association (backend/src/core/auth/__tests__/test_auth.py)
/**!
 * @brief Confirms user-role assignment persists and is queryable from repository reads.
 */

// --- test_ad_group_mapping (backend/src/core/auth/__tests__/test_auth.py)
/**!
 * @brief Verifies AD group mapping rows persist and reference the expected role.
 */

// --- test_authenticate_user_updates_last_login (backend/src/core/auth/__tests__/test_auth.py)
/**!
 * @brief Verifies successful authentication updates last_login audit field.
 */

// --- test_authenticate_inactive_user (backend/src/core/auth/__tests__/test_auth.py)
/**!
 * @brief Verifies inactive accounts are rejected during password authentication.
 */

// --- test_verify_password_empty_hash (backend/src/core/auth/__tests__/test_auth.py)
/**!
 * @brief Verifies password verification safely rejects empty or null password hashes.
 */

// --- test_provision_adfs_user_new (backend/src/core/auth/__tests__/test_auth.py)
/**!
 * @brief Verifies JIT provisioning creates a new ADFS user and maps group-derived roles.
 */

// --- test_provision_adfs_user_existing (backend/src/core/auth/__tests__/test_auth.py)
/**!
 * @brief Verifies JIT provisioning reuses existing ADFS user and refreshes role assignments.
 */

// --- APIKeyUtilities (backend/src/core/auth/api_key.py)
/**!
 * @brief API key generation and hashing utilities for service-to-service authentication.
 * @complexity 2
 * @invariant hash_api_key() produces SHA-256 hex digest for lookup and storage.
 * @layer Core
 */

// --- generate_api_key (backend/src/core/auth/api_key.py)
/**!
 * @brief Generate a new API key in ssk_ format with SHA-256 hash.
 * @complexity 2
 * @post Returns (raw_key, prefix, key_hash) — raw_key shown ONCE to caller, never stored.
 * @side_effect Uses secrets.token_urlsafe(32) for cryptographic randomness.
 */

// --- hash_api_key (backend/src/core/auth/api_key.py)
/**!
 * @brief Hash an API key string to SHA-256 hex digest for lookup.
 * @complexity 1
 * @post Returns 64-character hex digest.
 * @pre raw_key is a non-empty string.
 */

// --- AuthConfigModule (backend/src/core/auth/config.py)
/**!
 * @brief Centralized configuration for authentication and authorization.
 * @complexity 2
 * @invariant All sensitive configuration must be loaded from environment; no hardcoded secrets.
 * @layer Core
 * @rationale SECRET_KEY and AUTH_DATABASE_URL now crash-early if env vars are missing.
 */

// --- AuthConfig (backend/src/core/auth/config.py)
/**!
 * @brief Holds authentication-related settings.
 * @post Returns a configuration object with validated settings.
 * @pre Environment variables may be provided via .env file.
 */

// --- auth_config (backend/src/core/auth/config.py)
/**!
 * @brief Singleton instance of AuthConfig.
 */

// --- AuthJwtModule (backend/src/core/auth/jwt.py)
/**!
 * @brief JWT token generation and validation logic.
 * @complexity 5
 * @data_contract TokenPayload -> JWT string
 * @invariant Tokens must include expiration time and user identifier.
 * @layer Core
 * @post Token encode/decode functions exported
 * @pre JWT secret configured in environment
 * @side_effect None
 */

// --- create_access_token (backend/src/core/auth/jwt.py)
/**!
 * @brief Generates a new JWT access token.
 * @post Returns a signed JWT string.
 * @pre data dict contains 'sub' (user_id) and optional 'scopes' (roles).
 */

// --- decode_token (backend/src/core/auth/jwt.py)
/**!
 * @brief Decodes and validates a JWT token.
 * @post Returns the decoded payload if valid.
 * @pre token is a signed JWT string.
 */

// --- AuthLoggerModule (backend/src/core/auth/logger.py)
/**!
 * @brief Structured auth logging module for audit trail generation.
 * @complexity 5
 * @data_contract AuthEvent -> LogEntry
 * @invariant Must not log sensitive data like passwords or full tokens.
 * @layer Core
 * @post Audit logging functions exported
 * @pre Auth module initialized
 * @side_effect Writes auth audit log entries
 */

// --- log_security_event (backend/src/core/auth/logger.py)
/**!
 * @brief Logs a security-related event for audit trails.
 * @post Security event is written to the application log.
 * @pre event_type and username are strings.
 */

// --- AuthOauthModule (backend/src/core/auth/oauth.py)
/**!
 * @brief ADFS OIDC configuration and client using Authlib.
 * @complexity 2
 * @invariant Must use secure OIDC flows.
 * @layer Core
 */

// --- oauth (backend/src/core/auth/oauth.py)
/**!
 * @brief Global Authlib OAuth registry.
 */

// --- register_adfs (backend/src/core/auth/oauth.py)
/**!
 * @brief Registers the ADFS OIDC client.
 * @post ADFS client is registered in oauth registry.
 * @pre ADFS configuration is provided in auth_config.
 */

// --- is_adfs_configured (backend/src/core/auth/oauth.py)
/**!
 * @brief Checks if ADFS is properly configured.
 * @post Returns True if ADFS client is registered, False otherwise.
 * @pre None.
 */

// --- AuthRepositoryModule (backend/src/core/auth/repository.py)
/**!
 * @brief Data access layer for authentication and user preference entities.
 * @complexity 5
 * @data_contract Input[EXT:Library:sqlalchemy.orm.Session] -> Output[User|Role|Permission|UserDashboardPreference access]
 * @invariant All database read/write operations must execute via the injected SQLAlchemy session boundary.
 * @layer Domain
 * @post Provides valid access to identity data.
 * @pre Database connection is active.
 * @side_effect Executes database read queries through the injected SQLAlchemy session boundary.
 */

// --- AuthRepository (backend/src/core/auth/repository.py)
/**!
 * @brief Provides low-level CRUD operations for identity and authorization records.
 * @post Entity instances returned safely.
 * @pre Database session is bound.
 * @side_effect Performs database reads.
 */

// --- get_user_by_id (backend/src/core/auth/repository.py)
/**!
 * @brief Retrieve user by UUID.
 * @post Returns User object if found, else None.
 * @pre user_id is a valid UUID string.
 */

// --- get_user_by_username (backend/src/core/auth/repository.py)
/**!
 * @brief Retrieve user by username.
 * @post Returns User object if found, else None.
 * @pre username is a non-empty string.
 */

// --- get_role_by_id (backend/src/core/auth/repository.py)
/**!
 * @brief Retrieve role by UUID with permissions preloaded.
 */

// --- get_role_by_name (backend/src/core/auth/repository.py)
/**!
 * @brief Retrieve role by unique name.
 */

// --- get_permission_by_id (backend/src/core/auth/repository.py)
/**!
 * @brief Retrieve permission by UUID.
 */

// --- get_permission_by_resource_action (backend/src/core/auth/repository.py)
/**!
 * @brief Retrieve permission by resource and action tuple.
 */

// --- list_permissions (backend/src/core/auth/repository.py)
/**!
 * @brief List all system permissions.
 */

// --- get_user_dashboard_preference (backend/src/core/auth/repository.py)
/**!
 * @brief Retrieve dashboard filters/preferences for a user.
 */

// --- get_roles_by_ad_groups (backend/src/core/auth/repository.py)
/**!
 * @brief Retrieve roles that match a list of AD group names.
 * @post Returns a list of Role objects mapped to the provided AD groups.
 * @pre groups is a list of strings representing AD group identifiers.
 */

// --- AuthSecurityModule (backend/src/core/auth/security.py)
/**!
 * @brief Utility for password hashing and verification using Passlib.
 * @complexity 2
 * @invariant Uses bcrypt for hashing with standard work factor.
 * @layer Core
 */

// --- verify_password (backend/src/core/auth/security.py)
/**!
 * @brief Verifies a plain password against a hashed password.
 * @post Returns True if password matches, False otherwise.
 * @pre plain_password is a string, hashed_password is a bcrypt hash.
 */

// --- get_password_hash (backend/src/core/auth/security.py)
/**!
 * @brief Generates a bcrypt hash for a plain password.
 * @post Returns a secure bcrypt hash string.
 * @pre password is a string.
 */

// --- ConfigManager (backend/src/core/config_manager.py)
/**!
 * @brief Manages application configuration persistence in DB with one-time migration from legacy JSON.
 * @complexity 5
 * @data_contract Input[json, record] -> Model[AppConfig]
 * @invariant Configuration must always be representable by AppConfig and persisted under global record id.
 * @layer Domain
 * @post Configuration is loaded into memory and logger is configured.
 * @pre Database schema for AppConfigRecord must be initialized.
 * @side_effect Performs DB I/O and may update global logging level.
 */

// --- _apply_features_from_env (backend/src/core/config_manager.py)
/**!
 * @brief Read FEATURES__* env vars and apply them to a GlobalSettings features config.
 * @rationale Env vars seed the initial defaults. After first bootstrap, DB is source of truth.
 * @side_effect Reads os.environ; mutates settings.features in-place.
 */

// --- _default_config (backend/src/core/config_manager.py)
/**!
 * @brief Build default application configuration fallback.
 */

// --- _sync_raw_payload_from_config (backend/src/core/config_manager.py)
/**!
 * @brief Merge typed AppConfig state into raw payload while preserving unsupported legacy sections.
 */

// --- _load_from_legacy_file (backend/src/core/config_manager.py)
/**!
 * @brief Load legacy JSON configuration for migration fallback path.
 */

// --- _get_record (backend/src/core/config_manager.py)
/**!
 * @brief Resolve global configuration record from DB.
 */

// --- _load_config (backend/src/core/config_manager.py)
/**!
 * @brief Load configuration from DB or perform one-time migration from legacy JSON.
 */

// --- _sync_environment_records (backend/src/core/config_manager.py)
/**!
 * @brief Mirror configured environments into the relational environments table used by FK-backed domain models.
 */

// --- _delete_stale_environment_records (backend/src/core/config_manager.py)
/**!
 * @brief Remove persisted environment records that are no longer in the configured environments.
 * @post Stale Environment rows are deleted via the session (caller must commit).
 * @pre _sync_environment_records must already have run so the query returns a current view.
 * @side_effect Only safe to call during explicit save (_save_config_to_db), NOT during _load_config,
 */

// --- _save_config_to_db (backend/src/core/config_manager.py)
/**!
 * @brief Persist provided AppConfig into the global DB configuration record.
 */

// --- save (backend/src/core/config_manager.py)
/**!
 * @brief Persist current in-memory configuration state.
 */

// --- get_config (backend/src/core/config_manager.py)
/**!
 * @brief Return current in-memory configuration snapshot.
 */

// --- get_payload (backend/src/core/config_manager.py)
/**!
 * @brief Return full persisted payload including sections outside typed AppConfig schema.
 */

// --- save_config (backend/src/core/config_manager.py)
/**!
 * @brief Persist configuration provided either as typed AppConfig or raw payload dict.
 */

// --- update_global_settings (backend/src/core/config_manager.py)
/**!
 * @brief Replace global settings and persist the resulting configuration.
 */

// --- validate_path (backend/src/core/config_manager.py)
/**!
 * @brief Validate that path exists and is writable, creating it when absent.
 */

// --- get_environments (backend/src/core/config_manager.py)
/**!
 * @brief Return all configured environments.
 */

// --- has_environments (backend/src/core/config_manager.py)
/**!
 * @brief Check whether at least one environment exists in configuration.
 */

// --- get_environment (backend/src/core/config_manager.py)
/**!
 * @brief Resolve a configured environment by identifier.
 */

// --- add_environment (backend/src/core/config_manager.py)
/**!
 * @brief Upsert environment by id into configuration and persist.
 */

// --- update_environment (backend/src/core/config_manager.py)
/**!
 * @brief Update existing environment by id and preserve masked password placeholder behavior.
 */

// --- delete_environment (backend/src/core/config_manager.py)
/**!
 * @brief Delete environment by id and persist when deletion occurs.
 */

// --- ConfigModels (backend/src/core/config_models.py)
/**!
 * @brief Defines the data models for application configuration using Pydantic.
 * @complexity 3
 * @layer Core
 */

// --- CoreContracts (backend/src/core/config_models.py)
/**!
 * @brief Contract for core configuration models — Pydantic BaseModel subclasses with scheduler config.
 * @complexity 2
 */

// --- ConnectionContracts (backend/src/core/config_models.py)
/**!
 * @brief Contract for database/environment connection configuration models.
 * @complexity 2
 */

// --- Schedule (backend/src/core/config_models.py)
/**!
 * @brief Represents a backup schedule configuration.
 */

// --- Environment (backend/src/core/config_models.py)
/**!
 * @brief Represents a Superset environment configuration.
 */

// --- LoggingConfig (backend/src/core/config_models.py)
/**!
 * @brief Defines the configuration for the application's logging system.
 */

// --- CleanReleaseConfig (backend/src/core/config_models.py)
/**!
 * @brief Configuration for clean release compliance subsystem.
 */

// --- FeaturesConfig (backend/src/core/config_models.py)
/**!
 * @brief Top-level feature flags that toggle entire project features on/off.
 * @complexity 1
 * @rationale Features are read from environment variables on bootstrap and persisted in DB.
 */

// --- GlobalSettings (backend/src/core/config_models.py)
/**!
 * @brief Represents global application settings.
 */

// --- AppConfig (backend/src/core/config_models.py)
/**!
 * @brief The root configuration model containing all application settings.
 */

// --- CotLoggerModule (backend/src/core/cot_logger.py)
/**!
 * @brief Structured JSON logger implementing the molecular CoT (Chain-of-Thought) logging protocol.
 * @complexity 4
 */

// --- cot_trace_context (backend/src/core/cot_logger.py)
/**!
 * @brief ContextVars for trace ID and span ID propagation across async boundaries.
 * @complexity 1
 */

// --- cot_logger_instance (backend/src/core/cot_logger.py)
/**!
 * @brief Dedicated Python logger for all CoT (molecular) log output.
 * @complexity 1
 */

// --- seed_trace_id (backend/src/core/cot_logger.py)
/**!
 * @brief Generate a new UUID4 trace_id, set it in ContextVar, and return it.
 * @complexity 1
 */

// --- set_trace_id (backend/src/core/cot_logger.py)
/**!
 * @brief Set an explicit trace_id into the ContextVar (e.g. from an incoming header).
 * @complexity 1
 */

// --- get_trace_id (backend/src/core/cot_logger.py)
/**!
 * @brief Get the current trace_id from ContextVar.
 * @complexity 1
 */

// --- push_span (backend/src/core/cot_logger.py)
/**!
 * @brief Set a new span_id in ContextVar and return the previous span_id for later restoration.
 * @complexity 1
 */

// --- pop_span (backend/src/core/cot_logger.py)
/**!
 * @brief Restore a previous span_id into the ContextVar.
 * @complexity 1
 */

// --- cot_log_function (backend/src/core/cot_logger.py)
/**!
 * @brief Core structured logging function that emits a single-line JSON record.
 * @complexity 2
 */

// --- MarkerLogger (backend/src/core/cot_logger.py)
/**!
 * @brief Thin proxy class providing .reason(), .reflect(), .explore() convenience methods.
 * @complexity 2
 */

// --- MarkerLogger.__init__ (backend/src/core/cot_logger.py)
/**!
 * @brief Store the module/component name used as the 'src' field in all log calls.
 */

// --- MarkerLogger.reason (backend/src/core/cot_logger.py)
/**!
 * @brief Log a REASON marker — strict deduction, core logic.
 */

// --- MarkerLogger.reflect (backend/src/core/cot_logger.py)
/**!
 * @brief Log a REFLECT marker — self-check, structural validation.
 */

// --- MarkerLogger.explore (backend/src/core/cot_logger.py)
/**!
 * @brief Log an EXPLORE marker — searching, alternatives, violated assumptions.
 */

// --- DatabaseModule (backend/src/core/database.py)
/**!
 * @brief Configures database connection and session management (PostgreSQL-first).
 * @complexity 3
 * @invariant A single engine instance is used for the entire application.
 * @layer Infrastructure
 */

// --- BASE_DIR (backend/src/core/database.py)
/**!
 * @brief Base directory for the backend.
 * @complexity 1
 */

// --- DATABASE_URL (backend/src/core/database.py)
/**!
 * @brief URL for the main application database. Read from env; dev fallback only.
 * @complexity 1
 * @rationale DATABASE_URL reads from env (DATABASE_URL or POSTGRES_URL).
 */

// --- TASKS_DATABASE_URL (backend/src/core/database.py)
/**!
 * @brief URL for the tasks execution database.
 * @complexity 1
 */

// --- AUTH_DATABASE_URL (backend/src/core/database.py)
/**!
 * @brief URL for the authentication database.
 * @complexity 1
 */

// --- engine (backend/src/core/database.py)
/**!
 * @brief SQLAlchemy engine for mappings database.
 * @complexity 1
 * @side_effect Creates database engine and manages connection pool.
 */

// --- tasks_engine (backend/src/core/database.py)
/**!
 * @brief SQLAlchemy engine for tasks database.
 * @complexity 1
 */

// --- auth_engine (backend/src/core/database.py)
/**!
 * @brief SQLAlchemy engine for authentication database.
 * @complexity 1
 */

// --- SessionLocal (backend/src/core/database.py)
/**!
 * @brief A session factory for the main mappings database.
 * @complexity 1
 * @pre engine is initialized.
 */

// --- TasksSessionLocal (backend/src/core/database.py)
/**!
 * @brief A session factory for the tasks execution database.
 * @complexity 1
 * @pre tasks_engine is initialized.
 */

// --- AuthSessionLocal (backend/src/core/database.py)
/**!
 * @brief A session factory for the authentication database.
 * @complexity 1
 * @pre auth_engine is initialized.
 */

// --- _ensure_user_dashboard_preferences_columns (backend/src/core/database.py)
/**!
 * @brief Applies additive schema upgrades for user_dashboard_preferences table.
 * @complexity 3
 * @post Missing columns are added without data loss.
 * @pre bind_engine points to application database where profile table is stored.
 */

// --- _ensure_user_dashboard_preferences_health_columns (backend/src/core/database.py)
/**!
 * @brief Applies additive schema upgrades for user_dashboard_preferences table (health fields).
 * @complexity 3
 */

// --- _ensure_llm_validation_results_columns (backend/src/core/database.py)
/**!
 * @brief Applies additive schema upgrades for llm_validation_results table.
 * @complexity 3
 */

// --- _ensure_git_server_configs_columns (backend/src/core/database.py)
/**!
 * @brief Applies additive schema upgrades for git_server_configs table.
 * @complexity 3
 * @post Missing columns are added without data loss.
 * @pre bind_engine points to application database.
 */

// --- _ensure_auth_users_columns (backend/src/core/database.py)
/**!
 * @brief Applies additive schema upgrades for auth users table.
 * @complexity 3
 * @post Missing columns are added without data loss.
 * @pre bind_engine points to authentication database.
 */

// --- _ensure_filter_source_enum_values (backend/src/core/database.py)
/**!
 * @brief Adds missing FilterSource enum values to the PostgreSQL native filtersource type.
 * @complexity 3
 * @post New enum values are available without data loss.
 * @pre bind_engine points to application database with imported_filters table.
 */

// --- _ensure_dataset_review_session_columns (backend/src/core/database.py)
/**!
 * @brief Apply additive schema upgrades for dataset review persistence required by optimistic-lock and recovery metadata semantics.
 * @complexity 4
 * @post Missing additive columns across legacy dataset review tables are created without removing existing data.
 * @pre bind_engine points to the application database where dataset review tables are stored.
 * @side_effect Executes ALTER TABLE statements against dataset review tables in the application database.
 */

// --- _ensure_translation_schedules_columns (backend/src/core/database.py)
/**!
 * @brief Applies additive schema upgrades for translation_schedules table.
 * @complexity 3
 * @post Missing columns are added without data loss.
 * @pre bind_engine points to application database.
 */

// --- _ensure_dictionary_entries_columns (backend/src/core/database.py)
/**!
 * @brief Additive migration for dictionary_entries origin tracking columns.
 * @complexity 3
 */

// --- init_db (backend/src/core/database.py)
/**!
 * @brief Initializes the database by creating all tables.
 * @complexity 3
 * @post Database tables created in all databases.
 * @pre engine, tasks_engine and auth_engine are initialized.
 * @side_effect Creates physical database files if they don't exist.
 */

// --- get_db (backend/src/core/database.py)
/**!
 * @brief Dependency for getting a database session.
 * @complexity 3
 * @post Session is closed after use.
 * @pre SessionLocal is initialized.
 */

// --- get_tasks_db (backend/src/core/database.py)
/**!
 * @brief Dependency for getting a tasks database session.
 * @complexity 3
 * @post Session is closed after use.
 * @pre TasksSessionLocal is initialized.
 */

// --- get_auth_db (backend/src/core/database.py)
/**!
 * @brief Dependency for getting an authentication database session.
 * @complexity 3
 * @data_contract None -> Output[EXT:Library:sqlalchemy.orm.Session]
 * @post Session is closed after use.
 * @pre AuthSessionLocal is initialized.
 */

// --- EncryptionKeyModule (backend/src/core/encryption_key.py)
/**!
 * @brief Resolve and persist the Fernet encryption key required by runtime services.
 * @complexity 5
 * @data_contract Input[env_file_path] -> Output[encryption_key]
 * @invariant Runtime key resolution never falls back to an ephemeral secret.
 * @layer Infrastructure
 * @post A valid Fernet key is available to runtime services via ENCRYPTION_KEY.
 * @pre Runtime environment can read process variables and target .env path is writable when key generation is required.
 * @rationale Replaced Path(__file__).parents[2] with BASE_DIR import from database.py — same result, avoids recomputing path traversal.
 * @side_effect May append ENCRYPTION_KEY entry into backend .env file and set process environment variable.
 */

// --- ensure_encryption_key (backend/src/core/encryption_key.py)
/**!
 * @brief Ensure backend runtime has a persistent valid Fernet key.
 * @post Returns a valid Fernet key and guarantees it is present in process environment.
 * @pre env_file_path points to a writable backend .env file or ENCRYPTION_KEY exists in process environment.
 * @side_effect May create or append backend/.env when key is missing.
 */

// --- LoggerModule (backend/src/core/logger.py)
/**!
 * @brief Application logging system with CotJsonFormatter producing molecular CoT JSON output.
 * @complexity 5
 * @data_contract All log records conform to molecular CoT JSON schema: {ts, level, trace_id, src, marker, intent, span_id?, payload?, error?}
 * @invariant CotJsonFormatter.format() always returns valid single-line JSON string.
 * @layer Core
 * @post All log output is single-line JSON with ts, level, trace_id, src, marker, intent, payload, error, span_id.
 * @pre Python 3.7+ with cot_logger ContextVars available.
 * @rationale Replaced BeliefFormatter text-based [Entry]/[Exit]/[Action] logging with CotJsonFormatter JSON output. Old format was not machine-parseable and mixed presentation with intent. CotJsonFormatter produces structured JSON consistent with cot_logger.py MarkerLogger protocol.
 * @rejected Keeping both formatters side-by-side was rejected (two inconsistent output formats would confuse log consumers).
 * @side_effect Configures global logger handlers and formatters; seeds global _enable_belief_state and _task_log_level; writes JSON to console/files.
 */

// --- CotJsonFormatter (backend/src/core/logger.py)
/**!
 * @brief JSON formatter implementing the molecular CoT logging protocol. Outputs single-line JSON with ts, level, trace_id, src, marker, intent, payload, error, span_id.
 * @complexity 3
 */

// --- CotJsonFormatter.format (backend/src/core/logger.py)
/**!
 * @brief Format a LogRecord into a single-line CoT JSON string with molecular CoT protocol fields.
 * @complexity 2
 * @invariant Output is always valid single-line JSON.
 */

// --- BeliefFormatter (backend/src/core/logger.py)
/**!
 * @brief Legacy formatter that adds belief state prefixes to log messages. Deprecated in favor of CotJsonFormatter.
 * @complexity 2
 * @rationale Kept for backward compatibility; may be used by external consumers of this module.
 */

// --- LogEntry (backend/src/core/logger.py)
/**!
 * @brief A Pydantic model representing a single, structured log entry.
 * @complexity 1
 */

// --- belief_scope (backend/src/core/logger.py)
/**!
 * @brief Context manager for Molecular CoT structured logging. Uses cot_logger.log() for JSON output.
 * @complexity 3
 * @post Thread-local belief state is updated; REASON/REFLECT/EXPLORE markers emitted via structured JSON logger.
 * @pre anchor_id must be provided.
 */

// --- configure_logger (backend/src/core/logger.py)
/**!
 * @brief Configures the main logger and the CoT logger with CotJsonFormatter, file handlers, and global flags.
 * @complexity 4
 * @post Logger levels, handlers, formatters, belief state flag, and task log level are updated.
 * @pre config is a valid LoggingConfig instance.
 * @side_effect Mutates global _enable_belief_state, _task_log_level; adds/removes handlers on both logger and cot_logger; creates file directories.
 */

// --- get_task_log_level (backend/src/core/logger.py)
/**!
 * @brief Returns the current task log level filter.
 * @complexity 1
 */

// --- should_log_task_level (backend/src/core/logger.py)
/**!
 * @brief Checks if a log level should be recorded based on task_log_level setting.
 * @complexity 1
 */

// --- Logger (backend/src/core/logger.py)
/**!
 * @brief The global application logger instance configured with CotJsonFormatter, console handler, and WebSocketLogHandler.
 * @complexity 2
 */

// --- believed (backend/src/core/logger.py)
/**!
 * @brief A decorator that wraps a function in a belief scope.
 * @complexity 2
 */

// --- explore (backend/src/core/logger.py)
/**!
 * @brief Logs an EXPLORE marker (WARNING level) with structured extra data for CotJsonFormatter.
 * @complexity 2
 */

// --- reason (backend/src/core/logger.py)
/**!
 * @brief Logs a REASON marker (DEBUG level) with structured extra data for CotJsonFormatter.
 * @complexity 2
 */

// --- reflect (backend/src/core/logger.py)
/**!
 * @brief Logs a REFLECT marker (DEBUG level) with structured extra data for CotJsonFormatter.
 * @complexity 2
 */

// --- test_logger (backend/src/core/logger/__tests__/test_logger.py)
/**!
 * @brief Unit tests for logger module
 * @complexity 3
 * @layer Infrastructure
 */

// --- test_belief_scope_logs_reason_reflect_at_debug (backend/src/core/logger/__tests__/test_logger.py)
/**!
 * @brief Test that belief_scope generates [REASON] and [REFLECT] logs at DEBUG level.
 * @post Logs are verified to contain REASON and REFLECT markers at DEBUG level.
 * @pre belief_scope is available. caplog fixture is used. Logger configured to DEBUG.
 */

// --- test_belief_scope_error_handling (backend/src/core/logger/__tests__/test_logger.py)
/**!
 * @brief Test that belief_scope logs EXPLORE on exception.
 * @post Logs are verified to contain EXPLORE marker.
 * @pre belief_scope is available. caplog fixture is used. Logger configured to DEBUG.
 */

// --- test_belief_scope_success_reflect (backend/src/core/logger/__tests__/test_logger.py)
/**!
 * @brief Test that belief_scope logs REFLECT on success.
 * @post Logs are verified to contain REFLECT marker.
 * @pre belief_scope is available. caplog fixture is used. Logger configured to DEBUG.
 */

// --- test_belief_scope_not_visible_at_info (backend/src/core/logger/__tests__/test_logger.py)
/**!
 * @brief Test that belief_scope REFLECT logs are NOT visible at INFO level.
 * @post REASON is visible at INFO (uses info()); REFLECT is not (uses debug()).
 * @pre belief_scope is available. caplog fixture is used.
 */

// --- test_task_log_level_default (backend/src/core/logger/__tests__/test_logger.py)
/**!
 * @brief Test that default task log level is INFO.
 * @post Default level is INFO.
 * @pre None.
 */

// --- test_should_log_task_level (backend/src/core/logger/__tests__/test_logger.py)
/**!
 * @brief Test that should_log_task_level correctly filters log levels.
 * @post Filtering works correctly for all level combinations.
 * @pre None.
 */

// --- test_configure_logger_task_log_level (backend/src/core/logger/__tests__/test_logger.py)
/**!
 * @brief Test that configure_logger updates task_log_level.
 * @post task_log_level is updated correctly.
 * @pre LoggingConfig is available.
 */

// --- test_enable_belief_state_flag (backend/src/core/logger/__tests__/test_logger.py)
/**!
 * @brief Test that enable_belief_state flag controls belief_scope logging.
 * @post belief_scope explicit REASON logs are controlled by the flag; REFLECT always logged.
 * @pre LoggingConfig is available. caplog fixture is used.
 */

// --- test_belief_scope_missing_anchor (backend/src/core/logger/__tests__/test_logger.py)
/**!
 * @brief Test @PRE condition: anchor_id must be provided
 */

// --- test_configure_logger_post_conditions (backend/src/core/logger/__tests__/test_logger.py)
/**!
 * @brief Test @POST condition: Logger level, handlers, belief state flag, and task log level are updated.
 */

// --- IdMappingServiceModule (backend/src/core/mapping_service.py)
/**!
 * @brief Service for tracking and synchronizing Superset Resource IDs (UUID <-> Integer ID)
 * @complexity 5
 * @data_contract Input[environment_id, resource_type, uuid] -> Output[remote_integer_id|None]
 * @invariant sync_environment must handle remote API failures gracefully.
 * @layer Core
 * @post Mapping synchronization and lookup APIs are available for environment-scoped UUID-to-integer resolution.
 * @pre Database session is valid and Superset client factory returns authenticated clients for requested environments.
 * @side_effect Reads/writes ResourceMapping rows, emits logs, and schedules periodic sync jobs.
 * @test_data mock_superset_resources -> {'chart': [{'id': 42, 'uuid': '1234', 'slice_name': 'test'}], 'dataset': [{'id': 99, 'uuid': '5678', 'table_name': 'data'}]}
 */

// --- IdMappingService (backend/src/core/mapping_service.py)
/**!
 * @brief Service handling the cataloging and retrieval of remote Superset Integer IDs.
 * @complexity 5
 * @data_contract Input[db_session] -> Output[IdMappingService]
 * @invariant self.db remains the authoritative session for all mapping operations.
 * @post Service instance provides scheduler control and environment-scoped mapping synchronization APIs.
 * @pre db_session is an active SQLAlchemy Session bound to mapping tables.
 * @side_effect Instantiates an in-process scheduler and performs database writes during sync cycles.
 * @test_contract IdMappingServiceModel ->
 */

// --- start_scheduler (backend/src/core/mapping_service.py)
/**!
 * @brief Starts the background scheduler with a given cron string.
 * @param superset_client_factory - Function to get a client for an environment.
 */

// --- sync_environment (backend/src/core/mapping_service.py)
/**!
 * @brief Fully synchronizes mapping for a specific environment.
 * @param superset_client - Instance capable of hitting the Superset API.
 * @post ResourceMapping records for the environment are created or updated.
 * @pre environment_id exists in the database.
 */

// --- get_remote_id (backend/src/core/mapping_service.py)
/**!
 * @brief Retrieves the remote integer ID for a given universal UUID.
 * @param uuid (str)
 * @return Optional[int]
 */

// --- get_remote_ids_batch (backend/src/core/mapping_service.py)
/**!
 * @brief Retrieves remote integer IDs for a list of universal UUIDs efficiently.
 * @param uuids (List[str])
 * @return Dict[str, int] - Mapping of UUID -> Integer ID
 */

// --- middleware_package (backend/src/core/middleware/__init__.py)
/**!
 * @brief FastAPI/Starlette middleware package for request-level context and tracing.
 * @complexity 1
 */

// --- TraceContextMiddlewareModule (backend/src/core/middleware/trace.py)
/**!
 * @brief FastAPI/Starlette middleware that seeds a trace_id for every incoming HTTP request.
 * @complexity 3
 */

// --- TraceContextMiddleware (backend/src/core/middleware/trace.py)
/**!
 * @brief Starlette BaseHTTPMiddleware that seeds a trace_id per request.
 * @complexity 2
 */

// --- TraceContextMiddleware.__init__ (backend/src/core/middleware/trace.py)
/**!
 * @brief Standard BaseHTTPMiddleware initialiser.
 */

// --- TraceContextMiddleware.dispatch (backend/src/core/middleware/trace.py)
/**!
 * @brief Dispatch handler that seeds trace_id before passing to the next middleware.
 * @complexity 2
 */

// --- MigrationPackage (backend/src/core/migration/__init__.py)
/**!
 */

// --- MigrationArchiveParserModule (backend/src/core/migration/archive_parser.py)
/**!
 * @brief Parse Superset export ZIP archives into normalized object catalogs for diffing.
 * @complexity 5
 * @data_contract ArchivePath -> ParsedMigration
 * @invariant Parsing is read-only and never mutates archive files.
 * @layer Domain
 * @post Parsed migration archive returned
 * @pre Archive file path is valid and readable
 * @side_effect Reads archive file (read-only)
 */

// --- MigrationArchiveParser (backend/src/core/migration/archive_parser.py)
/**!
 * @brief Extract normalized dashboards/charts/datasets metadata from ZIP archives.
 */

// --- extract_objects_from_zip (backend/src/core/migration/archive_parser.py)
/**!
 * @brief Extract object catalogs from Superset archive.
 * @post Returns object lists grouped by resource type.
 * @pre zip_path points to a valid readable ZIP.
 * @return Dict[str, List[Dict[str, Any]]]
 */

// --- _collect_yaml_objects (backend/src/core/migration/archive_parser.py)
/**!
 * @brief Read and normalize YAML manifests for one object type.
 * @post Returns only valid normalized objects.
 * @pre object_type is one of dashboards/charts/datasets.
 */

// --- _normalize_object_payload (backend/src/core/migration/archive_parser.py)
/**!
 * @brief Convert raw YAML payload to stable diff signature shape.
 * @post Returns normalized descriptor with `uuid`, `title`, and `signature`.
 * @pre payload is parsed YAML mapping.
 */

// --- MigrationDryRunOrchestratorModule (backend/src/core/migration/dry_run_orchestrator.py)
/**!
 * @brief Compute pre-flight migration diff and risk scoring without apply.
 * @complexity 5
 * @data_contract EnvironmentConfig -> MigrationDiffReport
 * @invariant Dry run is informative only and must not mutate target environment.
 * @layer Domain
 * @post Dry-run diff returned without mutation
 * @pre Source and target environments configured
 * @side_effect Reads source environment (read-only)
 */

// --- MigrationDryRunService (backend/src/core/migration/dry_run_orchestrator.py)
/**!
 * @brief Build deterministic diff/risk payload for migration pre-flight.
 */

// --- run (backend/src/core/migration/dry_run_orchestrator.py)
/**!
 * @brief Execute full dry-run computation for selected dashboards.
 * @post Returns JSON-serializable pre-flight payload with summary, diff and risk.
 * @pre source/target clients are authenticated and selection validated by caller.
 * @side_effect Reads source export archives and target metadata via network.
 */

// --- _load_db_mapping (backend/src/core/migration/dry_run_orchestrator.py)
/**!
 * @brief Resolve UUID mapping for optional DB config replacement.
 */

// --- _accumulate_objects (backend/src/core/migration/dry_run_orchestrator.py)
/**!
 * @brief Merge extracted resources by UUID to avoid duplicates.
 */

// --- _index_by_uuid (backend/src/core/migration/dry_run_orchestrator.py)
/**!
 * @brief Build UUID-index map for normalized resources.
 */

// --- _build_object_diff (backend/src/core/migration/dry_run_orchestrator.py)
/**!
 * @brief Compute create/update/delete buckets by UUID+signature.
 */

// --- _build_target_signatures (backend/src/core/migration/dry_run_orchestrator.py)
/**!
 * @brief Pull target metadata and normalize it into comparable signatures.
 */

// --- _build_risks (backend/src/core/migration/dry_run_orchestrator.py)
/**!
 * @brief Build risk items for missing datasource, broken refs, overwrite, owner mismatch.
 */

// --- RiskAssessorModule (backend/src/core/migration/risk_assessor.py)
/**!
 * @brief Compute deterministic migration risk items and aggregate score for dry-run reporting.
 * @complexity 5
 * @data_contract Module[build_risks, score_risks]
 * @invariant Risk scoring must remain bounded to [0,100] and preserve severity-to-weight mapping.
 * @layer Domain
 * @post Risk scoring output preserves item list and provides bounded score with derived level.
 * @pre Risk assessor functions receive normalized migration object collections from dry-run orchestration.
 * @side_effect Emits diagnostic logs and performs read-only metadata requests via Superset client.
 * @test_contract [source_objects,target_objects,diff,target_client] -> [List[RiskItem]]
 * @test_edge [external_fail] -> [target_client get_databases exception propagates to caller]
 * @test_invariant [score_upper_bound_100] -> VERIFIED_BY: [severity_weight_aggregation]
 * @test_scenario [owner_mismatch_dashboard] -> [low owner_mismatch risk is emitted]
 * @ux_feedback [N/A] -> [No direct UI side effects in this module]
 * @ux_reactivity [N/A] -> [Backend synchronous function contracts]
 * @ux_recovery [N/A] -> [Caller-level retry/recovery]
 * @ux_state [Idle] -> [N/A backend domain module]
 */

// --- index_by_uuid (backend/src/core/migration/risk_assessor.py)
/**!
 * @brief Build UUID-index from normalized objects.
 * @data_contract List[Dict[str, Any]] -> Dict[str, Dict[str, Any]]
 * @post Returns mapping keyed by string uuid; only truthy uuid values are included.
 * @pre Input list items are dict-like payloads potentially containing "uuid".
 * @side_effect Emits reasoning/reflective logs only.
 */

// --- extract_owner_identifiers (backend/src/core/migration/risk_assessor.py)
/**!
 * @brief Normalize owner payloads for stable comparison.
 * @data_contract Any -> List[str]
 * @post Returns sorted unique owner identifiers as strings.
 * @pre Owners may be list payload, scalar values, or None.
 * @side_effect Emits reasoning/reflective logs only.
 */

// --- build_risks (backend/src/core/migration/risk_assessor.py)
/**!
 * @brief Build risk list from computed diffs and target catalog state.
 * @data_contract ) -> List[Dict[str, Any]]
 * @post Returns list of deterministic risk items derived from overwrite, missing datasource, reference, and owner mismatch checks.
 * @pre target_client is authenticated/usable for database list retrieval.
 * @side_effect Calls target Superset API for databases metadata and emits logs.
 */

// --- score_risks (backend/src/core/migration/risk_assessor.py)
/**!
 * @brief Aggregate risk list into score and level.
 * @data_contract List[Dict[str, Any]] -> Dict[str, Any]
 * @post Returns dict with score in [0,100], derived level, and original items.
 * @pre risk_items contains optional severity fields expected in {high,medium,low} or defaults to low weight.
 * @side_effect Emits reasoning/reflective logs only.
 */

// --- MigrationEngineModule (backend/src/core/migration_engine.py)
/**!
 * @brief Transforms Superset export ZIP archives while preserving archive integrity and patching mapped identifiers.
 * @complexity 5
 * @data_contract Input[zip_path, output_path, db_mapping, target_env_id?, fix_cross_filters?] -> Output[Transformed Superset archive]
 * @invariant ZIP structure and non-targeted metadata must remain valid after transformation.
 * @layer Domain
 * @post Migration engine contracts preserve ZIP integrity while exposing transformation entrypoints for import pipelines.
 * @pre Input archives are readable Superset exports and optional mapping collaborators expose remote id lookup APIs.
 * @side_effect Reads and writes temporary archive contents during transformation workflows and emits structured belief-state logs.
 */

// --- MigrationEngine (backend/src/core/migration_engine.py)
/**!
 * @brief Engine for transforming Superset export ZIPs.
 */

// --- transform_zip (backend/src/core/migration_engine.py)
/**!
 * @brief Extracts ZIP, replaces database UUIDs in YAMLs, patches cross-filters, and re-packages.
 * @data_contract Input[(str zip_path, str output_path, Dict[str,str] db_mapping, bool strip_databases, Optional[str] target_env_id, bool fix_cross_filters)] -> Output[bool]
 * @param fix_cross_filters (bool) - Whether to patch dashboard json_metadata.
 * @post Returns True only when extraction, transformation, and packaging complete without exception.
 * @pre zip_path points to a readable ZIP; output_path parent is writable; db_mapping keys/values are UUID strings.
 * @return bool - True if successful.
 * @side_effect Reads/writes filesystem archives, creates temporary directory, emits structured logs.
 */

// --- _transform_yaml (backend/src/core/migration_engine.py)
/**!
 * @brief Replaces database_uuid in a single YAML file.
 * @data_contract Input[(Path file_path, Dict[str,str] db_mapping)] -> Output[None]
 * @param db_mapping (Dict[str, str]) - UUID mapping dictionary.
 * @post database_uuid is replaced in-place only when source UUID is present in db_mapping.
 * @pre file_path exists, is readable YAML, and db_mapping contains source->target UUID pairs.
 * @side_effect Reads and conditionally rewrites YAML file on disk.
 */

// --- _extract_chart_uuids_from_archive (backend/src/core/migration_engine.py)
/**!
 * @brief Scans extracted chart YAML files and builds a source chart ID to UUID lookup map.
 * @data_contract Input[Path] -> Output[Dict[int,str]]
 * @param temp_dir (Path) - Root dir of unpacked archive.
 * @post Returns a best-effort Dict[int, str] containing only parseable chart id/uuid pairs.
 * @pre temp_dir exists and points to extracted archive root with optional chart YAML resources.
 * @return Dict[int, str] - Mapping of source Integer ID to UUID.
 * @side_effect Reads chart YAML files from filesystem; suppresses per-file parsing failures.
 */

// --- _patch_dashboard_metadata (backend/src/core/migration_engine.py)
/**!
 * @brief Rewrites dashboard json_metadata chart/dataset integer identifiers using target environment mappings.
 * @data_contract Input[(Path file_path, str target_env_id, Dict[int,str] source_map)] -> Output[None]
 * @param source_map (Dict[int, str])
 * @post json_metadata is re-serialized with mapped integer IDs when remote mappings are available; otherwise file remains unchanged.
 * @pre file_path points to dashboard YAML with json_metadata; target_env_id is non-empty; source_map contains source id->uuid.
 * @side_effect Reads/writes YAML file, performs mapping lookup via mapping_service, emits logs for recoverable/terminal failures.
 */

// --- PluginBase (backend/src/core/plugin_base.py)
/**!
 * @brief PluginLoader scans for subclasses of PluginBase.
 * @invariant All plugins MUST inherit from this class.
 * @layer Core
 */

// --- id (backend/src/core/plugin_base.py)
/**!
 * @brief Returns the unique identifier for the plugin.
 * @post Returns string ID.
 * @pre Plugin instance exists.
 * @return str - Plugin ID.
 */

// --- name (backend/src/core/plugin_base.py)
/**!
 * @brief Returns the human-readable name of the plugin.
 * @post Returns string name.
 * @pre Plugin instance exists.
 * @return str - Plugin name.
 */

// --- description (backend/src/core/plugin_base.py)
/**!
 * @brief Returns a brief description of the plugin.
 * @post Returns string description.
 * @pre Plugin instance exists.
 * @return str - Plugin description.
 */

// --- version (backend/src/core/plugin_base.py)
/**!
 * @brief Returns the version of the plugin.
 * @post Returns string version.
 * @pre Plugin instance exists.
 * @return str - Plugin version.
 */

// --- required_permission (backend/src/core/plugin_base.py)
/**!
 * @brief Returns the required permission string to execute this plugin.
 * @post Returns string permission.
 * @pre Plugin instance exists.
 * @return str - Required permission (e.g., "plugin:backup:execute").
 */

// --- ui_route (backend/src/core/plugin_base.py)
/**!
 * @brief Returns the frontend route for the plugin's UI, if applicable.
 * @post Returns string route or None.
 * @pre Plugin instance exists.
 * @return Optional[str] - Frontend route.
 */

// --- get_schema (backend/src/core/plugin_base.py)
/**!
 * @brief Returns the JSON schema for the plugin's input parameters.
 * @post Returns dict schema.
 * @pre Plugin instance exists.
 * @return Dict[str, Any] - JSON schema.
 */

// --- execute (backend/src/core/plugin_base.py)
/**!
 * @brief Executes the plugin's core logic.
 * @param params (Dict[str, Any]) - Validated input parameters.
 * @post Plugin execution is completed.
 * @pre params must be a dictionary.
 */

// --- PluginConfig (backend/src/core/plugin_base.py)
/**!
 * @brief Validated PluginConfig exposed to API layer.
 * @layer Core
 */

// --- PluginLoader (backend/src/core/plugin_loader.py)
/**!
 * @brief Discovers and manages available PluginBase implementations.
 * @complexity 3
 * @layer Core
 * @rationale Replaced print() with _logger calls to eliminate silent failures. Added top-level logger import, removed late imports.
 * @rejected Keeping print() statements with "Replace with proper logging" comments was rejected — they produce no structured output and cannot be filtered by log level.
 */

// --- _load_plugins (backend/src/core/plugin_loader.py)
/**!
 * @brief Scans the plugin directory and loads all valid plugins.
 * @post _load_module is called for each .py file.
 * @pre plugin_dir exists or can be created.
 */

// --- _load_module (backend/src/core/plugin_loader.py)
/**!
 * @brief Loads a single Python module and discovers PluginBase implementations.
 * @param file_path (str) - The path to the module file.
 * @post Plugin classes are instantiated and registered.
 * @pre module_name and file_path are valid.
 */

// --- _register_plugin (backend/src/core/plugin_loader.py)
/**!
 * @brief Registers a PluginBase instance and its configuration.
 * @param plugin_instance (PluginBase) - The plugin instance to register.
 * @post Plugin is added to _plugins and _plugin_configs.
 * @pre plugin_instance is a valid implementation of PluginBase.
 */

// --- get_plugin (backend/src/core/plugin_loader.py)
/**!
 * @brief Retrieves a loaded plugin instance by its ID.
 * @param plugin_id (str) - The unique identifier of the plugin.
 * @post Returns plugin instance or None.
 * @pre plugin_id is a string.
 * @return Optional[PluginBase] - The plugin instance if found, otherwise None.
 */

// --- get_all_plugin_configs (backend/src/core/plugin_loader.py)
/**!
 * @brief Returns a list of all registered plugin configurations.
 * @post Returns list of all PluginConfig objects.
 * @pre None.
 * @return List[PluginConfig] - A list of plugin configurations.
 */

// --- has_plugin (backend/src/core/plugin_loader.py)
/**!
 * @brief Checks if a plugin with the given ID is registered.
 * @param plugin_id (str) - The unique identifier of the plugin.
 * @post Returns True if plugin exists.
 * @pre plugin_id is a string.
 * @return bool - True if the plugin is registered, False otherwise.
 */

// --- SchedulerModule (backend/src/core/scheduler.py)
/**!
 * @brief Manages scheduled tasks using APScheduler.
 * @complexity 3
 * @layer Core
 */

// --- SchedulerService (backend/src/core/scheduler.py)
/**!
 * @brief Provides a service to manage scheduled backup tasks.
 * @complexity 3
 */

// --- start (backend/src/core/scheduler.py)
/**!
 * @brief Starts the background scheduler and loads initial schedules.
 * @post Scheduler is running and schedules are loaded.
 * @pre Scheduler should be initialized.
 */

// --- stop (backend/src/core/scheduler.py)
/**!
 * @brief Stops the background scheduler.
 * @post Scheduler is shut down.
 * @pre Scheduler should be running.
 */

// --- load_schedules (backend/src/core/scheduler.py)
/**!
 * @brief Load backup and active translation schedules from config and DB, re-registering all jobs.
 * @complexity 4
 * @post All enabled backup jobs and active translation schedules are re-registered in APScheduler.
 * @pre config_manager must have valid configuration; database is accessible.
 * @side_effect Removes all existing APScheduler jobs; queries translation_schedules table; registers APScheduler jobs for translation.
 */

// --- add_backup_job (backend/src/core/scheduler.py)
/**!
 * @brief Adds a scheduled backup job for an environment.
 * @param cron_expression (str) - The cron expression for the schedule.
 * @post A new job is added to the scheduler or replaced if it already exists.
 * @pre env_id and cron_expression must be valid strings.
 */

// --- add_translation_job (backend/src/core/scheduler.py)
/**!
 * @brief Register a translation schedule with APScheduler.
 * @complexity 4
 * @post A new APScheduler job is registered or replaced if it already exists.
 * @pre schedule_id, job_id, and cron_expression are valid strings.
 * @side_effect Mutates APScheduler state; calls execute_scheduled_translation on trigger.
 */

// --- remove_translation_job (backend/src/core/scheduler.py)
/**!
 * @brief Remove a translation schedule from APScheduler.
 * @complexity 4
 * @post The APScheduler job is removed if it exists; silently ignored otherwise.
 * @pre schedule_id is a valid string.
 * @side_effect Mutates APScheduler state.
 */

// --- _trigger_backup (backend/src/core/scheduler.py)
/**!
 * @brief Triggered by the scheduler to start a backup task.
 * @param env_id (str) - The ID of the environment.
 * @post A new backup task is created in the task manager if not already running.
 * @pre env_id must be a valid environment ID.
 */

// --- add_validation_job (backend/src/core/scheduler.py)
/**!
 * @brief Register a validation policy schedule with APScheduler.
 * @complexity 3
 * @post A new APScheduler job is registered or replaced if it already exists.
 * @pre policy_id and cron_expression are valid strings.
 * @side_effect Mutates APScheduler state; calls _trigger_validation on trigger.
 */

// --- remove_validation_job (backend/src/core/scheduler.py)
/**!
 * @brief Remove a validation policy schedule from APScheduler.
 * @complexity 2
 * @post The APScheduler job is removed if it exists; silently ignored otherwise.
 * @pre policy_id is a valid string.
 * @side_effect Mutates APScheduler state.
 */

// --- reload_validation_policy (backend/src/core/scheduler.py)
/**!
 * @brief Reload a single validation policy schedule — calls remove then add.
 * @complexity 2
 * @post Old job is removed; new job is registered if policy is active and has schedule_days.
 * @pre policy_id is a valid ValidationPolicy id with schedule data in DB.
 * @side_effect Mutates APScheduler state; queries ValidationPolicy from DB.
 */

// --- _trigger_validation (backend/src/core/scheduler.py)
/**!
 * @brief APScheduler job handler — triggers validation runs for a policy.
 * @complexity 3
 * @post A validation task is spawned via TaskManager for each dashboard in the policy.
 * @pre policy_id is a valid ValidationPolicy id with dashboard_ids.
 * @side_effect Creates TaskRecord entries for validation runs; logs progress.
 */

// --- ThrottledSchedulerConfigurator (backend/src/core/scheduler.py)
/**!
 * @brief Distributes validation tasks evenly within an execution window.
 * @complexity 5
 * @data_contract Input[window_start, window_end, dashboard_ids, current_date] -> Output[List[EXT:Python:datetime]]
 * @invariant Returned schedule size always matches number of dashboard IDs.
 * @post Produces deterministic per-dashboard run timestamps within the configured window.
 * @pre Validation policies provide a finite dashboard list and a valid execution window.
 * @side_effect Emits warning logs for degenerate or near-zero scheduling windows.
 */

// --- calculate_schedule (backend/src/core/scheduler.py)
/**!
 * @brief Calculates execution times for N tasks within a window.
 * @invariant Tasks are distributed with near-even spacing.
 * @post Returns List[EXT:Python:datetime] of scheduled times.
 * @pre window_start, window_end (time), dashboard_ids (List), current_date (date).
 */

// --- SupersetClientModule (backend/src/core/superset_client/__init__.py)
/**!
 * @brief Предоставляет высокоуровневый клиент для взаимодействия с Superset REST API, инкапсулируя логику запросов, обработку ошибок и пагинацию.
 * @complexity 5
 * @invariant All network operations must use the internal APIClient instance.
 * @layer Service
 * @public_api SupersetClient
 * @rationale Decomposed from monolithic superset_client.py (2145 lines) into
 */

// --- SupersetClient (backend/src/core/superset_client/__init__.py)
/**!
 * @brief Класс-обёртка над Superset REST API, предоставляющий методы для работы с дашбордами и датасетами.
 * @complexity 3
 */

// --- SupersetClientBase (backend/src/core/superset_client/_base.py)
/**!
 * @brief Base class for SupersetClient providing initialization, authentication, pagination, and import/export helpers.
 * @complexity 3
 * @layer Infrastructure
 * @rationale Extracted magic number 100 into DEFAULT_PAGE_SIZE constant at module level. Value unchanged — Superset API caps page_size at 100.
 */

// --- SupersetClientInit (backend/src/core/superset_client/_base.py)
/**!
 * @brief Инициализирует клиент, проверяет конфигурацию и создает сетевой клиент.
 * @complexity 3
 */

// --- SupersetClientAuthenticate (backend/src/core/superset_client/_base.py)
/**!
 * @brief Authenticates the client using the configured credentials.
 * @complexity 3
 */

// --- SupersetClientHeaders (backend/src/core/superset_client/_base.py)
/**!
 * @brief Возвращает базовые HTTP-заголовки, используемые сетевым клиентом.
 * @complexity 1
 */

// --- SupersetClientValidateQueryParams (backend/src/core/superset_client/_base.py)
/**!
 * @brief Ensures query parameters have default page and page_size.
 * @complexity 1
 */

// --- SupersetClientFetchTotalObjectCount (backend/src/core/superset_client/_base.py)
/**!
 * @brief Fetches the total number of items for a given endpoint.
 * @complexity 1
 */

// --- SupersetClientFetchAllPages (backend/src/core/superset_client/_base.py)
/**!
 * @brief Iterates through all pages to collect all data items.
 * @complexity 1
 */

// --- SupersetClientDoImport (backend/src/core/superset_client/_base.py)
/**!
 * @brief Performs the actual multipart upload for import.
 * @complexity 1
 */

// --- SupersetClientValidateExportResponse (backend/src/core/superset_client/_base.py)
/**!
 * @brief Validates that the export response is a non-empty ZIP archive.
 * @complexity 1
 */

// --- SupersetClientResolveExportFilename (backend/src/core/superset_client/_base.py)
/**!
 * @brief Determines the filename for an exported dashboard.
 * @complexity 1
 */

// --- SupersetClientValidateImportFile (backend/src/core/superset_client/_base.py)
/**!
 * @brief Validates that the file to be imported is a valid ZIP with metadata.yaml.
 * @complexity 1
 */

// --- SupersetClientResolveTargetIdForDelete (backend/src/core/superset_client/_base.py)
/**!
 * @brief Resolves a dashboard ID from either an ID or a slug.
 * @complexity 1
 */

// --- SupersetClientGetAllResources (backend/src/core/superset_client/_base.py)
/**!
 * @brief Fetches all resources of a given type with id, uuid, and name columns.
 * @complexity 3
 */

// --- SupersetChartsMixin (backend/src/core/superset_client/_charts.py)
/**!
 * @brief Chart domain mixin for SupersetClient — list, get, extract IDs from layout.
 * @complexity 3
 * @layer Infrastructure
 */

// --- SupersetClientGetChart (backend/src/core/superset_client/_charts.py)
/**!
 * @brief Fetches a single chart by ID.
 * @complexity 3
 */

// --- SupersetClientGetCharts (backend/src/core/superset_client/_charts.py)
/**!
 * @brief Fetches all charts with pagination support.
 * @complexity 3
 */

// --- SupersetClientExtractChartIdsFromLayout (backend/src/core/superset_client/_charts.py)
/**!
 * @brief Traverses dashboard layout metadata and extracts chart IDs from common keys.
 * @complexity 1
 */

// --- SupersetDashboardsCrudMixin (backend/src/core/superset_client/_dashboards_crud.py)
/**!
 * @brief Dashboard CRUD mixin for SupersetClient — detail, export, import, delete.
 * @complexity 3
 * @layer Infrastructure
 */

// --- SupersetClientGetDashboardDetail (backend/src/core/superset_client/_dashboards_crud.py)
/**!
 * @brief Fetches detailed dashboard information including related charts and datasets.
 * @complexity 3
 */

// --- extract_dataset_id_from_form_data (backend/src/core/superset_client/_dashboards_crud.py)
/**!
 */

// --- SupersetClientExportDashboard (backend/src/core/superset_client/_dashboards_crud.py)
/**!
 * @brief Экспортирует дашборд в виде ZIP-архива.
 * @complexity 3
 * @side_effect Performs network I/O to download archive.
 */

// --- SupersetClientImportDashboard (backend/src/core/superset_client/_dashboards_crud.py)
/**!
 * @brief Импортирует дашборд из ZIP-файла.
 * @complexity 3
 * @side_effect Performs network I/O to upload archive.
 */

// --- SupersetClientDeleteDashboard (backend/src/core/superset_client/_dashboards_crud.py)
/**!
 * @brief Удаляет дашборд по его ID или slug.
 * @complexity 3
 * @side_effect Deletes resource from upstream Superset environment.
 */

// --- SupersetDashboardsFiltersMixin (backend/src/core/superset_client/_dashboards_filters.py)
/**!
 * @brief Dashboard native filter extraction mixin for SupersetClient.
 * @complexity 3
 * @layer Infrastructure
 */

// --- SupersetClientGetDashboard (backend/src/core/superset_client/_dashboards_filters.py)
/**!
 * @brief Fetches a single dashboard by ID or slug.
 * @complexity 3
 */

// --- SupersetClientGetDashboardPermalinkState (backend/src/core/superset_client/_dashboards_filters.py)
/**!
 * @brief Fetches stored dashboard permalink state by permalink key.
 * @complexity 2
 */

// --- SupersetClientGetNativeFilterState (backend/src/core/superset_client/_dashboards_filters.py)
/**!
 * @brief Fetches stored native filter state by filter state key.
 * @complexity 2
 */

// --- SupersetClientExtractNativeFiltersFromPermalink (backend/src/core/superset_client/_dashboards_filters.py)
/**!
 * @brief Extract native filters dataMask from a permalink key.
 * @complexity 3
 */

// --- SupersetClientExtractNativeFiltersFromKey (backend/src/core/superset_client/_dashboards_filters.py)
/**!
 * @brief Extract native filters from a native_filters_key URL parameter.
 * @complexity 3
 */

// --- SupersetClientParseDashboardUrlForFilters (backend/src/core/superset_client/_dashboards_filters.py)
/**!
 * @brief Parse a Superset dashboard URL and extract native filter state if present.
 * @complexity 3
 */

// --- SupersetDashboardsListMixin (backend/src/core/superset_client/_dashboards_list.py)
/**!
 * @brief Dashboard listing mixin for SupersetClient — paginated list, summary projection.
 * @complexity 3
 * @layer Infrastructure
 */

// --- SupersetClientGetDashboards (backend/src/core/superset_client/_dashboards_list.py)
/**!
 * @brief Получает полный список дашбордов, автоматически обрабатывая пагинацию.
 * @complexity 3
 */

// --- SupersetClientGetDashboardsPage (backend/src/core/superset_client/_dashboards_list.py)
/**!
 * @brief Fetches a single dashboards page from Superset without iterating all pages.
 * @complexity 3
 */

// --- SupersetClientGetDashboardsSummary (backend/src/core/superset_client/_dashboards_list.py)
/**!
 * @brief Fetches dashboard metadata optimized for the grid.
 * @complexity 3
 */

// --- SupersetClientGetDashboardsSummaryPage (backend/src/core/superset_client/_dashboards_list.py)
/**!
 * @brief Fetches one page of dashboard metadata optimized for the grid.
 * @complexity 3
 */

// --- SupersetDashboardsWriteMixin (backend/src/core/superset_client/_dashboards_write.py)
/**!
 * @brief Dashboard write mixin for SupersetClient — markdown chart CRUD and layout manipulation for maintenance banners.
 * @complexity 4
 * @data_contract Input: dashboard_id / chart_id / markdown_text → Output: API response dict or chart_id int
 * @invariant All network operations use self.network.request()
 * @layer Infrastructure
 * @rationale Extracted from monolithic superset_client to satisfy INV_7.
 * @side_effect Creates, updates, deletes markdown charts & modifies dashboard layout via Superset API.
 */

// --- create_markdown_chart (backend/src/core/superset_client/_dashboards_write.py)
/**!
 * @brief Create a markdown chart and return the new chart ID.
 * @complexity 3
 * @post Returns chart_id (int). Chart is NOT yet placed in dashboard layout.
 * @pre dashboard_id exists in Superset. markdown_text not empty.
 * @side_effect Creates a new chart resource in Superset.
 */

// --- update_markdown_chart (backend/src/core/superset_client/_dashboards_write.py)
/**!
 * @brief Update the markdown text of an existing markdown chart.
 * @complexity 3
 * @post Chart markdown content updated.
 * @pre chart_id exists and is a markdown chart.
 * @side_effect Modifies a chart resource in Superset.
 */

// --- update_dashboard_layout (backend/src/core/superset_client/_dashboards_write.py)
/**!
 * @brief Insert a native MARKDOWN element at (0,0) with full width (12 cols),
 * @complexity 4
 */

// --- remove_chart_from_layout (backend/src/core/superset_client/_dashboards_write.py)
/**!
 * @brief Remove banner markdown element from dashboard layout without deleting the chart.
 * @complexity 3
 * @post MARKDOWN element removed from position_json; items shifted up.
 * @pre dashboard_id exists. chart_id exists in layout as MARKDOWN-banner-{chart_id}.
 * @side_effect Modifies dashboard layout JSON.
 */

// --- delete_chart (backend/src/core/superset_client/_dashboards_write.py)
/**!
 * @brief Delete a chart from Superset by ID.
 * @complexity 3
 * @post Chart permanently deleted from Superset.
 * @pre chart_id exists.
 * @side_effect Destroys chart resource.
 */

// --- update_banner_on_dashboard (backend/src/core/superset_client/_dashboards_write.py)
/**!
 * @brief Update the content of a native MARKDOWN banner element on a dashboard.
 * @complexity 3
 * @post MARKDOWN element content updated on dashboard.
 * @pre dashboard_id exists. chart_id used for key lookup.
 * @side_effect Modifies dashboard layout JSON in Superset.
 */

// --- get_dashboard_layout (backend/src/core/superset_client/_dashboards_write.py)
/**!
 * @brief Fetch the position_json layout of a dashboard.
 * @complexity 3
 * @post Returns the dashboard layout dict.
 * @pre dashboard_id exists.
 */

// --- _resolve_markdown_datasource (backend/src/core/superset_client/_dashboards_write.py)
/**!
 * @brief Find a valid datasource_id for markdown chart creation.
 * @complexity 2
 * @post Returns an integer datasource_id.
 * @pre dashboard_id exists.
 */

// --- SupersetDatabasesMixin (backend/src/core/superset_client/_databases.py)
/**!
 * @brief Database domain mixin for SupersetClient — list, get, summary, by_uuid.
 * @complexity 3
 * @layer Infrastructure
 */

// --- SupersetClientGetDatabases (backend/src/core/superset_client/_databases.py)
/**!
 * @brief Получает полный список баз данных.
 * @complexity 3
 */

// --- SupersetClientGetDatabase (backend/src/core/superset_client/_databases.py)
/**!
 * @brief Получает информацию о конкретной базе данных по её ID.
 * @complexity 3
 */

// --- SupersetClientGetDatabasesSummary (backend/src/core/superset_client/_databases.py)
/**!
 * @brief Fetch a summary of databases including uuid, name, and engine.
 * @complexity 3
 */

// --- SupersetClientGetDatabaseByUuid (backend/src/core/superset_client/_databases.py)
/**!
 * @brief Find a database by its UUID.
 * @complexity 3
 */

// --- SupersetDatasetsMixin (backend/src/core/superset_client/_datasets.py)
/**!
 * @brief Dataset domain mixin for SupersetClient — list, get, detail, update.
 * @complexity 3
 * @layer Infrastructure
 */

// --- SupersetClientGetDatasets (backend/src/core/superset_client/_datasets.py)
/**!
 * @brief Получает полный список датасетов, автоматически обрабатывая пагинацию.
 * @complexity 3
 */

// --- SupersetClientGetDatasetsSummary (backend/src/core/superset_client/_datasets.py)
/**!
 * @brief Fetches dataset metadata optimized for the Dataset Hub grid.
 * @complexity 3
 */

// --- SupersetClientGetDatasetLinkedDashboardCount (backend/src/core/superset_client/_datasets.py)
/**!
 * @brief Fetch the number of dashboards linked to a dataset via related_objects endpoint.
 * @complexity 2
 * @rationale Added to fix linked_count=0 in StatsBar. Reuses the same /dataset/{id}/related_objects call
 */

// --- SupersetClientGetDatasetDetail (backend/src/core/superset_client/_datasets.py)
/**!
 * @brief Fetches detailed dataset information including columns and linked dashboards.
 * @complexity 3
 */

// --- SupersetClientGetDataset (backend/src/core/superset_client/_datasets.py)
/**!
 * @brief Получает информацию о конкретном датасете по его ID.
 * @complexity 3
 */

// --- SupersetClientUpdateDataset (backend/src/core/superset_client/_datasets.py)
/**!
 * @brief Обновляет данные датасета по его ID.
 * @complexity 3
 * @side_effect Modifies resource in upstream Superset environment.
 */

// --- SupersetDatasetsPreviewMixin (backend/src/core/superset_client/_datasets_preview.py)
/**!
 * @brief Dataset preview compilation mixin for SupersetClient — build query context, compile SQL.
 * @complexity 4
 * @layer Infrastructure
 */

// --- SupersetClientCompileDatasetPreview (backend/src/core/superset_client/_datasets_preview.py)
/**!
 * @brief Compile dataset preview SQL through the strongest supported Superset preview endpoint family and return normalized SQL output.
 * @complexity 4
 */

// --- SupersetClientBuildDatasetPreviewLegacyFormData (backend/src/core/superset_client/_datasets_preview.py)
/**!
 * @brief Build browser-style legacy form_data payload for Superset preview endpoints inferred from observed deployment traffic.
 * @complexity 4
 */

// --- SupersetClientBuildDatasetPreviewQueryContext (backend/src/core/superset_client/_datasets_preview.py)
/**!
 * @brief Build a reduced-scope chart-data query context for deterministic dataset preview compilation.
 * @complexity 4
 */

// --- SupersetDatasetsPreviewFiltersMixin (backend/src/core/superset_client/_datasets_preview_filters.py)
/**!
 * @brief Filter normalization and SQL extraction helpers for dataset preview compilation.
 * @complexity 3
 * @layer Infrastructure
 */

// --- SupersetClientNormalizeEffectiveFiltersForQueryContext (backend/src/core/superset_client/_datasets_preview_filters.py)
/**!
 * @brief Convert execution mappings into Superset chart-data filter objects.
 * @complexity 3
 */

// --- SupersetClientExtractCompiledSqlFromPreviewResponse (backend/src/core/superset_client/_datasets_preview_filters.py)
/**!
 * @brief Normalize compiled SQL from either chart-data or legacy form_data preview responses.
 * @complexity 3
 */

// --- LayoutUtils (backend/src/core/superset_client/_layout_utils.py)
/**!
 * @brief Utility functions for manipulating Superset dashboard position_json layout.
 * @complexity 2
 * @layer Infrastructure
 * @rationale Extracted from SupersetDashboardsWriteMixin to stay under INV_7 400 LOC.
 */

// --- parse_position_json (backend/src/core/superset_client/_layout_utils.py)
/**!
 * @brief Parse position_json from a dashboard API response (may be string or dict).
 * @complexity 1
 * @post Returns a dict.
 * @pre raw_position is a string, dict, or None.
 */

// --- _estimate_markdown_height (backend/src/core/superset_client/_layout_utils.py)
/**!
 * @brief Estimate grid height for a MARKDOWN element based on HTML content.
 * @complexity 1
 */

// --- _generate_banner_id (backend/src/core/superset_client/_layout_utils.py)
/**!
 * @brief Generate a deterministic row and markdown key for a banner chart.
 * @complexity 1
 */

// --- insert_banner_markdown_at_top (backend/src/core/superset_client/_layout_utils.py)
/**!
 * @brief Insert a ROW + native MARKDOWN pair at the top of the dashboard grid.
 * @complexity 2
 */

// --- update_banner_markdown_content (backend/src/core/superset_client/_layout_utils.py)
/**!
 * @brief Update the code content and adaptive height of an existing banner markdown element.
 * @complexity 1
 * @post position_json is mutated; markdown content and height updated.
 * @pre position_json has markdown_key. content is the new HTML/markdown string.
 */

// --- remove_banner_from_position (backend/src/core/superset_client/_layout_utils.py)
/**!
 * @brief Remove the banner ROW + MARKDOWN pair from the position dict and GRID children.
 * @complexity 2
 */

// --- SupersetUserProjection (backend/src/core/superset_client/_user_projection.py)
/**!
 * @brief User/owner payload normalization helpers for Superset client responses.
 * @complexity 2
 * @layer Infrastructure
 */

// --- SupersetUserProjectionMixin (backend/src/core/superset_client/_user_projection.py)
/**!
 * @brief Mixin providing user/owner payload normalization for Superset API responses.
 * @complexity 2
 */

// --- SupersetClientExtractOwnerLabels (backend/src/core/superset_client/_user_projection.py)
/**!
 * @brief Normalize dashboard owners payload to stable display labels.
 * @complexity 1
 */

// --- SupersetClientExtractUserDisplay (backend/src/core/superset_client/_user_projection.py)
/**!
 * @brief Normalize user payload to a stable display name.
 * @complexity 1
 */

// --- SupersetClientSanitizeUserText (backend/src/core/superset_client/_user_projection.py)
/**!
 * @brief Convert scalar value to non-empty user-facing text.
 * @complexity 1
 */

// --- SupersetProfileLookup (backend/src/core/superset_profile_lookup.py)
/**!
 * @brief Provides environment-scoped Superset account lookup adapter with stable normalized output.
 * @complexity 5
 * @data_contract ProfileQuery -> SupersetProfile
 * @invariant Adapter never leaks raw upstream payload shape to API consumers.
 * @layer Service
 * @side_effect Makes HTTP requests to Superset
 */

// --- SupersetAccountLookupAdapter (backend/src/core/superset_profile_lookup.py)
/**!
 * @brief Lookup Superset users and normalize candidates for profile binding.
 * @complexity 3
 */

// --- __init__ (backend/src/core/superset_profile_lookup.py)
/**!
 * @brief Initializes lookup adapter with authenticated API client and environment context.
 * @post Adapter is ready to perform users lookup requests.
 * @pre network_client supports request(method, endpoint, params=...).
 */

// --- get_users_page (backend/src/core/superset_profile_lookup.py)
/**!
 * @brief Fetch one users page from Superset with passthrough search/sort parameters.
 * @post Returns deterministic payload with normalized items and total count.
 * @pre page_index >= 0 and page_size >= 1.
 * @return Dict[str, Any]
 */

// --- _normalize_lookup_payload (backend/src/core/superset_profile_lookup.py)
/**!
 * @brief Convert Superset users response variants into stable candidates payload.
 * @post Output contains canonical keys: status, environment_id, page_index, page_size, total, items.
 * @pre response can be dict/list in any supported upstream shape.
 * @return Dict[str, Any]
 */

// --- normalize_user_payload (backend/src/core/superset_profile_lookup.py)
/**!
 * @brief Project raw Superset user object to canonical candidate shape.
 * @post Returns normalized candidate keys (environment_id, username, display_name, email, is_active).
 * @pre raw_user may have heterogenous key names between Superset versions.
 * @return Dict[str, Any]
 */

// --- TaskManagerPackage (backend/src/core/task_manager/__init__.py)
/**!
 */

// --- TestContext (backend/src/core/task_manager/__tests__/test_context.py)
/**!
 * @brief Verify TaskContext preserves optional background task scheduler across sub-context creation.
 * @complexity 3
 */

// --- test_task_context_preserves_background_tasks_across_sub_context (backend/src/core/task_manager/__tests__/test_context.py)
/**!
 * @brief Plugins must be able to access background_tasks from both root and sub-context loggers.
 * @post background_tasks remains available on root and derived sub-contexts.
 * @pre TaskContext is initialized with a BackgroundTasks-like object.
 */

// --- __tests__/test_task_logger (backend/src/core/task_manager/__tests__/test_task_logger.py)
/**!
 * @brief Contract testing for TaskLogger
 */

// --- test_task_logger_initialization (backend/src/core/task_manager/__tests__/test_task_logger.py)
/**!
 * @brief Verify TaskLogger initializes with correct task_id and state.
 * @test_contract invariants -> "All specific log methods (info, error) delegate to _log"
 */

// --- test_log_methods_delegation (backend/src/core/task_manager/__tests__/test_task_logger.py)
/**!
 * @brief Verify TaskLogger delegates log method calls to the underlying persistence service.
 * @test_contract invariants -> "with_source creates a new logger with the same task_id"
 */

// --- test_with_source (backend/src/core/task_manager/__tests__/test_task_logger.py)
/**!
 * @brief Verify TaskLogger.with_source returns a new logger with the correct source attribution.
 * @test_edge missing_task_id -> raises TypeError
 */

// --- test_missing_task_id (backend/src/core/task_manager/__tests__/test_task_logger.py)
/**!
 * @brief Verify TaskLogger raises or handles missing task_id gracefully.
 * @test_edge invalid_add_log_fn -> raises TypeError
 */

// --- test_invalid_add_log_fn (backend/src/core/task_manager/__tests__/test_task_logger.py)
/**!
 * @brief Verify TaskLogger raises ValueError for invalid add_log_fn parameter.
 * @test_invariant consistent_delegation
 */

// --- test_progress_log (backend/src/core/task_manager/__tests__/test_task_logger.py)
/**!
 * @brief Verify TaskLogger correctly logs progress updates with percentage and message.
 */

// --- TaskCleanupModule (backend/src/core/task_manager/cleanup.py)
/**!
 * @brief Implements task cleanup and retention policies, including associated logs.
 * @complexity 3
 * @layer Core
 */

// --- TaskCleanupService (backend/src/core/task_manager/cleanup.py)
/**!
 * @brief Provides methods to clean up old task records and their associated logs.
 * @complexity 3
 */

// --- run_cleanup (backend/src/core/task_manager/cleanup.py)
/**!
 * @brief Deletes tasks older than the configured retention period and their logs.
 * @post Old tasks and their logs are deleted from persistence.
 * @pre Config manager has valid settings.
 */

// --- delete_task_with_logs (backend/src/core/task_manager/cleanup.py)
/**!
 * @brief Delete a single task and all its associated logs.
 * @param task_id (str) - The task ID to delete.
 * @post Task and all its logs are deleted.
 * @pre task_id is a valid task ID.
 */

// --- TaskContextModule (backend/src/core/task_manager/context.py)
/**!
 * @brief Provides execution context passed to plugins during task execution.
 * @complexity 5
 * @data_contract Input[task_id, add_log_fn, params, default_source, background_tasks] -> Output[TaskContext]
 * @invariant Each TaskContext is bound to a single task execution.
 * @layer Core
 * @post Plugins receive context instances with stable logger and parameter accessors.
 * @pre Task execution pipeline provides valid task identifiers, logging callbacks, and parameter dictionaries.
 * @side_effect Creates task-scoped logger wrappers and carries optional background task handles across sub-contexts.
 */

// --- TaskContext (backend/src/core/task_manager/context.py)
/**!
 * @brief A container passed to plugin.execute() providing the logger and other task-specific utilities.
 * @complexity 5
 * @data_contract Input[task_id, add_log_fn, params, default_source, background_tasks] -> Output[TaskContext]
 * @invariant logger is always a valid TaskLogger instance.
 * @post Instance exposes immutable task identity with logger, params, and optional background task access.
 * @pre Constructor receives non-empty task_id, callable add_log_fn, and params mapping.
 * @side_effect Emits structured task logs through TaskLogger on plugin interactions.
 * @test_contract TaskContextContract ->
 * @ux_state Idle -> Active -> Complete
 */

// --- task_id (backend/src/core/task_manager/context.py)
/**!
 * @brief Get the task ID.
 * @post Returns the task ID string.
 * @pre TaskContext must be initialized.
 * @return str - The task ID.
 */

// --- logger (backend/src/core/task_manager/context.py)
/**!
 * @brief Get the TaskLogger instance for this context.
 * @post Returns the TaskLogger instance.
 * @pre TaskContext must be initialized.
 * @return TaskLogger - The logger instance.
 */

// --- params (backend/src/core/task_manager/context.py)
/**!
 * @brief Get the task parameters.
 * @post Returns the parameters dictionary.
 * @pre TaskContext must be initialized.
 * @return Dict[str, Any] - The task parameters.
 */

// --- background_tasks (backend/src/core/task_manager/context.py)
/**!
 * @brief Expose optional background task scheduler for plugins that dispatch deferred side effects.
 * @post Returns BackgroundTasks-like object or None.
 * @pre TaskContext must be initialized.
 */

// --- get_param (backend/src/core/task_manager/context.py)
/**!
 * @brief Get a specific parameter value with optional default.
 * @param default (Any) - Default value if key not found.
 * @post Returns parameter value or default.
 * @pre TaskContext must be initialized.
 * @return Any - Parameter value or default.
 */

// --- create_sub_context (backend/src/core/task_manager/context.py)
/**!
 * @brief Create a sub-context with a different default source.
 * @param source (str) - New default source for logging.
 * @post Returns new TaskContext with different logger source.
 * @pre source is a non-empty string.
 * @return TaskContext - New context with different source.
 */

// --- EventBusModule (backend/src/core/task_manager/event_bus.py)
/**!
 * @brief Task-scoped log buffering, persistence flushes, and subscriber fan-out for real-time
 * @complexity 5
 */

// --- EventBus (backend/src/core/task_manager/event_bus.py)
/**!
 * @brief Coordinates task-scoped log buffering, persistence flushes, and subscriber fan-out
 * @complexity 5
 */

// --- flush_task_logs (backend/src/core/task_manager/event_bus.py)
/**!
 * @brief Flush logs for a specific task immediately.
 * @complexity 3
 * @post Task's buffered logs are written to database.
 * @pre task_id exists.
 */

// --- add_log (backend/src/core/task_manager/event_bus.py)
/**!
 * @brief Adds a log entry to a task buffer and notifies subscribers.
 * @complexity 3
 * @post Log added to buffer and pushed to queues (if level meets task_log_level filter).
 * @pre Task exists.
 */

// --- TaskGraphModule (backend/src/core/task_manager/graph.py)
/**!
 * @brief In-memory task registry with persistence-backed hydration, pagination, and
 * @complexity 5
 */

// --- TaskGraph (backend/src/core/task_manager/graph.py)
/**!
 * @brief In-memory task dependency graph spanning task registry nodes, pause futures,
 * @complexity 5
 */

// --- add_task (backend/src/core/task_manager/graph.py)
/**!
 * @brief Register a task in the in-memory registry.
 * @complexity 2
 */

// --- remove_tasks (backend/src/core/task_manager/graph.py)
/**!
 * @brief Remove tasks from registry and persistence, cancel futures for waiting tasks.
 * @complexity 3
 */

// --- create_future (backend/src/core/task_manager/graph.py)
/**!
 * @brief Create and store a future for a paused task.
 * @complexity 1
 */

// --- resolve_future (backend/src/core/task_manager/graph.py)
/**!
 * @brief Resolve a paused task's future and remove it from the map.
 * @complexity 1
 */

// --- remove_future (backend/src/core/task_manager/graph.py)
/**!
 * @brief Remove a future without resolving it.
 * @complexity 1
 */

// --- JobLifecycleModule (backend/src/core/task_manager/lifecycle.py)
/**!
 * @brief Task creation, execution, pause/resume, and completion transitions for plugin-backed
 * @complexity 5
 */

// --- JobLifecycle (backend/src/core/task_manager/lifecycle.py)
/**!
 * @brief Encodes task creation, execution, pause/resume, and completion transitions for
 * @complexity 5
 */

// --- _broadcast_dataset_updated (backend/src/core/task_manager/lifecycle.py)
/**!
 * @brief Broadcast dataset.updated event to all subscribers for a given environment.
 * @complexity 3
 */

// --- TaskManagerModule (backend/src/core/task_manager/manager.py)
/**!
 * @brief Thin facade composing TaskGraph (registry), EventBus (log/pub-sub), and JobLifecycle
 * @complexity 5
 */

// --- TaskManager (backend/src/core/task_manager/manager.py)
/**!
 * @brief Facade composing TaskGraph, EventBus, and JobLifecycle into a single interface.
 * @complexity 5
 * @layer Core
 * @post In-memory task graph, lifecycle scheduler, and log event bus stay consistent with
 * @pre Plugin loader resolves plugin ids and persistence services are available.
 */

// --- _make_add_log_callback (backend/src/core/task_manager/manager.py)
/**!
 * @brief Create a closure for adding logs that looks up the task and delegates to EventBus.
 * @complexity 2
 */

// --- _flusher_loop (backend/src/core/task_manager/manager.py)
/**!
 * @brief Legacy alias delegating to EventBus._flusher_loop.
 * @complexity 3
 */

// --- _flush_logs (backend/src/core/task_manager/manager.py)
/**!
 * @brief Legacy alias delegating to EventBus._flush_logs.
 * @complexity 3
 */

// --- _flush_task_logs (backend/src/core/task_manager/manager.py)
/**!
 * @brief Legacy alias delegating to EventBus.flush_task_logs.
 * @complexity 3
 */

// --- get_task (backend/src/core/task_manager/manager.py)
/**!
 * @brief Retrieves a task by its ID.
 * @complexity 2
 */

// --- get_all_tasks (backend/src/core/task_manager/manager.py)
/**!
 * @brief Retrieves all registered tasks.
 * @complexity 1
 */

// --- get_tasks (backend/src/core/task_manager/manager.py)
/**!
 * @brief Retrieves tasks with pagination and optional status filter.
 * @complexity 3
 */

// --- load_persisted_tasks (backend/src/core/task_manager/manager.py)
/**!
 * @brief Load persisted tasks using persistence service.
 * @complexity 2
 */

// --- clear_tasks (backend/src/core/task_manager/manager.py)
/**!
 * @brief Clears tasks based on status filter (also deletes associated logs).
 * @complexity 4
 * @side_effect Removes tasks from registry and persistence; cancels futures.
 */

// --- get_task_logs (backend/src/core/task_manager/manager.py)
/**!
 * @brief Retrieves logs for a specific task (from memory or persistence).
 * @complexity 3
 */

// --- get_task_log_stats (backend/src/core/task_manager/manager.py)
/**!
 * @brief Get statistics about logs for a task.
 * @complexity 2
 */

// --- get_task_log_sources (backend/src/core/task_manager/manager.py)
/**!
 * @brief Get unique sources for a task's logs.
 * @complexity 2
 */

// --- subscribe_logs (backend/src/core/task_manager/manager.py)
/**!
 * @brief Subscribes to real-time logs for a task.
 * @complexity 2
 */

// --- unsubscribe_logs (backend/src/core/task_manager/manager.py)
/**!
 * @brief Unsubscribes from real-time logs for a task.
 * @complexity 2
 */

// --- create_task (backend/src/core/task_manager/manager.py)
/**!
 * @brief Creates and queues a new task for execution.
 * @complexity 4
 */

// --- _run_task (backend/src/core/task_manager/manager.py)
/**!
 * @brief Internal method to execute a task with TaskContext support (delegates to lifecycle).
 * @complexity 4
 */

// --- resolve_task (backend/src/core/task_manager/manager.py)
/**!
 * @brief Resumes a task that is awaiting mapping.
 * @complexity 3
 */

// --- wait_for_resolution (backend/src/core/task_manager/manager.py)
/**!
 * @brief Pauses execution and waits for a resolution signal.
 * @complexity 3
 */

// --- wait_for_input (backend/src/core/task_manager/manager.py)
/**!
 * @brief Pauses execution and waits for user input.
 * @complexity 3
 */

// --- await_input (backend/src/core/task_manager/manager.py)
/**!
 * @brief Transition a task to AWAITING_INPUT state with input request.
 * @complexity 3
 */

// --- resume_task_with_password (backend/src/core/task_manager/manager.py)
/**!
 * @brief Resume a task that is awaiting input with provided passwords.
 * @complexity 3
 */

// --- subscribe_dataset_events (backend/src/core/task_manager/manager.py)
/**!
 * @brief Subscribe to dataset.updated events for an environment.
 * @complexity 2
 */

// --- unsubscribe_dataset_events (backend/src/core/task_manager/manager.py)
/**!
 * @brief Unsubscribe from dataset.updated events.
 * @complexity 2
 */

// --- TaskManagerModels (backend/src/core/task_manager/models.py)
/**!
 * @brief Defines the data models and enumerations used by the Task Manager.
 * @complexity 5
 * @data_contract TaskInput -> TaskModel
 * @invariant Must use Pydantic for data validation.
 * @layer Domain
 * @post Task models exported with immutable IDs
 * @pre Task manager initialized
 * @side_effect Defines task data schema
 */

// --- TaskStatus (backend/src/core/task_manager/models.py)
/**!
 */

// --- LogLevel (backend/src/core/task_manager/models.py)
/**!
 */

// --- TaskLog (backend/src/core/task_manager/models.py)
/**!
 * @brief A Pydantic model representing a persisted log entry from the database.
 * @complexity 3
 */

// --- LogFilter (backend/src/core/task_manager/models.py)
/**!
 */

// --- LogStats (backend/src/core/task_manager/models.py)
/**!
 * @brief Statistics about log entries for a task.
 * @complexity 1
 */

// --- Task (backend/src/core/task_manager/models.py)
/**!
 * @brief A Pydantic model representing a single execution instance of a plugin, including its status, parameters, and logs.
 * @complexity 3
 */

// --- TaskPersistenceModule (backend/src/core/task_manager/persistence.py)
/**!
 * @brief Handles the persistence of tasks using SQLAlchemy and the tasks.db database.
 * @complexity 5
 * @data_contract Input[Task, LogEntry] -> Model[TaskRecord, TaskLogRecord]
 * @invariant Database schema must match the TaskRecord model structure.
 * @layer Core
 * @post Provides reliable storage and retrieval for task metadata and logs.
 * @pre Tasks database must be initialized with TaskRecord and TaskLogRecord schemas.
 * @side_effect Performs database I/O on tasks.db.
 */

// --- TaskPersistenceService (backend/src/core/task_manager/persistence.py)
/**!
 * @brief Provides methods to save, load, and delete task records in tasks.db using SQLAlchemy models.
 * @complexity 5
 * @data_contract Input[Task | List[Task] | List[str] | Query(limit:int,status:Optional[TaskStatus])] -> Model[TaskRecord, Environment] -> Output[None | List[Task]]
 * @invariant Persistence must handle potentially missing task fields natively.
 * @post Persist operations leave matching TaskRecord rows committed or rolled back without leaking sessions, load operations return reconstructed Task objects from stored TaskRecord rows, and delete operations remove only the addressed task rows.
 * @pre TasksSessionLocal must provide an active SQLAlchemy session, Task inputs must expose id/plugin_id/status/params/result/logs fields, and TaskRecord plus Environment schemas must be available.
 * @side_effect Opens SQLAlchemy sessions, reads and writes task_records rows, resolves environment foreign keys against environments, commits or rolls back transactions, and emits error logs on persistence failures.
 * @test_contract TaskPersistenceContract ->
 */

// --- _json_load_if_needed (backend/src/core/task_manager/persistence.py)
/**!
 * @brief Safely load JSON strings from DB if necessary
 * @complexity 1
 * @post Returns parsed JSON object, list, string, or primitive
 * @pre value is an arbitrary database value
 */

// --- _parse_datetime (backend/src/core/task_manager/persistence.py)
/**!
 * @brief Safely parse a datetime string from the database
 * @complexity 1
 * @post Returns datetime object or None
 * @pre value is an ISO string or datetime object
 */

// --- _resolve_environment_id (backend/src/core/task_manager/persistence.py)
/**!
 * @brief Resolve environment id into existing environments.id value to satisfy FK constraints.
 * @complexity 3
 * @data_contract Input[env_id: Optional[str]] -> Output[Optional[str]]
 * @post Returns existing environments.id or None when unresolved.
 * @pre Session is active
 */

// --- persist_task (backend/src/core/task_manager/persistence.py)
/**!
 * @brief Persists or updates a single task in the database.
 * @complexity 3
 * @data_contract Input[Task] -> Model[TaskRecord]
 * @param task (Task) - The task object to persist.
 * @post Task record created or updated in database.
 * @pre isinstance(task, Task)
 * @side_effect Writes to task_records table in tasks.db
 */

// --- persist_tasks (backend/src/core/task_manager/persistence.py)
/**!
 * @brief Persists multiple tasks.
 * @complexity 3
 * @param tasks (List[Task]) - The list of tasks to persist.
 * @post All tasks in list are persisted.
 * @pre isinstance(tasks, list)
 */

// --- load_tasks (backend/src/core/task_manager/persistence.py)
/**!
 * @brief Loads tasks from the database.
 * @complexity 3
 * @data_contract Model[TaskRecord] -> Output[List[Task]]
 * @param status (Optional[TaskStatus]) - Filter by status.
 * @post Returns list of Task objects.
 * @pre limit is an integer.
 * @return List[Task] - The loaded tasks.
 */

// --- delete_tasks (backend/src/core/task_manager/persistence.py)
/**!
 * @brief Deletes specific tasks from the database.
 * @complexity 3
 * @param task_ids (List[str]) - List of task IDs to delete.
 * @post Specified task records deleted from database.
 * @pre task_ids is a list of strings.
 * @side_effect Deletes rows from task_records table.
 */

// --- TaskLogPersistenceService (backend/src/core/task_manager/persistence.py)
/**!
 * @brief Provides methods to store, query, summarize, and delete task log rows in the task_logs table.
 * @complexity 5
 * @data_contract Input[task_id:str, logs:List[LogEntry], log_filter:LogFilter, task_ids:List[str]] -> Model[TaskLogRecord] -> Output[None | List[TaskLog] | LogStats | List[str]]
 * @invariant Log entries are batch-inserted for performance.
 * @post add_logs commits all provided log entries or rolls back on failure, query methods return TaskLog or LogStats views reconstructed from TaskLogRecord rows, and delete methods remove only log rows matching the supplied task identifiers.
 * @pre TasksSessionLocal must provide an active SQLAlchemy session, task_id inputs must identify task log rows, LogEntry batches must expose timestamp/level/source/message/metadata fields, and LogFilter inputs must provide pagination and filter attributes used by queries.
 * @side_effect Opens SQLAlchemy sessions, inserts, reads, aggregates, and deletes task_logs rows, serializes log metadata to JSON, commits or rolls back transactions, and emits error logs on persistence failures.
 * @test_contract TaskLogPersistenceContract ->
 */

// --- add_logs (backend/src/core/task_manager/persistence.py)
/**!
 * @brief Batch insert log entries for a task.
 * @complexity 3
 * @data_contract Input[List[LogEntry]] -> Model[TaskLogRecord]
 * @param logs (List[LogEntry]) - Log entries to insert.
 * @post All logs inserted into task_logs table.
 * @pre logs is a list of LogEntry objects.
 * @side_effect Writes to task_logs table.
 */

// --- get_logs (backend/src/core/task_manager/persistence.py)
/**!
 * @brief Query logs for a task with filtering and pagination.
 * @complexity 3
 * @data_contract Model[TaskLogRecord] -> Output[List[TaskLog]]
 * @param log_filter (LogFilter) - Filter parameters.
 * @post Returns list of TaskLog objects matching filters.
 * @pre task_id is a valid task ID.
 * @return List[TaskLog] - Filtered log entries.
 */

// --- get_log_stats (backend/src/core/task_manager/persistence.py)
/**!
 * @brief Get statistics about logs for a task.
 * @complexity 3
 * @data_contract Model[TaskLogRecord] -> Output[LogStats]
 * @param task_id (str) - The task ID.
 * @post Returns LogStats with counts by level and source.
 * @pre task_id is a valid task ID.
 * @return LogStats - Statistics about task logs.
 */

// --- get_sources (backend/src/core/task_manager/persistence.py)
/**!
 * @brief Get unique sources for a task's logs.
 * @complexity 3
 * @data_contract Model[TaskLogRecord] -> Output[List[str]]
 * @param task_id (str) - The task ID.
 * @post Returns list of unique source strings.
 * @pre task_id is a valid task ID.
 * @return List[str] - Unique source names.
 */

// --- delete_logs_for_task (backend/src/core/task_manager/persistence.py)
/**!
 * @brief Delete all logs for a specific task.
 * @complexity 3
 * @param task_id (str) - The task ID.
 * @post All logs for the task are deleted.
 * @pre task_id is a valid task ID.
 * @side_effect Deletes from task_logs table.
 */

// --- delete_logs_for_tasks (backend/src/core/task_manager/persistence.py)
/**!
 * @brief Delete all logs for multiple tasks.
 * @complexity 3
 * @param task_ids (List[str]) - List of task IDs.
 * @post All logs for the tasks are deleted.
 * @pre task_ids is a list of task IDs.
 * @side_effect Deletes rows from task_logs table.
 */

// --- TaskLoggerModule (backend/src/core/task_manager/task_logger.py)
/**!
 * @brief Provides a dedicated logger for tasks with automatic source attribution.
 * @complexity 2
 * @invariant Each TaskLogger instance is bound to a specific task_id and default source.
 * @layer Core
 */

// --- TaskLogger (backend/src/core/task_manager/task_logger.py)
/**!
 * @brief A wrapper around TaskManager._add_log that carries task_id and source context.
 * @complexity 2
 * @invariant All log calls include the task_id and source.
 * @test_contract TaskLoggerContract ->
 * @ux_state Idle -> Logging -> (system records log)
 */

// --- with_source (backend/src/core/task_manager/task_logger.py)
/**!
 * @brief Create a sub-logger with a different default source.
 * @param source (str) - New default source.
 * @post Returns new TaskLogger with the same task_id but different source.
 * @pre source is a non-empty string.
 * @return TaskLogger - New logger instance.
 */

// --- _log (backend/src/core/task_manager/task_logger.py)
/**!
 * @brief Internal method to log a message at a given level.
 * @param metadata (Optional[Dict]) - Additional structured data.
 * @post Log entry added via add_log_fn.
 * @pre level is a valid log level string.
 * @ux_state Logging -> (writing internal log)
 */

// --- debug (backend/src/core/task_manager/task_logger.py)
/**!
 * @brief Log a DEBUG level message.
 * @param metadata (Optional[Dict]) - Additional data.
 * @post Log entry added via internally with DEBUG level.
 * @pre message is a string.
 */

// --- info (backend/src/core/task_manager/task_logger.py)
/**!
 * @brief Log an INFO level message.
 * @param metadata (Optional[Dict]) - Additional data.
 * @post Log entry added internally with INFO level.
 * @pre message is a string.
 */

// --- warning (backend/src/core/task_manager/task_logger.py)
/**!
 * @brief Log a WARNING level message.
 * @param metadata (Optional[Dict]) - Additional data.
 * @post Log entry added internally with WARNING level.
 * @pre message is a string.
 */

// --- error (backend/src/core/task_manager/task_logger.py)
/**!
 * @brief Log an ERROR level message.
 * @param metadata (Optional[Dict]) - Additional data.
 * @post Log entry added internally with ERROR level.
 * @pre message is a string.
 */

// --- progress (backend/src/core/task_manager/task_logger.py)
/**!
 * @brief Log a progress update with percentage.
 * @param source (Optional[str]) - Override source.
 * @post Log entry with progress metadata added.
 * @pre percent is between 0 and 100.
 */

// --- AppTimezone (backend/src/core/timezone.py)
/**!
 * @brief Application-level timezone utilities. Reads APP_TIMEZONE from env (default Europe/Moscow)
 * @complexity 3
 */

// --- _get_default_tz_name (backend/src/core/timezone.py)
/**!
 * @brief Read APP_TIMEZONE from env, fall back to Europe/Moscow.
 * @complexity 1
 * @post Returns a valid IANA timezone string.
 * @pre Environment is loaded (dotenv or os.environ).
 */

// --- get_app_timezone (backend/src/core/timezone.py)
/**!
 * @brief Return cached ZoneInfo for the configured application timezone.
 * @complexity 1
 * @post Returns a ZoneInfo instance matching APP_TIMEZONE env var.
 * @side_effect Reads os.environ on first call; result is cached.
 */

// --- invalidate_timezone_cache (backend/src/core/timezone.py)
/**!
 * @brief Reset the cached ZoneInfo so the next get_app_timezone() call re-reads from env/DB.
 * @complexity 1
 * @post _APP_TZ_CACHE is set to None; subsequent get_app_timezone() will re-resolve.
 * @rationale Called after PATCH /settings/consolidated updates app_timezone.
 */

// --- validate_timezone (backend/src/core/timezone.py)
/**!
 * @brief Validate that a timezone string is a known IANA timezone.
 * @complexity 1
 * @post Returns True if ZoneInfo accepts the name, False otherwise.
 * @pre tz_name is a string.
 */

// --- localize (backend/src/core/timezone.py)
/**!
 * @brief Convert a timezone-aware or naive UTC datetime to the configured app timezone.
 * @complexity 1
 * @post Returns a datetime with the app timezone attached (astimezone).
 * @pre If dt is timezone-naive, it is assumed to be UTC.
 */

// --- now (backend/src/core/timezone.py)
/**!
 * @brief Get current time in the configured application timezone.
 * @complexity 1
 * @post Returns timezone-aware datetime in the app timezone.
 */

// --- format_timezone_offset (backend/src/core/timezone.py)
/**!
 * @brief Return the UTC offset string for the configured timezone (e.g. "+03:00").
 * @complexity 1
 * @post Returns string like "+03:00" or "+00:00".
 */

// --- CoreUtils (backend/src/core/utils/__init__.py)
/**!
 * @brief Shared utility package root.
 */

// --- AsyncAPIClient.__init__ (backend/src/core/utils/async_network.py)
/**!
 * @brief Initialize async API client for one environment.
 * @complexity 3
 * @data_contract Input[config: Dict[str, Any]] -> self._auth_cache_key[str]
 * @post Client is ready for async request/authentication flow.
 * @pre config contains base_url and auth payload.
 */

// --- AsyncAPIClient._normalize_base_url (backend/src/core/utils/async_network.py)
/**!
 * @brief Normalize base URL for Superset API root construction.
 * @complexity 1
 * @post Returns canonical base URL without trailing slash and duplicate /api/v1 suffix.
 */

// --- AsyncAPIClient._build_api_url (backend/src/core/utils/async_network.py)
/**!
 * @brief Build full API URL from relative Superset endpoint.
 * @complexity 1
 * @post Returns absolute URL for upstream request.
 */

// --- AsyncAPIClient._get_auth_lock (backend/src/core/utils/async_network.py)
/**!
 * @brief Return per-cache-key async lock to serialize fresh login attempts.
 * @complexity 1
 * @post Returns stable asyncio.Lock instance.
 */

// --- AsyncAPIClient.authenticate (backend/src/core/utils/async_network.py)
/**!
 * @brief Authenticate against Superset and cache access/csrf tokens.
 * @complexity 3
 * @data_contract None -> Output[Dict[str, str]]
 * @post Client tokens are populated and reusable across requests.
 * @side_effect Performs network requests to Superset authentication endpoints.
 */

// --- AsyncAPIClient.get_headers (backend/src/core/utils/async_network.py)
/**!
 * @brief Return authenticated Superset headers for async requests.
 * @complexity 3
 * @post Headers include Authorization and CSRF tokens.
 */

// --- AsyncAPIClient._is_dashboard_endpoint (backend/src/core/utils/async_network.py)
/**!
 * @brief Determine whether an API endpoint represents a dashboard resource for 404 translation.
 * @complexity 2
 * @post Returns true only for dashboard-specific endpoints.
 */

// --- AsyncAPIClient._handle_network_error (backend/src/core/utils/async_network.py)
/**!
 * @brief Translate generic httpx errors into NetworkError.
 * @complexity 3
 * @data_contract Input[httpx.HTTPError] -> NetworkError
 * @post Raises NetworkError with URL context.
 */

// --- AsyncAPIClient.aclose (backend/src/core/utils/async_network.py)
/**!
 * @brief Close underlying httpx client.
 * @complexity 3
 * @post Client resources are released.
 * @side_effect Closes network connections.
 */

// --- DatasetMapperModule (backend/src/core/utils/dataset_mapper.py)
/**!
 * @brief Этот модуль отвечает за обновление метаданных (verbose_name) в датасетах Superset,
 */

// --- DatasetMapper (backend/src/core/utils/dataset_mapper.py)
/**!
 * @brief Класс для маппинга и обновления verbose_name в датасетах Superset.
 */

// --- get_sqllab_mappings (backend/src/core/utils/dataset_mapper.py)
/**!
 * @brief Извлекает маппинги column_name -> verbose_name через SQL Lab Superset.
 * @post Возвращается словарь column_name -> verbose_name из результатов SQL-запроса.
 * @pre dataset_id должен существовать в Superset.
 */

// --- load_excel_mappings (backend/src/core/utils/dataset_mapper.py)
/**!
 * @brief Загружает маппинги column_name -> verbose_name из XLSX файла.
 * @error Exception - При ошибках чтения файла или парсинга.
 * @param file_path (str) - Путь к XLSX файлу.
 * @post Возвращается словарь с маппингами из файла.
 * @pre file_path должен указывать на существующий XLSX файл.
 * @return Dict[str, str] - Словарь с маппингами.
 */

// --- run_mapping (backend/src/core/utils/dataset_mapper.py)
/**!
 * @brief Основная функция для выполнения маппинга и обновления verbose_name датасета в Superset.
 * @param excel_path (Optional[str]) - Путь к XLSX файлу.
 * @post Если найдены изменения, датасет в Superset обновлен через API.
 * @pre dataset_id должен быть существующим ID в Superset.
 */

// --- FileIO (backend/src/core/utils/fileio.py)
/**!
 * @brief Предоставляет набор утилит для управления файловыми операциями, включая работу с временными файлами, архивами ZIP, файлами YAML и очистку директорий.
 * @complexity 3
 * @layer Infrastructure
 * @public_api create_temp_file, remove_empty_directories, read_dashboard_from_disk, calculate_crc32, RetentionPolicy, archive_exports, save_and_unpack_dashboard, update_yamls, create_dashboard_export, sanitize_filename, get_filename_from_headers, consolidate_archive_folders
 */

// --- InvalidZipFormatError (backend/src/core/utils/fileio.py)
/**!
 * @brief Exception raised when a file is not a valid ZIP archive.
 */

// --- create_temp_file (backend/src/core/utils/fileio.py)
/**!
 * @brief Контекстный менеджер для создания временного файла или директории с гарантированным удалением.
 * @post Временный ресурс создан и путь к нему возвращен; ресурс удален после выхода из контекста.
 * @pre suffix должен быть строкой, определяющей тип ресурса.
 * @yields Path - Путь к временному ресурсу.
 */

// --- remove_empty_directories (backend/src/core/utils/fileio.py)
/**!
 * @brief Рекурсивно удаляет все пустые поддиректории, начиная с указанного пути.
 * @post Все пустые поддиректории удалены, возвращено их количество.
 * @pre root_dir должен быть путем к существующей директории.
 */

// --- read_dashboard_from_disk (backend/src/core/utils/fileio.py)
/**!
 * @brief Читает бинарное содержимое файла с диска.
 * @post Возвращает байты содержимого и имя файла.
 * @pre file_path должен указывать на существующий файл.
 */

// --- calculate_crc32 (backend/src/core/utils/fileio.py)
/**!
 * @brief Вычисляет контрольную сумму CRC32 для файла.
 * @post Возвращает 8-значную hex-строку CRC32.
 * @pre file_path должен быть объектом Path к существующему файлу.
 */

// --- RetentionPolicy (backend/src/core/utils/fileio.py)
/**!
 * @brief Определяет политику хранения для архивов (ежедневные, еженедельные, ежемесячные).
 */

// --- archive_exports (backend/src/core/utils/fileio.py)
/**!
 * @brief Управляет архивом экспортированных файлов, применяя политику хранения и дедупликацию.
 * @post Старые или дублирующиеся архивы удалены согласно политике.
 * @pre output_dir должен быть путем к существующей директории.
 */

// --- apply_retention_policy (backend/src/core/utils/fileio.py)
/**!
 * @brief (Helper) Применяет политику хранения к списку файлов, возвращая те, что нужно сохранить.
 * @post Returns a set of files to keep.
 * @pre files_with_dates is a list of (Path, date) tuples.
 */

// --- save_and_unpack_dashboard (backend/src/core/utils/fileio.py)
/**!
 * @brief Сохраняет бинарное содержимое ZIP-архива на диск и опционально распаковывает его.
 * @post ZIP-файл сохранен, и если unpack=True, он распакован в output_dir.
 * @pre zip_content должен быть байтами валидного ZIP-архива.
 */

// --- update_yamls (backend/src/core/utils/fileio.py)
/**!
 * @brief Обновляет конфигурации в YAML-файлах, заменяя значения или применяя regex.
 * @post Все YAML файлы в директории обновлены согласно переданным параметрам.
 * @pre path должен быть существующей директорией.
 */

// --- _update_yaml_file (backend/src/core/utils/fileio.py)
/**!
 * @brief (Helper) Обновляет один YAML файл.
 * @post Файл обновлен согласно переданным конфигурациям или регулярному выражению.
 * @pre file_path должен быть объектом Path к существующему YAML файлу.
 */

// --- replacer (backend/src/core/utils/fileio.py)
/**!
 * @brief Функция замены, сохраняющая кавычки если они были.
 * @post Возвращает строку с новым значением, сохраняя префикс и кавычки.
 * @pre match должен быть объектом совпадения регулярного выражения.
 */

// --- create_dashboard_export (backend/src/core/utils/fileio.py)
/**!
 * @brief Создает ZIP-архив из указанных исходных путей.
 * @post ZIP-архив создан по пути zip_path.
 * @pre source_paths должен содержать существующие пути.
 */

// --- sanitize_filename (backend/src/core/utils/fileio.py)
/**!
 * @brief Очищает строку от символов, недопустимых в именах файлов.
 * @post Возвращает строку без спецсимволов.
 * @pre filename должен быть строкой.
 */

// --- get_filename_from_headers (backend/src/core/utils/fileio.py)
/**!
 * @brief Извлекает имя файла из HTTP заголовка 'Content-Disposition'.
 * @post Возвращает имя файла или None, если заголовок отсутствует.
 * @pre headers должен быть словарем заголовков.
 */

// --- consolidate_archive_folders (backend/src/core/utils/fileio.py)
/**!
 * @brief Консолидирует директории архивов на основе общего слага в имени.
 * @post Директории с одинаковым префиксом объединены в одну.
 * @pre root_directory должен быть объектом Path к существующей директории.
 */

// --- FuzzyMatching (backend/src/core/utils/matching.py)
/**!
 * @brief Provides utility functions for fuzzy matching database names.
 * @invariant Confidence scores are returned as floats between 0.0 and 1.0.
 * @layer Core
 */

// --- suggest_mappings (backend/src/core/utils/matching.py)
/**!
 * @brief Suggests mappings between source and target databases using fuzzy matching.
 * @post Returns a list of suggested mappings with confidence scores.
 * @pre source_databases and target_databases are lists of dictionaries with 'uuid' and 'database_name'.
 */

// --- NetworkModule (backend/src/core/utils/network.py)
/**!
 * @brief Инкапсулирует низкоуровневую HTTP-логику для взаимодействия с Superset API, включая аутентификацию, управление сессией, retry-логику и обработку ошибок.
 * @complexity 3
 * @layer Infrastructure
 * @public_api APIClient
 */

// --- SupersetAPIError (backend/src/core/utils/network.py)
/**!
 * @brief Base exception for all Superset API related errors.
 * @complexity 1
 */

// --- AuthenticationError (backend/src/core/utils/network.py)
/**!
 * @brief Exception raised when authentication fails.
 * @complexity 1
 */

// --- PermissionDeniedError (backend/src/core/utils/network.py)
/**!
 * @brief Exception raised when access is denied.
 */

// --- DashboardNotFoundError (backend/src/core/utils/network.py)
/**!
 * @brief Exception raised when a dashboard cannot be found.
 */

// --- NetworkError (backend/src/core/utils/network.py)
/**!
 * @brief Exception raised when a network level error occurs.
 */

// --- NetworkError.__init__ (backend/src/core/utils/network.py)
/**!
 * @brief Initializes the network error.
 * @post NetworkError is initialized.
 * @pre message is a string.
 */

// --- SupersetAuthCache (backend/src/core/utils/network.py)
/**!
 * @brief Process-local cache for Superset access/csrf tokens keyed by environment credentials.
 * @post Cached entries expire automatically by TTL and can be reused across requests.
 * @pre base_url and username are stable strings.
 */

// --- SupersetAuthCache.get (backend/src/core/utils/network.py)
/**!
 */

// --- SupersetAuthCache.set (backend/src/core/utils/network.py)
/**!
 */

// --- APIClient (backend/src/core/utils/network.py)
/**!
 * @brief Synchronous Superset API client with process-local auth token caching.
 * @complexity 3
 */

// --- APIClient.__init__ (backend/src/core/utils/network.py)
/**!
 * @brief Инициализирует API клиент с конфигурацией, сессией и логгером.
 * @param timeout (int) - Таймаут запросов.
 * @post APIClient instance is initialized with a session.
 * @pre config must contain 'base_url' and 'auth'.
 */

// --- _init_session (backend/src/core/utils/network.py)
/**!
 * @brief Создает и настраивает `requests.Session` с retry-логикой.
 * @post Returns a configured requests.Session instance.
 * @pre self.request_settings must be initialized.
 * @return requests.Session - Настроенная сессия.
 */

// --- _normalize_base_url (backend/src/core/utils/network.py)
/**!
 * @brief Normalize Superset environment URL to base host/path without trailing slash and /api/v1 suffix.
 */

// --- _build_api_url (backend/src/core/utils/network.py)
/**!
 * @brief Build absolute Superset API URL for endpoint using canonical /api/v1 base.
 * @post Returns full URL without accidental duplicate slashes.
 * @pre endpoint is relative path or absolute URL.
 * @return str
 */

// --- APIClient.authenticate (backend/src/core/utils/network.py)
/**!
 * @brief Выполняет аутентификацию в Superset API и получает access и CSRF токены.
 * @error AuthenticationError, NetworkError - при ошибках.
 * @post `self._tokens` заполнен, `self._authenticated` установлен в `True`.
 * @pre self.auth and self.base_url must be valid.
 * @return Dict[str, str] - Словарь с токенами.
 */

// --- headers (backend/src/core/utils/network.py)
/**!
 * @brief Возвращает HTTP-заголовки для аутентифицированных запросов.
 * @post Returns headers including auth tokens.
 * @pre APIClient is initialized and authenticated or can be authenticated.
 */

// --- request (backend/src/core/utils/network.py)
/**!
 * @brief Выполняет универсальный HTTP-запрос к API.
 * @error SupersetAPIError, NetworkError и их подклассы.
 * @param raw_response (bool) - Возвращать ли сырой ответ.
 * @post Returns response content or raw Response object.
 * @pre method and endpoint must be strings.
 * @return `requests.Response` если `raw_response=True`, иначе `dict`.
 */

// --- _handle_http_error (backend/src/core/utils/network.py)
/**!
 * @brief (Helper) Преобразует HTTP ошибки в кастомные исключения.
 * @param endpoint (str) - Эндпоинт.
 * @post Raises a specific SupersetAPIError or subclass.
 * @pre e must be a valid HTTPError with a response.
 */

// --- _is_dashboard_endpoint (backend/src/core/utils/network.py)
/**!
 * @brief Determine whether an API endpoint represents a dashboard resource for 404 translation.
 * @post Returns true only for dashboard-specific endpoints.
 * @pre endpoint may be relative or absolute.
 */

// --- _handle_network_error (backend/src/core/utils/network.py)
/**!
 * @brief (Helper) Преобразует сетевые ошибки в `NetworkError`.
 * @param url (str) - URL.
 * @post Raises a NetworkError.
 * @pre e must be a RequestException.
 */

// --- upload_file (backend/src/core/utils/network.py)
/**!
 * @brief Загружает файл на сервер через multipart/form-data.
 * @error SupersetAPIError, NetworkError, TypeError.
 * @param timeout (Optional[int]) - Таймаут.
 * @post File is uploaded and response returned.
 * @pre file_info must contain 'file_obj' and 'file_name'.
 * @return Ответ API в виде словаря.
 */

// --- _perform_upload (backend/src/core/utils/network.py)
/**!
 * @brief (Helper) Выполняет POST запрос с файлом.
 * @param timeout (Optional[int]) - Таймаут.
 * @post POST request is performed and JSON response returned.
 * @pre url, files, and headers must be provided.
 * @return Dict - Ответ.
 */

// --- fetch_paginated_count (backend/src/core/utils/network.py)
/**!
 * @brief Получает общее количество элементов для пагинации.
 * @param count_field (str) - Поле с количеством.
 * @post Returns total count of items.
 * @pre query_params must be a dictionary.
 * @return int - Количество.
 */

// --- fetch_paginated_data (backend/src/core/utils/network.py)
/**!
 * @brief Автоматически собирает данные со всех страниц пагинированного эндпоинта.
 * @param pagination_options (Dict[str, Any]) - Опции пагинации.
 * @post Returns all items across all pages.
 * @pre pagination_options must contain 'base_query', 'results_field'. 'total_count' is optional.
 * @return List[Any] - Список данных.
 */

// --- SupersetCompilationAdapter (backend/src/core/utils/superset_compilation_adapter.py)
/**!
 * @brief Interact with Superset preview compilation and SQL Lab execution endpoints using the current approved execution context.
 * @complexity 4
 * @invariant The adapter never fabricates compiled SQL locally; preview truth is delegated to Superset only.
 * @layer Infrastructure
 * @post preview and launch calls return Superset-originated artifacts or explicit errors.
 * @pre effective template params and dataset execution reference are available.
 * @side_effect performs upstream Superset preview and SQL Lab calls.
 */

// --- SupersetCompilationAdapter.imports (backend/src/core/utils/superset_compilation_adapter.py)
/**!
 */

// --- PreviewCompilationPayload (backend/src/core/utils/superset_compilation_adapter.py)
/**!
 * @brief Typed preview payload for Superset-side compilation.
 * @complexity 2
 */

// --- SqlLabLaunchPayload (backend/src/core/utils/superset_compilation_adapter.py)
/**!
 * @brief Typed SQL Lab payload for audited launch handoff.
 * @complexity 2
 */

// --- SupersetCompilationAdapter.__init__ (backend/src/core/utils/superset_compilation_adapter.py)
/**!
 * @brief Bind adapter to one Superset environment and client instance.
 * @complexity 2
 */

// --- SupersetCompilationAdapter._supports_client_method (backend/src/core/utils/superset_compilation_adapter.py)
/**!
 * @brief Detect explicitly implemented client capabilities without treating loose mocks as real methods.
 * @complexity 2
 */

// --- SupersetCompilationAdapter.compile_preview (backend/src/core/utils/superset_compilation_adapter.py)
/**!
 * @brief Request Superset-side compiled SQL preview for the current effective inputs.
 * @complexity 4
 * @data_contract Input[PreviewCompilationPayload] -> Output[CompiledPreview]
 * @post returns a ready or failed preview artifact backed only by Superset-originated SQL or diagnostics.
 * @pre dataset_id and effective inputs are available for the current session.
 * @side_effect performs upstream preview requests.
 */

// --- SupersetCompilationAdapter.mark_preview_stale (backend/src/core/utils/superset_compilation_adapter.py)
/**!
 * @brief Invalidate previous preview after mapping or value changes.
 * @complexity 2
 * @post preview status becomes stale without fabricating a replacement artifact.
 * @pre preview is a persisted preview artifact or current in-memory snapshot.
 */

// --- SupersetCompilationAdapter.create_sql_lab_session (backend/src/core/utils/superset_compilation_adapter.py)
/**!
 * @brief Create the canonical audited execution session after all launch gates pass.
 * @complexity 4
 * @data_contract Input[SqlLabLaunchPayload] -> Output[str]
 * @post returns one canonical SQL Lab session reference from Superset.
 * @pre compiled_sql is Superset-originated and launch gates are already satisfied.
 * @side_effect performs upstream SQL Lab execution/session creation.
 */

// --- SupersetCompilationAdapter._request_superset_preview (backend/src/core/utils/superset_compilation_adapter.py)
/**!
 * @brief Request preview compilation through explicit client support backed by real Superset endpoints only.
 * @complexity 4
 * @data_contract Input[PreviewCompilationPayload] -> Output[Dict[str,Any]]
 * @post returns one normalized upstream compilation response including the chosen strategy metadata.
 * @pre payload contains a valid dataset identifier and deterministic execution inputs for one preview attempt.
 * @side_effect issues one or more Superset preview requests through the client fallback chain.
 */

// --- SupersetCompilationAdapter._request_sql_lab_session (backend/src/core/utils/superset_compilation_adapter.py)
/**!
 * @brief Probe supported SQL Lab execution surfaces and return the first successful response.
 * @complexity 4
 * @data_contract Input[SqlLabLaunchPayload] -> Output[Dict[str,Any]]
 * @post returns the first successful SQL Lab execution response from Superset.
 * @pre payload carries non-empty Superset-originated SQL and a preview identifier for the current launch.
 * @side_effect issues Superset dataset lookup and SQL Lab execution requests.
 */

// --- SupersetCompilationAdapter._normalize_preview_response (backend/src/core/utils/superset_compilation_adapter.py)
/**!
 * @brief Normalize candidate Superset preview responses into one compiled-sql structure.
 * @complexity 3
 */

// --- SupersetCompilationAdapter._dump_json (backend/src/core/utils/superset_compilation_adapter.py)
/**!
 * @brief Serialize Superset request payload deterministically for network transport.
 * @complexity 1
 */

// --- SupersetContextExtractorPackage (backend/src/core/utils/superset_context_extractor/__init__.py)
/**!
 * @brief Recover dataset and dashboard context from Superset links while preserving explicit partial-recovery markers.
 * @complexity 4
 * @invariant Partial recovery is surfaced explicitly and never misrepresented as fully confirmed context.
 * @layer Infrastructure
 * @post Returns the best available recovered context with explicit provenance and partial-recovery markers when necessary.
 * @pre Superset link or dataset reference must be parseable enough to resolve an environment-scoped target resource.
 * @rationale Decomposed from monolithic superset_context_extractor.py (1397 lines) into
 * @side_effect Performs upstream Superset API reads.
 */

// --- SupersetContextExtractor (backend/src/core/utils/superset_context_extractor/__init__.py)
/**!
 * @brief Parse supported Superset URLs and recover canonical dataset/dashboard references for review-session intake.
 * @complexity 4
 * @post extractor instance is ready to parse links against one Superset environment.
 * @pre constructor receives a configured environment with a usable Superset base URL.
 * @side_effect downstream parse operations may call Superset APIs through SupersetClient.
 */

// --- SupersetContextExtractorBase (backend/src/core/utils/superset_context_extractor/_base.py)
/**!
 * @brief Base class and helpers for recovering dataset/dashboard context from Superset links with explicit partial-recovery markers.
 * @complexity 4
 * @invariant Partial recovery is surfaced explicitly and never misrepresented as fully confirmed context.
 * @layer Infrastructure
 * @post Returns the best available recovered context with explicit provenance and partial-recovery markers when necessary.
 * @pre Superset link or dataset reference must be parseable enough to resolve an environment-scoped target resource.
 * @side_effect Performs upstream Superset API reads.
 */

// --- _base_imports (backend/src/core/utils/superset_context_extractor/_base.py)
/**!
 */

// --- SupersetParsedContext (backend/src/core/utils/superset_context_extractor/_base.py)
/**!
 * @brief Normalized output of Superset link parsing for session intake and recovery.
 * @complexity 2
 */

// --- SupersetContextExtractorBase.__init__ (backend/src/core/utils/superset_context_extractor/_base.py)
/**!
 * @brief Bind extractor to one Superset environment and client instance.
 * @complexity 2
 */

// --- SupersetContextExtractorBase.build_recovery_summary (backend/src/core/utils/superset_context_extractor/_base.py)
/**!
 * @brief Summarize recovered, partial, and unresolved context for session state and UX.
 * @complexity 2
 */

// --- SupersetContextExtractorBase._extract_numeric_identifier (backend/src/core/utils/superset_context_extractor/_base.py)
/**!
 * @brief Extract a numeric identifier from a REST-like Superset URL path.
 * @complexity 2
 */

// --- SupersetContextExtractorBase._extract_dashboard_reference (backend/src/core/utils/superset_context_extractor/_base.py)
/**!
 * @brief Extract a dashboard id-or-slug reference from a Superset URL path.
 * @complexity 2
 */

// --- SupersetContextExtractorBase._extract_dashboard_permalink_key (backend/src/core/utils/superset_context_extractor/_base.py)
/**!
 * @brief Extract a dashboard permalink key from a Superset URL path.
 * @complexity 2
 */

// --- SupersetContextExtractorBase._extract_dashboard_id_from_state (backend/src/core/utils/superset_context_extractor/_base.py)
/**!
 * @brief Extract a dashboard identifier from returned permalink state when present.
 * @complexity 2
 */

// --- SupersetContextExtractorBase._extract_chart_id_from_state (backend/src/core/utils/superset_context_extractor/_base.py)
/**!
 * @brief Extract a chart identifier from returned permalink state when dashboard id is absent.
 * @complexity 2
 */

// --- SupersetContextExtractorBase._search_nested_numeric_key (backend/src/core/utils/superset_context_extractor/_base.py)
/**!
 * @brief Recursively search nested dict/list payloads for the first numeric value under a candidate key set.
 * @complexity 3
 */

// --- SupersetContextExtractorBase._decode_query_state (backend/src/core/utils/superset_context_extractor/_base.py)
/**!
 * @brief Decode query-string structures used by Superset URL state transport.
 * @complexity 2
 */

// --- SupersetContextFiltersExtractMixin (backend/src/core/utils/superset_context_extractor/_filters.py)
/**!
 * @brief Extract normalized imported filters from decoded Superset query state (native_filters, dataMask, native_filter_state, form_data).
 * @complexity 3
 * @layer Infrastructure
 */

// --- _filters_imports (backend/src/core/utils/superset_context_extractor/_filters.py)
/**!
 */

// --- SupersetContextFiltersExtractMixin._extract_imported_filters (backend/src/core/utils/superset_context_extractor/_filters.py)
/**!
 * @brief Normalize imported filters from decoded query state without fabricating missing values.
 * @complexity 2
 */

// --- SupersetContextParsingMixin (backend/src/core/utils/superset_context_extractor/_parsing.py)
/**!
 * @brief Parse supported Superset URLs and recover canonical dataset/dashboard references for review-session intake.
 * @complexity 4
 * @layer Infrastructure
 */

// --- _parsing_imports (backend/src/core/utils/superset_context_extractor/_parsing.py)
/**!
 */

// --- SupersetContextParsingMixin.parse_superset_link (backend/src/core/utils/superset_context_extractor/_parsing.py)
/**!
 * @brief Extract candidate identifiers and query state from supported Superset URLs.
 * @complexity 4
 * @data_contract Input[link:str] -> Output[SupersetParsedContext]
 * @post returns resolved dataset/dashboard context, preserving explicit partial-recovery state if some identifiers cannot be confirmed.
 * @pre link is a non-empty Superset URL compatible with the configured environment.
 * @side_effect may issue Superset API reads to resolve dataset references from dashboard or chart URLs.
 */

// --- SupersetContextParsingMixin._recover_dataset_binding_from_dashboard (backend/src/core/utils/superset_context_extractor/_parsing.py)
/**!
 * @brief Recover a dataset binding from resolved dashboard context while preserving explicit unresolved markers.
 * @complexity 3
 */

// --- SupersetContextExtractorPII (backend/src/core/utils/superset_context_extractor/_pii.py)
/**!
 * @brief PII redaction helpers for assistant-facing dataset-review context — mask emails, UUIDs, long digit strings, and mixed identifiers.
 * @complexity 3
 * @layer Infrastructure
 */

// --- _pii_imports (backend/src/core/utils/superset_context_extractor/_pii.py)
/**!
 */

// --- mask_pii_value (backend/src/core/utils/superset_context_extractor/_pii.py)
/**!
 * @brief Redact likely sensitive identifiers while preserving structural hints for assistant-facing dataset-review context.
 * @complexity 2
 */

// --- sanitize_imported_filter_for_assistant (backend/src/core/utils/superset_context_extractor/_pii.py)
/**!
 * @brief Build assistant-safe imported-filter payload with raw-value redaction metadata when sensitive tokens are detected.
 * @complexity 2
 */

// --- _mask_sensitive_text (backend/src/core/utils/superset_context_extractor/_pii.py)
/**!
 * @brief Redact likely PII substrings from one string while preserving non-sensitive delimiters and token shape.
 * @complexity 2
 */

// --- SupersetContextRecoveryMixin (backend/src/core/utils/superset_context_extractor/_recovery.py)
/**!
 * @brief Recover imported filters from Superset parsed context and dashboard metadata.
 * @complexity 4
 * @layer Infrastructure
 */

// --- _recovery_imports (backend/src/core/utils/superset_context_extractor/_recovery.py)
/**!
 */

// --- SupersetContextRecoveryMixin.recover_imported_filters (backend/src/core/utils/superset_context_extractor/_recovery.py)
/**!
 * @brief Build imported filter entries from URL state and Superset-side saved context.
 * @complexity 4
 * @data_contract Input[SupersetParsedContext] -> Output[List[Dict[str,Any]]]
 * @post returns explicit recovered and partial filter entries with preserved provenance and confirmation requirements.
 * @pre parsed_context comes from a successful Superset link parse for one environment.
 * @side_effect may issue Superset reads for dashboard metadata enrichment.
 */

// --- SupersetContextRecoveryMixin._normalize_imported_filter_payload (backend/src/core/utils/superset_context_extractor/_recovery.py)
/**!
 * @brief Normalize one imported-filter payload with explicit provenance and confirmation state.
 * @complexity 2
 */

// --- SupersetContextTemplatesMixin (backend/src/core/utils/superset_context_extractor/_templates.py)
/**!
 * @brief Deterministically detect runtime variables and Jinja references from dataset query-bearing fields without execution.
 * @complexity 3
 * @layer Infrastructure
 */

// --- _templates_imports (backend/src/core/utils/superset_context_extractor/_templates.py)
/**!
 */

// --- SupersetContextTemplatesMixin.discover_template_variables (backend/src/core/utils/superset_context_extractor/_templates.py)
/**!
 * @brief Detect runtime variables and Jinja references from dataset query-bearing fields.
 * @complexity 4
 * @data_contract Input[dataset_payload:Dict[str,Any]] -> Output[List[Dict[str,Any]]]
 * @post returns deduplicated explicit variable records without executing Jinja or fabricating runtime values.
 * @pre dataset_payload is a Superset dataset-detail style payload with query-bearing fields when available.
 * @side_effect none.
 */

// --- SupersetContextTemplatesMixin._collect_query_bearing_expressions (backend/src/core/utils/superset_context_extractor/_templates.py)
/**!
 * @brief Collect SQL and expression-bearing dataset fields for deterministic template-variable discovery.
 * @complexity 3
 */

// --- SupersetContextTemplatesMixin._append_template_variable (backend/src/core/utils/superset_context_extractor/_templates.py)
/**!
 * @brief Append one deduplicated template-variable descriptor.
 * @complexity 2
 */

// --- SupersetContextTemplatesMixin._extract_primary_jinja_identifier (backend/src/core/utils/superset_context_extractor/_templates.py)
/**!
 * @brief Extract a deterministic primary identifier from a Jinja expression without executing it.
 * @complexity 2
 */

// --- SupersetContextTemplatesMixin._normalize_default_literal (backend/src/core/utils/superset_context_extractor/_templates.py)
/**!
 * @brief Normalize literal default fragments from template helper calls into JSON-safe values.
 * @complexity 2
 */

// --- WsLogHandlerModule (backend/src/core/ws_log_handler.py)
/**!
 * @brief WebSocket log handler module providing LogEntry DTO and WebSocketLogHandler for buffered log streaming.
 * @complexity 3
 */

// --- WebSocketLogHandler (backend/src/core/ws_log_handler.py)
/**!
 * @brief Custom logging handler that captures log records into a fixed-capacity buffer for WebSocket streaming.
 * @complexity 3
 */

// --- WebSocketLogHandler.__init__ (backend/src/core/ws_log_handler.py)
/**!
 * @complexity 1
 */

// --- WebSocketLogHandler.emit (backend/src/core/ws_log_handler.py)
/**!
 * @brief Captures a log record, formats it, and stores it in the buffer as a LogEntry.
 * @complexity 2
 */

// --- WebSocketLogHandler.get_recent_logs (backend/src/core/ws_log_handler.py)
/**!
 * @brief Returns a list of recent log entries from the buffer.
 * @complexity 2
 */

// --- AppDependencies (backend/src/dependencies.py)
/**!
 * @brief Provides shared instances to app and routers.
 * @complexity 4
 * @layer Core
 */

// --- get_config_manager (backend/src/dependencies.py)
/**!
 * @brief Dependency injector for ConfigManager.
 * @complexity 1
 * @post Returns shared ConfigManager instance.
 * @pre Global config_manager must be initialized.
 */

// --- get_plugin_loader (backend/src/dependencies.py)
/**!
 * @brief Dependency injector for PluginLoader.
 * @complexity 1
 * @post Returns shared PluginLoader instance.
 * @pre Global plugin_loader must be initialized.
 */

// --- get_task_manager (backend/src/dependencies.py)
/**!
 * @brief Dependency injector for TaskManager.
 * @complexity 1
 * @post Returns shared TaskManager instance.
 * @pre Global task_manager must be initialized.
 */

// --- get_scheduler_service (backend/src/dependencies.py)
/**!
 * @brief Dependency injector for SchedulerService.
 * @complexity 1
 * @post Returns shared SchedulerService instance.
 * @pre Global scheduler_service must be initialized.
 */

// --- get_resource_service (backend/src/dependencies.py)
/**!
 * @brief Dependency injector for ResourceService.
 * @complexity 1
 * @post Returns shared ResourceService instance.
 * @pre Global resource_service must be initialized.
 */

// --- get_mapping_service (backend/src/dependencies.py)
/**!
 * @brief Dependency injector for MappingService.
 * @complexity 1
 * @post Returns new MappingService instance.
 * @pre Global config_manager must be initialized.
 */

// --- get_clean_release_repository (backend/src/dependencies.py)
/**!
 * @brief Legacy compatibility shim for CleanReleaseRepository.
 * @complexity 1
 * @post Returns a shared CleanReleaseRepository instance.
 */

// --- get_clean_release_facade (backend/src/dependencies.py)
/**!
 * @brief Dependency injector for CleanReleaseFacade.
 * @complexity 1
 * @post Returns a facade instance with a fresh DB session.
 */

// --- APIKeyPrincipal (backend/src/dependencies.py)
/**!
 * @brief Dataclass representing an authenticated API key principal for service-to-service auth.
 * @complexity 1
 */

// --- require_api_key_or_jwt (backend/src/dependencies.py)
/**!
 * @brief Factory: creates a dependency that accepts either a valid API key (with permission check)
 * @complexity 4
 */

// --- check_api_key_environment_scope (backend/src/dependencies.py)
/**!
 * @brief Check the request's API key environment scope against a target env_id. Raises 400 if mismatch.
 * @complexity 1
 */

// --- get_api_key_principal (backend/src/dependencies.py)
/**!
 * @brief FastAPI dependency that reads X-API-Key header and returns APIKeyPrincipal or None.
 * @complexity 3
 * @post If valid key: returns APIKeyPrincipal; if no header: returns None; if invalid: raises 401.
 * @pre X-API-Key header may be present in the request.
 * @side_effect Updates last_used_at on the APIKey row (non-blocking flush).
 */

// --- oauth2_scheme (backend/src/dependencies.py)
/**!
 * @brief OAuth2 password bearer scheme for token extraction (raises 401 on missing token).
 * @complexity 1
 */

// --- oauth2_scheme_optional (backend/src/dependencies.py)
/**!
 * @brief Optional OAuth2 scheme — returns None instead of raising 401 when no token.
 * @complexity 1
 * @rationale Used in dual-auth routes (API key OR JWT) where JWT may be absent.
 */

// --- get_current_user (backend/src/dependencies.py)
/**!
 * @brief Dependency for retrieving currently authenticated user from a JWT.
 * @complexity 3
 * @post Returns User object if token is valid.
 * @pre JWT token provided in Authorization header.
 */

// --- has_permission (backend/src/dependencies.py)
/**!
 * @brief Dependency for checking if the current user has a specific permission.
 * @complexity 3
 * @post Returns True if user has permission.
 * @pre User is authenticated.
 */

// --- ModelsPackage (backend/src/models/__init__.py)
/**!
 * @brief Domain model package root.
 */

// --- TestCleanReleaseModels (backend/src/models/__tests__/test_clean_release.py)
/**!
 * @brief Contract testing for Clean Release models
 */

// --- test_release_candidate_valid (backend/src/models/__tests__/test_clean_release.py)
/**!
 * @brief Verify that a valid release candidate can be instantiated.
 */

// --- test_release_candidate_empty_id (backend/src/models/__tests__/test_clean_release.py)
/**!
 * @brief Verify that a release candidate with an empty ID is rejected.
 * @test_fixture valid_enterprise_policy
 */

// --- test_enterprise_policy_valid (backend/src/models/__tests__/test_clean_release.py)
/**!
 * @brief Verify that a valid enterprise policy is accepted.
 * @test_edge enterprise_policy_missing_prohibited
 */

// --- test_enterprise_policy_missing_prohibited (backend/src/models/__tests__/test_clean_release.py)
/**!
 * @brief Verify that an enterprise policy without prohibited categories is rejected.
 * @test_edge enterprise_policy_external_allowed
 */

// --- test_enterprise_policy_external_allowed (backend/src/models/__tests__/test_clean_release.py)
/**!
 * @brief Verify that an enterprise policy allowing external sources is rejected.
 * @test_edge manifest_count_mismatch
 * @test_invariant manifest_consistency
 */

// --- test_manifest_count_mismatch (backend/src/models/__tests__/test_clean_release.py)
/**!
 * @brief Verify that a manifest with count mismatches is rejected.
 */

// --- test_compliant_run_validation (backend/src/models/__tests__/test_clean_release.py)
/**!
 * @brief Verify compliant run validation logic and mandatory stage checks.
 */

// --- test_report_validation (backend/src/models/__tests__/test_clean_release.py)
/**!
 * @brief Verify compliance report validation based on status and violation counts.
 */

// --- test_models (backend/src/models/__tests__/test_models.py)
/**!
 * @brief Unit tests for data models
 * @complexity 1
 * @layer Domain
 */

// --- test_environment_model (backend/src/models/__tests__/test_models.py)
/**!
 * @brief Tests that Environment model correctly stores values.
 * @post Values are verified.
 * @pre Environment class is available.
 */

// --- test_report_models (backend/src/models/__tests__/test_report_models.py)
/**!
 * @brief Unit tests for report Pydantic models and their validators
 * @complexity 3
 * @layer Domain
 */

// --- APIKeyModel (backend/src/models/api_key.py)
/**!
 * @brief SQLAlchemy model for API Key authentication — stores SHA-256 hash only, raw key shown once at creation.
 * @complexity 1
 * @invariant Raw key is NEVER stored — shown once at creation and discarded.
 * @layer Domain
 */

// --- APIKey (backend/src/models/api_key.py)
/**!
 * @brief Stores API key metadata and SHA-256 hash for service-to-service authentication.
 * @complexity 1
 */

// --- AssistantModels (backend/src/models/assistant.py)
/**!
 * @brief SQLAlchemy models for assistant audit trail and confirmation tokens.
 * @complexity 3
 * @data_contract AssistantData -> AssistantRecord
 * @invariant Assistant records preserve immutable ids and creation timestamps.
 * @layer Domain
 * @side_effect Defines assistant audit/message/confirmation tables
 */

// --- AssistantAuditRecord (backend/src/models/assistant.py)
/**!
 * @brief Store audit decisions and outcomes produced by assistant command handling.
 * @complexity 3
 * @post Audit payload remains available for compliance and debugging.
 * @pre user_id must identify the actor for every record.
 */

// --- AssistantMessageRecord (backend/src/models/assistant.py)
/**!
 * @brief Persist chat history entries for assistant conversations.
 * @complexity 3
 * @post Message row can be queried in chronological order.
 * @pre user_id, conversation_id, role and text must be present.
 */

// --- AssistantConfirmationRecord (backend/src/models/assistant.py)
/**!
 * @brief Persist risky operation confirmation tokens with lifecycle state.
 * @complexity 3
 * @post State transitions can be tracked and audited.
 * @pre intent/dispatch and expiry timestamp must be provided.
 */

// --- AuthModels (backend/src/models/auth.py)
/**!
 * @brief SQLAlchemy models for multi-user authentication and authorization.
 * @complexity 5
 * @data_contract UserData -> UserRecord
 * @invariant Usernames and emails must be unique.
 * @layer Domain
 * @post Auth ORM models registered with unique constraints
 * @pre Database engine initialized
 * @side_effect Defines auth user tables
 */

// --- generate_uuid (backend/src/models/auth.py)
/**!
 * @brief Generates a unique UUID string.
 * @post Returns a string representation of a new UUID.
 */

// --- user_roles (backend/src/models/auth.py)
/**!
 * @brief Association table for many-to-many relationship between Users and Roles.
 */

// --- role_permissions (backend/src/models/auth.py)
/**!
 * @brief Association table for many-to-many relationship between Roles and Permissions.
 */

// --- Role (backend/src/models/auth.py)
/**!
 * @brief Represents a collection of permissions.
 */

// --- Permission (backend/src/models/auth.py)
/**!
 * @brief Represents a specific capability within the system.
 */

// --- ADGroupMapping (backend/src/models/auth.py)
/**!
 * @brief Maps an Active Directory group to a local System Role.
 */

// --- CleanReleaseModels (backend/src/models/clean_release.py)
/**!
 * @brief Define canonical clean release domain entities and lifecycle guards.
 * @complexity 3
 * @data_contract Model[ReleaseCandidate, CandidateArtifact, DistributionManifest, ComplianceRun, ComplianceReport]
 * @invariant Immutable snapshots are never mutated; forbidden lifecycle transitions are rejected.
 * @layer Domain
 * @post Provides SQLAlchemy and dataclass definitions for governance domain.
 * @pre Base mapping model and release enums are available.
 * @side_effect None (schema definition).
 */

// --- ExecutionMode (backend/src/models/clean_release.py)
/**!
 * @brief Backward-compatible execution mode enum for legacy TUI/orchestrator tests.
 */

// --- CheckFinalStatus (backend/src/models/clean_release.py)
/**!
 * @brief Backward-compatible final status enum for legacy TUI/orchestrator tests.
 */

// --- CheckStageName (backend/src/models/clean_release.py)
/**!
 * @brief Backward-compatible stage name enum for legacy TUI/orchestrator tests.
 */

// --- CheckStageStatus (backend/src/models/clean_release.py)
/**!
 * @brief Backward-compatible stage status enum for legacy TUI/orchestrator tests.
 */

// --- CheckStageResult (backend/src/models/clean_release.py)
/**!
 * @brief Backward-compatible stage result container for legacy TUI/orchestrator tests.
 */

// --- ProfileType (backend/src/models/clean_release.py)
/**!
 * @brief Backward-compatible profile enum for legacy TUI bootstrap logic.
 */

// --- RegistryStatus (backend/src/models/clean_release.py)
/**!
 * @brief Backward-compatible registry status enum for legacy TUI bootstrap logic.
 */

// --- ReleaseCandidateStatus (backend/src/models/clean_release.py)
/**!
 * @brief Backward-compatible release candidate status enum for legacy TUI.
 */

// --- ResourceSourceEntry (backend/src/models/clean_release.py)
/**!
 * @brief Backward-compatible source entry model for legacy TUI bootstrap logic.
 */

// --- ResourceSourceRegistry (backend/src/models/clean_release.py)
/**!
 * @brief Backward-compatible source registry model for legacy TUI bootstrap logic.
 */

// --- CleanProfilePolicy (backend/src/models/clean_release.py)
/**!
 * @brief Backward-compatible policy model for legacy TUI bootstrap logic.
 */

// --- ComplianceCheckRun (backend/src/models/clean_release.py)
/**!
 * @brief Backward-compatible run model for legacy TUI typing/import compatibility.
 */

// --- ReleaseCandidate (backend/src/models/clean_release.py)
/**!
 * @brief Represents the release unit being prepared and governed.
 * @post status advances only through legal transitions.
 * @pre id, version, source_snapshot_ref are non-empty.
 */

// --- CandidateArtifact (backend/src/models/clean_release.py)
/**!
 * @brief Represents one artifact associated with a release candidate.
 */

// --- ManifestItem (backend/src/models/clean_release.py)
/**!
 */

// --- ManifestSummary (backend/src/models/clean_release.py)
/**!
 */

// --- DistributionManifest (backend/src/models/clean_release.py)
/**!
 * @brief Immutable snapshot of the candidate payload.
 * @invariant Immutable after creation.
 */

// --- SourceRegistrySnapshot (backend/src/models/clean_release.py)
/**!
 * @brief Immutable registry snapshot for allowed sources.
 */

// --- CleanPolicySnapshot (backend/src/models/clean_release.py)
/**!
 * @brief Immutable policy snapshot used to evaluate a run.
 */

// --- ComplianceRun (backend/src/models/clean_release.py)
/**!
 * @brief Operational record for one compliance execution.
 */

// --- ComplianceStageRun (backend/src/models/clean_release.py)
/**!
 * @brief Stage-level execution record inside a run.
 */

// --- ViolationSeverity (backend/src/models/clean_release.py)
/**!
 * @brief Backward-compatible violation severity enum for legacy clean-release tests.
 */

// --- ViolationCategory (backend/src/models/clean_release.py)
/**!
 * @brief Backward-compatible violation category enum for legacy clean-release tests.
 */

// --- ComplianceViolation (backend/src/models/clean_release.py)
/**!
 * @brief Violation produced by a stage.
 */

// --- ComplianceReport (backend/src/models/clean_release.py)
/**!
 * @brief Immutable result derived from a completed run.
 * @invariant Immutable after creation.
 */

// --- ApprovalDecision (backend/src/models/clean_release.py)
/**!
 * @brief Approval or rejection bound to a candidate and report.
 */

// --- PublicationRecord (backend/src/models/clean_release.py)
/**!
 * @brief Publication or revocation record.
 */

// --- CleanReleaseAuditLog (backend/src/models/clean_release.py)
/**!
 * @brief Represents a persistent audit log entry for clean release actions.
 */

// --- AppConfigRecord (backend/src/models/config.py)
/**!
 * @brief Stores persisted application configuration as a single authoritative record model.
 * @data_contract Input -> persistence row {id:str, payload:json, updated_at:datetime}; Output -> AppConfigRecord ORM entity.
 * @post ORM table 'app_configurations' exposes id, payload, and updated_at fields with declared nullability/default semantics.
 * @pre SQLAlchemy declarative Base is initialized and table metadata registration is active.
 * @side_effect Registers ORM mapping metadata during module import.
 */

// --- NotificationConfig (backend/src/models/config.py)
/**!
 * @brief Stores persisted provider-level notification configuration and encrypted credentials metadata.
 * @data_contract Input -> persistence row {id:str, type:str, name:str, credentials:json, is_active:bool, created_at:datetime, updated_at:datetime}; Output -> NotificationConfig ORM entity.
 * @post ORM table 'notification_configs' exposes id, type, name, credentials, is_active, created_at, updated_at fields with declared constraints/defaults.
 * @pre SQLAlchemy declarative Base is initialized and uuid generation is available at instance creation time.
 * @side_effect Registers ORM mapping metadata during module import; may generate UUID values for new entity instances.
 */

// --- DashboardModels (backend/src/models/dashboard.py)
/**!
 * @brief Defines data models for dashboard metadata and selection.
 * @complexity 3
 * @layer Domain
 */

// --- DashboardMetadata (backend/src/models/dashboard.py)
/**!
 * @brief Represents a dashboard available for migration.
 * @complexity 1
 */

// --- DashboardSelection (backend/src/models/dashboard.py)
/**!
 * @brief Represents the user's selection of dashboards to migrate.
 * @complexity 1
 */

// --- DatasetReviewModels (backend/src/models/dataset_review.py)
/**!
 * @brief Thin facade re-exporting all dataset review domain models from the decomposed sub-package.
 * @complexity 2
 * @invariant All public model classes and enums remain importable from `src.models.dataset_review` without changes.
 * @layer Domain
 * @rationale Original 984-line monolith violated INV_7 (400-line module limit). Decomposed into domain-focused sub-modules while preserving backward-compatible import paths.
 * @rejected Keeping all models in a single file because it exceeded the fractal limit by 2.5x and accumulated structural erosion risk.
 */

// --- DatasetReviewClarificationModels (backend/src/models/dataset_review_pkg/_clarification_models.py)
/**!
 * @brief Clarification session, question, option, and answer models for guided review flow.
 * @complexity 3
 * @data_contract ClarificationData -> ClarificationRecord
 * @invariant Only one active clarification question may exist at a time per session.
 * @layer Domain
 * @post Clarification ORM models registered
 * @pre Database engine initialized
 * @side_effect Defines dataset review clarification tables
 */

// --- ClarificationSession (backend/src/models/dataset_review_pkg/_clarification_models.py)
/**!
 * @brief One clarification session aggregate owning questions and tracking resolution progress.
 * @complexity 2
 */

// --- ClarificationQuestion (backend/src/models/dataset_review_pkg/_clarification_models.py)
/**!
 * @brief One clarification question with priority ordering, options, and state machine.
 * @complexity 2
 */

// --- ClarificationOption (backend/src/models/dataset_review_pkg/_clarification_models.py)
/**!
 * @brief One selectable option for a clarification question with recommendation flag.
 * @complexity 1
 */

// --- ClarificationAnswer (backend/src/models/dataset_review_pkg/_clarification_models.py)
/**!
 * @brief One persisted clarification answer with impact summary and feedback tracking.
 * @complexity 2
 */

// --- DatasetReviewEnums (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief All enumeration types for the dataset review domain, grouped for stable cross-module reuse.
 * @complexity 2
 * @invariant Enum values are string-based for JSON serialization compatibility.
 * @layer Domain
 */

// --- SessionStatus (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Lifecycle status of a dataset review session.
 * @complexity 1
 */

// --- SessionPhase (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Ordered phase progression for dataset review orchestration.
 * @complexity 1
 */

// --- ReadinessState (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Granular readiness indicator driving the recommended-action UX flow.
 * @complexity 1
 */

// --- RecommendedAction (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Next-action guidance derived from the current readiness state.
 * @complexity 1
 */

// --- SessionCollaboratorRole (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief RBAC role for session collaborators.
 * @complexity 1
 */

// --- BusinessSummarySource (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Provenance of the dataset business summary text.
 * @complexity 1
 */

// --- ConfidenceState (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Confidence level for dataset profile completeness.
 * @complexity 1
 */

// --- FindingArea (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Domain area classification for validation findings.
 * @complexity 1
 */

// --- FindingSeverity (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Severity classification for validation findings.
 * @complexity 1
 */

// --- ResolutionState (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Resolution status for validation findings and clarification items.
 * @complexity 1
 */

// --- SemanticSourceType (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Classification of semantic enrichment source origins.
 * @complexity 1
 */

// --- TrustLevel (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Trust classification for semantic source reliability.
 * @complexity 1
 */

// --- SemanticSourceStatus (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Lifecycle status for semantic source application.
 * @complexity 1
 */

// --- FieldKind (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Kind classification for semantic field entries.
 * @complexity 1
 */

// --- FieldProvenance (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Provenance tracking for semantic field value origin.
 * @complexity 1
 */

// --- CandidateMatchType (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Match type classification for semantic candidates.
 * @complexity 1
 */

// --- CandidateStatus (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Lifecycle status for semantic candidate proposals.
 * @complexity 1
 */

// --- FilterSource (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Origin classification for imported filters.
 * @complexity 1
 */

// --- FilterConfidenceState (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Confidence classification for imported filter values.
 * @complexity 1
 */

// --- FilterRecoveryStatus (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Recovery quality status for imported filters.
 * @complexity 1
 */

// --- VariableKind (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Kind classification for template variables.
 * @complexity 1
 */

// --- MappingStatus (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Lifecycle status for template variable mapping.
 * @complexity 1
 */

// --- MappingMethod (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Method classification for execution mapping creation.
 * @complexity 1
 */

// --- MappingWarningLevel (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Warning severity for execution mapping quality indicators.
 * @complexity 1
 */

// --- ApprovalState (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Approval lifecycle for execution mapping gate checks.
 * @complexity 1
 */

// --- ClarificationStatus (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Lifecycle status for clarification sessions.
 * @complexity 1
 */

// --- QuestionState (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief State machine for individual clarification questions.
 * @complexity 1
 */

// --- AnswerKind (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Classification of clarification answer types.
 * @complexity 1
 */

// --- PreviewStatus (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Lifecycle status for compiled SQL previews.
 * @complexity 1
 */

// --- LaunchStatus (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Outcome status for dataset launch handoff.
 * @complexity 1
 */

// --- ArtifactType (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Type classification for export artifacts.
 * @complexity 1
 */

// --- ArtifactFormat (backend/src/models/dataset_review_pkg/_enums.py)
/**!
 * @brief Format classification for export artifact output.
 * @complexity 1
 */

// --- DatasetReviewExecutionModels (backend/src/models/dataset_review_pkg/_execution_models.py)
/**!
 * @brief Compiled preview, run context, session event, and export artifact models for execution and audit.
 * @complexity 3
 * @layer Domain
 */

// --- CompiledPreview (backend/src/models/dataset_review_pkg/_execution_models.py)
/**!
 * @brief One compiled SQL preview snapshot with fingerprint for staleness detection.
 * @complexity 2
 */

// --- DatasetRunContext (backend/src/models/dataset_review_pkg/_execution_models.py)
/**!
 * @brief Immutable launch audit snapshot capturing effective filters, template params, and approval state at launch time.
 * @complexity 2
 */

// --- SessionEvent (backend/src/models/dataset_review_pkg/_execution_models.py)
/**!
 * @brief One persisted audit event for dataset review session mutations.
 * @complexity 2
 */

// --- ExportArtifact (backend/src/models/dataset_review_pkg/_execution_models.py)
/**!
 * @brief One persisted export artifact reference for documentation and validation outputs.
 * @complexity 2
 */

// --- DatasetReviewFilterModels (backend/src/models/dataset_review_pkg/_filter_models.py)
/**!
 * @brief Imported filter and template variable models for Superset context recovery and execution mapping.
 * @complexity 3
 * @layer Domain
 */

// --- ImportedFilter (backend/src/models/dataset_review_pkg/_filter_models.py)
/**!
 * @brief Recovered Superset filter with confidence and recovery status tracking.
 * @complexity 2
 */

// --- TemplateVariable (backend/src/models/dataset_review_pkg/_filter_models.py)
/**!
 * @brief Discovered template variable from dataset SQL with mapping status tracking.
 * @complexity 2
 */

// --- DatasetReviewFindingModels (backend/src/models/dataset_review_pkg/_finding_models.py)
/**!
 * @brief Validation finding model for tracking blocking, warning, and informational issues during review.
 * @complexity 2
 * @layer Domain
 */

// --- ValidationFinding (backend/src/models/dataset_review_pkg/_finding_models.py)
/**!
 * @brief Structured finding record for dataset review validation issues with resolution tracking.
 * @complexity 2
 */

// --- DatasetReviewMappingModels (backend/src/models/dataset_review_pkg/_mapping_models.py)
/**!
 * @brief Execution mapping model linking imported filters to template variables with approval gates.
 * @complexity 2
 * @layer Domain
 */

// --- ExecutionMapping (backend/src/models/dataset_review_pkg/_mapping_models.py)
/**!
 * @brief One filter-to-variable mapping with approval gate, effective value, and transformation metadata.
 * @complexity 2
 * @invariant Explicit approval is required before launch when requires_explicit_approval is true.
 */

// --- DatasetReviewProfileModels (backend/src/models/dataset_review_pkg/_profile_models.py)
/**!
 * @brief Dataset profile model capturing business summary, confidence, and completeness metadata.
 * @complexity 2
 * @layer Domain
 */

// --- DatasetProfile (backend/src/models/dataset_review_pkg/_profile_models.py)
/**!
 * @brief One-to-one profile snapshot for a dataset review session, tracking business summary provenance and completeness.
 * @complexity 2
 */

// --- DatasetReviewSemanticModels (backend/src/models/dataset_review_pkg/_semantic_models.py)
/**!
 * @brief Semantic source, field entry, and candidate models for dictionary-driven semantic enrichment.
 * @complexity 3
 * @data_contract SemanticData -> SemanticFieldEntry
 * @invariant Manual overrides are never silently replaced by imported, inferred, or AI-generated values.
 * @layer Domain
 * @post Semantic ORM models registered with override protection
 * @pre Database engine initialized
 * @side_effect Defines dataset review semantic tables
 */

// --- SemanticSource (backend/src/models/dataset_review_pkg/_semantic_models.py)
/**!
 * @brief Registered semantic enrichment source with trust level and application status.
 * @complexity 2
 */

// --- SemanticFieldEntry (backend/src/models/dataset_review_pkg/_semantic_models.py)
/**!
 * @brief Per-field semantic metadata entry with provenance tracking, lock state, and candidate set.
 * @complexity 3
 * @invariant Locked fields preserve their active value regardless of later candidate proposals.
 */

// --- SemanticCandidate (backend/src/models/dataset_review_pkg/_semantic_models.py)
/**!
 * @brief One proposed semantic value for a field entry, ranked by match type and confidence.
 * @complexity 2
 */

// --- DatasetReviewSessionModels (backend/src/models/dataset_review_pkg/_session_models.py)
/**!
 * @brief Session aggregate root and collaborator models for dataset review orchestration.
 * @complexity 3
 * @data_contract SessionData -> SessionRecord
 * @invariant Session and profile entities are strictly scoped to an authenticated user.
 * @layer Domain
 * @post Session ORM models registered with optimistic locking
 * @pre Database engine initialized
 * @side_effect Defines dataset review session tables
 */

// --- SessionCollaborator (backend/src/models/dataset_review_pkg/_session_models.py)
/**!
 * @brief RBAC collaborator record linking a user to a dataset review session with a specific role.
 * @complexity 2
 */

// --- DatasetReviewSession (backend/src/models/dataset_review_pkg/_session_models.py)
/**!
 * @brief Aggregate root for the dataset review lifecycle, owning all child entities and driving readiness transitions.
 * @complexity 3
 * @invariant Optimistic-lock version column prevents lost-update races on concurrent mutations.
 */

// --- FilterStateModels (backend/src/models/filter_state.py)
/**!
 * @brief Pydantic models for Superset native filter state extraction and restoration.
 * @complexity 2
 * @layer Domain
 */

// --- FilterState (backend/src/models/filter_state.py)
/**!
 * @brief Represents the state of a single native filter.
 * @complexity 2
 * @data_contract Input[extraFormData: Dict, filterState: Dict, ownState: Optional[Dict]] -> Model[FilterState]
 */

// --- NativeFilterDataMask (backend/src/models/filter_state.py)
/**!
 * @brief Represents the dataMask containing all native filter states.
 * @complexity 2
 * @data_contract Input[Dict[filter_id, FilterState]] -> Model[NativeFilterDataMask]
 */

// --- ParsedNativeFilters (backend/src/models/filter_state.py)
/**!
 * @brief Result of parsing native filters from permalink or native_filters_key.
 * @complexity 2
 * @data_contract Input[dataMask: Dict, metadata: Dict] -> Model[ParsedNativeFilters]
 */

// --- DashboardURLFilterExtraction (backend/src/models/filter_state.py)
/**!
 * @brief Result of parsing a complete dashboard URL for filter information.
 * @complexity 2
 * @data_contract Input[url: str, dashboard_id: Optional, filter_type: Optional, filters: Dict] -> Model[DashboardURLFilterExtraction]
 */

// --- ExtraFormDataMerge (backend/src/models/filter_state.py)
/**!
 * @brief Configuration for merging extraFormData from different sources.
 * @complexity 2
 * @data_contract Input[append_keys: List[str], override_keys: List[str]] -> Model[ExtraFormDataMerge]
 */

// --- GitModels (backend/src/models/git.py)
/**!
 */

// --- GitServerConfig (backend/src/models/git.py)
/**!
 * @brief Configuration for a Git server connection.
 * @complexity 1
 */

// --- GitRepository (backend/src/models/git.py)
/**!
 * @brief Tracking for a local Git repository linked to a dashboard.
 * @complexity 1
 */

// --- DeploymentEnvironment (backend/src/models/git.py)
/**!
 * @brief Target Superset environments for dashboard deployment.
 * @complexity 1
 */

// --- LlmModels (backend/src/models/llm.py)
/**!
 * @brief SQLAlchemy models for LLM provider configuration and validation results.
 * @complexity 3
 * @layer Domain
 */

// --- ValidationPolicy (backend/src/models/llm.py)
/**!
 * @brief Defines a scheduled rule for validating a group of dashboards within an execution window.
 */

// --- LLMProvider (backend/src/models/llm.py)
/**!
 * @brief SQLAlchemy model for LLM provider configuration.
 */

// --- ValidationRecord (backend/src/models/llm.py)
/**!
 * @brief SQLAlchemy model for dashboard validation history.
 */

// --- MaintenanceModels (backend/src/models/maintenance.py)
/**!
 * @brief SQLAlchemy models for the Maintenance Banner feature: event, banner, dashboard state, and settings.
 * @complexity 2
 * @invariant MaintenanceSettings is a singleton row (id='default') enforced by CheckConstraint
 * @layer Domain
 */

// --- MaintenanceEventStatus (backend/src/models/maintenance.py)
/**!
 * @complexity 1
 */

// --- MaintenanceDashboardBannerStatus (backend/src/models/maintenance.py)
/**!
 * @complexity 1
 */

// --- MaintenanceDashboardStateStatus (backend/src/models/maintenance.py)
/**!
 * @complexity 1
 */

// --- DashboardScope (backend/src/models/maintenance.py)
/**!
 * @complexity 1
 */

// --- MaintenanceEvent (backend/src/models/maintenance.py)
/**!
 * @brief A record of a maintenance event with table list, time window, status, and linked dashboard states.
 * @complexity 1
 */

// --- MaintenanceDashboardBanner (backend/src/models/maintenance.py)
/**!
 * @brief The canonical "one chart per dashboard" entity. Unique partial index enforces single active banner per dashboard.
 * @complexity 1
 * @invariant Unique partial index (environment_id, dashboard_id) WHERE status='active'
 */

// --- MaintenanceDashboardState (backend/src/models/maintenance.py)
/**!
 * @brief Links a maintenance event to a dashboard via a banner. Tracks per-dashboard-per-event lifecycle.
 * @complexity 1
 */

// --- MaintenanceSettings (backend/src/models/maintenance.py)
/**!
 * @brief Single-row maintenance mode configuration. Enforces singleton via CheckConstraint(id='default').
 * @complexity 1
 * @invariant id must always be 'default' — enforced by CheckConstraint
 */

// --- MappingModels (backend/src/models/mapping.py)
/**!
 * @brief Defines the database schema for environment metadata and database mappings using SQLAlchemy.
 * @complexity 5
 * @invariant All primary keys are UUID strings.
 * @layer Domain
 */

// --- Base (backend/src/models/mapping.py)
/**!
 * @brief SQLAlchemy declarative base for all domain models.
 * @complexity 1
 */

// --- ResourceType (backend/src/models/mapping.py)
/**!
 * @brief Enumeration of possible Superset resource types for ID mapping.
 * @complexity 1
 */

// --- MigrationStatus (backend/src/models/mapping.py)
/**!
 * @brief Enumeration of possible migration job statuses.
 * @complexity 1
 */

// --- MigrationJob (backend/src/models/mapping.py)
/**!
 * @brief Represents a single migration execution job.
 * @complexity 2
 */

// --- ResourceMapping (backend/src/models/mapping.py)
/**!
 * @brief Maps a universal UUID for a resource to its actual ID on a specific environment.
 * @complexity 3
 * @test_data resource_mapping_record -> {'environment_id': 'prod-env-1', 'resource_type': 'chart', 'uuid': '123e4567-e89b-12d3-a456-426614174000', 'remote_integer_id': '42'}
 */

// --- ProfileModels (backend/src/models/profile.py)
/**!
 * @brief Defines persistent per-user profile settings for dashboard filter, Git identity/token, and UX preferences.
 * @complexity 5
 * @data_contract ProfileData -> PreferenceRecord
 * @invariant Sensitive Git token is stored encrypted and never returned in plaintext.
 * @layer Domain
 * @post Profile ORM models registered
 * @pre Database engine initialized
 * @side_effect Defines user profile/preference tables
 */

// --- UserDashboardPreference (backend/src/models/profile.py)
/**!
 * @brief Stores Superset username binding and default "my dashboards" toggle for one authenticated user.
 * @complexity 3
 */

// --- ReportModels (backend/src/models/report.py)
/**!
 * @brief Canonical report schemas for unified task reporting across heterogeneous task types.
 * @complexity 3
 * @data_contract Model[TaskReport, ReportCollection, ReportDetailView]
 * @invariant Canonical report fields are always present for every report item.
 * @layer Domain
 * @post Provides validated schemas for cross-plugin reporting and UI consumption.
 * @pre Pydantic library and task manager models are available.
 * @side_effect None (schema definition).
 */

// --- TaskType (backend/src/models/report.py)
/**!
 * @brief Supported normalized task report types.
 * @complexity 3
 * @invariant Must contain valid generic task type mappings.
 */

// --- ReportStatus (backend/src/models/report.py)
/**!
 * @brief Supported normalized report status values.
 * @complexity 3
 * @invariant TaskStatus enum mapping logic holds.
 */

// --- ErrorContext (backend/src/models/report.py)
/**!
 * @brief Error and recovery context for failed/partial reports.
 * @complexity 3
 * @invariant The properties accurately describe error state.
 * @test_contract ErrorContextModel ->
 */

// --- TaskReport (backend/src/models/report.py)
/**!
 * @brief Canonical normalized report envelope for one task execution.
 * @complexity 3
 * @invariant Must represent canonical task record attributes.
 * @test_contract TaskReportModel ->
 */

// --- ReportQuery (backend/src/models/report.py)
/**!
 * @brief Query object for server-side report filtering, sorting, and pagination.
 * @complexity 3
 * @invariant Time and pagination queries are mutually consistent.
 * @test_contract ReportQueryModel ->
 */

// --- ReportCollection (backend/src/models/report.py)
/**!
 * @brief Paginated collection of normalized task reports.
 * @complexity 3
 * @invariant Represents paginated data correctly.
 * @test_contract ReportCollectionModel ->
 */

// --- ReportDetailView (backend/src/models/report.py)
/**!
 * @brief Detailed report representation including diagnostics and recovery actions.
 * @complexity 3
 * @invariant Incorporates a report and logs correctly.
 * @test_contract ReportDetailViewModel ->
 */

// --- StorageModels (backend/src/models/storage.py)
/**!
 * @rationale Fixed typo 'repositorys' → 'repositories' in FileCategory.REPOSITORY and StorageConfig.repo_path default. Breaking change documented for existing installations.
 */

// --- FileCategory (backend/src/models/storage.py)
/**!
 * @brief Enumeration of supported file categories in the storage system.
 * @complexity 1
 */

// --- StorageConfig (backend/src/models/storage.py)
/**!
 * @brief Configuration model for the storage system, defining paths and naming patterns.
 * @complexity 1
 */

// --- StoredFile (backend/src/models/storage.py)
/**!
 * @brief Data model representing metadata for a file stored in the system.
 * @complexity 1
 */

// --- TaskModels (backend/src/models/task.py)
/**!
 * @brief Defines the database schema for task execution records.
 * @complexity 1
 * @invariant All primary keys are UUID strings.
 * @layer Domain
 */

// --- TaskRecord (backend/src/models/task.py)
/**!
 * @brief Represents a persistent record of a task execution.
 * @complexity 1
 */

// --- TaskLogRecord (backend/src/models/task.py)
/**!
 * @brief Represents a single persistent log entry for a task.
 * @complexity 3
 * @invariant Each log entry belongs to exactly one task.
 * @test_contract TaskLogCreate ->
 */

// --- TranslateModels (backend/src/models/translate.py)
/**!
 * @brief SQLAlchemy ORM models for LLM-based SQL/dashboard translation across dialects.
 * @complexity 3
 * @layer Domain
 */

// --- TranslationJob (backend/src/models/translate.py)
/**!
 * @brief A translation job representing a multi-dialect conversion task with column mappings, LLM config, and dictionary attachments.
 * @rationale Snapshot isolation — in-progress runs use config snapshot; config edits affect future runs only.
 * @rejected Invalidating in-progress runs on config edit would break scheduled run continuity.
 */

// --- TranslationRun (backend/src/models/translate.py)
/**!
 * @brief Represents a single execution of a translation job, capturing status, timing, and Superset execution metadata.
 */

// --- TranslationBatch (backend/src/models/translate.py)
/**!
 * @brief Groups translation records within a run into manageable batches with timing and record counts.
 */

// --- TranslationRecord (backend/src/models/translate.py)
/**!
 * @brief Individual translation result for a single SQL statement or dashboard element, tracking source, target, and error state.
 */

// --- TranslationEvent (backend/src/models/translate.py)
/**!
 * @brief Audit/event log for translation operations, with optional run_id for context.
 */

// --- TranslationPreviewSession (backend/src/models/translate.py)
/**!
 * @brief A preview session allowing users to review proposed translations before applying them.
 */

// --- TranslationPreviewRecord (backend/src/models/translate.py)
/**!
 * @brief Individual preview entry within a preview session, showing original and translated content side by side.
 */

// --- TerminologyDictionary (backend/src/models/translate.py)
/**!
 * @brief A named collection of terminology mappings used during translation to ensure consistent term translation.
 */

// --- DictionaryEntry (backend/src/models/translate.py)
/**!
 * @brief A single term mapping entry with case-insensitive unique constraint on source_term_normalized and origin tracking.
 */

// --- TranslationSchedule (backend/src/models/translate.py)
/**!
 * @brief Defines a cron-based schedule for recurring translation jobs.
 */

// --- TranslationJobDictionary (backend/src/models/translate.py)
/**!
 * @brief Many-to-many association between translation jobs and terminology dictionaries.
 */

// --- MetricSnapshot (backend/src/models/translate.py)
/**!
 * @brief Captures translation performance metrics at a point in time with config/content/dictionary hash keys for aggregation.
 */

// --- TranslationLanguage (backend/src/models/translate.py)
/**!
 * @brief Per-language translation result for a single record, supporting multi-language output.
 * @complexity 1
 */

// --- TranslationPreviewLanguage (backend/src/models/translate.py)
/**!
 * @brief Per-language preview entry within a preview session.
 * @complexity 1
 */

// --- TranslationRunLanguageStats (backend/src/models/translate.py)
/**!
 * @brief Per-language statistics for a translation run (row counts, tokens, cost).
 * @complexity 1
 */

// --- src.plugins (backend/src/plugins/__init__.py)
/**!
 * @brief Plugin package root for dynamic discovery and runtime imports.
 */

// --- BackupPlugin (backend/src/plugins/backup.py)
/**!
 * @brief A plugin that provides functionality to back up Superset dashboards.
 * @layer App
 */

// --- DebugPluginModule (backend/src/plugins/debug.py)
/**!
 * @brief Plugin for diagnostics. Inherits PluginBase.
 * @layer Plugin
 */

// --- DebugPlugin (backend/src/plugins/debug.py)
/**!
 * @brief Plugin for system diagnostics and debugging.
 */

// --- GitPluginExt (backend/src/plugins/git/__init__.py)
/**!
 * @brief Git plugin extension package root.
 */

// --- GitLLMExtensionModule (backend/src/plugins/git/llm_extension.py)
/**!
 * @brief LLM-based extensions for the Git plugin, specifically for commit message generation.
 * @complexity 3
 * @layer Domain
 */

// --- GitLLMExtension (backend/src/plugins/git/llm_extension.py)
/**!
 * @brief Provides LLM capabilities to the Git plugin.
 */

// --- GitPluginModule (backend/src/plugins/git_plugin.py)
/**!
 * @brief Предоставляет плагин для версионирования и развертывания дашбордов Superset.
 * @complexity 4
 * @invariant _handle_sync сохраняет backup управляемых директорий перед удалением;
 * @layer Plugin
 */

// --- GitPlugin (backend/src/plugins/git_plugin.py)
/**!
 * @brief Реализация плагина Git Integration для управления версиями дашбордов.
 */

// --- LLMAnalysisPackage (backend/src/plugins/llm_analysis/__init__.py)
/**!
 */

// --- LLMAnalysisModels (backend/src/plugins/llm_analysis/models.py)
/**!
 * @brief Define Pydantic models for LLM Analysis plugin.
 * @complexity 3
 * @layer Domain
 */

// --- LLMProviderType (backend/src/plugins/llm_analysis/models.py)
/**!
 * @brief Enum for supported LLM providers.
 */

// --- LLMProviderConfig (backend/src/plugins/llm_analysis/models.py)
/**!
 * @brief Configuration for an LLM provider.
 */

// --- ValidationStatus (backend/src/plugins/llm_analysis/models.py)
/**!
 * @brief Enum for dashboard validation status.
 */

// --- DetectedIssue (backend/src/plugins/llm_analysis/models.py)
/**!
 * @brief Model for a single issue detected during validation.
 */

// --- ValidationResult (backend/src/plugins/llm_analysis/models.py)
/**!
 * @brief Model for dashboard validation result.
 */

// --- LLMAnalysisPlugin (backend/src/plugins/llm_analysis/plugin.py)
/**!
 * @brief Implements DashboardValidationPlugin and DocumentationPlugin.
 * @complexity 5
 * @data_contract AnalysisRequest -> AnalysisResult
 * @invariant All LLM interactions must be executed as asynchronous tasks.
 * @layer Plugin
 */

// --- _is_masked_or_invalid_api_key (backend/src/plugins/llm_analysis/plugin.py)
/**!
 * @brief Guards against placeholder or malformed API keys in runtime.
 * @post Returns True when value cannot be used for authenticated provider calls.
 * @pre value may be None.
 */

// --- _json_safe_value (backend/src/plugins/llm_analysis/plugin.py)
/**!
 * @brief Recursively normalize payload values for JSON serialization.
 * @post datetime values are converted to ISO strings.
 * @pre value may be nested dict/list with datetime values.
 */

// --- DashboardValidationPlugin (backend/src/plugins/llm_analysis/plugin.py)
/**!
 * @brief Plugin for automated dashboard health analysis using LLMs.
 */

// --- DocumentationPlugin (backend/src/plugins/llm_analysis/plugin.py)
/**!
 * @brief Plugin for automated dataset documentation using LLMs.
 */

// --- LLMAnalysisScheduler (backend/src/plugins/llm_analysis/scheduler.py)
/**!
 * @brief Provides helper functions to schedule LLM-based validation tasks.
 * @complexity 3
 * @layer Domain
 */

// --- schedule_dashboard_validation (backend/src/plugins/llm_analysis/scheduler.py)
/**!
 * @brief Schedules a recurring dashboard validation task.
 * @side_effect Adds a job to the scheduler service.
 */

// --- _parse_cron (backend/src/plugins/llm_analysis/scheduler.py)
/**!
 * @brief Basic cron parser placeholder.
 */

// --- LLMAnalysisService (backend/src/plugins/llm_analysis/service.py)
/**!
 * @brief Services for LLM interaction and dashboard screenshots.
 * @complexity 5
 * @data_contract DashboardSpec -> Screenshot + Analysis
 * @invariant Screenshots must be 1920px width and capture full page height.
 * @layer Plugin
 * @rationale Extracted all hardcoded timeouts into named module-level constants (PLAYWRIGHT_NAVIGATION_TIMEOUT_MS, PLAYWRIGHT_WAIT_TIMEOUT_MS, PLAYWRIGHT_SHORT_TIMEOUT_MS, HTTP_REQUEST_TIMEOUT_MS, SCREENSHOT_SERVICE_TIMEOUT_MS, LLM_HTTP_TIMEOUT_S) and DEFAULT_USER_AGENT. Zero remaining numeric timeout literals.
 */

// --- ScreenshotService (backend/src/plugins/llm_analysis/service.py)
/**!
 * @brief Handles capturing screenshots of Superset dashboards.
 */

// --- LLMClient (backend/src/plugins/llm_analysis/service.py)
/**!
 * @brief Wrapper for LLM provider APIs.
 */

// --- MaintenanceBannerPlugin (backend/src/plugins/maintenance_banner.py)
/**!
 * @brief TaskManager plugin for executing maintenance banner operations (start, end, end-all).
 * @complexity 4
 */

// --- MapperPluginModule (backend/src/plugins/mapper.py)
/**!
 * @brief Plugin for dataset column mapping. Inherits PluginBase.
 * @layer Plugin
 */

// --- MapperPlugin (backend/src/plugins/mapper.py)
/**!
 * @brief Plugin for mapping dataset columns verbose names.
 */

// --- MigrationPlugin (backend/src/plugins/migration.py)
/**!
 * @brief Orchestrates export, DB-mapping transformation, and import of Superset dashboards across environments.
 * @complexity 5
 * @data_contract Input[TaskContext{from_env,to_env,dashboard_regex,replace_db_config,from_db_id,to_db_id,passwords?}] -> Output[MigrationResult|artifact set]
 * @invariant Dashboards must never be imported with unmapped/source DB connections to prevent data leaks or cross-environment pollution.
 * @layer App
 * @post Plugin metadata remains stable and migration execution preserves mapped-environment import guarantees.
 * @pre Plugin loader can resolve infrastructure dependencies and execution requests provide validated migration context.
 * @side_effect Reads config, opens database sessions, creates temporary artifacts, and triggers Superset export/import workflows.
 */

// --- SearchPluginModule (backend/src/plugins/search.py)
/**!
 * @brief Plugin for text search across datasets. Inherits PluginBase.
 * @layer Plugin
 */

// --- SearchPlugin (backend/src/plugins/search.py)
/**!
 * @brief Plugin for searching text patterns in Superset datasets.
 */

// --- StoragePluginPackage (backend/src/plugins/storage/__init__.py)
/**!
 */

// --- StoragePlugin (backend/src/plugins/storage/plugin.py)
/**!
 * @brief Provides core filesystem operations for managing backups and repositories.
 * @invariant All file operations must be restricted to the configured storage root.
 * @layer App
 * @rationale Replaced Path(__file__).parents[3] with BASE_DIR import from database.py for path resolution consistency.
 */

// --- TranslatePluginPackage (backend/src/plugins/translate/__init__.py)
/**!
 */

// --- TestClickHouseTimestampNormalization (backend/src/plugins/translate/__tests__/test_clickhouse_insert_integration.py)
/**!
 * @brief Verify Unix timestamp detection and conversion for ClickHouse Date columns.
 */

// --- TestClickHouseInsertSqlGeneration (backend/src/plugins/translate/__tests__/test_clickhouse_insert_integration.py)
/**!
 * @brief Verify SQLGenerator produces valid ClickHouse INSERT SQL with normalized dates.
 */

// --- TestClickHouseJoinVerification (backend/src/plugins/translate/__tests__/test_clickhouse_insert_integration.py)
/**!
 * @brief Verify the JOIN query SQL is syntactically correct for ClickHouse.
 */

// --- TestOrchestratorInsertFlow (backend/src/plugins/translate/__tests__/test_clickhouse_insert_integration.py)
/**!
 * @brief Verify the orchestrator's _generate_and_insert_sql produces correct SQL for ClickHouse.
 */

// --- TestClickHouseEndToEnd (backend/src/plugins/translate/__tests__/test_clickhouse_insert_integration.py)
/**!
 * @brief End-to-end test: generate SQL, verify structure, simulate execution.
 */

// --- TestDictionaryLegacyHub (backend/src/plugins/translate/__tests__/test_dictionary.py)
/**!
 * @brief Legacy test module — all tests migrated to domain-specific test files:
 * @complexity 3
 */

// --- TestDictionaryCorrection (backend/src/plugins/translate/__tests__/test_dictionary_correction.py)
/**!
 * @brief Validate InlineCorrectionService and dictionary correction flows.
 * @complexity 3
 */

// --- TestDictionaryCRUD (backend/src/plugins/translate/__tests__/test_dictionary_crud.py)
/**!
 * @brief Validate DictionaryCRUD and DictionaryEntryCRUD operations.
 * @complexity 3
 * @test_edge same_term_different_lang_pair -> allowed (not duplicate)
 * @test_invariant unique_normalized -> verifies: [duplicate_entry, same_term_different_lang_pair allowed]
 */

// --- TestDictionaryFilter (backend/src/plugins/translate/__tests__/test_dictionary_filter.py)
/**!
 * @brief Validate DictionaryBatchFilter operations.
 * @complexity 3
 */

// --- TestDictionaryImport (backend/src/plugins/translate/__tests__/test_dictionary_import.py)
/**!
 * @brief Validate DictionaryImportExport operations.
 * @complexity 3
 * @test_edge import_invalid_format -> ValueError for missing required columns
 */

// --- TestDictionaryPromptBuilder (backend/src/plugins/translate/__tests__/test_dictionary_prompt_builder.py)
/**!
 * @brief Validate ContextAwarePromptBuilder operations: Jaccard similarity, context truncation, entry rendering.
 * @complexity 3
 */

// --- TestDictionaryUtils (backend/src/plugins/translate/__tests__/test_dictionary_utils.py)
/**!
 * @brief Validate utility functions: _normalize_term and _detect_delimiter.
 * @complexity 3
 */

// --- LanguageDetectServiceTests (backend/src/plugins/translate/__tests__/test_lang_detect.py)
/**!
 * @brief Unit tests for LanguageDetectService — local language detection via lingua.
 * @complexity 3
 */

// --- test_detect_language_basic (backend/src/plugins/translate/__tests__/test_lang_detect.py)
/**!
 * @brief Verify core language detection for common languages.
 * @complexity 1
 */

// --- test_detect_language_edge_cases (backend/src/plugins/translate/__tests__/test_lang_detect.py)
/**!
 * @complexity 1
 */

// --- test_batch_detect (backend/src/plugins/translate/__tests__/test_lang_detect.py)
/**!
 * @complexity 1
 */

// --- test_build_detector (backend/src/plugins/translate/__tests__/test_lang_detect.py)
/**!
 * @complexity 1
 */

// --- test_get_detector_cache (backend/src/plugins/translate/__tests__/test_lang_detect.py)
/**!
 * @complexity 1
 */

// --- test_code_to_lang_mapping (backend/src/plugins/translate/__tests__/test_lang_detect.py)
/**!
 * @complexity 1
 */

// --- fixtures (backend/src/plugins/translate/__tests__/test_lang_detect.py)
/**!
 * @complexity 1
 */

// --- TestTextCleaner (backend/src/plugins/translate/__tests__/test_text_cleaner.py)
/**!
 * @brief Verify text cleaning contracts — normalize_whitespace, truncate_text, clean_text.
 * @complexity 3
 * @test_edge zero_max_length — max_length=0 forces truncation on any non-empty text
 */

// --- TestTokenBudget (backend/src/plugins/translate/__tests__/test_token_budget.py)
/**!
 * @brief Verify estimate_token_budget contracts — safe batch sizing, auto-reduction, warning generation.
 * @complexity 3
 * @test_edge conservative_min — even with huge rows, batch_size_adjusted >= 1
 * @test_invariant warning is None when batch fits, str when reduced
 */

// --- BatchInsertService (backend/src/plugins/translate/_batch_insert.py)
/**!
 * @brief Insert successful translation records into target table via Superset SQL Lab.
 * @complexity 3
 */

// --- insert_batch_to_target (backend/src/plugins/translate/_batch_insert.py)
/**!
 * @brief Insert successful records from a single batch into the target table.
 * @complexity 3
 */

// --- _fetch_batch_records (backend/src/plugins/translate/_batch_insert.py)
/**!
 * @complexity 1
 */

// --- _build_target_columns (backend/src/plugins/translate/_batch_insert.py)
/**!
 * @complexity 1
 */

// --- _build_context_keys (backend/src/plugins/translate/_batch_insert.py)
/**!
 * @complexity 1
 */

// --- _build_insert_rows (backend/src/plugins/translate/_batch_insert.py)
/**!
 * @complexity 3
 */

// --- _resolve_insert_backend (backend/src/plugins/translate/_batch_insert.py)
/**!
 * @complexity 1
 */

// --- _generate_insert_sql (backend/src/plugins/translate/_batch_insert.py)
/**!
 * @complexity 1
 */

// --- _execute_insert_sql (backend/src/plugins/translate/_batch_insert.py)
/**!
 * @complexity 1
 */

// --- BatchProcessingService (backend/src/plugins/translate/_batch_proc.py)
/**!
 * @brief Batch processing for translation: classify rows (same-language/cache/preview/LLM),
 * @complexity 4
 */

// --- process_batch (backend/src/plugins/translate/_batch_proc.py)
/**!
 * @brief Process a single batch: create record, classify rows, call LLM, persist.
 * @complexity 3
 * @post TranslationBatch and TranslationRecord rows are created.
 * @pre job and batch_rows are valid.
 * @side_effect LLM API call; DB writes.
 */

// --- AdaptiveBatchSizer (backend/src/plugins/translate/_batch_sizer.py)
/**!
 * @brief Adaptive batch sizing for LLM translation — splits source rows into variable-sized
 * @complexity 3
 */

// --- resolve_provider_model (backend/src/plugins/translate/_batch_sizer.py)
/**!
 * @brief Resolve the LLM provider model name for token budget estimation.
 * @complexity 2
 * @post Returns model name string or None if resolution fails.
 * @side_effect DB query to LLM provider table.
 */

// --- auto_size_batches (backend/src/plugins/translate/_batch_sizer.py)
/**!
 * @brief Split source rows into variable-sized batches based on content length.
 * @complexity 3
 * @post Returns list of batches, each batch is a list of row dicts.
 * @pre source_rows is non-empty. job has valid config.
 */

// --- LanguageDetectService (backend/src/plugins/translate/_lang_detect.py)
/**!
 * @brief Local language detection powered by lingua-language-detector (no LLM).
 * @complexity 2
 */

// --- _detector_cache_key (backend/src/plugins/translate/_lang_detect.py)
/**!
 * @brief Build a deterministic cache key from target languages list.
 * @complexity 1
 */

// --- build_detector (backend/src/plugins/translate/_lang_detect.py)
/**!
 * @brief Build a LanguageDetector restricted to target + common source languages.
 * @complexity 2
 */

// --- get_detector (backend/src/plugins/translate/_lang_detect.py)
/**!
 * @brief Get or create a cached detector for the given target languages.
 * @complexity 2
 */

// --- detect_language (backend/src/plugins/translate/_lang_detect.py)
/**!
 * @brief Detect the language of a single text string. Returns BCP-47 code or "und".
 * @complexity 2
 * @error Does not raise — all exceptions caught internally and return "und".
 */

// --- _character_block_fallback (backend/src/plugins/translate/_lang_detect.py)
/**!
 * @brief When lingua returns "und", check if character-block dominance (e.g. Cyrillic)
 * @complexity 2
 */

// --- batch_detect (backend/src/plugins/translate/_lang_detect.py)
/**!
 * @brief Detect language for multiple texts in batch. Builds detector if not provided.
 * @complexity 3
 */

// --- LLMTranslationService (backend/src/plugins/translate/_llm_call.py)
/**!
 * @brief LLM interaction for batch translation: call provider with retry, handle truncation
 * @complexity 4
 */

// --- call_llm_for_batch (backend/src/plugins/translate/_llm_call.py)
/**!
 * @brief Call LLM for a batch of rows requiring translation. Parse and persist results.
 * @complexity 3
 * @post Returns dict with successful/failed/skipped counts.
 * @pre job has valid provider_id. batch_rows is non-empty.
 * @side_effect HTTP call to LLM provider; DB writes.
 */

// --- call_llm (backend/src/plugins/translate/_llm_call.py)
/**!
 * @brief Route to provider-specific LLM call implementation.
 * @complexity 3
 */

// --- LLMHttpClient (backend/src/plugins/translate/_llm_http.py)
/**!
 * @brief HTTP client for OpenAI-compatible LLM API calls with rate-limit handling and
 * @complexity 3
 * @rationale Extracted 'openai' default provider type and 8192 default max_tokens into module-level constants DEFAULT_PROVIDER_TYPE and DEFAULT_MAX_TOKENS.
 */

// --- call_openai_compatible (backend/src/plugins/translate/_llm_http.py)
/**!
 * @brief Call OpenAI-compatible API with rate-limit handling and structured output fallback.
 * @complexity 3
 * @post Returns (response text, finish_reason).
 * @pre Valid API endpoint, key, model, and prompt.
 * @side_effect HTTP POST to LLM API.
 */

// --- _do_http_request (backend/src/plugins/translate/_llm_http.py)
/**!
 * @complexity 1
 */

// --- _handle_response_format_fallback (backend/src/plugins/translate/_llm_http.py)
/**!
 * @complexity 1
 */

// --- LLMResponseParser (backend/src/plugins/translate/_llm_parse.py)
/**!
 * @brief Parse LLM JSON response into per-row translations with support for markdown code
 * @complexity 3
 */

// --- _recover_from_markdown (backend/src/plugins/translate/_llm_parse.py)
/**!
 * @complexity 1
 */

// --- _recover_truncated_rows (backend/src/plugins/translate/_llm_parse.py)
/**!
 * @complexity 1
 */

// --- RunExecutionService (backend/src/plugins/translate/_run_service.py)
/**!
 * @brief Full run lifecycle: prepare run, fetch source rows, filter new keys, orchestrate batches,
 * @complexity 4
 */

// --- RunSourceFetcher (backend/src/plugins/translate/_run_source.py)
/**!
 * @brief Fetch source rows for translation runs from Superset datasource or preview session.
 * @complexity 3
 */

// --- fetch_source_rows (backend/src/plugins/translate/_run_source.py)
/**!
 * @brief Fetch source rows from Superset datasource or preview session fallback.
 * @complexity 3
 */

// --- _extract_chart_data_rows (backend/src/plugins/translate/_run_source.py)
/**!
 * @complexity 1
 */

// --- TextCleaner (backend/src/plugins/translate/_text_cleaner.py)
/**!
 * @brief Text cleaning utilities for the translation pipeline — whitespace normalization
 * @complexity 3
 */

// --- normalize_whitespace (backend/src/plugins/translate/_text_cleaner.py)
/**!
 * @brief Collapse multiple spaces, tabs, and newlines into single spaces; trim leading/trailing
 * @complexity 2
 */

// --- truncate_text (backend/src/plugins/translate/_text_cleaner.py)
/**!
 * @brief Truncate text to max_length characters, appending "..." if truncation occurs.
 * @complexity 2
 * @post When len(text) <= max_length, returns text unchanged.
 * @pre text is a string. max_length >= 0.
 */

// --- clean_text (backend/src/plugins/translate/_text_cleaner.py)
/**!
 * @brief Combine whitespace normalization and truncation into one step.
 * @complexity 2
 */

// --- estimate_token_budget (backend/src/plugins/translate/_token_budget.py)
/**!
 * @brief Calculate safe batch_size and max_tokens for LLM translation calls based on actual content length and model context window limits.
 * @complexity 3
 * @layer Domain
 * @rationale Added comment clarifying PROVIDER_DEFAULTS is a fallback — primary source should be LLMProvider API.
 */

// --- DEFAULT_CONTEXT_WINDOW (backend/src/plugins/translate/_token_budget.py)
/**!
 */

// --- DEFAULT_MAX_OUTPUT_TOKENS (backend/src/plugins/translate/_token_budget.py)
/**!
 */

// --- REASONING_OVERHEAD (backend/src/plugins/translate/_token_budget.py)
/**!
 */

// --- PROVIDER_DEFAULTS (backend/src/plugins/translate/_token_budget.py)
/**!
 */

// --- OUTPUT_PER_ROW_PER_LANG (backend/src/plugins/translate/_token_budget.py)
/**!
 */

// --- JSON_OVERHEAD_PER_ROW (backend/src/plugins/translate/_token_budget.py)
/**!
 */

// --- PROMPT_BASE_TOKENS (backend/src/plugins/translate/_token_budget.py)
/**!
 */

// --- DICT_TOKENS_PER_ENTRY (backend/src/plugins/translate/_token_budget.py)
/**!
 */

// --- DICT_TOKENS_MAX (backend/src/plugins/translate/_token_budget.py)
/**!
 */

// --- CHARS_PER_TOKEN_MIXED (backend/src/plugins/translate/_token_budget.py)
/**!
 */

// --- MIN_MAX_TOKENS (backend/src/plugins/translate/_token_budget.py)
/**!
 */

// --- MAX_OUTPUT_HEADROOM (backend/src/plugins/translate/_token_budget.py)
/**!
 */

// --- TranslationUtils (backend/src/plugins/translate/_utils.py)
/**!
 * @brief Shared utility functions for the translation plugin — dictionary enforcement,
 * @complexity 3
 */

// --- _normalize_term (backend/src/plugins/translate/_utils.py)
/**!
 * @brief Normalize a term for case-insensitive unique constraint lookup.
 * @rationale NFC normalization is applied before lowercasing to ensure consistent
 */

// --- _detect_delimiter (backend/src/plugins/translate/_utils.py)
/**!
 * @brief Detect the delimiter used in a CSV/TSV header line.
 */

// --- _enforce_dictionary (backend/src/plugins/translate/_utils.py)
/**!
 * @brief Post-process LLM output: enforce dictionary term replacements.
 * @complexity 2
 * @post per_lang_values may be mutated to include forced dictionary replacements.
 * @pre dict_matches is a list of dict entries with source_term/target_term.
 * @side_effect Logs when enforcement is applied.
 */

// --- _compute_source_hash (backend/src/plugins/translate/_utils.py)
/**!
 * @brief Compute deterministic cache key for a source row.
 * @complexity 2
 */

// --- _check_translation_cache (backend/src/plugins/translate/_utils.py)
/**!
 * @brief Look up a previously successful translation by source_hash.
 * @complexity 2
 */

// --- _compute_key_hash (backend/src/plugins/translate/_utils.py)
/**!
 * @brief Compute a stable hash from source_data dict for matching preview edits.
 * @complexity 1
 */

// --- estimate_row_tokens (backend/src/plugins/translate/_utils.py)
/**!
 * @brief Estimate token count for a single source row including context fields.
 * @complexity 2
 * @post Returns estimated token count >= 1.
 * @pre source_text is a string.
 */

// --- DictionaryManagerModule (backend/src/plugins/translate/dictionary.py)
/**!
 * @brief Business logic for terminology dictionary management, entry CRUD, CSV/TSV import with conflict detection, and per-batch filtering.
 * @complexity 4
 * @layer Domain
 * @post Dictionary and entry mutations are persisted with conflict detection.
 * @pre Database session is open and valid.
 * @rationale C4 complexity because dictionary CRUD is stateful with referential integrity enforcement on deletion.
 * @rejected Monolithic DictionaryManager class — violated INV_7. Decomposed into DictionaryCRUD, DictionaryEntryCRUD, DictionaryImportExport, DictionaryBatchFilter, DictionaryCorrectionService.
 * @side_effect Creates, updates, deletes TerminologyDictionary and DictionaryEntry rows; enforces deletion guards.
 */

// --- DictionaryManager (backend/src/plugins/translate/dictionary.py)
/**!
 * @brief Facade for terminology dictionaries: delegates to DictionaryCRUD, DictionaryEntryCRUD, DictionaryImportExport, DictionaryBatchFilter, DictionaryCorrectionService.
 * @complexity 4
 * @post Dictionary and entry mutations are persisted with conflict detection.
 * @pre Database session is open and valid.
 * @rationale Thin facade preserves API compatibility after decomposition.
 * @rejected Removing the facade would break all upstream imports; delegation pattern preferred.
 * @side_effect Creates, updates, deletes TerminologyDictionary and DictionaryEntry rows; enforces deletion guards.
 */

// --- DictionaryCorrectionService (backend/src/plugins/translate/dictionary_correction.py)
/**!
 * @brief Submit term corrections and bulk corrections to dictionaries with conflict detection.
 * @complexity 3
 */

// --- DictionaryCRUD (backend/src/plugins/translate/dictionary_crud.py)
/**!
 * @brief CRUD operations for TerminologyDictionary records.
 * @complexity 3
 */

// --- DictionaryEntryCRUD (backend/src/plugins/translate/dictionary_entries.py)
/**!
 * @brief CRUD operations for DictionaryEntry records.
 * @complexity 3
 */

// --- DictionaryBatchFilter (backend/src/plugins/translate/dictionary_filter.py)
/**!
 * @brief Scan batch texts for case-insensitive, word-boundary-aware matches against dictionaries.
 * @complexity 3
 */

// --- DictionaryImportExport (backend/src/plugins/translate/dictionary_import_export.py)
/**!
 * @brief Import/export entries as CSV/TSV with conflict detection, and migration of old entries.
 * @complexity 3
 */

// --- _validate_bcp47 (backend/src/plugins/translate/dictionary_validation.py)
/**!
 * @brief Validate that a language tag is a non-empty BCP-47 string.
 * @complexity 2
 */

// --- TranslationEventLog (backend/src/plugins/translate/events.py)
/**!
 * @brief Structured event logging for translation operations with terminal event invariant enforcement.
 * @complexity 5
 * @data_contract Input[run_id:Optional[str], job_id:str, event_type:str, payload:dict] -> Output[TranslationEvent]
 * @invariant Exactly one run_started + exactly one terminal event per non-null run_id.
 * @layer Domain
 * @post Events are persisted immutably; terminal events enforce exactly-one invariant per run.
 * @pre Database session is open and valid.
 * @rationale Immutable event log with nullable run_id allows job-level events (no run context) and run-level events.
 * @rejected Separate event table per entity — single TranslationEvent table with nullable run_id is simpler for audit.
 * @side_effect Writes TranslationEvent rows; prunes expired events with MetricSnapshot before deletion.
 */

// --- TranslationExecutor (backend/src/plugins/translate/executor.py)
/**!
 * @brief Process translation in batches: fetch source rows, call LLM, persist TranslationBatch
 * @complexity 4
 */

// --- TranslationMetrics (backend/src/plugins/translate/metrics.py)
/**!
 * @brief Aggregate translation metrics from live TranslationEvent + MetricSnapshot for per-job reporting.
 * @complexity 4
 * @layer Domain
 * @post Metrics are aggregated and returned; no side effects.
 * @pre Database session is open.
 * @rationale Live events (<90 days) + MetricSnapshot (>=90 days) fusion for complete picture.
 * @rejected Querying all events for all time — would be slow; MetricSnapshot provides historical summary.
 */

// --- TranslationOrchestrator (backend/src/plugins/translate/orchestrator.py)
/**!
 * @brief Run lifecycle coordination: validate preconditions, dispatch executor, generate SQL, submit to Superset, record events.
 * @complexity 5
 * @data_contract Input[db, config_manager, current_user] -> Output[TranslationRun]
 * @invariant State transitions: PENDING -> RUNNING -> COMPLETED|FAILED|CANCELLED. Exactly one terminal event per run.
 * @layer Domain
 * @post Translation run is executed, SQL generated and submitted, events recorded.
 * @pre Valid job and accepted preview (for manual runs). Superset and LLM are reachable.
 * @rationale C5 orchestrator because preview, execution, event logging, and retry share state within single transaction boundary.
 * @rejected stdout-only logging — lacks structured payload integrity; cannot enforce terminal-event invariant.
 * @side_effect Creates TranslationRun; creates batches and records; generates SQL; submits to Superset; records events.
 */

// --- TranslationResultAggregator (backend/src/plugins/translate/orchestrator_aggregator.py)
/**!
 * @brief Query translation run status, records, and history.
 * @complexity 4
 * @post Returns structured run data with pagination.
 * @pre Database session is available.
 * @rationale Language stats aggregation extracted to orchestrator_lang_stats; query methods to orchestrator_query.
 */

// --- orchestrator_cancel (backend/src/plugins/translate/orchestrator_cancel.py)
/**!
 * @brief Cancel and retry-insert operations for translation runs.
 * @complexity 3
 * @rationale Extracted from orchestrator_retry.py for INV_7 compliance (module < 150 lines).
 */

// --- orchestrator_config (backend/src/plugins/translate/orchestrator_config.py)
/**!
 * @brief Config hash and dictionary snapshot hash utilities for translation planning.
 * @complexity 3
 */

// --- TranslationExecutionEngine (backend/src/plugins/translate/orchestrator_exec.py)
/**!
 * @brief Execute translation runs: dispatch executor, manage completion and failure paths.
 * @complexity 4
 * @post Run is executed with SQL generated; events recorded.
 * @pre Database session and config manager are available. Run is in valid state.
 * @side_effect LLM calls, DB writes, Superset API calls.
 */

// --- update_language_stats (backend/src/plugins/translate/orchestrator_lang_stats.py)
/**!
 * @brief Aggregate TranslationLanguage entries by language_code and update TranslationRunLanguageStats.
 * @complexity 3
 * @side_effect DB writes on language_stats objects.
 */

// --- TranslationPlanner (backend/src/plugins/translate/orchestrator_planner.py)
/**!
 * @brief Handle translation run planning: validation, config hashing, dictionary snapshot.
 * @complexity 4
 * @post TranslationRun is planned with hashes and config snapshot; events recorded.
 * @pre Database session and config manager are available.
 * @rationale Split from monolithic class: validation -> orchestrator_validation, hashing -> orchestrator_config.
 * @side_effect Creates TranslationRun; computes config and dict hashes; logs events.
 */

// --- orchestrator_query (backend/src/plugins/translate/orchestrator_query.py)
/**!
 * @brief Query translation run records and history with pagination.
 * @complexity 3
 */

// --- TranslationRunRetryManager (backend/src/plugins/translate/orchestrator_retry.py)
/**!
 * @brief Manage retry of translation run batches.
 * @complexity 4
 * @post Retried batches are re-executed.
 * @pre Database session and config manager are available.
 * @rationale Cancel and retry-insert extracted to orchestrator_cancel module for INV_7 compliance.
 * @side_effect DB writes, event log entries.
 */

// --- orchestrator_run_completion (backend/src/plugins/translate/orchestrator_run_completion.py)
/**!
 * @brief Post-execution run completion handlers: cancelled, success-with-insert, and failure paths.
 * @complexity 3
 */

// --- TranslationStageRunner (backend/src/plugins/translate/orchestrator_runner.py)
/**!
 * @brief Coordinate translation run execution, retry, and cancellation via delegated components.
 * @complexity 4
 * @post Run is executed; events recorded.
 * @pre Database session and config manager are available. Run is in valid state.
 * @side_effect LLM calls, DB writes, Superset API calls.
 */

// --- SQLInsertService (backend/src/plugins/translate/orchestrator_sql.py)
/**!
 * @brief Generate INSERT SQL from translation records and submit to Superset SQL Lab.
 * @complexity 4
 * @post SQL is generated and submitted to Superset; returns execution result.
 * @pre Job has target table configured. Run has successful records.
 * @rationale Row/column building extracted to orchestrator_sql_rows module for INV_7 compliance.
 * @side_effect Superset API call; event log entries.
 */

// --- orchestrator_sql_rows (backend/src/plugins/translate/orchestrator_sql_rows.py)
/**!
 * @brief Column and row building utilities for SQL insertion in translate plugin.
 * @complexity 3
 */

// --- build_columns (backend/src/plugins/translate/orchestrator_sql_rows.py)
/**!
 * @brief Build list of target columns for SQL INSERT from job configuration.
 * @complexity 2
 */

// --- build_context_keys (backend/src/plugins/translate/orchestrator_sql_rows.py)
/**!
 * @brief Build list of context keys for SQL row data.
 * @complexity 1
 */

// --- build_rows (backend/src/plugins/translate/orchestrator_sql_rows.py)
/**!
 * @brief Build row data for SQL INSERT with per-language expansion.
 * @complexity 2
 * @side_effect Reads translation record language entries.
 */

// --- validate_job_preconditions (backend/src/plugins/translate/orchestrator_validation.py)
/**!
 * @brief Validate preconditions before starting a translation run.
 * @complexity 3
 * @post Raises ValueError if any precondition fails.
 * @pre Job exists and db session is valid.
 */

// --- TranslatePlugin (backend/src/plugins/translate/plugin.py)
/**!
 * @brief TranslatePlugin skeleton for cross-dialect SQL and dashboard translation.
 * @complexity 2
 * @layer Domain
 * @rationale Separate plugin avoids bloating LLMAnalysisPlugin beyond fractal limit (<400 lines).
 * @rejected Extending LLMAnalysisPlugin would conflate two distinct feature domains.
 */

// --- DEFAULT_EXECUTION_PROMPT_TEMPLATE (backend/src/plugins/translate/preview_constants.py)
/**!
 * @brief Default LLM prompt template for full execution (batch translation).
 * @complexity 1
 */

// --- DEFAULT_PREVIEW_PROMPT_TEMPLATE (backend/src/plugins/translate/preview_constants.py)
/**!
 * @brief Default LLM prompt template for preview (sample translation).
 * @complexity 1
 */

// --- PreviewExecutor (backend/src/plugins/translate/preview_executor.py)
/**!
 * @brief Fetch sample data from Superset and call LLM provider for preview.
 * @complexity 4
 * @post Sample rows fetched, LLM called.
 * @pre Database session, config manager, and Superset client are available.
 * @rationale LLM response parsing and hash utilities extracted to preview_response_parser module for INV_7 compliance.
 * @side_effect Fetches data from Superset; makes HTTP calls to LLM provider.
 */

// --- PreviewPromptBuilder (backend/src/plugins/translate/preview_prompt_builder.py)
/**!
 * @brief Build LLM prompts for preview sessions including dictionary glossary and row context.
 * @complexity 3
 * @rationale Token estimation and budget helpers extracted to preview_prompt_helpers module for INV_7 compliance.
 */

// --- preview_prompt_helpers (backend/src/plugins/translate/preview_prompt_helpers.py)
/**!
 * @brief Token estimation metadata and budget helpers for preview prompt building.
 * @complexity 2
 */

// --- estimate_token_budget_for_rows (backend/src/plugins/translate/preview_prompt_helpers.py)
/**!
 * @brief Check token budget and optionally truncate source rows for preview.
 * @complexity 2
 * @post Returns adjusted source_rows, actual_row_count, and token_budget dict.
 */

// --- compute_build_token_metadata (backend/src/plugins/translate/preview_prompt_helpers.py)
/**!
 * @brief Compute token estimation metadata for prompt builder return dict.
 * @complexity 1
 * @post Returns prompt, row_meta, target_languages, cost estimates, and cost_warning.
 */

// --- preview_response_parser (backend/src/plugins/translate/preview_response_parser.py)
/**!
 * @brief Parse LLM JSON responses and Superset data; compute config/dict hashes for preview.
 * @complexity 3
 */

// --- parse_llm_response (backend/src/plugins/translate/preview_response_parser.py)
/**!
 * @brief Parse LLM JSON response into structured translations dict with per-language support.
 * @complexity 3
 * @post Returns dict mapping row_id -> {detected_source_language, lang_code: translation, ...}.
 * @pre response_text is a valid JSON string (possibly wrapped in markdown code block).
 */

// --- extract_data_rows (backend/src/plugins/translate/preview_response_parser.py)
/**!
 * @brief Extract data rows from Superset chart data API response.
 * @complexity 1
 */

// --- compute_config_hash (backend/src/plugins/translate/preview_response_parser.py)
/**!
 * @brief Compute a deterministic hash of job configuration for snapshot comparison.
 * @complexity 1
 */

// --- compute_dict_snapshot_hash (backend/src/plugins/translate/preview_response_parser.py)
/**!
 * @brief Compute a hash of dictionary state for snapshot comparison.
 * @complexity 2
 */

// --- PreviewSessionManager (backend/src/plugins/translate/preview_review.py)
/**!
 * @brief Manage preview session row-level actions: approve/edit/reject rows.
 * @complexity 3
 * @rationale Session accept/get and serialization extracted to preview_session_ops module for INV_7 compliance.
 */

// --- preview_session_ops (backend/src/plugins/translate/preview_session_ops.py)
/**!
 * @brief Preview session lifecycle operations: accept and query preview sessions.
 * @complexity 3
 */

// --- get_preview_session (backend/src/plugins/translate/preview_session_ops.py)
/**!
 * @brief Get the latest preview session for a job with its records.
 * @complexity 2
 */

// --- preview_session_serializer (backend/src/plugins/translate/preview_session_serializer.py)
/**!
 * @brief Serialization and action helpers for preview sessions: record serialization and per-row approve/reject/edit actions.
 * @complexity 3
 * @rationale Extracted from preview_session_ops.py for INV_7 compliance (module < 150 lines).
 */

// --- serialize_preview_record (backend/src/plugins/translate/preview_session_serializer.py)
/**!
 * @brief Serialize a TranslationPreviewRecord to a response dict.
 * @complexity 1
 */

// --- apply_language_action (backend/src/plugins/translate/preview_session_serializer.py)
/**!
 * @brief Apply approve/reject/edit action to a TranslationPreviewLanguage entry.
 * @complexity 2
 */

// --- apply_record_action (backend/src/plugins/translate/preview_session_serializer.py)
/**!
 * @brief Apply approve/reject/edit action to a TranslationPreviewRecord and its language entries.
 * @complexity 2
 */

// --- TokenEstimator (backend/src/plugins/translate/preview_token_estimator.py)
/**!
 * @brief Estimate token counts and costs for LLM translation operations.
 * @complexity 2
 * @rationale Token estimation uses a heuristic (chars/token ratio) since exact tokenization depends on the LLM model.
 * @rejected Using an external tokenizer library would introduce a heavy dependency for estimation only.
 */

// --- ContextAwarePromptBuilder (backend/src/plugins/translate/prompt_builder.py)
/**!
 * @brief Pure-function prompt builder that enhances dictionary entries with context annotations.
 * @complexity 2
 * @layer Domain
 * @rationale Pure functions only — no I/O, no DB access. Separated from executor for testability.
 * @rejected Embedding context inline in the executor would make it untestable without mocking DB.
 */

// --- TranslationScheduler (backend/src/plugins/translate/scheduler.py)
/**!
 * @brief Manage TranslationSchedule rows and register them with core SchedulerService.
 * @complexity 4
 * @layer Domain
 * @post TranslationSchedule CRUD persisted; APScheduler jobs registered/updated/removed.
 * @pre Database session and SchedulerService are available.
 * @rationale Uses existing SchedulerService (APScheduler) to avoid creating a second scheduler instance.
 * @rejected Polling-based approach — event-driven APScheduler is more precise.
 * @side_effect Registers APScheduler jobs; runs translations on trigger; creates events.
 */

// --- execute_scheduled_translation (backend/src/plugins/translate/scheduler.py)
/**!
 * @brief APScheduler job handler — runs scheduled translation with concurrency check and new-key-only fallback.
 * @complexity 4
 * @post Translation run created and executed if no concurrent run exists.
 * @pre schedule_id is valid.
 * @rationale New-key-only mode compares keys against most recent succeeded run; baseline_expired fallback does full.
 * @side_effect DB writes; LLM calls; Superset API calls.
 */

// --- TranslateJobService (backend/src/plugins/translate/service.py)
/**!
 * @brief Service layer for translation job CRUD with datasource column validation and database dialect detection.
 * @complexity 4
 * @layer Domain
 * @post Translation jobs are created/updated/deleted with column validation and dialect caching.
 * @pre Database session and config manager are available.
 * @rationale Snapshot isolation — in-progress runs use config snapshot; config edits affect future runs only.
 * @rejected Monolithic service.py — violated INV_7. Decomposed into service_datasource, service_inline_correction, service_bulk_replace, service_utils.
 * @side_effect Queries Superset for column metadata and database dialect at save time.
 */

// --- BulkFindReplaceService (backend/src/plugins/translate/service_bulk_replace.py)
/**!
 * @brief Service for bulk find-and-replace operations on translated values.
 * @complexity 3
 */

// --- DatasourceMetadataService (backend/src/plugins/translate/service_datasource.py)
/**!
 * @brief Fetch datasource column metadata and database dialect from Superset.
 * @complexity 4
 * @layer Domain
 * @post Datasource metadata is fetched with column details and normalized dialect.
 * @pre Database session and config manager are available.
 */

// --- get_dialect_from_database (backend/src/plugins/translate/service_datasource.py)
/**!
 * @brief Extract normalized dialect string from a Superset database record.
 * @complexity 2
 */

// --- fetch_datasource_metadata (backend/src/plugins/translate/service_datasource.py)
/**!
 * @brief Fetch datasource columns and database dialect from Superset.
 * @complexity 3
 */

// --- detect_virtual_columns (backend/src/plugins/translate/service_datasource.py)
/**!
 * @brief Identify virtual (calculated) columns from column metadata.
 * @complexity 2
 */

// --- InlineCorrectionService (backend/src/plugins/translate/service_inline_correction.py)
/**!
 * @brief Service for inline editing translated values and submitting corrections to dictionaries.
 * @complexity 4
 * @post Inline edits applied with optional dictionary submission.
 * @pre Database session is available.
 * @side_effect Modifies TranslationLanguage entries; optionally creates DictionaryEntry rows.
 */

// --- TargetSchemaValidation (backend/src/plugins/translate/service_target_schema.py)
/**!
 * @brief Проверка схемы целевой таблицы: запрос колонок через Superset SQL Lab,
 * @complexity 4
 */

// --- _build_expected_columns (backend/src/plugins/translate/service_target_schema.py)
/**!
 * @brief Собирает список ожидаемых колонок по конфигурации column mapping.
 * @complexity 2
 */

// --- _extract_columns_from_rows (backend/src/plugins/translate/service_target_schema.py)
/**!
 * @brief Извлекает список колонок таблицы из data-строк результата SQL Lab.
 * @complexity 2
 */

// --- _parse_sqllab_result (backend/src/plugins/translate/service_target_schema.py)
/**!
 * @brief Извлекает data-строки из ответа Superset SQL Lab.
 * @complexity 2
 */

// --- validate_target_table_schema (backend/src/plugins/translate/service_target_schema.py)
/**!
 * @brief Основная функция: проверяет схему целевой таблицы через Superset SQL Lab.
 * @complexity 4
 * @post Возвращает TargetSchemaValidationResponse с diff-анализом.
 * @pre Superset окружение и target_database_id валидны.
 * @side_effect Выполняет SQL-запрос к information_schema через Superset SQL Lab API.
 */

// --- ServiceUtils (backend/src/plugins/translate/service_utils.py)
/**!
 * @brief Utility functions for the translate service layer.
 * @complexity 1
 */

// --- _extract_dialect (backend/src/plugins/translate/service_utils.py)
/**!
 * @brief Extract database dialect from Superset backend URI.
 */

// --- job_to_response (backend/src/plugins/translate/service_utils.py)
/**!
 * @brief Convert a TranslationJob ORM model to a TranslateJobResponse schema with dictionary_ids.
 */

// --- SQLGenerator (backend/src/plugins/translate/sql_generator.py)
/**!
 * @brief Dialect-aware safe SQL generation for INSERT/UPSERT operations.
 * @complexity 3
 * @layer Domain
 * @post Returns safe SQL strings for the target dialect.
 * @pre Job has target_schema and target_table configured. Dialect is one of supported SUPPORTED_DIALECTS.
 * @rationale Dialect-aware SQL uses ON CONFLICT for PostgreSQL; plain INSERT for ClickHouse with documented limitations.
 * @rejected ORM-based insert bypasses Superset's SQL Lab audit trail.
 * @side_effect None — pure code generation.
 */

// --- _normalize_timestamp_value (backend/src/plugins/translate/sql_generator.py)
/**!
 * @brief Detect Unix timestamp strings (seconds or millis) and convert to 'YYYY-MM-DD' for Date columns.
 * @complexity 2
 */

// --- _quote_identifier (backend/src/plugins/translate/sql_generator.py)
/**!
 * @brief Quote an identifier per dialect rules. PostgreSQL uses double quotes; ClickHouse uses backticks.
 * @complexity 4
 * @post Returns safely quoted identifier.
 * @pre identifier is a non-empty string.
 */

// --- _encode_sql_value (backend/src/plugins/translate/sql_generator.py)
/**!
 * @brief Encode a Python value into a SQL-safe literal for INSERT VALUES, with ClickHouse timestamp normalization.
 * @complexity 2
 */

// --- _build_values_clause (backend/src/plugins/translate/sql_generator.py)
/**!
 * @brief Build a VALUES clause for multiple rows with per-column value encoding and dialect-aware quoting.
 * @complexity 2
 */

// --- generate_insert_sql (backend/src/plugins/translate/sql_generator.py)
/**!
 * @brief Generate a dialect-aware plain INSERT SQL statement for the given table, columns, and rows.
 * @complexity 3
 */

// --- generate_upsert_sql (backend/src/plugins/translate/sql_generator.py)
/**!
 * @brief Generate PostgreSQL dialect UPSERT SQL with ON CONFLICT DO UPDATE.
 * @complexity 4
 * @post Returns UPSERT SQL string or raises ValueError.
 * @pre dialect is postgresql-compatible. target_table, columns, key_columns are non-empty.
 */

// --- SupersetSqlLabExecutor (backend/src/plugins/translate/superset_executor.py)
/**!
 * @brief Submit SQL to Superset SQL Lab API and poll execution status.
 * @complexity 4
 * @layer Infrastructure
 * @post SQL is submitted to Superset SQL Lab; execution reference is returned.
 * @pre Valid Superset environment configuration and authenticated client.
 * @rationale Direct SQL Lab API submission provides audit trail and execution monitoring within Superset.
 * @rejected Direct database connection bypass — would skip Superset's SQL Lab audit and RBAC.
 * @side_effect Makes HTTP calls to Superset /api/v1/sqllab/execute/; polls status.
 */

// --- SchemasPackage (backend/src/schemas/__init__.py)
/**!
 * @brief API schema package root.
 */

// --- TestSettingsAndHealthSchemas (backend/src/schemas/__tests__/test_settings_and_health_schemas.py)
/**!
 * @brief Regression tests for settings and health schema contracts updated in 026 fix batch.
 * @complexity 3
 */

// --- test_validation_policy_create_accepts_structured_custom_channels (backend/src/schemas/__tests__/test_settings_and_health_schemas.py)
/**!
 * @brief Ensure policy schema accepts structured custom channel objects with type/target fields.
 */

// --- test_validation_policy_create_rejects_legacy_string_custom_channels (backend/src/schemas/__tests__/test_settings_and_health_schemas.py)
/**!
 * @brief Ensure legacy list[str] custom channel payload is rejected by typed channel contract.
 */

// --- test_dashboard_health_item_status_accepts_only_whitelisted_values (backend/src/schemas/__tests__/test_settings_and_health_schemas.py)
/**!
 * @brief Verify strict grouped regex only accepts PASS/WARN/FAIL/UNKNOWN exact statuses.
 */

// --- AuthSchemas (backend/src/schemas/auth.py)
/**!
 * @brief Pydantic schemas for authentication requests and responses.
 * @complexity 5
 * @data_contract AuthPayload -> AuthSchema
 * @invariant Sensitive fields like password must not be included in response schemas.
 * @layer API
 */

// --- Token (backend/src/schemas/auth.py)
/**!
 * @brief Represents a JWT access token response.
 * @complexity 1
 */

// --- TokenData (backend/src/schemas/auth.py)
/**!
 * @brief Represents the data encoded in a JWT token.
 * @complexity 1
 */

// --- PermissionSchema (backend/src/schemas/auth.py)
/**!
 * @brief Represents a permission in API responses.
 * @complexity 1
 */

// --- RoleSchema (backend/src/schemas/auth.py)
/**!
 * @brief Represents a role in API responses.
 */

// --- RoleCreate (backend/src/schemas/auth.py)
/**!
 * @brief Schema for creating a new role.
 */

// --- RoleUpdate (backend/src/schemas/auth.py)
/**!
 * @brief Schema for updating an existing role.
 */

// --- ADGroupMappingSchema (backend/src/schemas/auth.py)
/**!
 * @brief Represents an AD Group to Role mapping in API responses.
 */

// --- ADGroupMappingCreate (backend/src/schemas/auth.py)
/**!
 * @brief Schema for creating an AD Group mapping.
 */

// --- UserBase (backend/src/schemas/auth.py)
/**!
 * @brief Base schema for user data.
 */

// --- UserCreate (backend/src/schemas/auth.py)
/**!
 * @brief Schema for creating a new user.
 */

// --- UserUpdate (backend/src/schemas/auth.py)
/**!
 * @brief Schema for updating an existing user.
 */

// --- User (backend/src/schemas/auth.py)
/**!
 * @brief Schema for user data in API responses.
 */

// --- DatasetReviewSchemas (backend/src/schemas/dataset_review.py)
/**!
 * @brief Thin facade re-exporting all dataset review API schemas from decomposed sub-modules.
 * @complexity 2
 * @layer API
 * @rationale Original 419-line file exceeded INV_7 (400-line module limit). Decomposed into DTO and composite sub-modules.
 * @rejected Keeping all schemas in a single file because it exceeded the fractal limit.
 */

// --- DatasetReviewSchemaComposites (backend/src/schemas/dataset_review_pkg/_composites.py)
/**!
 * @brief Composite Pydantic DTOs for clarification, preview, run context, and session summary/detail responses.
 * @complexity 2
 * @layer API
 */

// --- ClarificationOptionDto (backend/src/schemas/dataset_review_pkg/_composites.py)
/**!
 * @brief Clarification option DTO.
 * @complexity 1
 */

// --- ClarificationAnswerDto (backend/src/schemas/dataset_review_pkg/_composites.py)
/**!
 * @brief Clarification answer DTO with feedback.
 * @complexity 1
 */

// --- ClarificationQuestionDto (backend/src/schemas/dataset_review_pkg/_composites.py)
/**!
 * @brief Clarification question DTO with nested options and answer.
 * @complexity 2
 */

// --- ClarificationSessionDto (backend/src/schemas/dataset_review_pkg/_composites.py)
/**!
 * @brief Clarification session DTO with nested questions.
 * @complexity 2
 */

// --- CompiledPreviewDto (backend/src/schemas/dataset_review_pkg/_composites.py)
/**!
 * @brief Compiled preview DTO with fingerprint and session version.
 * @complexity 1
 */

// --- DatasetRunContextDto (backend/src/schemas/dataset_review_pkg/_composites.py)
/**!
 * @brief Run context DTO with launch audit data and session version.
 * @complexity 1
 */

// --- SessionSummary (backend/src/schemas/dataset_review_pkg/_composites.py)
/**!
 * @brief Lightweight session summary DTO for list responses.
 * @complexity 2
 */

// --- SessionDetail (backend/src/schemas/dataset_review_pkg/_composites.py)
/**!
 * @brief Full session detail DTO with all nested aggregates for detail views.
 * @complexity 2
 */

// --- DatasetReviewSchemaDtos (backend/src/schemas/dataset_review_pkg/_dtos.py)
/**!
 * @brief Pydantic DTOs for session, profile, findings, collaborators, and semantic field API payloads.
 * @complexity 2
 * @layer API
 */

// --- SessionCollaboratorDto (backend/src/schemas/dataset_review_pkg/_dtos.py)
/**!
 * @brief Collaborator DTO for session access control.
 * @complexity 1
 */

// --- DatasetProfileDto (backend/src/schemas/dataset_review_pkg/_dtos.py)
/**!
 * @brief Dataset profile DTO with business summary and confidence metadata.
 * @complexity 1
 */

// --- ValidationFindingDto (backend/src/schemas/dataset_review_pkg/_dtos.py)
/**!
 * @brief Validation finding DTO with resolution tracking.
 * @complexity 1
 */

// --- SemanticSourceDto (backend/src/schemas/dataset_review_pkg/_dtos.py)
/**!
 * @brief Semantic source DTO with trust level and status.
 * @complexity 1
 */

// --- SemanticCandidateDto (backend/src/schemas/dataset_review_pkg/_dtos.py)
/**!
 * @brief Semantic candidate DTO with match type and confidence score.
 * @complexity 1
 */

// --- SemanticFieldEntryDto (backend/src/schemas/dataset_review_pkg/_dtos.py)
/**!
 * @brief Semantic field entry DTO with nested candidates and session version.
 * @complexity 2
 */

// --- ImportedFilterDto (backend/src/schemas/dataset_review_pkg/_dtos.py)
/**!
 * @brief Imported filter DTO with confidence and recovery status.
 * @complexity 1
 */

// --- TemplateVariableDto (backend/src/schemas/dataset_review_pkg/_dtos.py)
/**!
 * @brief Template variable DTO with mapping status.
 * @complexity 1
 */

// --- ExecutionMappingDto (backend/src/schemas/dataset_review_pkg/_dtos.py)
/**!
 * @brief Execution mapping DTO with approval state and session version.
 * @complexity 1
 */

// --- HealthSchemas (backend/src/schemas/health.py)
/**!
 * @brief Pydantic schemas for dashboard health summary.
 * @complexity 3
 * @layer Domain
 */

// --- DashboardHealthItem (backend/src/schemas/health.py)
/**!
 * @brief Represents the latest health status of a single dashboard.
 */

// --- HealthSummaryResponse (backend/src/schemas/health.py)
/**!
 * @brief Aggregated health summary for all dashboards.
 */

// --- ProfileSchemas (backend/src/schemas/profile.py)
/**!
 * @brief Defines API schemas for profile preference persistence, security read-only snapshot, and Superset account lookup.
 * @complexity 5
 * @data_contract ProfilePayload -> ProfileSchema
 * @invariant Schema shapes stay stable for profile UI states and backend preference contracts.
 * @layer API
 */

// --- ProfilePermissionState (backend/src/schemas/profile.py)
/**!
 * @brief Represents one permission badge state for profile read-only security view.
 * @complexity 3
 */

// --- ProfileSecuritySummary (backend/src/schemas/profile.py)
/**!
 * @brief Read-only security and access snapshot for current user.
 * @complexity 3
 */

// --- ProfilePreference (backend/src/schemas/profile.py)
/**!
 * @brief Represents persisted profile preference for a single authenticated user.
 * @complexity 3
 */

// --- ProfilePreferenceUpdateRequest (backend/src/schemas/profile.py)
/**!
 * @brief Request payload for updating current user's profile settings.
 * @complexity 3
 */

// --- ProfilePreferenceResponse (backend/src/schemas/profile.py)
/**!
 * @brief Response envelope for profile preference read/update endpoints.
 * @complexity 3
 */

// --- SupersetAccountLookupRequest (backend/src/schemas/profile.py)
/**!
 * @brief Query contract for Superset account lookup by selected environment.
 * @complexity 3
 */

// --- SupersetAccountCandidate (backend/src/schemas/profile.py)
/**!
 * @brief Canonical account candidate projected from Superset users payload.
 * @complexity 3
 */

// --- SupersetAccountLookupResponse (backend/src/schemas/profile.py)
/**!
 * @brief Response envelope for Superset account lookup (success or degraded mode).
 * @complexity 3
 */

// --- SettingsSchemas (backend/src/schemas/settings.py)
/**!
 * @brief Pydantic schemas for application settings and automation policies.
 * @complexity 3
 * @layer Domain
 */

// --- NotificationChannel (backend/src/schemas/settings.py)
/**!
 * @brief Structured notification channel definition for policy-level custom routing.
 */

// --- ValidationPolicyBase (backend/src/schemas/settings.py)
/**!
 * @brief Base schema for validation policy data.
 */

// --- ValidationPolicyCreate (backend/src/schemas/settings.py)
/**!
 * @brief Schema for creating a new validation policy.
 */

// --- ValidationPolicyUpdate (backend/src/schemas/settings.py)
/**!
 * @brief Schema for updating an existing validation policy.
 */

// --- ValidationPolicyResponse (backend/src/schemas/settings.py)
/**!
 * @brief Schema for validation policy response data.
 */

// --- TranslationScheduleItem (backend/src/schemas/settings.py)
/**!
 * @brief Response schema for a translation schedule item with joined job name.
 * @complexity 1
 */

// --- TranslateSchemas (backend/src/schemas/translate.py)
/**!
 * @brief Pydantic v2 schemas for translation API request/response serialization.
 * @complexity 3
 * @layer API
 */

// --- TranslateJobCreate (backend/src/schemas/translate.py)
/**!
 * @brief Schema for creating a new translation job.
 */

// --- TranslateJobUpdate (backend/src/schemas/translate.py)
/**!
 * @brief Schema for updating an existing translation job.
 */

// --- TranslateJobResponse (backend/src/schemas/translate.py)
/**!
 * @brief Schema for translation job API responses.
 */

// --- DatasourceColumnResponse (backend/src/schemas/translate.py)
/**!
 * @brief Schema for datasource column metadata response.
 */

// --- DatasourceColumnsResponse (backend/src/schemas/translate.py)
/**!
 * @brief Schema for datasource columns endpoint response.
 */

// --- DuplicateJobResponse (backend/src/schemas/translate.py)
/**!
 * @brief Schema for duplicate job response.
 */

// --- DictionaryCreate (backend/src/schemas/translate.py)
/**!
 * @brief Schema for creating a new terminology dictionary.
 */

// --- DictionaryImport (backend/src/schemas/translate.py)
/**!
 * @brief Schema for importing entries into a terminology dictionary.
 */

// --- DictionaryResponse (backend/src/schemas/translate.py)
/**!
 * @brief Schema for terminology dictionary API responses.
 */

// --- DictionaryEntryCreate (backend/src/schemas/translate.py)
/**!
 * @brief Schema for adding/editing a dictionary entry with language pair support.
 */

// --- DictionaryEntryResponse (backend/src/schemas/translate.py)
/**!
 * @brief Schema for dictionary entry API responses.
 */

// --- DictionaryImportResult (backend/src/schemas/translate.py)
/**!
 * @brief Schema for dictionary import result.
 */

// --- PreviewRequest (backend/src/schemas/translate.py)
/**!
 * @brief Schema for triggering a translation preview.
 */

// --- PreviewRowUpdate (backend/src/schemas/translate.py)
/**!
 * @brief Schema for approving/editing/rejecting a preview row.
 */

// --- PreviewAcceptResponse (backend/src/schemas/translate.py)
/**!
 * @brief Schema for preview accept response.
 */

// --- CostEstimate (backend/src/schemas/translate.py)
/**!
 * @brief Schema for cost estimation in preview response.
 */

// --- TermCorrectionSubmit (backend/src/schemas/translate.py)
/**!
 * @brief Schema for submitting a term correction in a translation preview.
 */

// --- TermCorrectionBulkSubmit (backend/src/schemas/translate.py)
/**!
 * @brief Schema for submitting multiple term corrections atomically.
 */

// --- CorrectionConflictResult (backend/src/schemas/translate.py)
/**!
 * @brief Schema for reporting conflicts in correction submission.
 */

// --- CorrectionSubmitResponse (backend/src/schemas/translate.py)
/**!
 * @brief Schema for correction submission response.
 */

// --- ScheduleResponse (backend/src/schemas/translate.py)
/**!
 * @brief Schema for schedule API responses.
 */

// --- NextExecutionResponse (backend/src/schemas/translate.py)
/**!
 * @brief Schema for next execution preview.
 */

// --- TranslationRunResponse (backend/src/schemas/translate.py)
/**!
 * @brief Schema for translation run API responses.
 */

// --- RunDetailResponse (backend/src/schemas/translate.py)
/**!
 * @brief Schema for detailed run response including records, events, and config snapshot.
 */

// --- RunHistoryFilter (backend/src/schemas/translate.py)
/**!
 * @brief Schema for filtering run history.
 */

// --- RunListResponse (backend/src/schemas/translate.py)
/**!
 * @brief Schema for paginated run list response.
 */

// --- AggregatedMetricsResponse (backend/src/schemas/translate.py)
/**!
 * @brief Schema for aggregated per-job metrics.
 */

// --- TranslationPreviewLanguageResponse (backend/src/schemas/translate.py)
/**!
 * @brief Schema for per-language preview data in API responses.
 * @complexity 1
 */

// --- PreviewRow (backend/src/schemas/translate.py)
/**!
 * @brief A single row in a translation preview showing original and translated content side by side.
 */

// --- TranslationPreviewResponse (backend/src/schemas/translate.py)
/**!
 * @brief Schema for translation preview session API responses.
 */

// --- TranslationBatchResponse (backend/src/schemas/translate.py)
/**!
 * @brief Schema for translation batch API responses.
 */

// --- MetricsResponse (backend/src/schemas/translate.py)
/**!
 * @brief Schema for translation metrics API responses.
 */

// --- TranslationLanguageResponse (backend/src/schemas/translate.py)
/**!
 * @brief Schema for per-language translation data in API responses.
 * @complexity 1
 */

// --- TranslationRunLanguageStatsResponse (backend/src/schemas/translate.py)
/**!
 * @brief Schema for per-language statistics in run API responses.
 * @complexity 1
 */

// --- OverrideLanguageRequest (backend/src/schemas/translate.py)
/**!
 * @brief Schema for manually overriding the detected source language of a translation.
 * @complexity 1
 */

// --- BulkFindReplaceRequest (backend/src/schemas/translate.py)
/**!
 * @brief Schema for bulk find-and-replace within translations for a target language.
 * @complexity 1
 */

// --- InlineEditRequest (backend/src/schemas/translate.py)
/**!
 * @brief Schema for inline editing a translated value on a completed run result.
 * @complexity 1
 */

// --- BulkReplacePreviewItem (backend/src/schemas/translate.py)
/**!
 * @brief A single item in a bulk replace preview list.
 * @complexity 1
 */

// --- BulkReplaceResponse (backend/src/schemas/translate.py)
/**!
 * @brief Response for bulk find-and-replace operation.
 * @complexity 1
 */

// --- InlineCorrectionSubmit (backend/src/schemas/translate.py)
/**!
 * @brief Schema for submitting an inline correction for a specific translated record.
 * @complexity 1
 */

// --- TargetSchemaValidationRequest (backend/src/schemas/translate.py)
/**!
 * @brief Schema for requesting target table schema validation.
 * @complexity 1
 */

// --- TargetSchemaColumnInfo (backend/src/schemas/translate.py)
/**!
 * @brief Schema for a single column in the schema validation response.
 * @complexity 1
 */

// --- TargetSchemaValidationResponse (backend/src/schemas/translate.py)
/**!
 * @brief Schema for target table schema validation response.
 * @complexity 1
 */

// --- ValidationSchemas (backend/src/schemas/validation.py)
/**!
 * @brief Pydantic v2 schemas for validation task management and run history API serialization.
 * @complexity 3
 * @layer API
 */

// --- ValidationTaskCreate (backend/src/schemas/validation.py)
/**!
 * @brief Schema for creating a new validation task (policy).
 * @complexity 1
 */

// --- ValidationTaskUpdate (backend/src/schemas/validation.py)
/**!
 * @brief Schema for updating an existing validation task (policy).
 * @complexity 1
 */

// --- ValidationTaskResponse (backend/src/schemas/validation.py)
/**!
 * @brief Schema for validation task API responses — includes last run status from join.
 * @complexity 1
 */

// --- ValidationTaskListResponse (backend/src/schemas/validation.py)
/**!
 * @brief Schema for paginated task list response.
 * @complexity 1
 */

// --- ValidationRunResponse (backend/src/schemas/validation.py)
/**!
 * @brief Schema for validation run history listing.
 * @complexity 1
 */

// --- ValidationRunListResponse (backend/src/schemas/validation.py)
/**!
 * @brief Schema for paginated run list response.
 * @complexity 1
 */

// --- ValidationRunDetailResponse (backend/src/schemas/validation.py)
/**!
 * @brief Schema for full run detail including parsed issues and raw response.
 * @complexity 1
 */

// --- TriggerRunResponse (backend/src/schemas/validation.py)
/**!
 * @brief Schema for trigger-run response — returns spawned task ID.
 * @complexity 1
 */

// --- ScriptsPackage (backend/src/scripts/__init__.py)
/**!
 * @brief Script entrypoint package root.
 */

// --- CleanReleaseCliScript (backend/src/scripts/clean_release_cli.py)
/**!
 * @brief Provide headless CLI commands for candidate registration, artifact import and manifest build.
 * @complexity 3
 * @layer Service
 */

// --- build_parser (backend/src/scripts/clean_release_cli.py)
/**!
 * @brief Build argparse parser for clean release CLI.
 */

// --- run_candidate_register (backend/src/scripts/clean_release_cli.py)
/**!
 * @brief Register candidate in repository via CLI command.
 * @post Candidate is persisted in DRAFT status.
 * @pre Candidate ID must be unique.
 */

// --- run_artifact_import (backend/src/scripts/clean_release_cli.py)
/**!
 * @brief Import single artifact for existing candidate.
 * @post Artifact is persisted for candidate.
 * @pre Candidate must exist.
 */

// --- run_manifest_build (backend/src/scripts/clean_release_cli.py)
/**!
 * @brief Build immutable manifest snapshot for candidate.
 * @post New manifest version is persisted.
 * @pre Candidate must exist.
 */

// --- run_compliance_run (backend/src/scripts/clean_release_cli.py)
/**!
 * @brief Execute compliance run for candidate with optional manifest fallback.
 * @post Returns run payload and exit code 0 on success.
 * @pre Candidate exists and trusted snapshots are configured.
 */

// --- run_compliance_status (backend/src/scripts/clean_release_cli.py)
/**!
 * @brief Read run status by run id.
 * @post Returns run status payload.
 * @pre Run exists.
 */

// --- _to_payload (backend/src/scripts/clean_release_cli.py)
/**!
 * @brief Serialize domain models for CLI JSON output across SQLAlchemy/Pydantic variants.
 * @post Returns dictionary payload without mutating value.
 * @pre value is serializable model or primitive object.
 */

// --- run_compliance_report (backend/src/scripts/clean_release_cli.py)
/**!
 * @brief Read immutable report by run id.
 * @post Returns report payload.
 * @pre Run and report exist.
 */

// --- run_compliance_violations (backend/src/scripts/clean_release_cli.py)
/**!
 * @brief Read run violations by run id.
 * @post Returns violations payload.
 * @pre Run exists.
 */

// --- run_approve (backend/src/scripts/clean_release_cli.py)
/**!
 * @brief Approve candidate based on immutable PASSED report.
 * @post Persists APPROVED decision and returns success payload.
 * @pre Candidate and report exist; report is PASSED.
 */

// --- run_reject (backend/src/scripts/clean_release_cli.py)
/**!
 * @brief Reject candidate without mutating compliance evidence.
 * @post Persists REJECTED decision and returns success payload.
 * @pre Candidate and report exist.
 */

// --- run_publish (backend/src/scripts/clean_release_cli.py)
/**!
 * @brief Publish approved candidate to target channel.
 * @post Appends ACTIVE publication record and returns payload.
 * @pre Candidate is approved and report belongs to candidate.
 */

// --- run_revoke (backend/src/scripts/clean_release_cli.py)
/**!
 * @brief Revoke active publication record.
 * @post Publication record status becomes REVOKED.
 * @pre Publication id exists and is ACTIVE.
 */

// --- CleanReleaseTuiScript (backend/src/scripts/clean_release_tui.py)
/**!
 * @brief Interactive terminal interface for Enterprise Clean Release compliance validation.
 * @complexity 3
 * @data_contract CLIArgs -> TUIExitCode
 * @invariant TUI refuses startup in non-TTY environments; headless flow is CLI/API only.
 * @layer UI
 */

// --- TuiFacadeAdapter (backend/src/scripts/clean_release_tui.py)
/**!
 * @brief Thin TUI adapter that routes business mutations through application services.
 * @post Business actions return service results/errors without direct TUI-owned mutations.
 * @pre repository contains candidate and trusted policy/registry snapshots for execution.
 */

// --- CleanReleaseTUI (backend/src/scripts/clean_release_tui.py)
/**!
 * @brief Curses-based application for compliance monitoring.
 * @ux_feedback Red alerts for BLOCKED status, Green for COMPLIANT.
 * @ux_state BLOCKED -> Violations detected, release forbidden.
 */

// --- run_checks (backend/src/scripts/clean_release_tui.py)
/**!
 * @brief Execute compliance run via facade adapter and update UI state.
 * @post UI reflects final run/report/violation state from service result.
 * @pre Candidate and policy snapshots are present in repository.
 */

// --- bundle_build_mode (backend/src/scripts/clean_release_tui.py)
/**!
 * @brief Interactive bundle build screen — select type, enter tag, watch live build output.
 * @complexity 4
 * @post Subprocess completes (success/failure). Output displayed. User returns via Esc.
 * @pre TTY is available. Bundle type selected (1 or 2). Tag is non-empty.
 * @side_effect Runs docker build subprocess, creates dist/docker/ files
 * @ux_state BUNDLE_DONE -> Build completed with success/failure result
 */

// --- CreateAdminScript (backend/src/scripts/create_admin.py)
/**!
 * @brief CLI tool for creating the initial admin user.
 * @complexity 5
 * @data_contract CLIArgs -> AdminUser
 * @invariant Admin user must have the "Admin" role.
 * @layer Infrastructure
 * @side_effect Writes admin user to database
 */

// --- create_admin (backend/src/scripts/create_admin.py)
/**!
 * @brief Creates an admin user and necessary roles/permissions.
 * @post Admin user exists in auth.db.
 * @pre username and password provided via CLI.
 */

// --- DeleteRunningTasksUtil (backend/src/scripts/delete_running_tasks.py)
/**!
 * @brief Script to delete tasks with RUNNING status from the database.
 * @complexity 3
 * @layer Infrastructure
 * @semantics maintenance, database, cleanup
 */

// --- delete_running_tasks (backend/src/scripts/delete_running_tasks.py)
/**!
 * @brief Delete all tasks with RUNNING status from the database.
 * @complexity 4
 * @post All tasks with status 'RUNNING' are removed from the database.
 * @pre Database is accessible and TaskRecord model is defined.
 * @side_effect Modifies DB: deletes RUNNING tasks. Prints to stdout.
 */

// --- InitAuthDbScript (backend/src/scripts/init_auth_db.py)
/**!
 * @brief Initializes the auth database and creates the necessary tables.
 * @complexity 2
 * @invariant Safe to run multiple times (idempotent).
 * @layer Service
 */

// --- run_init (backend/src/scripts/init_auth_db.py)
/**!
 * @brief Main entry point for the initialization script.
 * @complexity 3
 * @post auth.db is initialized with the correct schema and seeded permissions.
 */

// --- SeedPermissionsScript (backend/src/scripts/seed_permissions.py)
/**!
 * @brief Populates the auth database with initial system permissions.
 * @complexity 5
 * @data_contract CLIArgs -> SeedSummary
 * @invariant Safe to run multiple times (idempotent).
 * @layer Infrastructure
 * @side_effect Writes permissions to database
 */

// --- INITIAL_PERMISSIONS (backend/src/scripts/seed_permissions.py)
/**!
 * @brief Canonical bootstrap permission tuples seeded into auth storage.
 * @complexity 3
 */

// --- seed_permissions (backend/src/scripts/seed_permissions.py)
/**!
 * @brief Inserts missing permissions into the database.
 * @complexity 3
 * @post All INITIAL_PERMISSIONS exist in the DB.
 */

// --- SeedSupersetLoadTestScript (backend/src/scripts/seed_superset_load_test.py)
/**!
 * @brief Creates randomized load-test data in Superset by cloning chart configurations and creating dashboards in target environments.
 * @complexity 5
 * @data_contract CLIArgs -> TestDataSummary
 * @invariant Created chart and dashboard names are globally unique for one script run.
 * @layer Infrastructure
 */

// --- _parse_args (backend/src/scripts/seed_superset_load_test.py)
/**!
 * @brief Parses CLI arguments for load-test data generation.
 * @post Returns validated argument namespace.
 * @pre Script is called from CLI.
 */

// --- _extract_result_payload (backend/src/scripts/seed_superset_load_test.py)
/**!
 * @brief Normalizes Superset API payloads that may be wrapped in `result`.
 * @post Returns the unwrapped object when present.
 * @pre payload is a JSON-decoded API response.
 */

// --- _extract_created_id (backend/src/scripts/seed_superset_load_test.py)
/**!
 * @brief Extracts object ID from create/update API response.
 * @post Returns integer object ID or None if missing.
 * @pre payload is a JSON-decoded API response.
 */

// --- _generate_unique_name (backend/src/scripts/seed_superset_load_test.py)
/**!
 * @brief Generates globally unique random names for charts/dashboards.
 * @post Returns a unique string and stores it in used_names.
 * @pre used_names is mutable set for collision tracking.
 */

// --- _resolve_target_envs (backend/src/scripts/seed_superset_load_test.py)
/**!
 * @brief Resolves requested environment IDs from configuration.
 * @post Returns mapping env_id -> configured environment object.
 * @pre env_ids is non-empty.
 */

// --- _build_chart_template_pool (backend/src/scripts/seed_superset_load_test.py)
/**!
 * @brief Builds a pool of source chart templates to clone in one environment.
 * @post Returns non-empty list of chart payload templates.
 * @pre Client is authenticated.
 */

// --- seed_superset_load_data (backend/src/scripts/seed_superset_load_test.py)
/**!
 * @brief Creates dashboards and cloned charts for load testing across target environments.
 * @post Returns execution statistics dictionary.
 * @pre Target environments must be reachable and authenticated.
 * @side_effect Creates objects in Superset environments.
 */

// --- main (backend/src/scripts/seed_superset_load_test.py)
/**!
 * @brief CLI entrypoint for Superset load-test data seeding.
 * @post Prints summary and exits with non-zero status on failure.
 * @pre Command line arguments are valid.
 */

// --- test_dataset_dashboard_relations_script (backend/src/scripts/test_dataset_dashboard_relations.py)
/**!
 * @brief Tests and inspects dataset-to-dashboard relationship responses from Superset API.
 * @complexity 2
 * @rationale Added '# DIAGNOSTIC SCRIPT — not a test' header comment. Script already had if __name__ guard.
 */

// --- services (backend/src/services/__init__.py)
/**!
 * @brief Package initialization for services module
 * @complexity 2
 * @note GitService, AuthService, LLMProviderService have circular import issues - import directly when needed
 */

// --- auth_service (backend/src/services/auth_service.py)
/**!
 * @brief Orchestrates credential authentication and ADFS JIT user provisioning.
 * @complexity 5
 * @data_contract [Credentials | ADFSClaims] -> [UserEntity | SessionToken]
 * @invariant Authentication succeeds only for active users with valid credentials; issued sessions encode subject and scopes from assigned roles.
 * @layer Domain
 * @post User identity verified and session tokens issued according to role scopes.
 * @pre Core auth models and security utilities available.
 * @side_effect Writes last login timestamps and JIT-provisions external users.
 */

// --- AuthService (backend/src/services/auth_service.py)
/**!
 * @brief Provides high-level authentication services.
 * @complexity 3
 */

// --- CleanReleaseContracts (backend/src/services/clean_release/__init__.py)
/**!
 * @brief Publish the canonical semantic root for the clean-release backend service cluster.
 * @complexity 3
 * @layer Domain
 */

// --- ApprovalService (backend/src/services/clean_release/approval_service.py)
/**!
 * @brief Enforce approval/rejection gates over immutable compliance reports.
 * @complexity 5
 * @data_contract ApprovalRequest -> ApprovalDecision
 * @invariant Approval is allowed only for PASSED report bound to candidate; decisions are append-only.
 * @layer Domain
 * @post Approval decision appended; candidate lifecycle advanced
 * @pre Report with PASSED final_status exists for candidate
 * @side_effect Persists approval decisions, transitions candidate status
 */

// --- _get_or_init_decisions_store (backend/src/services/clean_release/approval_service.py)
/**!
 * @brief Provide append-only in-memory storage for approval decisions.
 * @post Returns mutable decision list attached to repository.
 * @pre repository is initialized.
 */

// --- _latest_decision_for_candidate (backend/src/services/clean_release/approval_service.py)
/**!
 * @brief Resolve latest approval decision for candidate from append-only store.
 * @post Returns latest ApprovalDecision or None.
 * @pre candidate_id is non-empty.
 */

// --- _resolve_candidate_and_report (backend/src/services/clean_release/approval_service.py)
/**!
 * @brief Validate candidate/report existence and ownership prior to decision persistence.
 * @post Returns tuple(candidate, report); raises ApprovalGateError on contract violation.
 * @pre candidate_id and report_id are non-empty.
 */

// --- approve_candidate (backend/src/services/clean_release/approval_service.py)
/**!
 * @brief Persist immutable APPROVED decision and advance candidate lifecycle to APPROVED.
 * @post Approval decision is appended and candidate transitions to APPROVED.
 * @pre Candidate exists, report belongs to candidate, report final_status is PASSED, candidate not already APPROVED.
 */

// --- reject_candidate (backend/src/services/clean_release/approval_service.py)
/**!
 * @brief Persist immutable REJECTED decision without promoting candidate lifecycle.
 * @post Rejected decision is appended; candidate lifecycle is unchanged.
 * @pre Candidate exists and report belongs to candidate.
 */

// --- ArtifactCatalogLoader (backend/src/services/clean_release/artifact_catalog_loader.py)
/**!
 * @brief Load bootstrap artifact catalogs for clean release real-mode flows.
 * @complexity 5
 * @data_contract FilePath -> CandidateArtifact[]
 * @invariant Artifact catalog must produce deterministic CandidateArtifact entries with required identity and checksum fields.
 * @layer Domain
 * @side_effect Reads JSON file from filesystem
 */

// --- load_bootstrap_artifacts (backend/src/services/clean_release/artifact_catalog_loader.py)
/**!
 * @brief Parse artifact catalog JSON into CandidateArtifact models for TUI/bootstrap flows.
 * @post Returns non-mutated CandidateArtifact models with required fields populated.
 * @pre path points to readable JSON file; payload is list[artifact] or {"artifacts": list[artifact]}.
 */

// --- AuditService (backend/src/services/clean_release/audit_service.py)
/**!
 * @brief Provide lightweight audit hooks for clean release preparation/check/report lifecycle.
 * @complexity 3
 * @data_contract AuditAction -> LogEntry
 * @invariant Audit hooks are append-only log actions.
 * @layer Infrastructure
 * @post Audit events appended to log
 * @pre Logger configured
 * @side_effect Writes audit events to logger and repository
 */

// --- candidate_service (backend/src/services/clean_release/candidate_service.py)
/**!
 * @brief Register release candidates with validated artifacts and advance lifecycle through legal transitions.
 * @complexity 5
 * @invariant Candidate lifecycle transitions are delegated to domain guard logic.
 * @layer Domain
 * @post candidate and artifacts are persisted; candidate transitions DRAFT -> PREPARED only.
 * @pre candidate_id must be unique; artifacts input must be non-empty and valid.
 */

// --- _validate_artifacts (backend/src/services/clean_release/candidate_service.py)
/**!
 * @brief Validate raw artifact payload list for required fields and shape.
 * @post Returns normalized artifact list or raises ValueError.
 * @pre artifacts payload is provided by caller.
 */

// --- ComplianceExecutionService (backend/src/services/clean_release/compliance_execution_service.py)
/**!
 * @brief Create and execute compliance runs with trusted snapshots, deterministic stages, violations and immutable report persistence.
 * @complexity 5
 * @data_contract Input[candidate_id, requested_by, manifest_id?, policy snapshots, stage results] -> Output[ComplianceExecutionResult]
 * @invariant A run binds to exactly one candidate/manifest/policy/registry snapshot set.
 * @layer Domain
 * @post Candidate-scoped compliance runs persist stage evidence, terminal status, and immutable report artifacts when execution succeeds.
 * @pre Repository adapters, trusted policy resolution, and deterministic stage implementations are available for the run request.
 * @side_effect Persists runs, stage results, violations, and reports through repository adapters and audit helpers.
 */

// --- ComplianceExecutionResult (backend/src/services/clean_release/compliance_execution_service.py)
/**!
 * @brief Return envelope for compliance execution with run/report and persisted stage artifacts.
 */

// --- ComplianceOrchestrator (backend/src/services/clean_release/compliance_orchestrator.py)
/**!
 * @brief Execute mandatory clean compliance stages and produce final COMPLIANT/BLOCKED/FAILED outcome.
 * @complexity 5
 * @data_contract Manifest -> ComplianceReport
 * @invariant COMPLIANT is impossible when any mandatory stage fails.
 * @layer Domain
 * @post OrchestrationResult with compliance status
 * @pre ManifestService and PolicyEngine are available
 * @side_effect Triggers compliance checks; may modify manifest state
 * @test_contract ComplianceCheckRun -> ComplianceCheckRun
 * @test_edge report_generation_error -> Downstream reporting failure does not alter orchestrator status derivation contract
 * @test_fixture compliant_candidate -> file:backend/tests/fixtures/clean_release/fixtures_clean_release.json
 * @test_invariant compliant_requires_all_mandatory_pass -> VERIFIED_BY: [stage_failure_blocks_release]
 */

// --- CleanComplianceOrchestrator (backend/src/services/clean_release/compliance_orchestrator.py)
/**!
 * @brief Coordinate clean-release compliance verification stages.
 */

// --- run_check_legacy (backend/src/services/clean_release/compliance_orchestrator.py)
/**!
 * @brief Legacy wrapper for compatibility with previous orchestrator call style.
 * @data_contract Input -> (repository:CleanReleaseRepository, candidate_id:str, policy_id:str, requested_by:str, manifest_id:str), Output -> ComplianceRun
 * @post Returns finalized ComplianceRun produced by orchestrator start->execute->finalize sequence.
 * @pre repository and identifiers are valid and resolvable by orchestrator dependencies.
 * @side_effect Reads/writes compliance entities through repository during orchestrator calls.
 */

// --- DemoDataService (backend/src/services/clean_release/demo_data_service.py)
/**!
 * @brief Provide deterministic namespace helpers and isolated in-memory repository creation for demo and real modes.
 * @complexity 5
 * @data_contract SeedConfig -> DemoEntities
 * @invariant Demo and real namespaces must never collide for generated physical identifiers.
 * @layer Domain
 * @side_effect Writes demo entities to repository
 */

// --- resolve_namespace (backend/src/services/clean_release/demo_data_service.py)
/**!
 * @brief Resolve canonical clean-release namespace for requested mode.
 * @post Returns deterministic namespace key for demo/real separation.
 * @pre mode is a non-empty string identifying runtime mode.
 */

// --- build_namespaced_id (backend/src/services/clean_release/demo_data_service.py)
/**!
 * @brief Build storage-safe physical identifier under mode namespace.
 * @post Returns deterministic "{namespace}::{logical_id}" identifier.
 * @pre namespace and logical_id are non-empty strings.
 */

// --- create_isolated_repository (backend/src/services/clean_release/demo_data_service.py)
/**!
 * @brief Create isolated in-memory repository instance for selected mode namespace.
 * @post Returns repository instance tagged with namespace metadata.
 * @pre mode is a valid runtime mode marker.
 */

// --- clean_release_dto (backend/src/services/clean_release/dto.py)
/**!
 * @brief Data Transfer Objects for clean release compliance subsystem.
 * @complexity 3
 * @layer Application
 */

// --- clean_release_enums (backend/src/services/clean_release/enums.py)
/**!
 * @brief Canonical enums for clean release lifecycle and compliance.
 * @complexity 3
 * @layer Domain
 */

// --- clean_release_exceptions (backend/src/services/clean_release/exceptions.py)
/**!
 * @brief Domain exceptions for clean release compliance subsystem.
 * @complexity 3
 * @layer Domain
 */

// --- clean_release_facade (backend/src/services/clean_release/facade.py)
/**!
 * @brief Unified entry point for clean release operations.
 * @complexity 3
 * @layer Application
 */

// --- ManifestBuilder (backend/src/services/clean_release/manifest_builder.py)
/**!
 * @brief Build deterministic distribution manifest from classified artifact input.
 * @complexity 5
 * @data_contract ArtifactSet -> Manifest
 * @invariant Equal semantic artifact sets produce identical deterministic hash values.
 * @layer Domain
 * @side_effect Computes hash of artifact set
 */

// --- build_distribution_manifest (backend/src/services/clean_release/manifest_builder.py)
/**!
 * @brief Build DistributionManifest with deterministic hash and validated counters.
 * @post Returns DistributionManifest with summary counts matching items cardinality.
 * @pre artifacts list contains normalized classification values.
 */

// --- ManifestService (backend/src/services/clean_release/manifest_service.py)
/**!
 * @brief Build immutable distribution manifests with deterministic digest and version increment.
 * @complexity 5
 * @data_contract Manifest -> ManifestRecord; Candidate -> ManifestRecord
 * @invariant Existing manifests are never mutated.
 * @layer Domain
 * @post New immutable manifest is persisted with incremented version and deterministic digest.
 * @pre Candidate exists and is PREPARED or MANIFEST_BUILT; artifacts are present.
 * @side_effect May modify manifest state during processing
 */

// --- build_manifest_snapshot (backend/src/services/clean_release/manifest_service.py)
/**!
 * @brief Create a new immutable manifest version for a candidate.
 * @post Returns persisted DistributionManifest with monotonically incremented version.
 * @pre Candidate is prepared, artifacts are available, candidate_id is valid.
 */

// --- clean_release_mappers (backend/src/services/clean_release/mappers.py)
/**!
 * @brief Map between domain entities (SQLAlchemy models) and DTOs.
 * @complexity 3
 * @layer Application
 */

// --- PolicyEngine (backend/src/services/clean_release/policy_engine.py)
/**!
 * @brief Evaluate artifact/source policies for enterprise clean profile with deterministic outcomes.
 * @complexity 5
 * @data_contract Candidate -> PolicyDecision
 * @invariant Enterprise-clean policy always treats non-registry sources as violations.
 * @layer Domain
 * @post PolicyDecision returned with approval status
 * @pre PolicyRepository is accessible
 * @side_effect Read-only policy evaluation; no state changes
 */

// --- CleanPolicyEngine (backend/src/services/clean_release/policy_engine.py)
/**!
 * @post Deterministic classification and source validation are available.
 * @pre Active policy exists and is internally consistent.
 * @test_contract CandidateEvaluationInput -> PolicyValidationResult|SourceValidationResult
 * @test_edge external_endpoint -> endpoint not present in enabled internal registry entries
 * @test_fixture policy_enterprise_clean -> file:backend/tests/fixtures/clean_release/fixtures_clean_release.json
 * @test_invariant deterministic_classification -> VERIFIED_BY: [policy_valid]
 * @test_scenario policy_valid -> Enterprise clean policy with matching registry returns ok=True
 */

// --- PolicyResolutionService (backend/src/services/clean_release/policy_resolution_service.py)
/**!
 * @brief Resolve trusted policy and registry snapshots from ConfigManager without runtime overrides.
 * @complexity 5
 * @data_contract PolicyRequest -> ResolutionResult
 * @invariant Trusted snapshot resolution is based only on ConfigManager active identifiers.
 * @layer Domain
 * @post ResolutionResult with matched policies
 * @pre PolicyRepository and Manifest are available
 * @side_effect Read-only policy evaluation; logs resolution decisions
 */

// --- resolve_trusted_policy_snapshots (backend/src/services/clean_release/policy_resolution_service.py)
/**!
 * @brief Resolve immutable trusted policy and registry snapshots using active config IDs only.
 * @post Returns immutable policy and registry snapshots; runtime override attempts are rejected.
 * @pre ConfigManager provides active_policy_id and active_registry_id; repository contains referenced snapshots.
 * @side_effect None.
 */

// --- PreparationService (backend/src/services/clean_release/preparation_service.py)
/**!
 * @brief Prepare release candidate by policy evaluation and deterministic manifest creation.
 * @complexity 5
 * @data_contract PrepareRequest -> PrepareResult
 * @invariant Candidate preparation always persists manifest and candidate status deterministically.
 * @layer Domain
 * @side_effect Persists candidate and manifest
 */

// --- prepare_candidate_legacy (backend/src/services/clean_release/preparation_service.py)
/**!
 * @brief Legacy compatibility wrapper kept for migration period.
 * @post Delegates to canonical prepare_candidate and preserves response shape.
 * @pre Same as prepare_candidate.
 */

// --- PublicationService (backend/src/services/clean_release/publication_service.py)
/**!
 * @brief Enforce publication and revocation gates with append-only publication records.
 * @complexity 5
 * @invariant Publication records are append-only snapshots; revoke mutates only publication status for targeted record.
 * @layer Domain
 */

// --- _get_or_init_publications_store (backend/src/services/clean_release/publication_service.py)
/**!
 * @brief Provide in-memory append-only publication storage.
 * @post Returns publication list attached to repository.
 * @pre repository is initialized.
 */

// --- _latest_publication_for_candidate (backend/src/services/clean_release/publication_service.py)
/**!
 * @brief Resolve latest publication record for candidate.
 * @post Returns latest record or None.
 * @pre candidate_id is non-empty.
 */

// --- _latest_approval_for_candidate (backend/src/services/clean_release/publication_service.py)
/**!
 * @brief Resolve latest approval decision from repository decision store.
 * @post Returns latest decision object or None.
 * @pre candidate_id is non-empty.
 */

// --- publish_candidate (backend/src/services/clean_release/publication_service.py)
/**!
 * @brief Create immutable publication record for approved candidate.
 * @post New ACTIVE publication record is appended.
 * @pre Candidate exists, report belongs to candidate, latest approval is APPROVED.
 */

// --- revoke_publication (backend/src/services/clean_release/publication_service.py)
/**!
 * @brief Revoke existing publication record without deleting history.
 * @post Target publication status becomes REVOKED and updated record is returned.
 * @pre publication_id exists in repository publication store.
 */

// --- ReportBuilder (backend/src/services/clean_release/report_builder.py)
/**!
 * @brief Build and persist compliance reports with consistent counter invariants.
 * @complexity 5
 * @data_contract Input[ComplianceRun, List[ComplianceViolation]] -> Output[ComplianceReport]
 * @invariant blocking_violations_count never exceeds violations_count.
 * @layer Domain
 * @post Returns immutable report payloads with consistent violation counters and operator summary content.
 * @pre Compliance run is terminal and repository persistence is available for report storage.
 * @side_effect Writes report artifacts to repository when persistence helpers are invoked.
 * @test_contract ComplianceCheckRun,List[ComplianceViolation] -> ComplianceReport
 * @test_edge missing_operator_summary -> non-terminal run prevents report creation and summary generation
 * @test_fixture blocked_with_two_violations -> file:backend/tests/fixtures/clean_release/fixtures_clean_release.json
 * @test_invariant blocking_count_le_total_count -> VERIFIED_BY: [counter_mismatch, empty_violations_for_blocked]
 */

// --- clean_release_repositories (backend/src/services/clean_release/repositories/__init__.py)
/**!
 * @brief Export all clean release repositories.
 * @complexity 3
 */

// --- approval_repository (backend/src/services/clean_release/repositories/approval_repository.py)
/**!
 * @brief Persist and query approval decisions.
 * @complexity 3
 * @layer Infrastructure
 */

// --- artifact_repository (backend/src/services/clean_release/repositories/artifact_repository.py)
/**!
 * @brief Persist and query candidate artifacts.
 * @complexity 3
 * @layer Infrastructure
 */

// --- audit_repository (backend/src/services/clean_release/repositories/audit_repository.py)
/**!
 * @brief Persist and query audit logs for clean release operations.
 * @complexity 3
 * @layer Infrastructure
 */

// --- candidate_repository (backend/src/services/clean_release/repositories/candidate_repository.py)
/**!
 * @brief Persist and query release candidates.
 * @complexity 3
 * @layer Infrastructure
 */

// --- compliance_repository (backend/src/services/clean_release/repositories/compliance_repository.py)
/**!
 * @brief Persist and query compliance runs, stage runs, and violations.
 * @complexity 3
 * @layer Infrastructure
 */

// --- ManifestRepositoryModule (backend/src/services/clean_release/repositories/manifest_repository.py)
/**!
 * @brief Persist and query distribution manifests.
 * @complexity 3
 * @layer Infrastructure
 */

// --- ManifestRepository (backend/src/services/clean_release/repositories/manifest_repository.py)
/**!
 * @brief Encapsulates database CRUD operations for DistributionManifest entities.
 * @complexity 3
 */

// --- policy_repository (backend/src/services/clean_release/repositories/policy_repository.py)
/**!
 * @brief Persist and query policy and registry snapshots.
 * @complexity 3
 * @layer Infrastructure
 */

// --- publication_repository (backend/src/services/clean_release/repositories/publication_repository.py)
/**!
 * @brief Persist and query publication records.
 * @complexity 3
 * @layer Infrastructure
 */

// --- report_repository (backend/src/services/clean_release/repositories/report_repository.py)
/**!
 * @brief Persist and query compliance reports.
 * @complexity 3
 * @layer Infrastructure
 */

// --- RepositoryRelations (backend/src/services/clean_release/repository.py)
/**!
 * @brief Provide repository adapter for clean release entities with deterministic access methods.
 * @complexity 5
 * @data_contract Entity -> RepositoryOperation
 * @invariant Repository operations are side-effect free outside explicit save/update calls.
 * @layer Infrastructure
 * @post Repository operations exported
 * @pre In-memory storage initialized
 * @side_effect Modifies in-memory state on save/update
 */

// --- CleanReleaseRepository (backend/src/services/clean_release/repository.py)
/**!
 * @brief Data access object for clean release lifecycle.
 */

// --- SourceIsolation (backend/src/services/clean_release/source_isolation.py)
/**!
 * @brief Validate that all resource endpoints belong to the approved internal source registry.
 * @complexity 5
 * @data_contract SourceURL -> ViolationReport
 * @invariant Any endpoint outside enabled registry entries is treated as external-source violation.
 * @layer Domain
 * @post Source isolation violations identified
 * @pre Source registry configured
 * @side_effect None (read-only check)
 */

// --- ComplianceStages (backend/src/services/clean_release/stages/__init__.py)
/**!
 * @brief Define compliance stage order and helper functions for deterministic run-state evaluation.
 * @complexity 5
 * @data_contract StagePipeline -> ComplianceResult
 * @invariant Stage order remains deterministic for all compliance runs.
 * @layer Domain
 * @side_effect Registers compliance stages
 */

// --- build_default_stages (backend/src/services/clean_release/stages/__init__.py)
/**!
 * @brief Build default deterministic stage pipeline implementation order.
 * @post Returns stage instances in mandatory execution order.
 * @pre None.
 */

// --- stage_result_map (backend/src/services/clean_release/stages/__init__.py)
/**!
 * @brief Convert stage result list to dictionary by stage name.
 * @post Returns stage->status dictionary for downstream evaluation.
 * @pre stage_results may be empty or contain unique stage names.
 */

// --- missing_mandatory_stages (backend/src/services/clean_release/stages/__init__.py)
/**!
 * @brief Identify mandatory stages that are absent from run results.
 * @post Returns ordered list of missing mandatory stages.
 * @pre stage_status_map contains zero or more known stage statuses.
 */

// --- derive_final_status (backend/src/services/clean_release/stages/__init__.py)
/**!
 * @brief Derive final run status from stage results with deterministic blocking behavior.
 * @post Returns one of PASSED/BLOCKED/ERROR according to mandatory stage outcomes.
 * @pre Stage statuses correspond to compliance checks.
 */

// --- ComplianceStageBase (backend/src/services/clean_release/stages/base.py)
/**!
 * @brief Define shared contracts and helpers for pluggable clean-release compliance stages.
 * @complexity 5
 * @data_contract Context -> StageResult
 * @invariant Stage execution is deterministic for equal input context.
 * @layer Domain
 * @side_effect None (deterministic execution)
 */

// --- ComplianceStageContext (backend/src/services/clean_release/stages/base.py)
/**!
 * @brief Immutable input envelope passed to each compliance stage.
 */

// --- StageExecutionResult (backend/src/services/clean_release/stages/base.py)
/**!
 * @brief Structured stage output containing decision, details and violations.
 */

// --- ComplianceStage (backend/src/services/clean_release/stages/base.py)
/**!
 * @brief Protocol for pluggable stage implementations.
 */

// --- build_stage_run_record (backend/src/services/clean_release/stages/base.py)
/**!
 * @brief Build persisted stage run record from stage result.
 * @post Returns ComplianceStageRun with deterministic identifiers and timestamps.
 * @pre run_id and stage_name are non-empty.
 */

// --- build_violation (backend/src/services/clean_release/stages/base.py)
/**!
 * @brief Construct a compliance violation with normalized defaults.
 * @post Returns immutable-style violation payload ready for persistence.
 * @pre run_id, stage_name, code and message are non-empty.
 */

// --- data_purity (backend/src/services/clean_release/stages/data_purity.py)
/**!
 * @brief Evaluate manifest purity counters and emit blocking violations for prohibited artifacts.
 * @complexity 5
 * @data_contract Manifest -> DataPurityVerdict
 * @invariant prohibited_detected_count > 0 always yields BLOCKED stage decision.
 * @layer Domain
 * @side_effect None (read-only validation)
 */

// --- DataPurityStage (backend/src/services/clean_release/stages/data_purity.py)
/**!
 * @brief Validate manifest summary for prohibited artifacts.
 * @post Returns PASSED when no prohibited artifacts are detected, otherwise BLOCKED with violations.
 * @pre context.manifest.content_json contains summary block or defaults to safe counters.
 */

// --- internal_sources_only (backend/src/services/clean_release/stages/internal_sources_only.py)
/**!
 * @brief Verify manifest-declared sources belong to trusted internal registry allowlist.
 * @complexity 5
 * @data_contract Sources -> SourceViolationReport
 * @invariant Any source host outside allowed_hosts yields BLOCKED decision with at least one violation.
 * @layer Domain
 * @side_effect None (read-only validation)
 */

// --- InternalSourcesOnlyStage (backend/src/services/clean_release/stages/internal_sources_only.py)
/**!
 * @brief Enforce internal-source-only policy from trusted registry snapshot.
 * @post Returns PASSED when all hosts are allowed; otherwise BLOCKED and violations captured.
 * @pre context.registry.allowed_hosts is available.
 */

// --- manifest_consistency (backend/src/services/clean_release/stages/manifest_consistency.py)
/**!
 * @brief Ensure run is bound to the exact manifest snapshot and digest used at run creation time.
 * @complexity 5
 * @data_contract RunData -> ConsistencyVerdict
 * @invariant Digest mismatch between run and manifest yields ERROR with blocking violation evidence.
 * @layer Domain
 * @side_effect None (read-only validation)
 */

// --- ManifestConsistencyStage (backend/src/services/clean_release/stages/manifest_consistency.py)
/**!
 * @brief Validate run/manifest linkage consistency.
 * @post Returns PASSED when digests match, otherwise ERROR with one violation.
 * @pre context.run and context.manifest are loaded from repository for same run.
 */

// --- no_external_endpoints (backend/src/services/clean_release/stages/no_external_endpoints.py)
/**!
 * @brief Block manifest payloads that expose external endpoints outside trusted schemes and hosts.
 * @complexity 5
 * @data_contract Endpoints -> EndpointViolationReport
 * @invariant Endpoint outside allowed scheme/host always yields BLOCKED stage decision.
 * @layer Domain
 * @side_effect None (read-only validation)
 */

// --- NoExternalEndpointsStage (backend/src/services/clean_release/stages/no_external_endpoints.py)
/**!
 * @brief Validate endpoint references from manifest against trusted registry.
 * @post Returns PASSED when all endpoints are trusted, otherwise BLOCKED with endpoint violations.
 * @pre context.registry includes allowed hosts and schemes.
 */

// --- dataset_review (backend/src/services/dataset_review/__init__.py)
/**!
 * @brief Provides services for dataset-centered orchestration flow.
 * @layer Service
 */

// --- ClarificationEngine (backend/src/services/dataset_review/clarification_engine.py)
/**!
 * @brief Manage one-question-at-a-time clarification state, deterministic answer persistence, and readiness/finding updates.
 * @complexity 4
 * @data_contract Input[DatasetReviewSession|ClarificationAnswerCommand] -> Output[ClarificationStateResult]
 * @invariant Only one active clarification question may exist at a time; skipped and expert-review items remain unresolved and visible.
 * @layer Domain
 * @post Active clarification payload exposes one highest-priority unresolved question, and each recorded answer is persisted before pointer/readiness mutation.
 * @pre Target session contains a persisted clarification aggregate in the current ownership scope.
 * @rationale Original 635-line file exceeded INV_7 (400-line module limit). Extracted pure helpers into _helpers sub-module.
 * @rejected Keeping all clarification logic in one file because it exceeded the fractal limit.
 * @side_effect Persists clarification answers, question/session states, and related readiness/finding changes.
 */

// --- ClarificationQuestionPayload (backend/src/services/dataset_review/clarification_engine.py)
/**!
 * @brief Typed active-question payload returned to the API layer.
 * @complexity 2
 */

// --- ClarificationStateResult (backend/src/services/dataset_review/clarification_engine.py)
/**!
 * @brief Clarification state result carrying the current session, active payload, and changed findings.
 * @complexity 2
 */

// --- ClarificationAnswerCommand (backend/src/services/dataset_review/clarification_engine.py)
/**!
 * @brief Typed answer command for clarification state mutation.
 * @complexity 2
 */

// --- ClarificationHelpers (backend/src/services/dataset_review/clarification_pkg/_helpers.py)
/**!
 * @brief Pure helper functions for clarification engine — question selection, counting, normalization, finding upsert, and readiness derivation.
 * @complexity 3
 * @layer Domain
 */

// --- select_next_open_question (backend/src/services/dataset_review/clarification_pkg/_helpers.py)
/**!
 * @brief Select the next unresolved question in deterministic priority order.
 * @complexity 2
 */

// --- count_resolved_questions (backend/src/services/dataset_review/clarification_pkg/_helpers.py)
/**!
 * @brief Count questions whose answers fully resolved the ambiguity.
 * @complexity 1
 */

// --- count_remaining_questions (backend/src/services/dataset_review/clarification_pkg/_helpers.py)
/**!
 * @brief Count questions still unresolved or deferred after clarification interaction.
 * @complexity 1
 */

// --- normalize_answer_value (backend/src/services/dataset_review/clarification_pkg/_helpers.py)
/**!
 * @brief Validate and normalize answer payload based on answer kind and active question options.
 * @complexity 2
 */

// --- build_impact_summary (backend/src/services/dataset_review/clarification_pkg/_helpers.py)
/**!
 * @brief Build a compact audit note describing how the clarification answer affects session state.
 * @complexity 1
 */

// --- upsert_clarification_finding (backend/src/services/dataset_review/clarification_pkg/_helpers.py)
/**!
 * @brief Keep one finding per clarification topic aligned with answer outcome and unresolved visibility rules.
 * @complexity 3
 */

// --- derive_readiness_state (backend/src/services/dataset_review/clarification_pkg/_helpers.py)
/**!
 * @brief Recompute readiness after clarification mutation while preserving unresolved visibility semantics.
 * @complexity 2
 */

// --- derive_recommended_action (backend/src/services/dataset_review/clarification_pkg/_helpers.py)
/**!
 * @brief Recompute next-action guidance after clarification mutations.
 * @complexity 2
 */

// --- SessionEventLoggerModule (backend/src/services/dataset_review/event_logger.py)
/**!
 * @brief Persist explicit session mutation events for dataset-review audit trails without weakening ownership or approval invariants.
 * @complexity 4
 * @data_contract Input[SessionEventPayload] -> Output[SessionEvent]
 * @layer Domain
 * @post Every logged event is committed as an explicit, queryable audit record with deterministic event metadata.
 * @pre Caller provides an owned session scope and an authenticated actor identifier for each persisted mutation event.
 * @side_effect Inserts persisted session event rows and emits runtime belief-state logs for audit-sensitive mutations.
 */

// --- SessionEventLoggerImports (backend/src/services/dataset_review/event_logger.py)
/**!
 */

// --- SessionEventPayload (backend/src/services/dataset_review/event_logger.py)
/**!
 * @brief Typed input contract for one persisted dataset-review session audit event.
 * @complexity 2
 */

// --- SessionEventLogger (backend/src/services/dataset_review/event_logger.py)
/**!
 * @brief Persist explicit dataset-review session audit events with meaningful runtime reasoning logs.
 * @complexity 4
 * @data_contract Input[SessionEventPayload] -> Output[SessionEvent]
 * @post Returns the committed session event row with a stable identifier and stored detail payload.
 * @pre The database session is live and payload identifiers are non-empty.
 * @side_effect Writes one audit row to persistence and emits logger.reason/logger.reflect traces.
 */

// --- DatasetReviewOrchestrator (backend/src/services/dataset_review/orchestrator.py)
/**!
 * @brief Coordinate dataset review session startup and lifecycle-safe intake recovery for one authenticated user.
 * @complexity 5
 * @data_contract Input[SessionCommand] -> Output[DatasetReviewSession | CompiledPreview | DatasetRunContext]
 * @invariant Launch is blocked unless a current session has no open blocking findings, all launch-sensitive mappings are approved, and a non-stale Superset-generated compiled preview matches the current input fingerprint.
 * @layer Domain
 * @post state transitions are persisted atomically and emit observable progress for long-running steps.
 * @pre session mutations must execute inside a persisted session boundary scoped to one authenticated user.
 * @rationale Original 1198-line monolith violated INV_7 (400-line module limit). Decomposed into commands and helpers sub-modules while preserving the orchestrator class as the single entry point.
 * @rejected Keeping all orchestration logic in one file because it exceeded the fractal limit by 3x.
 * @side_effect creates task records, updates session aggregates, triggers upstream Superset calls, persists audit artifacts.
 */

// --- OrchestratorCommands (backend/src/services/dataset_review/orchestrator_pkg/_commands.py)
/**!
 * @brief Typed command and result dataclasses for dataset review orchestration boundary.
 * @complexity 2
 * @layer Domain
 */

// --- StartSessionCommand (backend/src/services/dataset_review/orchestrator_pkg/_commands.py)
/**!
 * @brief Typed input contract for starting a dataset review session.
 * @complexity 2
 */

// --- StartSessionResult (backend/src/services/dataset_review/orchestrator_pkg/_commands.py)
/**!
 * @brief Session-start result carrying the persisted session and intake recovery metadata.
 * @complexity 2
 */

// --- PreparePreviewCommand (backend/src/services/dataset_review/orchestrator_pkg/_commands.py)
/**!
 * @brief Typed input contract for compiling one Superset-backed session preview.
 * @complexity 2
 */

// --- PreparePreviewResult (backend/src/services/dataset_review/orchestrator_pkg/_commands.py)
/**!
 * @brief Result contract for one persisted compiled preview attempt.
 * @complexity 2
 */

// --- LaunchDatasetCommand (backend/src/services/dataset_review/orchestrator_pkg/_commands.py)
/**!
 * @brief Typed input contract for launching one dataset-review session into SQL Lab.
 * @complexity 2
 */

// --- LaunchDatasetResult (backend/src/services/dataset_review/orchestrator_pkg/_commands.py)
/**!
 * @brief Launch result carrying immutable run context and any gate blockers.
 * @complexity 2
 */

// --- OrchestratorHelpers (backend/src/services/dataset_review/orchestrator_pkg/_helpers.py)
/**!
 * @brief Pure helper methods extracted from DatasetReviewOrchestrator for INV_7 compliance — snapshot, blockers, fingerprint, recovery bootstrap.
 * @complexity 4
 * @layer Domain
 * @post Helper results are deterministic and do not mutate persistence directly.
 * @pre Caller provides a loaded session aggregate with hydrated child collections.
 */

// --- parse_dataset_selection (backend/src/services/dataset_review/orchestrator_pkg/_helpers.py)
/**!
 * @brief Normalize dataset-selection payload into canonical session references.
 * @complexity 2
 */

// --- build_initial_profile (backend/src/services/dataset_review/orchestrator_pkg/_helpers.py)
/**!
 * @brief Create the first profile snapshot so exports and detail views remain usable immediately after intake.
 * @complexity 2
 */

// --- build_partial_recovery_findings (backend/src/services/dataset_review/orchestrator_pkg/_helpers.py)
/**!
 * @brief Project partial Superset intake recovery into explicit findings without blocking session usability.
 * @complexity 3
 * @post Returns warning-level findings that preserve usable but incomplete state.
 * @pre parsed_context.partial_recovery is true.
 */

// --- extract_effective_filter_value (backend/src/services/dataset_review/orchestrator_pkg/_helpers.py)
/**!
 * @brief Separate normalized filter payload metadata from the user-facing effective filter value.
 * @complexity 2
 */

// --- build_execution_snapshot (backend/src/services/dataset_review/orchestrator_pkg/_helpers.py)
/**!
 * @brief Build effective filters, template params, approvals, and fingerprint for preview and launch gating.
 * @complexity 4
 * @post Returns deterministic execution snapshot for current session state without mutating persistence.
 * @pre Session aggregate includes imported filters, template variables, and current execution mappings.
 */

// --- build_launch_blockers (backend/src/services/dataset_review/orchestrator_pkg/_helpers.py)
/**!
 * @brief Enforce launch gates from findings, approvals, and current preview truth.
 * @complexity 3
 * @post Returns explicit blocker codes for every unmet launch invariant.
 * @pre execution_snapshot was computed from current session state.
 */

// --- get_latest_preview (backend/src/services/dataset_review/orchestrator_pkg/_helpers.py)
/**!
 * @brief Resolve the current latest preview snapshot for one session aggregate.
 * @complexity 2
 */

// --- compute_preview_fingerprint (backend/src/services/dataset_review/orchestrator_pkg/_helpers.py)
/**!
 * @brief Produce deterministic execution fingerprint for preview truth and staleness checks.
 * @complexity 1
 */

// --- SessionRepositoryMutations (backend/src/services/dataset_review/repositories/repository_pkg/_mutations.py)
/**!
 * @brief Persistence mutation operations for dataset review session aggregates — profile/findings, recovery state, preview, run context.
 * @complexity 4
 * @layer Domain
 * @post Session aggregate writes preserve ownership and version semantics.
 * @pre All mutations execute within authenticated request or task scope.
 */

// --- save_profile_and_findings (backend/src/services/dataset_review/repositories/repository_pkg/_mutations.py)
/**!
 * @brief Persist profile state and replace validation findings for an owned session in one transaction.
 * @complexity 4
 * @post stored profile matches the current session and findings are replaced by the supplied collection.
 * @pre session_id belongs to user_id and the supplied profile/findings belong to the same aggregate scope.
 * @side_effect updates profile rows, deletes stale findings, inserts current findings, and commits the transaction.
 */

// --- save_recovery_state (backend/src/services/dataset_review/repositories/repository_pkg/_mutations.py)
/**!
 * @brief Persist imported filters, template variables, and initial execution mappings for one owned session.
 * @complexity 4
 * @post Recovery state persisted to database.
 * @pre session_id belongs to user_id.
 * @side_effect Writes to database.
 */

// --- save_preview (backend/src/services/dataset_review/repositories/repository_pkg/_mutations.py)
/**!
 * @brief Persist a preview snapshot and mark prior session previews stale.
 * @complexity 3
 * @post preview is persisted and the session points to the latest preview identifier.
 * @pre session_id belongs to user_id and preview is prepared for the same session aggregate.
 * @side_effect updates prior preview statuses, inserts a preview row, mutates the parent session, and commits.
 */

// --- save_run_context (backend/src/services/dataset_review/repositories/repository_pkg/_mutations.py)
/**!
 * @brief Persist an immutable launch audit snapshot for an owned session.
 * @complexity 3
 * @post run context is persisted and linked as the latest launch snapshot for the session.
 * @pre session_id belongs to user_id and run_context targets the same aggregate.
 * @side_effect inserts a run-context row, mutates the parent session pointer, and commits.
 */

// --- DatasetReviewSessionRepository (backend/src/services/dataset_review/repositories/session_repository.py)
/**!
 * @brief Persist and retrieve dataset review session aggregates, including readiness, findings, semantic decisions, clarification state, previews, and run contexts.
 * @complexity 5
 * @data_contract Input[SessionMutation] -> Output[PersistedSessionAggregate]
 * @invariant answers, mapping approvals, preview artifacts, and launch snapshots are never attributed to the wrong user or session.
 * @layer Domain
 * @post session aggregate reads are structurally consistent and writes preserve ownership and version semantics.
 * @pre repository operations execute within authenticated request or task scope.
 * @rationale Original 627-line file exceeded INV_7 (400-line module limit). Extracted mutation operations into _mutations sub-module.
 * @rejected Keeping all repository operations in one file because it exceeded the fractal limit.
 * @side_effect reads and writes SQLAlchemy-backed session aggregates.
 */

// --- DatasetReviewSessionVersionConflictError (backend/src/services/dataset_review/repositories/session_repository.py)
/**!
 * @brief Signal optimistic-lock conflicts for dataset review session mutations.
 * @complexity 2
 */

// --- SemanticSourceResolver (backend/src/services/dataset_review/semantic_resolver.py)
/**!
 * @brief Resolve and rank semantic candidates from trusted dictionary-like sources before any inferred fallback.
 * @complexity 4
 * @invariant Manual overrides are never silently replaced by imported, inferred, or AI-generated values.
 * @layer Domain
 * @post candidate ranking follows the configured confidence hierarchy and unresolved fuzzy matches remain reviewable.
 * @pre selected source and target field set must be known.
 * @side_effect may create conflict findings and semantic candidate records.
 */

// --- imports (backend/src/services/dataset_review/semantic_resolver.py)
/**!
 */

// --- DictionaryResolutionResult (backend/src/services/dataset_review/semantic_resolver.py)
/**!
 * @brief Carries field-level dictionary resolution output with explicit review and partial-recovery state.
 * @complexity 2
 */

// --- GitServiceModule (backend/src/services/git/__init__.py)
/**!
 * @brief Composed GitService via multiple inheritance from domain-specific mixins.
 * @complexity 3
 * @layer Infrastructure
 * @rationale Decomposed from monolithic git_service.py (2101 lines) into
 */

// --- GitService (backend/src/services/git/__init__.py)
/**!
 * @brief Composed GitService class providing all Git operations — init, clone, branches, commits, push, pull,
 * @complexity 3
 */

// --- GitServiceBase (backend/src/services/git/_base.py)
/**!
 * @brief Core GitService base class — initialization, path resolution, repo lifecycle (init/delete/get), identity configuration, concurrent locking, and shared HTTP client pool.
 * @complexity 4
 * @layer Infrastructure
 * @rationale Extracted 'git_repos' default into DEFAULT_GIT_REPOS_PATH constant. Fixed typo 'repositorys' → 'repositories' with breaking change warning for existing installations.
 */

// --- GitServiceBranchMixin (backend/src/services/git/_branch.py)
/**!
 * @brief Branch and commit operations for GitService — gitflow branches, list/create/checkout branches, commit changes (all concurrent-safe via per-dashboard locks).
 * @complexity 4
 * @layer Infrastructure
 */

// --- GitServiceGiteaMixin (backend/src/services/git/_gitea.py)
/**!
 * @brief Gitea API operations for GitService — connection testing, repository CRUD, and pull request creation. Uses shared self._http_client for connection pooling.
 * @complexity 4
 * @layer Infrastructure
 */

// --- GitServiceMergeMixin (backend/src/services/git/_merge.py)
/**!
 * @brief Merge operations for GitService — conflict detection, resolution, abort, continue, and direct promote (all concurrent-safe via per-dashboard locks).
 * @complexity 4
 * @layer Infrastructure
 */

// --- GitServiceRemoteMixin (backend/src/services/git/_remote_providers.py)
/**!
 * @brief GitHub and GitLab provider operations for GitService — repository creation and PR/MR creation. Uses shared self._http_client for connection pooling.
 * @complexity 4
 * @layer Infrastructure
 */

// --- GitServiceGithubMixin (backend/src/services/git/_remote_providers.py)
/**!
 * @brief Mixin providing GitHub API operations for GitService.
 * @complexity 3
 */

// --- GitServiceGitlabMixin (backend/src/services/git/_remote_providers.py)
/**!
 * @brief Mixin providing GitLab API operations for GitService.
 * @complexity 3
 */

// --- GitServiceStatusMixin (backend/src/services/git/_status.py)
/**!
 * @brief Status, diff, and commit history operations for GitService (all concurrent-safe via per-dashboard locks).
 * @complexity 4
 * @layer Infrastructure
 */

// --- GitServiceSyncMixin (backend/src/services/git/_sync.py)
/**!
 * @brief Push and pull operations for GitService with origin host auto-alignment (concurrent-safe).
 * @complexity 4
 * @layer Infrastructure
 */

// --- GitServiceUrlMixin (backend/src/services/git/_url.py)
/**!
 * @brief URL helper mixin for GitService — parse, normalize, align, and strip credentials from Git URLs.
 * @complexity 3
 * @layer Infrastructure
 */

// --- health_service (backend/src/services/health_service.py)
/**!
 * @brief Business logic for aggregating dashboard health status from validation records.
 * @complexity 3
 * @layer Service
 */

// --- HealthService (backend/src/services/health_service.py)
/**!
 * @brief Aggregate latest dashboard validation state and manage persisted health report lifecycle.
 * @complexity 4
 * @data_contract Input[Session, Optional[Any]] -> Output[HealthSummaryResponse|bool]
 * @post Exposes health summary aggregation and validation report deletion operations.
 * @pre Service is constructed with a live SQLAlchemy session and optional config manager.
 * @side_effect Maintains in-memory dashboard metadata caches and may coordinate cleanup through collaborators.
 */

// --- llm_prompt_templates (backend/src/services/llm_prompt_templates.py)
/**!
 * @brief Provide default LLM prompt templates and normalization helpers for runtime usage.
 * @complexity 2
 * @invariant All required prompt template keys are always present after normalization.
 * @layer Domain
 */

// --- DEFAULT_LLM_PROMPTS (backend/src/services/llm_prompt_templates.py)
/**!
 * @brief Default prompt templates used by documentation, dashboard validation, and git commit generation.
 * @complexity 2
 */

// --- DEFAULT_LLM_PROVIDER_BINDINGS (backend/src/services/llm_prompt_templates.py)
/**!
 * @brief Default provider binding per task domain.
 * @complexity 2
 */

// --- DEFAULT_LLM_ASSISTANT_SETTINGS (backend/src/services/llm_prompt_templates.py)
/**!
 * @brief Default planner settings for assistant chat intent model/provider resolution.
 * @complexity 2
 */

// --- normalize_llm_settings (backend/src/services/llm_prompt_templates.py)
/**!
 * @brief Ensure llm settings contain stable schema with prompts section and default templates.
 * @complexity 3
 * @post Returned dict contains prompts with all required template keys.
 * @pre llm_settings is dictionary-like value or None.
 */

// --- is_multimodal_model (backend/src/services/llm_prompt_templates.py)
/**!
 * @brief Heuristically determine whether model supports image input required for dashboard validation.
 * @complexity 3
 * @deprecated Use the explicit `db_provider.is_multimodal` flag instead (see migration 9f8e7d6c5b4a).
 * @rationale Added import warnings + warnings.warn(DeprecationWarning) to is_multimodal_model as a deprecation shim.
 */

// --- resolve_bound_provider_id (backend/src/services/llm_prompt_templates.py)
/**!
 * @brief Resolve provider id configured for a task binding with fallback to default provider.
 * @complexity 3
 * @post Returns configured provider id or fallback id/empty string when not defined.
 * @pre llm_settings is normalized or raw dict from config.
 */

// --- render_prompt (backend/src/services/llm_prompt_templates.py)
/**!
 * @brief Render prompt template using deterministic placeholder replacement with graceful fallback.
 * @complexity 3
 * @post Returns rendered prompt text with known placeholders substituted. Warns about unfilled placeholders.
 * @pre template is a string and variables values are already stringifiable.
 */

// --- llm_provider (backend/src/services/llm_provider.py)
/**!
 * @brief Service for managing LLM provider configurations with encrypted API keys.
 * @complexity 3
 * @layer Domain
 */

// --- mask_api_key (backend/src/services/llm_provider.py)
/**!
 * @brief Mask an API key for safe display, showing first 4 and last 4 characters.
 * @complexity 2
 * @post Returns "****" for very short keys; "{first 2}...{last 2}" for <=8 chars;
 * @pre api_key is a plaintext string or None.
 */

// --- is_masked_or_placeholder (backend/src/services/llm_provider.py)
/**!
 * @brief Predicate: True when api_key is None, empty, "********", or contains "...".
 * @complexity 2
 * @post Returns True only for non-real-key values.
 * @pre api_key can be None.
 */

// --- _require_fernet_key (backend/src/services/llm_provider.py)
/**!
 * @brief Load and validate the Fernet key used for secret encryption.
 * @complexity 5
 * @data_contract Input[ENCRYPTION_KEY:str] -> Output[bytes]
 * @invariant Encryption initialization never falls back to a hardcoded secret.
 * @post Returns validated key bytes ready for Fernet initialization.
 * @pre ENCRYPTION_KEY environment variable must be set to a valid Fernet key.
 * @side_effect Emits belief-state logs for missing or invalid encryption configuration.
 */

// --- EncryptionManager (backend/src/services/llm_provider.py)
/**!
 * @brief Handles encryption and decryption of sensitive data like API keys.
 * @complexity 5
 * @data_contract Input[str] -> Output[str]
 * @invariant Uses only a validated secret key from environment.
 * @post Manager exposes reversible encrypt/decrypt operations for persisted secrets.
 * @pre ENCRYPTION_KEY is configured with a valid Fernet key before instantiation.
 * @side_effect Initializes Fernet cryptography state from process environment.
 * @test_contract EncryptionManagerModel ->
 */

// --- LLMProviderService (backend/src/services/llm_provider.py)
/**!
 * @brief Service to manage LLM provider lifecycle.
 * @complexity 3
 */

// --- MaintenancePackage (backend/src/services/maintenance/__init__.py)
/**!
 * @brief Maintenance Banner service package. Re-exports all public orchestrators and helpers.
 * @complexity 1
 * @layer Service
 */

// --- MaintenanceBannerRenderer (backend/src/services/maintenance/_banner_renderer.py)
/**!
 * @brief Banner text rendering and rebuild helpers. Build aggregated markdown from
 * @complexity 3
 */

// --- build_banner_text (backend/src/services/maintenance/_banner_renderer.py)
/**!
 * @brief Build aggregated banner markdown text from events using settings template.
 * @complexity 3
 */

// --- _build_banner_text_for_dashboard (backend/src/services/maintenance/_banner_renderer.py)
/**!
 * @brief Build aggregated banner text for a banner based on all active events linked to it.
 * @complexity 2
 */

// --- rebuild_banner (backend/src/services/maintenance/_banner_renderer.py)
/**!
 * @brief Rebuild aggregated banner text for a banner and update the Superset chart.
 * @complexity 3
 */

// --- MaintenanceChartManager (backend/src/services/maintenance/_chart_manager.py)
/**!
 * @brief Chart operations for maintenance banners: create/get banner charts, process
 * @complexity 3
 */

// --- ensure_banner_chart (backend/src/services/maintenance/_chart_manager.py)
/**!
 * @brief Get or create a MaintenanceDashboardBanner for a dashboard in the target environment.
 * @complexity 3
 */

// --- _process_dashboards_for_start (backend/src/services/maintenance/_chart_manager.py)
/**!
 * @brief Process each dashboard for a start maintenance event: ensure banner chart,
 * @complexity 3
 */

// --- _process_states_for_end (backend/src/services/maintenance/_chart_manager.py)
/**!
 * @brief Process each dashboard state for an end maintenance event: if other events
 * @complexity 3
 */

// --- MaintenanceDashboardScanner (backend/src/services/maintenance/_dashboard_scanner.py)
/**!
 * @brief Dashboard discovery and filtering helpers for maintenance banner feature.
 * @complexity 3
 */

// --- find_affected_dashboards (backend/src/services/maintenance/_dashboard_scanner.py)
/**!
 * @brief Find all dashboard IDs whose datasets reference any of the given tables.
 * @complexity 3
 */

// --- _get_linked_dashboards (backend/src/services/maintenance/_dashboard_scanner.py)
/**!
 * @brief Fetch linked dashboards for a dataset from Superset.
 * @complexity 2
 * @side_effect Calls Superset API.
 */

// --- _apply_dashboard_filters (backend/src/services/maintenance/_dashboard_scanner.py)
/**!
 * @brief Apply scope (published/draft/all), excluded, and forced filters from settings.
 * @complexity 2
 */

// --- _resolve_dashboard_title (backend/src/services/maintenance/_dashboard_scanner.py)
/**!
 * @brief Resolve dashboard title from Superset by ID.
 * @complexity 2
 */

// --- MaintenanceOrchestrators (backend/src/services/maintenance/_orchestrators.py)
/**!
 * @brief C4 orchestrators for maintenance event lifecycle: start, end, end-all.
 * @complexity 4
 */

// --- build_idempotency_key (backend/src/services/maintenance/_orchestrators.py)
/**!
 * @brief Build idempotency key from (tables, start_time, end_time). Sorted lowercased tables, ISO timestamps.
 * @complexity 2
 * @post Returns a tuple of (frozenset(str), str|None, str|None) for DB comparison.
 * @pre tables is a list of strings. start_time is a datetime or None. end_time is a datetime or None.
 * @rationale message is intentionally excluded from key per spec — different message with same tables/times = same event.
 */

// --- mapping_service (backend/src/services/mapping_service.py)
/**!
 * @brief Orchestrates database fetching and fuzzy matching suggestions.
 * @complexity 5
 * @data_contract Input[source_env_id: str, target_env_id: str] -> Output[List[Dict]]
 * @invariant Suggestions are based on database names.
 * @layer Service
 * @post Exposes stateless mapping suggestion orchestration over configured environments.
 * @pre source/target environment identifiers are provided by caller.
 * @side_effect Performs remote metadata reads through Superset API clients.
 */

// --- MappingService (backend/src/services/mapping_service.py)
/**!
 * @brief Service for handling database mapping logic.
 * @complexity 3
 * @data_contract Input[config_manager] -> Output[List[Dict]]
 * @post Provides client resolution and mapping suggestion methods.
 * @pre config_manager exposes get_environments() with environment objects containing id.
 * @side_effect Instantiates Superset clients and performs upstream metadata reads.
 */

// --- notifications (backend/src/services/notifications/__init__.py)
/**!
 * @brief Notification service package root.
 * @complexity 1
 */

// --- providers (backend/src/services/notifications/providers.py)
/**!
 * @brief Defines abstract base and concrete implementations for external notification delivery.
 * @complexity 5
 * @data_contract Input[target, subject, body, context?] -> Output[bool]
 * @invariant Sensitive credentials must be handled via encrypted config.
 * @layer Infrastructure
 * @post Each provider exposes async send contract returning boolean delivery outcome.
 * @pre Provider configuration dictionaries are supplied by trusted configuration sources.
 * @side_effect Performs outbound network I/O to SMTP or HTTP endpoints.
 */

// --- NotificationProvider (backend/src/services/notifications/providers.py)
/**!
 * @brief Abstract base class for all notification providers.
 * @complexity 2
 */

// --- SMTPProvider (backend/src/services/notifications/providers.py)
/**!
 * @brief Delivers notifications via SMTP.
 * @complexity 3
 */

// --- TelegramProvider (backend/src/services/notifications/providers.py)
/**!
 * @brief Delivers notifications via Telegram Bot API.
 * @complexity 3
 */

// --- SlackProvider (backend/src/services/notifications/providers.py)
/**!
 * @brief Delivers notifications via Slack Webhooks or API.
 * @complexity 3
 */

// --- service (backend/src/services/notifications/service.py)
/**!
 * @brief Orchestrates notification routing based on user preferences and policy context.
 * @complexity 5
 * @data_contract NotificationChannelConfig -> NotificationRecipient
 * @invariant NotificationService maintains singleton pattern for per-channel notifications
 * @layer Domain
 * @post Notification dispatched via configured providers
 * @pre channel_config is loaded
 * @side_effect Sends notifications via configured providers
 */

// --- NotificationService (backend/src/services/notifications/service.py)
/**!
 * @brief Routes validation reports to appropriate users and channels.
 * @complexity 4
 * @data_contract Input[ValidationRecord, Optional[ValidationPolicy], Optional[BackgroundTasks]] -> Output[None]
 * @post Service can resolve targets and dispatch provider sends without mutating validation records.
 * @pre Service receives a live DB session and configuration manager with notification payload settings.
 * @side_effect Reads notification configuration, queries user preferences, and dispatches provider I/O.
 */

// --- profile_preference_service (backend/src/services/profile_preference_service.py)
/**!
 * @brief Profile preference persistence — read, update, and normalize user dashboard filter preferences
 * @complexity 4
 */

// --- ProfilePreferenceService (backend/src/services/profile_preference_service.py)
/**!
 * @brief Handles profile preference persistence, validation, and token encryption.
 * @complexity 4
 * @post Preference CRUD operations are user-scoped and return normalized ProfilePreferenceResponse.
 * @pre db session is active.
 */

// --- get_my_preference (backend/src/services/profile_preference_service.py)
/**!
 * @brief Return current user's persisted preference or default non-configured view.
 * @post Returned payload belongs to current_user only.
 * @pre current_user is authenticated.
 */

// --- get_dashboard_filter_binding (backend/src/services/profile_preference_service.py)
/**!
 * @brief Return only dashboard-filter fields required by dashboards listing hot path.
 * @post Returns normalized username and profile-default filter toggles without security summary expansion.
 * @pre current_user is authenticated.
 */

// --- update_my_preference (backend/src/services/profile_preference_service.py)
/**!
 * @brief Validate and persist current user's profile preference in self-scoped mode.
 * @post Preference row for current_user is created/updated when validation passes.
 * @pre current_user is authenticated and payload is provided.
 */

// --- _to_preference_payload (backend/src/services/profile_preference_service.py)
/**!
 * @brief Map ORM preference row to API DTO with token metadata.
 * @post Returns normalized ProfilePreference object.
 * @pre preference row can contain nullable optional fields.
 */

// --- _build_default_preference (backend/src/services/profile_preference_service.py)
/**!
 * @brief Delegate to ProfileUtils.build_default_preference.
 * @complexity 1
 */

// --- _get_preference_row (backend/src/services/profile_preference_service.py)
/**!
 * @brief Return persisted preference row for user or None.
 * @complexity 2
 */

// --- _get_or_create_preference_row (backend/src/services/profile_preference_service.py)
/**!
 * @brief Return existing preference row or create new unsaved row.
 * @complexity 2
 */

// --- profile_service (backend/src/services/profile_service.py)
/**!
 * @brief Composite facade orchestrating profile preference persistence, Superset account lookup,
 * @complexity 5
 */

// --- ProfileService (backend/src/services/profile_service.py)
/**!
 * @brief Facade that composes ProfilePreferenceService, SupersetLookupService, and
 * @complexity 4
 */

// --- ProfileUtils (backend/src/services/profile_utils.py)
/**!
 * @brief Pure utility helpers for profile data sanitization, normalization, and secret masking.
 * @complexity 2
 */

// --- ProfileValidationError (backend/src/services/profile_utils.py)
/**!
 * @brief Domain validation error for profile preference update requests.
 * @complexity 2
 */

// --- EnvironmentNotFoundError (backend/src/services/profile_utils.py)
/**!
 * @brief Raised when environment_id from lookup request is unknown in app configuration.
 * @complexity 2
 */

// --- ProfileAuthorizationError (backend/src/services/profile_utils.py)
/**!
 * @brief Raised when caller attempts cross-user preference mutation.
 * @complexity 2
 */

// --- sanitize_text (backend/src/services/profile_utils.py)
/**!
 * @brief Normalize optional text into trimmed form or None.
 * @complexity 1
 */

// --- sanitize_secret (backend/src/services/profile_utils.py)
/**!
 * @brief Normalize secret input into trimmed form or None.
 * @complexity 1
 */

// --- sanitize_username (backend/src/services/profile_utils.py)
/**!
 * @brief Normalize raw username into trimmed form or None for empty input.
 * @complexity 1
 */

// --- normalize_username (backend/src/services/profile_utils.py)
/**!
 * @brief Apply deterministic trim+lower normalization for actor matching.
 * @complexity 1
 */

// --- normalize_start_page (backend/src/services/profile_utils.py)
/**!
 * @brief Normalize supported start page aliases to canonical values.
 * @complexity 1
 */

// --- normalize_density (backend/src/services/profile_utils.py)
/**!
 * @brief Normalize supported density aliases to canonical values.
 * @complexity 1
 */

// --- mask_secret_value (backend/src/services/profile_utils.py)
/**!
 * @brief Build a safe display value for sensitive secrets.
 * @complexity 1
 */

// --- validate_update_payload (backend/src/services/profile_utils.py)
/**!
 * @brief Validate username/toggle constraints for preference mutation.
 * @complexity 2
 * @post Returns validation errors list; empty list means valid.
 */

// --- build_default_preference (backend/src/services/profile_utils.py)
/**!
 * @brief Build non-persisted default preference DTO for unconfigured users.
 * @complexity 2
 */

// --- normalize_owner_tokens (backend/src/services/profile_utils.py)
/**!
 * @brief Normalize owners payload into deduplicated lower-cased tokens.
 * @complexity 2
 */

// --- rbac_permission_catalog (backend/src/services/rbac_permission_catalog.py)
/**!
 * @brief Discovers declared RBAC permissions from API routes/plugins and synchronizes them into auth database.
 * @complexity 2
 */

// --- HAS_PERMISSION_PATTERN (backend/src/services/rbac_permission_catalog.py)
/**!
 * @brief Regex pattern for extracting has_permission("resource", "ACTION") declarations.
 */

// --- ROUTES_DIR (backend/src/services/rbac_permission_catalog.py)
/**!
 * @brief Absolute directory path where API route RBAC declarations are defined.
 */

// --- _iter_route_files (backend/src/services/rbac_permission_catalog.py)
/**!
 * @brief Iterates API route files that may contain RBAC declarations.
 * @complexity 4
 * @post Yields Python files excluding test and cache directories.
 * @pre ROUTES_DIR points to backend/src/api/routes.
 */

// --- _discover_route_permissions (backend/src/services/rbac_permission_catalog.py)
/**!
 * @brief Extracts explicit has_permission declarations from API route source code.
 * @complexity 4
 * @post Returns unique set of (resource, action) pairs declared in route guards.
 * @pre Route files are readable UTF-8 text files.
 */

// --- _discover_route_permissions_cached (backend/src/services/rbac_permission_catalog.py)
/**!
 * @brief Cache route permission discovery because route source files are static during normal runtime.
 * @complexity 4
 * @post Returns stable discovered route permission pairs without repeated filesystem scans.
 * @pre None.
 */

// --- _discover_plugin_execute_permissions (backend/src/services/rbac_permission_catalog.py)
/**!
 * @brief Derives dynamic task permissions of form plugin:{plugin_id}:EXECUTE from plugin registry.
 * @complexity 4
 * @post Returns unique plugin EXECUTE permissions if loader is available.
 * @pre plugin_loader is optional and may expose get_all_plugin_configs.
 */

// --- _discover_plugin_execute_permissions_cached (backend/src/services/rbac_permission_catalog.py)
/**!
 * @brief Cache dynamic plugin EXECUTE permission pairs by normalized plugin id tuple.
 * @complexity 4
 * @post Returns stable permission tuple without repeated plugin catalog expansion.
 * @pre plugin_ids is a deterministic tuple of plugin ids.
 */

// --- discover_declared_permissions (backend/src/services/rbac_permission_catalog.py)
/**!
 * @brief Builds canonical RBAC permission catalog from routes and plugin registry.
 * @complexity 4
 * @post Returns union of route-declared and dynamic plugin EXECUTE permissions.
 * @pre plugin_loader may be provided for dynamic task plugin permission discovery.
 */

// --- sync_permission_catalog (backend/src/services/rbac_permission_catalog.py)
/**!
 * @brief Persists missing RBAC permission pairs into auth database.
 * @complexity 4
 * @post Missing permissions are inserted; existing permissions remain untouched.
 * @pre declared_permissions is an iterable of (resource, action) tuples.
 * @side_effect Commits auth database transaction when new permissions are added.
 */

// --- reports (backend/src/services/reports/__init__.py)
/**!
 * @brief Report service package root.
 */

// --- normalizer (backend/src/services/reports/normalizer.py)
/**!
 * @brief Convert task manager task objects into canonical unified TaskReport entities with deterministic fallback behavior.
 * @complexity 5
 * @data_contract ReportRow -> NormalizerInput; session_id -> valid UUID
 * @invariant Normalizer instance maintains consistent field order
 * @layer Domain
 * @post Returns Normalizer output with normalized fields
 * @pre session is active and valid
 * @side_effect Read-only database operations
 */

// --- status_to_report_status (backend/src/services/reports/normalizer.py)
/**!
 * @brief Normalize internal task status to canonical report status.
 * @post Always returns one of canonical ReportStatus values.
 * @pre status may be known or unknown string/enum value.
 */

// --- build_summary (backend/src/services/reports/normalizer.py)
/**!
 * @brief Build deterministic user-facing summary from task payload and status.
 * @post Returns non-empty summary text.
 * @pre report_status is canonical; plugin_id may be unknown.
 */

// --- extract_error_context (backend/src/services/reports/normalizer.py)
/**!
 * @brief Extract normalized error context and next actions for failed/partial reports.
 * @post Returns ErrorContext for failed/partial when context exists; otherwise None.
 * @pre task is a valid Task object.
 */

// --- normalize_task_report (backend/src/services/reports/normalizer.py)
/**!
 * @brief Convert one Task to canonical TaskReport envelope.
 * @post Returns TaskReport with required fields and deterministic fallback behavior.
 * @pre task has valid id and plugin_id fields.
 * @test_contract NormalizeTaskReport ->
 */

// --- report_service (backend/src/services/reports/report_service.py)
/**!
 * @brief Aggregate, normalize, filter, and paginate task reports for unified list/detail API use cases.
 * @complexity 5
 * @data_contract ReportQuery -> ReportRow; session_id -> valid UUID
 * @invariant ReportService maintains consistent report structure
 * @layer Domain
 * @post Returns Report with generated summary
 * @pre session is active and valid
 * @side_effect Read-only database operations; logs report generation
 */

// --- ReportsService (backend/src/services/reports/report_service.py)
/**!
 * @brief Service layer for list/detail report retrieval and normalization.
 * @complexity 5
 * @data_contract Input[TaskManager, Optional[CleanReleaseRepository], ReportQuery|report_id] -> Output[ReportCollection|ReportDetailView|None]
 * @invariant Service methods are read-only over task history source.
 * @post Provides deterministic list/detail report responses.
 * @pre TaskManager dependency is initialized.
 * @side_effect Reads task history and optional clean-release repository state without mutating source records.
 * @test_contract ReportsServiceModel ->
 */

// --- type_profiles (backend/src/services/reports/type_profiles.py)
/**!
 * @brief Deterministic mapping of plugin/task identifiers to canonical report task types and fallback profile metadata.
 * @complexity 2
 */

// --- PLUGIN_TO_TASK_TYPE (backend/src/services/reports/type_profiles.py)
/**!
 * @brief Maps plugin identifiers to normalized report task types.
 */

// --- TASK_TYPE_PROFILES (backend/src/services/reports/type_profiles.py)
/**!
 * @brief Profile metadata registry for each normalized task type.
 */

// --- resolve_task_type (backend/src/services/reports/type_profiles.py)
/**!
 * @brief Resolve canonical task type from plugin/task identifier with guaranteed fallback.
 * @post Always returns one of TaskType enum values.
 * @pre plugin_id may be None or unknown.
 * @test_contract ResolveTaskType ->
 */

// --- get_type_profile (backend/src/services/reports/type_profiles.py)
/**!
 * @brief Return deterministic profile metadata for a task type.
 * @post Returns a profile dict and never raises for unknown types.
 * @pre task_type may be known or unknown.
 * @test_contract GetTypeProfile ->
 */

// --- ResourceServiceModule (backend/src/services/resource_service.py)
/**!
 * @brief Shared service for fetching resource data with Git status and task status
 * @complexity 5
 * @data_contract ResourceQuery -> ResourceStatusSummary
 * @invariant All resources include metadata about their current state
 * @layer Service
 * @side_effect Queries multiple backends for status
 */

// --- ResourceService (backend/src/services/resource_service.py)
/**!
 * @brief Provides centralized access to resource data with enhanced metadata
 * @complexity 3
 */

// --- security_badge_service (backend/src/services/security_badge_service.py)
/**!
 * @brief Builds security summary and permission badges for profile UI — role extraction,
 * @complexity 4
 */

// --- SecurityBadgeService (backend/src/services/security_badge_service.py)
/**!
 * @brief Builds security summary with role names and permission badges for profile UI display.
 * @complexity 4
 * @post build_security_summary returns ProfileSecuritySummary with deterministic sorted permissions.
 * @pre plugin_loader may be None for degraded permission discovery.
 */

// --- build_security_summary (backend/src/services/security_badge_service.py)
/**!
 * @brief Build read-only security snapshot with role and permission badges.
 * @post Returns deterministic security projection for profile UI.
 * @pre current_user is authenticated.
 */

// --- _collect_user_permission_pairs (backend/src/services/security_badge_service.py)
/**!
 * @brief Collect effective permission tuples from current user's roles.
 * @post Returns unique normalized (resource, ACTION) tuples.
 * @pre current_user can include role/permission graph.
 */

// --- _format_permission_key (backend/src/services/security_badge_service.py)
/**!
 * @brief Convert normalized permission pair to compact UI key.
 * @complexity 1
 */

// --- SqlTableExtractorModule (backend/src/services/sql_table_extractor.py)
/**!
 * @brief Three-phase SQL+Jinja table name extractor for virtual datasets as per FR-003.
 * @complexity 2
 */

// --- detect_jinja_spans (backend/src/services/sql_table_extractor.py)
/**!
 * @brief Phase 1: Split raw SQL text into Jinja spans and SQL spans.
 * @complexity 2
 * @post Returns a list of (span_type: str, text: str) tuples.
 * @pre raw_sql is a string (possibly empty).
 */

// --- extract_tables_from_jinja (backend/src/services/sql_table_extractor.py)
/**!
 * @brief Phase 2: Extract "schema.table" references from Jinja string values.
 * @complexity 2
 */

// --- is_string_literal (backend/src/services/sql_table_extractor.py)
/**!
 * @brief Check if a sqlparse Token is a string literal (not a schema.table identifier).
 * @complexity 1
 * @post Returns True if the token is a string/Single/Literal.String.
 * @pre token is a sqlparse Token.
 */

// --- extract_tables_from_sql_span (backend/src/services/sql_table_extractor.py)
/**!
 * @brief Phase 3: Extract schema.table references from SQL text using regex + sqlparse filtering.
 * @complexity 2
 */

// --- extract_tables_from_sql (backend/src/services/sql_table_extractor.py)
/**!
 * @brief Three-phase entry point: extract all schema.table references from raw SQL+Jinja text.
 * @complexity 2
 * @post Returns a set of lowercased fully-qualified table names (schema.table format).
 * @pre raw_sql is a string (possibly empty).
 */

// --- superset_lookup_service (backend/src/services/superset_lookup_service.py)
/**!
 * @brief Environment-scoped Superset account lookup with degradation fallback for network failures.
 * @complexity 4
 * @layer Domain
 * @rationale Extracted from ProfileService to satisfy INV_7. Superset account lookup has distinct
 */

// --- SupersetLookupService (backend/src/services/superset_lookup_service.py)
/**!
 * @brief Resolves environments and queries Superset users in selected environment,
 * @complexity 4
 */

// --- _resolve_environment (backend/src/services/superset_lookup_service.py)
/**!
 * @brief Resolve environment model from configured environments by id.
 * @complexity 2
 * @post Returns environment object when found else None.
 * @pre environment_id is provided.
 */

// --- ValidationRunService (backend/src/services/validation_run_service.py)
/**!
 * @brief Business logic for validation run queries: list, detail, delete.
 * @complexity 3
 * @layer Service
 */

// --- _resolve_task_name (backend/src/services/validation_run_service.py)
/**!
 * @complexity 2
 */

// --- ValidationService (backend/src/services/validation_service.py)
/**!
 * @brief Business logic for validation task CRUD and trigger-run.
 * @complexity 3
 * @layer Service
 */

// --- ValidationTaskService (backend/src/services/validation_service.py)
/**!
 * @brief Validation task (policy) CRUD with provider validation and trigger-run.
 * @complexity 4
 * @rationale Service-layer class for validation task CRUD with provider validation and trigger-run. Separates API layer concerns from business logic; enables unit testing without HTTP.
 * @rejected Embedding CRUD in route handlers rejected — would duplicate validation logic across endpoints; centralized service ensures consistent provider/environment validation before persistence.
 */

// --- _validate_provider (backend/src/services/validation_service.py)
/**!
 * @complexity 2
 * @rationale Centralizes multimodal LLM provider check so all task operations (create, update, trigger) share the same validation gate. Uses LLMProviderService for reuse.
 * @rejected Duplicating multimodal check in each caller rejected — would create maintenance burden if provider validation rules change or error messages need updating.
 */

// --- _validate_environment (backend/src/services/validation_service.py)
/**!
 * @complexity 1
 */

// --- _policy_to_response (backend/src/services/validation_service.py)
/**!
 * @complexity 2
 */

// --- TestSessionConfig (backend/tests/conftest.py)
/**!
 * @brief Shared pytest fixtures and session configuration for backend tests.
 * @complexity 2
 * @post Database tables exist before test session executes.
 * @pre All test modules use sys.path patching to import from src/.
 * @rationale AUTH_SECRET_KEY/AUTH_DATABASE_URL/DATABASE_URL/DEV_MODE must be set before
 */

// --- TestArchiveParser (backend/tests/core/migration/test_archive_parser.py)
/**!
 * @brief Unit tests for MigrationArchiveParser ZIP extraction contract.
 * @complexity 2
 * @layer Domain
 */

// --- test_extract_objects_from_zip_collects_all_types (backend/tests/core/migration/test_archive_parser.py)
/**!
 * @brief Verify archive parser collects dashboard/chart/dataset YAML objects into typed buckets.
 * @complexity 2
 * @test_contract zip_archive_fixture -> typed dashboard/chart/dataset extraction buckets
 * @test_edge external_fail -> Corrupt archive would fail extraction before typed buckets are returned.
 * @test_scenario archive_with_supported_objects_extracts_all_types -> One YAML file per supported type lands in matching bucket.
 */

// --- TestDryRunOrchestrator (backend/tests/core/migration/test_dry_run_orchestrator.py)
/**!
 * @brief Unit tests for MigrationDryRunService diff and risk computation contracts.
 * @complexity 2
 * @layer Domain
 */

// --- _load_fixture (backend/tests/core/migration/test_dry_run_orchestrator.py)
/**!
 * @brief Load canonical migration dry-run fixture payload used by deterministic orchestration assertions.
 * @complexity 2
 */

// --- test_migration_dry_run_service_builds_diff_and_risk (backend/tests/core/migration/test_dry_run_orchestrator.py)
/**!
 * @brief Verify dry-run orchestration returns stable diff summary and required risk codes.
 * @complexity 2
 * @test_contract dry_run_result_contract -> {
 * @test_edge external_fail -> Engine transform stub failure would stop result production.
 * @test_invariant dry_run_result_contract_matches_fixture -> VERIFIED_BY: [dry_run_builds_diff_and_risk]
 * @test_scenario dry_run_builds_diff_and_risk -> Stable diff summary and required risk codes are returned.
 */

// --- test_git_service_get_repo_path_guard (backend/tests/core/test_defensive_guards.py)
/**!
 * @complexity 2
 */

// --- test_git_service_get_repo_path_recreates_base_dir (backend/tests/core/test_defensive_guards.py)
/**!
 * @complexity 2
 */

// --- test_superset_client_import_dashboard_guard (backend/tests/core/test_defensive_guards.py)
/**!
 * @complexity 2
 */

// --- test_git_service_init_repo_reclones_when_path_is_not_a_git_repo (backend/tests/core/test_defensive_guards.py)
/**!
 * @complexity 2
 */

// --- test_git_service_ensure_gitflow_branches_creates_and_pushes_missing_defaults (backend/tests/core/test_defensive_guards.py)
/**!
 * @complexity 2
 */

// --- test_git_service_configure_identity_updates_repo_local_config (backend/tests/core/test_defensive_guards.py)
/**!
 * @complexity 2
 */

// --- TestGitServiceGiteaPr (backend/tests/core/test_git_service_gitea_pr.py)
/**!
 * @brief Validate Gitea PR creation fallback behavior when configured server URL is stale.
 * @complexity 2
 * @invariant A 404 from primary Gitea URL retries once against remote-url host when different.
 * @layer Domain
 * @semantics tests, git, gitea, pull_request, fallback
 */

// --- test_derive_server_url_from_remote_strips_credentials (backend/tests/core/test_git_service_gitea_pr.py)
/**!
 * @brief Ensure helper returns host base URL and removes embedded credentials.
 * @complexity 2
 * @post Result is scheme+host only.
 * @pre remote_url is an https URL with username/token.
 */

// --- test_create_gitea_pull_request_retries_with_remote_host_on_404 (backend/tests/core/test_git_service_gitea_pr.py)
/**!
 * @brief Verify create_gitea_pull_request retries with remote URL host after primary 404.
 * @complexity 2
 * @post Method returns success payload from fallback request.
 * @pre primary server_url differs from remote_url host.
 */

// --- test_create_gitea_pull_request_returns_branch_error_when_target_missing (backend/tests/core/test_git_service_gitea_pr.py)
/**!
 * @brief Ensure Gitea 404 on PR creation is mapped to actionable target-branch validation error.
 * @complexity 2
 * @post Service raises HTTPException 400 with explicit missing target branch message.
 * @pre PR create call returns 404 and target branch is absent.
 */

// --- TestMappingService (backend/tests/core/test_mapping_service.py)
/**!
 * @brief Unit tests for the IdMappingService matching UUIDs to integer IDs.
 * @complexity 2
 * @layer Domain
 */

// --- test_sync_environment_upserts_correctly (backend/tests/core/test_mapping_service.py)
/**!
 * @complexity 2
 */

// --- test_get_remote_id_returns_integer (backend/tests/core/test_mapping_service.py)
/**!
 * @complexity 2
 */

// --- test_get_remote_ids_batch_returns_dict (backend/tests/core/test_mapping_service.py)
/**!
 * @complexity 2
 */

// --- test_sync_environment_updates_existing_mapping (backend/tests/core/test_mapping_service.py)
/**!
 * @complexity 2
 */

// --- test_sync_environment_skips_resources_without_uuid (backend/tests/core/test_mapping_service.py)
/**!
 * @complexity 2
 */

// --- test_sync_environment_handles_api_error_gracefully (backend/tests/core/test_mapping_service.py)
/**!
 * @complexity 2
 */

// --- test_get_remote_id_returns_none_for_missing (backend/tests/core/test_mapping_service.py)
/**!
 * @complexity 2
 */

// --- test_get_remote_ids_batch_returns_empty_for_empty_input (backend/tests/core/test_mapping_service.py)
/**!
 * @complexity 2
 */

// --- test_mapping_service_alignment_with_test_data (backend/tests/core/test_mapping_service.py)
/**!
 * @complexity 2
 */

// --- test_sync_environment_requires_existing_env (backend/tests/core/test_mapping_service.py)
/**!
 * @complexity 2
 */

// --- test_sync_environment_deletes_stale_mappings (backend/tests/core/test_mapping_service.py)
/**!
 * @complexity 2
 */

// --- TestMigrationEngine (backend/tests/core/test_migration_engine.py)
/**!
 * @brief Unit tests for MigrationEngine's cross-filter patching algorithms.
 * @complexity 2
 * @layer Domain
 */

// --- MockMappingService (backend/tests/core/test_migration_engine.py)
/**!
 * @brief Deterministic mapping service double for native filter ID remapping scenarios.
 * @complexity 2
 * @invariant Returns mappings only for requested UUID keys present in seeded map.
 * @invariant_violation resource_type parameter is silently ignored. Lookups are UUID-only; chart and dataset UUIDs share the same namespace. Tests that mix resource types will produce false positives.
 */

// --- _write_dashboard_yaml (backend/tests/core/test_migration_engine.py)
/**!
 * @brief Serialize dashboard metadata into YAML fixture with json_metadata payload for patch tests.
 * @complexity 2
 */

// --- test_patch_dashboard_metadata_replaces_chart_ids (backend/tests/core/test_migration_engine.py)
/**!
 * @brief Verify native filter target chartId values are remapped via mapping service results.
 * @complexity 2
 */

// --- test_patch_dashboard_metadata_replaces_dataset_ids (backend/tests/core/test_migration_engine.py)
/**!
 * @brief Verify native filter target datasetId values are remapped via mapping service results.
 * @complexity 2
 */

// --- test_patch_dashboard_metadata_skips_when_no_metadata (backend/tests/core/test_migration_engine.py)
/**!
 * @brief Ensure dashboard files without json_metadata are left unchanged by metadata patching.
 * @complexity 2
 */

// --- test_patch_dashboard_metadata_handles_missing_targets (backend/tests/core/test_migration_engine.py)
/**!
 * @brief Verify patching updates mapped targets while preserving unmapped native filter IDs.
 * @complexity 2
 */

// --- test_extract_chart_uuids_from_archive (backend/tests/core/test_migration_engine.py)
/**!
 * @brief Verify chart archive scan returns complete local chart id-to-uuid mapping.
 * @complexity 2
 */

// --- test_transform_yaml_replaces_database_uuid (backend/tests/core/test_migration_engine.py)
/**!
 * @brief Ensure dataset YAML database_uuid fields are replaced when source UUID mapping exists.
 * @complexity 2
 */

// --- test_transform_yaml_ignores_unmapped_uuid (backend/tests/core/test_migration_engine.py)
/**!
 * @brief Ensure transform_yaml leaves dataset files untouched when database_uuid is not mapped.
 * @complexity 2
 */

// --- test_transform_zip_end_to_end (backend/tests/core/test_migration_engine.py)
/**!
 * @brief Validate full ZIP transform pipeline remaps datasets and dashboard cross-filter chart IDs.
 * @complexity 2
 */

// --- test_transform_zip_invalid_path (backend/tests/core/test_migration_engine.py)
/**!
 * @brief Verify transform_zip returns False when source archive path does not exist.
 * @complexity 2
 */

// --- test_transform_yaml_nonexistent_file (backend/tests/core/test_migration_engine.py)
/**!
 * @brief Verify transform_yaml raises FileNotFoundError for missing YAML source files.
 * @complexity 2
 */

// --- test_clean_release_cli (backend/tests/scripts/test_clean_release_cli.py)
/**!
 * @brief Smoke tests for the redesigned clean release CLI.
 * @complexity 2
 * @layer Domain
 */

// --- test_cli_candidate_register_scaffold (backend/tests/scripts/test_clean_release_cli.py)
/**!
 * @brief Verify candidate-register command exits successfully for valid required arguments.
 * @complexity 2
 */

// --- test_cli_manifest_build_scaffold (backend/tests/scripts/test_clean_release_cli.py)
/**!
 * @brief Verify candidate-register/artifact-import/manifest-build smoke path succeeds end-to-end.
 * @complexity 2
 */

// --- test_cli_compliance_run_scaffold (backend/tests/scripts/test_clean_release_cli.py)
/**!
 * @brief Verify compliance run/status/violations/report commands complete for prepared candidate.
 * @complexity 2
 * @invariant SimpleNamespace substitutes for GlobalSettings — any field rename in GlobalSettings will silently not propagate here; re-verify on GlobalSettings schema changes.
 */

// --- test_cli_release_gate_commands_scaffold (backend/tests/scripts/test_clean_release_cli.py)
/**!
 * @brief Verify approve/reject/publish/revoke release-gate commands execute with valid fixtures.
 * @complexity 2
 */

// --- TestCleanReleaseTui (backend/tests/scripts/test_clean_release_tui.py)
/**!
 * @brief Unit tests for the interactive curses TUI of the clean release process.
 * @complexity 2
 * @invariant TUI initializes, handles hotkeys (F5, F10) and safely falls back without TTY.
 * @layer Tests
 * @semantics tests, tui, clean-release, curses
 */

// --- test_headless_fallback (backend/tests/scripts/test_clean_release_tui.py)
/**!
 * @complexity 2
 */

// --- test_tui_initial_render (backend/tests/scripts/test_clean_release_tui.py)
/**!
 * @complexity 2
 */

// --- test_tui_run_checks_f5 (backend/tests/scripts/test_clean_release_tui.py)
/**!
 * @complexity 2
 */

// --- test_tui_exit_f10 (backend/tests/scripts/test_clean_release_tui.py)
/**!
 * @complexity 2
 */

// --- test_tui_clear_history_f7 (backend/tests/scripts/test_clean_release_tui.py)
/**!
 * @complexity 2
 */

// --- test_tui_real_mode_bootstrap_imports_artifacts_catalog (backend/tests/scripts/test_clean_release_tui.py)
/**!
 * @complexity 2
 */

// --- test_clean_release_tui_v2 (backend/tests/scripts/test_clean_release_tui_v2.py)
/**!
 * @brief Smoke tests for thin-client TUI action dispatch and blocked transition behavior.
 * @complexity 2
 * @layer Domain
 */

// --- _build_mock_stdscr (backend/tests/scripts/test_clean_release_tui_v2.py)
/**!
 * @brief Build deterministic curses screen mock with default terminal geometry and exit key.
 * @complexity 2
 */

// --- test_tui_f5_dispatches_run_action (backend/tests/scripts/test_clean_release_tui_v2.py)
/**!
 * @brief Verify F5 key dispatch invokes run_checks exactly once before graceful exit.
 * @complexity 2
 */

// --- test_tui_f5_run_smoke_reports_blocked_state (backend/tests/scripts/test_clean_release_tui_v2.py)
/**!
 * @brief Verify blocked compliance state is surfaced after F5-triggered run action.
 * @complexity 2
 */

// --- test_tui_non_tty_refuses_startup (backend/tests/scripts/test_clean_release_tui_v2.py)
/**!
 * @brief Verify non-TTY execution returns exit code 2 with actionable stderr guidance.
 * @complexity 2
 */

// --- test_tui_f8_blocked_without_facade_binding (backend/tests/scripts/test_clean_release_tui_v2.py)
/**!
 * @brief Verify F8 path reports disabled action instead of mutating hidden facade state.
 * @complexity 2
 */

// --- TestApprovalService (backend/tests/services/clean_release/test_approval_service.py)
/**!
 * @brief Define approval gate contracts for approve/reject operations over immutable compliance evidence.
 * @complexity 2
 * @invariant Approval is allowed only for PASSED report bound to candidate; duplicate approve and foreign report must be rejected.
 * @layer Tests
 * @semantics tests, clean-release, approval, lifecycle, gate
 */

// --- _seed_candidate_with_report (backend/tests/services/clean_release/test_approval_service.py)
/**!
 * @brief Seed candidate and report fixtures for approval gate tests.
 * @complexity 2
 * @post Repository contains candidate and report linked by candidate_id.
 * @pre candidate_id and report_id are non-empty.
 */

// --- test_approve_rejects_blocked_report (backend/tests/services/clean_release/test_approval_service.py)
/**!
 * @brief Ensure approve is rejected when latest report final status is not PASSED.
 * @complexity 2
 * @post approve_candidate raises ApprovalGateError.
 * @pre Candidate has BLOCKED report.
 */

// --- test_approve_rejects_foreign_report (backend/tests/services/clean_release/test_approval_service.py)
/**!
 * @brief Ensure approve is rejected when report belongs to another candidate.
 * @complexity 2
 * @post approve_candidate raises ApprovalGateError.
 * @pre Candidate exists, report candidate_id differs.
 */

// --- test_approve_rejects_duplicate_approve (backend/tests/services/clean_release/test_approval_service.py)
/**!
 * @brief Ensure repeated approve decision for same candidate is blocked.
 * @complexity 2
 * @post Second approve_candidate call raises ApprovalGateError.
 * @pre Candidate has already been approved once.
 */

// --- test_reject_persists_decision_without_promoting_candidate_state (backend/tests/services/clean_release/test_approval_service.py)
/**!
 * @brief Ensure reject decision is immutable and does not promote candidate to APPROVED.
 * @complexity 2
 * @post reject_candidate persists REJECTED decision; candidate status remains unchanged.
 * @pre Candidate has PASSED report and CHECK_PASSED lifecycle state.
 */

// --- test_reject_then_publish_is_blocked (backend/tests/services/clean_release/test_approval_service.py)
/**!
 * @brief Ensure latest REJECTED decision blocks publication gate.
 * @complexity 2
 * @post publish_candidate raises PublicationGateError.
 * @pre Candidate is rejected for passed report.
 */

// --- test_candidate_manifest_services (backend/tests/services/clean_release/test_candidate_manifest_services.py)
/**!
 * @brief Test lifecycle and manifest versioning for release candidates.
 * @complexity 2
 * @layer Tests
 */

// --- test_candidate_lifecycle_transitions (backend/tests/services/clean_release/test_candidate_manifest_services.py)
/**!
 * @brief Verify release candidate allows legal status transitions and rejects forbidden back-transitions.
 * @complexity 2
 */

// --- test_manifest_versioning_and_immutability (backend/tests/services/clean_release/test_candidate_manifest_services.py)
/**!
 * @brief Verify manifest versions increment monotonically and older snapshots remain queryable.
 * @complexity 2
 */

// --- _valid_artifacts (backend/tests/services/clean_release/test_candidate_manifest_services.py)
/**!
 * @brief Provide canonical valid artifact payload used by candidate registration tests.
 * @complexity 2
 */

// --- test_register_candidate_rejects_duplicate_candidate_id (backend/tests/services/clean_release/test_candidate_manifest_services.py)
/**!
 * @brief Verify duplicate candidate_id registration is rejected by service invariants.
 * @complexity 2
 */

// --- test_register_candidate_rejects_malformed_artifact_input (backend/tests/services/clean_release/test_candidate_manifest_services.py)
/**!
 * @brief Verify candidate registration rejects artifact payloads missing required fields.
 * @complexity 2
 */

// --- test_register_candidate_rejects_empty_artifact_set (backend/tests/services/clean_release/test_candidate_manifest_services.py)
/**!
 * @brief Verify candidate registration rejects empty artifact collections.
 * @complexity 2
 */

// --- test_manifest_service_rebuild_creates_new_version (backend/tests/services/clean_release/test_candidate_manifest_services.py)
/**!
 * @brief Verify repeated manifest build creates a new incremented immutable version.
 * @complexity 2
 */

// --- test_manifest_service_existing_manifest_cannot_be_mutated (backend/tests/services/clean_release/test_candidate_manifest_services.py)
/**!
 * @brief Verify existing manifest snapshot remains immutable when rebuilding newer manifest version.
 * @complexity 2
 */

// --- test_manifest_service_rejects_missing_candidate (backend/tests/services/clean_release/test_candidate_manifest_services.py)
/**!
 * @brief Verify manifest build fails with missing candidate identifier.
 * @complexity 2
 */

// --- TestComplianceExecutionService (backend/tests/services/clean_release/test_compliance_execution_service.py)
/**!
 * @brief Validate stage pipeline and run finalization contracts for compliance execution.
 * @complexity 2
 * @invariant Missing manifest prevents run startup; failed execution cannot finalize as PASSED.
 * @layer Tests
 * @semantics tests, clean-release, compliance, pipeline, run-finalization
 */

// --- _seed_with_candidate_policy_registry (backend/tests/services/clean_release/test_compliance_execution_service.py)
/**!
 * @brief Build deterministic repository state for run startup tests.
 * @complexity 2
 * @post Returns repository with candidate, policy and registry; manifest is optional.
 * @pre candidate_id and snapshot ids are non-empty.
 */

// --- test_run_without_manifest_rejected (backend/tests/services/clean_release/test_compliance_execution_service.py)
/**!
 * @brief Ensure compliance run cannot start when manifest is unresolved.
 * @complexity 2
 * @post start_check_run raises ValueError and no run is persisted.
 * @pre Candidate/policy exist but manifest is missing.
 */

// --- test_task_crash_mid_run_marks_failed (backend/tests/services/clean_release/test_compliance_execution_service.py)
/**!
 * @brief Ensure execution crash conditions force FAILED run status.
 * @complexity 2
 * @post execute_stages persists run with FAILED status.
 * @pre Run exists, then required dependency becomes unavailable before execute_stages.
 */

// --- test_blocked_run_finalization_blocks_report_builder (backend/tests/services/clean_release/test_compliance_execution_service.py)
/**!
 * @brief Ensure blocked runs require blocking violations before report creation.
 * @complexity 2
 * @post finalize keeps BLOCKED and report_builder rejects zero blocking violations.
 * @pre Manifest contains prohibited artifacts leading to BLOCKED decision.
 */

// --- TestComplianceTaskIntegration (backend/tests/services/clean_release/test_compliance_task_integration.py)
/**!
 * @brief Verify clean release compliance runs execute through TaskManager lifecycle with observable success/failure outcomes.
 * @complexity 2
 * @invariant Compliance execution triggered as task produces terminal task status and persists run evidence.
 * @layer Tests
 * @semantics tests, clean-release, compliance, task-manager, integration
 */

// --- _seed_repository (backend/tests/services/clean_release/test_compliance_task_integration.py)
/**!
 * @brief Prepare deterministic candidate/policy/registry/manifest fixtures for task integration tests.
 * @complexity 2
 * @post Returns initialized repository and identifiers for compliance run startup.
 * @pre with_manifest controls manifest availability.
 */

// --- CleanReleaseCompliancePlugin (backend/tests/services/clean_release/test_compliance_task_integration.py)
/**!
 * @brief TaskManager plugin shim that executes clean release compliance orchestration.
 * @complexity 2
 */

// --- _PluginLoaderStub (backend/tests/services/clean_release/test_compliance_task_integration.py)
/**!
 * @brief Provide minimal plugin loader contract used by TaskManager in integration tests.
 * @complexity 2
 * @contract Partial PluginLoader stub. Implements: has_plugin, get_plugin. Stubs (NotImplementedError): list_plugins, get_all_plugins, get_all_plugin_configs.
 * @invariant has_plugin/get_plugin only acknowledge the seeded compliance plugin id.
 */

// --- _make_task_manager (backend/tests/services/clean_release/test_compliance_task_integration.py)
/**!
 * @brief Build TaskManager with mocked persistence services for isolated integration tests.
 * @complexity 2
 * @post Returns TaskManager ready for async task execution.
 */

// --- _wait_for_terminal_task (backend/tests/services/clean_release/test_compliance_task_integration.py)
/**!
 * @brief Poll task registry until target task reaches terminal status.
 * @complexity 2
 * @post Returns task with SUCCESS or FAILED status, otherwise raises TimeoutError.
 * @pre task_id exists in manager registry.
 */

// --- test_compliance_run_executes_as_task_manager_task (backend/tests/services/clean_release/test_compliance_task_integration.py)
/**!
 * @brief Verify successful compliance execution is observable as TaskManager SUCCESS task.
 * @complexity 2
 * @post Task ends with SUCCESS; run is persisted with SUCCEEDED status and task binding.
 * @pre Candidate, policy and manifest are available in repository.
 */

// --- test_compliance_run_missing_manifest_marks_task_failed (backend/tests/services/clean_release/test_compliance_task_integration.py)
/**!
 * @brief Verify missing manifest startup failure is surfaced as TaskManager FAILED task.
 * @complexity 2
 * @post Task ends with FAILED and run history remains empty.
 * @pre Candidate/policy exist but manifest is absent.
 */

// --- TestDemoModeIsolation (backend/tests/services/clean_release/test_demo_mode_isolation.py)
/**!
 * @brief Verify demo and real mode namespace isolation contracts before TUI integration.
 * @complexity 2
 * @layer Tests
 * @semantics clean-release, demo-mode, isolation, namespace, repository
 */

// --- test_resolve_namespace_separates_demo_and_real (backend/tests/services/clean_release/test_demo_mode_isolation.py)
/**!
 * @brief Ensure namespace resolver returns deterministic and distinct namespaces.
 * @complexity 2
 * @post Demo and real namespaces are different and stable.
 * @pre Mode names are provided as user/runtime strings.
 */

// --- test_build_namespaced_id_prevents_cross_mode_collisions (backend/tests/services/clean_release/test_demo_mode_isolation.py)
/**!
 * @brief Ensure ID generation prevents demo/real collisions for identical logical IDs.
 * @complexity 2
 * @post Produced physical IDs differ by namespace prefix.
 * @pre Same logical candidate id is used in two different namespaces.
 */

// --- test_create_isolated_repository_keeps_mode_data_separate (backend/tests/services/clean_release/test_demo_mode_isolation.py)
/**!
 * @brief Verify demo and real repositories do not leak state across mode boundaries.
 * @complexity 2
 * @post Candidate mutations in one mode are not visible in the other mode.
 * @pre Two repositories are created for distinct modes.
 */

// --- TestPolicyResolutionService (backend/tests/services/clean_release/test_policy_resolution_service.py)
/**!
 * @brief Verify trusted policy snapshot resolution contract and error guards.
 * @complexity 2
 * @invariant Resolution uses only ConfigManager active IDs and rejects runtime override attempts.
 * @layer Tests
 * @semantics clean-release, policy-resolution, trusted-snapshots, contracts
 */

// --- _config_manager (backend/tests/services/clean_release/test_policy_resolution_service.py)
/**!
 * @brief Build deterministic ConfigManager-like stub for tests.
 * @complexity 2
 * @invariant Only settings.clean_release.active_policy_id and active_registry_id are populated; any other settings field access raises AttributeError.
 * @post Returns object exposing get_config().settings.clean_release active IDs.
 * @pre policy_id and registry_id may be None or non-empty strings.
 */

// --- test_resolve_trusted_policy_snapshots_missing_profile (backend/tests/services/clean_release/test_policy_resolution_service.py)
/**!
 * @brief Ensure resolution fails when trusted profile is not configured.
 * @complexity 2
 * @post Raises PolicyResolutionError with missing trusted profile reason.
 * @pre active_policy_id is None.
 */

// --- test_resolve_trusted_policy_snapshots_missing_registry (backend/tests/services/clean_release/test_policy_resolution_service.py)
/**!
 * @brief Ensure resolution fails when trusted registry is not configured.
 * @complexity 2
 * @post Raises PolicyResolutionError with missing trusted registry reason.
 * @pre active_registry_id is None and active_policy_id is set.
 */

// --- test_resolve_trusted_policy_snapshots_rejects_override_attempt (backend/tests/services/clean_release/test_policy_resolution_service.py)
/**!
 * @brief Ensure runtime override attempt is rejected even if snapshots exist.
 * @complexity 2
 * @post Raises PolicyResolutionError with override forbidden reason.
 * @pre valid trusted snapshots exist in repository and override is provided.
 */

// --- TestPublicationService (backend/tests/services/clean_release/test_publication_service.py)
/**!
 * @brief Define publication gate contracts over approved candidates and immutable publication records.
 * @complexity 2
 * @invariant Publish requires approval; revoke requires existing publication; republish after revoke is allowed as a new record.
 * @layer Tests
 * @semantics tests, clean-release, publication, revoke, gate
 */

// --- _seed_candidate_with_passed_report (backend/tests/services/clean_release/test_publication_service.py)
/**!
 * @brief Seed candidate/report fixtures for publication gate scenarios.
 * @complexity 2
 * @post Repository contains candidate and PASSED report.
 * @pre candidate_id and report_id are non-empty.
 */

// --- test_publish_without_approval_rejected (backend/tests/services/clean_release/test_publication_service.py)
/**!
 * @brief Ensure publish action is blocked until candidate is approved.
 * @complexity 2
 * @post publish_candidate raises PublicationGateError.
 * @pre Candidate has PASSED report but status is not APPROVED.
 */

// --- test_revoke_unknown_publication_rejected (backend/tests/services/clean_release/test_publication_service.py)
/**!
 * @brief Ensure revocation is rejected for unknown publication id.
 * @complexity 2
 * @post revoke_publication raises PublicationGateError.
 * @pre Repository has no matching publication record.
 */

// --- test_republish_after_revoke_creates_new_active_record (backend/tests/services/clean_release/test_publication_service.py)
/**!
 * @brief Ensure republish after revoke is allowed and creates a new ACTIVE record.
 * @complexity 2
 * @post New publish call returns distinct publication id with ACTIVE status.
 * @pre Candidate is APPROVED and first publication has been revoked.
 */

// --- TestReportAuditImmutability (backend/tests/services/clean_release/test_report_audit_immutability.py)
/**!
 * @brief Validate report snapshot immutability expectations and append-only audit hook behavior for US2.
 * @complexity 2
 * @invariant Built reports are immutable snapshots; audit hooks produce append-only event traces.
 * @layer Tests
 * @semantics tests, clean-release, report, audit, immutability, append-only
 */

// --- _terminal_run (backend/tests/services/clean_release/test_report_audit_immutability.py)
/**!
 * @brief Build deterministic terminal run fixture for report snapshot tests.
 * @complexity 2
 * @post Returns a terminal ComplianceRun suitable for report generation.
 * @pre final_status is a valid ComplianceDecision value.
 */

// --- test_report_builder_sets_immutable_snapshot_flag (backend/tests/services/clean_release/test_report_audit_immutability.py)
/**!
 * @brief Ensure generated report payload is marked immutable and persisted as snapshot.
 * @complexity 2
 * @post Built report has immutable=True and repository stores same immutable object.
 * @pre Terminal run exists.
 */

// --- test_repository_rejects_report_overwrite_for_same_report_id (backend/tests/services/clean_release/test_report_audit_immutability.py)
/**!
 * @brief Define immutability contract that report snapshots cannot be overwritten by same identifier.
 * @complexity 2
 * @post Second save for same report id is rejected with explicit immutability error.
 * @pre Existing report with id is already persisted.
 */

// --- test_audit_hooks_emit_append_only_event_stream (backend/tests/services/clean_release/test_report_audit_immutability.py)
/**!
 * @brief Verify audit hooks emit one event per action call and preserve call order.
 * @complexity 2
 * @post Three calls produce three ordered info entries with molecular prefixes.
 * @pre Logger backend is patched.
 */

// --- SupersetCompatibilityMatrixTests (backend/tests/services/dataset_review/test_superset_matrix.py)
/**!
 * @brief Verifies Superset preview and SQL Lab endpoint fallback strategy used by dataset-review orchestration.
 * @complexity 2
 * @layer Tests
 * @semantics dataset_review, superset, compatibility_matrix, preview, sql_lab, tests
 */

// --- make_adapter (backend/tests/services/dataset_review/test_superset_matrix.py)
/**!
 * @brief Build an adapter with a mock Superset client and deterministic environment for compatibility tests.
 * @complexity 2
 */

// --- test_preview_prefers_supported_client_method_before_network_fallback (backend/tests/services/dataset_review/test_superset_matrix.py)
/**!
 * @brief Confirms preview compilation uses a supported client method first when the capability exists.
 * @complexity 2
 */

// --- test_preview_falls_back_across_matrix_until_supported_endpoint_returns_sql (backend/tests/services/dataset_review/test_superset_matrix.py)
/**!
 * @brief Confirms preview fallback walks the compatibility matrix from preferred to legacy endpoints until one returns compiled SQL.
 * @complexity 2
 * @fragile Positional call assertion — ordering changes will break this test without indicating a real regression. Prefer content-based assertion.
 */

// --- test_sql_lab_launch_falls_back_to_legacy_execute_endpoint (backend/tests/services/dataset_review/test_superset_matrix.py)
/**!
 * @brief Confirms SQL Lab launch falls back from modern to legacy execute endpoint and preserves canonical session reference extraction.
 * @complexity 2
 * @fragile Positional call assertion — ordering changes will break this test without indicating a real regression. Prefer content-based assertion.
 */

// --- TestAPIKeyAuth (backend/tests/test_api_key_auth.py)
/**!
 * @brief Contract tests for API key authentication — valid key, invalid, revoked, expired, missing permission,
 * @complexity 3
 */

// --- test_no_header_returns_none (backend/tests/test_api_key_auth.py)
/**!
 * @brief No X-API-Key header → returns None.
 * @complexity 2
 */

// --- test_valid_key_returns_principal (backend/tests/test_api_key_auth.py)
/**!
 * @brief Valid API key → returns APIKeyPrincipal with correct fields.
 * @complexity 2
 */

// --- test_invalid_key_raises_401 (backend/tests/test_api_key_auth.py)
/**!
 * @brief Invalid API key → 401.
 * @complexity 2
 */

// --- test_revoked_key_raises_401 (backend/tests/test_api_key_auth.py)
/**!
 * @brief Revoked (active=False) API key → 401.
 * @complexity 2
 */

// --- test_expired_key_raises_401 (backend/tests/test_api_key_auth.py)
/**!
 * @brief Expired API key → 401.
 * @complexity 2
 */

// --- test_api_key_auth_valid (backend/tests/test_api_key_auth.py)
/**!
 * @brief Valid API key with matching permission → 202.
 * @complexity 2
 */

// --- test_api_key_auth_wrong_permission (backend/tests/test_api_key_auth.py)
/**!
 * @brief API key lacks required permission → 403.
 * @complexity 2
 */

// --- test_api_key_auth_revoked (backend/tests/test_api_key_auth.py)
/**!
 * @brief Revoked API key → 401.
 * @complexity 2
 */

// --- test_api_key_auth_expired (backend/tests/test_api_key_auth.py)
/**!
 * @brief Expired API key → 401.
 * @complexity 2
 */

// --- test_api_key_auth_invalid (backend/tests/test_api_key_auth.py)
/**!
 * @brief Non-existent key → 401.
 * @complexity 2
 */

// --- test_api_key_auth_environment_scope (backend/tests/test_api_key_auth.py)
/**!
 * @brief Key scoped to ss-dev, request for ss-prod → 400.
 * @complexity 2
 */

// --- test_api_key_auth_environment_scope_ok (backend/tests/test_api_key_auth.py)
/**!
 * @brief Key scoped to ss-dev, request for ss-dev → 202.
 * @complexity 2
 */

// --- test_jwt_precedence (backend/tests/test_api_key_auth.py)
/**!
 * @brief Both valid API key + valid JWT → JWT takes precedence.
 * @complexity 2
 */

// --- TestAPIKeyModel (backend/tests/test_api_key_model.py)
/**!
 * @brief Contract tests for the APIKey SQLAlchemy model — creation, hash storage, and field constraints.
 * @complexity 2
 * @test_contract APIKey model stores SHA-256 hash and prefix; raw key never persisted.
 * @test_edge active defaults to True
 */

// --- clean_db (backend/tests/test_api_key_model.py)
/**!
 * @brief In-memory SQLite fixture for APIKey model tests.
 * @complexity 1
 */

// --- test_create_api_key (backend/tests/test_api_key_model.py)
/**!
 * @brief Create APIKey with required fields and verify defaults.
 * @complexity 2
 */

// --- test_key_hash_unique (backend/tests/test_api_key_model.py)
/**!
 * @brief key_hash is unique — duplicate raises IntegrityError.
 * @complexity 2
 */

// --- test_prefix_length (backend/tests/test_api_key_model.py)
/**!
 * @brief prefix is exactly 11 characters.
 * @complexity 2
 */

// --- test_active_default_true (backend/tests/test_api_key_model.py)
/**!
 * @brief active column defaults to True.
 * @complexity 2
 */

// --- TestAPIKeyRoutes (backend/tests/test_api_key_routes.py)
/**!
 * @brief Contract tests for admin API key CRUD endpoints — list, create (raw key present), revoke, idempotent revoke.
 * @complexity 3
 * @test_contract DELETE /api/admin/api-keys/{id} -> 200 with status=revoked
 * @test_edge missing_permissions -> 422
 */

// --- test_list_empty (backend/tests/test_api_key_routes.py)
/**!
 * @brief No keys → returns empty list.
 * @complexity 2
 */

// --- test_list_with_keys (backend/tests/test_api_key_routes.py)
/**!
 * @brief Keys exist → returns list without raw_key or key_hash fields.
 * @complexity 2
 */

// --- test_create_valid (backend/tests/test_api_key_routes.py)
/**!
 * @brief Valid request → 201 with raw_key, prefix, id.
 * @complexity 2
 */

// --- test_create_missing_name (backend/tests/test_api_key_routes.py)
/**!
 * @brief Missing name → 400 or 422.
 * @complexity 2
 */

// --- test_create_empty_permissions (backend/tests/test_api_key_routes.py)
/**!
 * @brief Empty permissions → 400 or 422.
 * @complexity 2
 */

// --- test_revoke_valid (backend/tests/test_api_key_routes.py)
/**!
 * @brief Revoke existing active key → 200 with status=revoked.
 * @complexity 2
 */

// --- test_revoke_already_revoked (backend/tests/test_api_key_routes.py)
/**!
 * @brief Revoke already revoked key → 404.
 * @complexity 2
 */

// --- test_revoke_not_found (backend/tests/test_api_key_routes.py)
/**!
 * @brief Revoke non-existent key → 404.
 * @complexity 2
 */

// --- TestAuth (backend/tests/test_auth.py)
/**!
 * @brief Covers authentication service/repository behavior and auth bootstrap helpers.
 * @complexity 2
 * @layer Tests
 */

// --- test_create_admin_creates_user_with_optional_email (backend/tests/test_auth.py)
/**!
 * @complexity 2
 */

// --- test_create_admin_is_idempotent_for_existing_user (backend/tests/test_auth.py)
/**!
 * @complexity 2
 */

// --- test_ensure_encryption_key_generates_backend_env_file (backend/tests/test_auth.py)
/**!
 * @complexity 2
 */

// --- test_ensure_encryption_key_reuses_existing_env_file_value (backend/tests/test_auth.py)
/**!
 * @complexity 2
 */

// --- test_ensure_encryption_key_prefers_process_environment (backend/tests/test_auth.py)
/**!
 * @complexity 2
 */

// --- TestConstantsAuditFixes (backend/tests/test_constants_audit_fixes.py)
/**!
 * @brief Verify Class 5 fix — hardcoded values extracted to named module-level constants.
 * @complexity 3
 * @test_edge git_typo_fix -> services/git/_base.py still has "repositorys" at line 148 (bug)
 */

// --- test_page_size_constant_exists (backend/tests/test_constants_audit_fixes.py)
/**!
 * @brief DEFAULT_PAGE_SIZE contract: importable, int > 0 (not yet defined in source).
 * @complexity 2
 */

// --- test_llm_analysis_timeout_constants (backend/tests/test_constants_audit_fixes.py)
/**!
 * @brief Named timeout constants should exist per RATIONALE comment (not yet defined).
 * @complexity 2
 */

// --- test_base_dir_constant_replaces_parents (backend/tests/test_constants_audit_fixes.py)
/**!
 * @brief BASE_DIR resolves to backend/ root, not __file__-dependent relative path.
 * @complexity 2
 */

// --- test_git_service_repositorys_typo_regression (backend/tests/test_constants_audit_fixes.py)
/**!
 * @brief services/git/_base.py still has "repositorys" (old typo) at line 148 — known bug.
 * @complexity 2
 */

// --- test_git_default_repos_path_constant (backend/tests/test_constants_audit_fixes.py)
/**!
 * @brief DEFAULT_GIT_REPOS_PATH should be defined per RATIONALE (not yet defined).
 * @complexity 2
 */

// --- test_superset_client_module_loads (backend/tests/test_constants_audit_fixes.py)
/**!
 * @brief superset_client._base is importable (no dependency on crashing modules).
 * @complexity 2
 */

// --- test_constants_are_immutable (backend/tests/test_constants_audit_fixes.py)
/**!
 * @brief Module-level constants use int/str types (immutable by convention).
 * @complexity 2
 */

// --- TestCoreScheduler (backend/tests/test_core_scheduler.py)
/**!
 * @brief Verify SchedulerService load_schedules and translation job add/remove contracts.
 * @complexity 3
 * @test_edge add_remove_translation_job — job correctly registered and removed from APScheduler
 * @test_invariant translation_jobs_persist_across_reload -> VERIFIED_BY: [test_load_schedules_reloads_translation_schedules]
 */

// --- test_load_schedules_reloads_translation_schedules (backend/tests/test_core_scheduler.py)
/**!
 * @complexity 1
 */

// --- test_add_and_remove_translation_job (backend/tests/test_core_scheduler.py)
/**!
 * @complexity 1
 */

// --- test_remove_nonexistent_translation_job_no_error (backend/tests/test_core_scheduler.py)
/**!
 * @complexity 1
 */

// --- test_add_validation_job (backend/tests/test_core_scheduler.py)
/**!
 * @complexity 1
 */

// --- test_load_schedules_loads_validation_policies (backend/tests/test_core_scheduler.py)
/**!
 * @complexity 1
 */

// --- test_trigger_validation_creates_tasks (backend/tests/test_core_scheduler.py)
/**!
 * @complexity 1
 */

// --- test_trigger_validation_skips_missing_policy (backend/tests/test_core_scheduler.py)
/**!
 * @complexity 1
 */

// --- test_trigger_validation_skips_inactive_policy (backend/tests/test_core_scheduler.py)
/**!
 * @complexity 1
 */

// --- test_trigger_validation_skips_no_dashboards (backend/tests/test_core_scheduler.py)
/**!
 * @complexity 1
 */

// --- test_remove_validation_job (backend/tests/test_core_scheduler.py)
/**!
 * @complexity 1
 */

// --- test_remove_nonexistent_validation_job (backend/tests/test_core_scheduler.py)
/**!
 * @complexity 1
 */

// --- test_reload_validation_policy_adds_job (backend/tests/test_core_scheduler.py)
/**!
 * @complexity 1
 */

// --- test_reload_validation_policy_removes_job_when_policy_gone (backend/tests/test_core_scheduler.py)
/**!
 * @complexity 1
 */

// --- TestDashboardsApi (backend/tests/test_dashboards_api.py)
/**!
 * @brief Comprehensive contract-driven tests for Dashboard Hub API
 * @complexity 2
 * @layer Tests
 * @semantics tests, dashboards, api, contract, remediation
 */

// --- test_get_dashboard_tasks_history_success (backend/tests/test_dashboards_api.py)
/**!
 * @complexity 2
 */

// --- test_get_dashboard_tasks_history_sorting (backend/tests/test_dashboards_api.py)
/**!
 * @complexity 2
 */

// --- test_get_dashboard_thumbnail_env_not_found (backend/tests/test_dashboards_api.py)
/**!
 * @complexity 2
 */

// --- test_get_dashboard_thumbnail_202 (backend/tests/test_dashboards_api.py)
/**!
 * @complexity 2
 */

// --- test_migrate_dashboards_pre_checks (backend/tests/test_dashboards_api.py)
/**!
 * @complexity 2
 */

// --- test_backup_dashboards_pre_checks (backend/tests/test_dashboards_api.py)
/**!
 * @complexity 2
 */

// --- test_backup_dashboards_with_schedule (backend/tests/test_dashboards_api.py)
/**!
 * @complexity 2
 */

// --- test_task_matches_dashboard_logic (backend/tests/test_dashboards_api.py)
/**!
 * @complexity 2
 */

// --- TestDeprecationAuditFixes (backend/tests/test_deprecation_audit_fixes.py)
/**!
 * @brief Verify Class 7 fix — is_multimodal_model should emit DeprecationWarning.
 * @complexity 3
 * @rationale The RATIONALE comment in llm_prompt_templates.py says warnings.warn(DeprecationWarning)
 * @test_edge text_only_model_returns_false -> models with text-only markers return False
 */

// --- test_is_multimodal_model_emits_warning (backend/tests/test_deprecation_audit_fixes.py)
/**!
 * @brief is_multimodal_model should emit DeprecationWarning (shim not yet implemented).
 * @complexity 2
 */

// --- test_multimodal_model_returns_true (backend/tests/test_deprecation_audit_fixes.py)
/**!
 * @brief Known multimodal models (gpt-4o, claude-3, gemini) return True.
 * @complexity 2
 */

// --- test_text_only_model_returns_false (backend/tests/test_deprecation_audit_fixes.py)
/**!
 * @brief Text-only models (embedding, whisper, rerank) return False.
 * @complexity 2
 */

// --- test_empty_model_returns_false (backend/tests/test_deprecation_audit_fixes.py)
/**!
 * @brief Empty or None model name returns False without error.
 * @complexity 2
 */

// --- test_case_insensitive_matching (backend/tests/test_deprecation_audit_fixes.py)
/**!
 * @brief Model name matching is case-insensitive.
 * @complexity 2
 */

// --- test_deprecation_comment_exists (backend/tests/test_deprecation_audit_fixes.py)
/**!
 * @brief The source module documents the @DEPRECATED rationale in the region header.
 * @complexity 2
 */

// --- TestLayoutUtils (backend/tests/test_layout_utils.py)
/**!
 * @brief Contract tests for layout utility functions — _estimate_markdown_height.
 * @complexity 3
 */

// --- test_empty_content (backend/tests/test_layout_utils.py)
/**!
 * @brief Empty string returns minimum height 19.
 * @complexity 2
 */

// --- test_single_line_text (backend/tests/test_layout_utils.py)
/**!
 * @brief Short text without padding returns expected computed height.
 * @complexity 2
 */

// --- test_content_with_padding (backend/tests/test_layout_utils.py)
/**!
 * @brief Content with padding:12 — 24px added to content height.
 * @complexity 2
 */

// --- test_very_long_content (backend/tests/test_layout_utils.py)
/**!
 * @brief Very long content (3000 chars) capped at max height 200.
 * @complexity 2
 */

// --- test_html_only_content (backend/tests/test_layout_utils.py)
/**!
 * @brief HTML-only content (no visible text) returns minimum height 19.
 * @complexity 2
 */

// --- test_log_persistence (backend/tests/test_log_persistence.py)
/**!
 * @brief Unit tests for TaskLogPersistenceService.
 * @complexity 2
 * @layer Tests
 * @semantics test, log, persistence, unit_test
 */

// --- TestLogPersistence (backend/tests/test_log_persistence.py)
/**!
 * @brief Test suite for TaskLogPersistenceService.
 * @complexity 2
 * @test_data log_entry -> {"task_id": "test-task-1", "level": "INFO", "source": "test_source", "message": "Test message"}
 */

// --- test_add_logs_single (backend/tests/test_log_persistence.py)
/**!
 * @brief Test adding a single log entry.
 * @complexity 2
 * @post Log entry persisted to database.
 * @pre Service and session initialized.
 */

// --- test_add_logs_batch (backend/tests/test_log_persistence.py)
/**!
 * @brief Test adding multiple log entries in batch.
 * @complexity 2
 * @post All log entries persisted to database.
 * @pre Service and session initialized.
 */

// --- test_add_logs_empty (backend/tests/test_log_persistence.py)
/**!
 * @brief Test adding empty log list (should be no-op).
 * @complexity 2
 * @post No logs added.
 * @pre Service initialized.
 */

// --- test_get_logs_by_task_id (backend/tests/test_log_persistence.py)
/**!
 * @brief Test retrieving logs by task ID.
 * @complexity 2
 * @post Returns logs for the specified task.
 * @pre Service and session initialized, logs exist.
 */

// --- test_get_logs_with_filters (backend/tests/test_log_persistence.py)
/**!
 * @brief Test retrieving logs with level and source filters.
 * @complexity 2
 * @post Returns filtered logs.
 * @pre Service and session initialized, logs exist.
 */

// --- test_get_logs_with_pagination (backend/tests/test_log_persistence.py)
/**!
 * @brief Test retrieving logs with pagination.
 * @complexity 2
 * @post Returns paginated logs.
 * @pre Service and session initialized, logs exist.
 */

// --- test_get_logs_with_search (backend/tests/test_log_persistence.py)
/**!
 * @brief Test retrieving logs with search query.
 * @complexity 2
 * @post Returns logs matching search query.
 * @pre Service and session initialized, logs exist.
 */

// --- test_get_log_stats (backend/tests/test_log_persistence.py)
/**!
 * @brief Test retrieving log statistics.
 * @complexity 2
 * @post Returns LogStats model with counts by level and source.
 * @pre Service and session initialized, logs exist.
 */

// --- test_get_sources (backend/tests/test_log_persistence.py)
/**!
 * @brief Test retrieving unique log sources.
 * @complexity 2
 * @post Returns list of unique sources.
 * @pre Service and session initialized, logs exist.
 */

// --- test_delete_logs_for_task (backend/tests/test_log_persistence.py)
/**!
 * @brief Test deleting logs by task ID.
 * @complexity 2
 * @post Logs for the task are deleted.
 * @pre Service and session initialized, logs exist.
 */

// --- test_delete_logs_for_tasks (backend/tests/test_log_persistence.py)
/**!
 * @brief Test deleting logs for multiple tasks.
 * @complexity 2
 * @post Logs for all specified tasks are deleted.
 * @pre Service and session initialized, logs exist.
 */

// --- test_delete_logs_for_tasks_empty (backend/tests/test_log_persistence.py)
/**!
 * @brief Test deleting with empty list (no-op).
 * @complexity 2
 * @post No error, no deletion.
 * @pre Service initialized.
 */

// --- TestLogger (backend/tests/test_logger.py)
/**!
 * @brief Unit tests for the custom logger CoT JSON formatters and configuration context manager.
 * @complexity 2
 * @invariant All required log statements must correctly check the threshold.
 * @layer Tests
 * @semantics logging, tests, belief_state, cot, json
 */

// --- test_belief_scope_success_coherence (backend/tests/test_logger.py)
/**!
 * @brief Test that belief_scope logs REFLECT marker on success.
 * @complexity 2
 * @post Logs are verified to contain REFLECT marker.
 * @pre belief_scope is available. caplog fixture is used. Logger configured to DEBUG.
 */

// --- test_belief_scope_reason_not_visible_at_info (backend/tests/test_logger.py)
/**!
 * @brief Test that belief_scope REASON/REFLECT markers are NOT visible at INFO level.
 * @complexity 2
 * @post REASON/REFLECT markers are not captured at INFO level.
 * @pre belief_scope is available. caplog fixture is used.
 */

// --- test_cot_json_formatter_output (backend/tests/test_logger.py)
/**!
 * @brief Test that CotJsonFormatter produces valid JSON with expected fields.
 * @complexity 2
 */

// --- test_cot_json_formatter_plain_message (backend/tests/test_logger.py)
/**!
 * @brief Test that CotJsonFormatter wraps plain messages (no extra) with default marker.
 * @complexity 2
 */

// --- TestLoggingAuditFixes (backend/tests/test_logging_audit_fixes.py)
/**!
 * @brief Verify Class 2 fix — no bare `except: pass` patterns remain in src/.
 * @complexity 3
 * @test_edge plugin_loader_uses_logger -> plugin_loader.py uses logger, not print
 */

// --- _collect_src_files (backend/tests/test_logging_audit_fixes.py)
/**!
 * @brief Collect all .py files under src/ excluding test/ and mock/ directories.
 * @complexity 1
 */

// --- test_except_pass_replaced_with_log (backend/tests/test_logging_audit_fixes.py)
/**!
 * @brief AST audit: bare `except: pass` nodes are absent from src/ source files.
 * @complexity 2
 */

// --- test_plugin_loader_uses_logger_not_print (backend/tests/test_logging_audit_fixes.py)
/**!
 * @brief plugin_loader.py (src/core/) uses logger for error/warning, not print().
 * @complexity 2
 */

// --- test_plugin_loader_imports_logger (backend/tests/test_logging_audit_fixes.py)
/**!
 * @brief plugin_loader.py imports a logger or _logger for structured reporting.
 * @complexity 2
 */

// --- test_plugin_loader_logger_calls_exist (backend/tests/test_logging_audit_fixes.py)
/**!
 * @brief plugin_loader.py references logger.error/warning/info in its code.
 * @complexity 2
 */

// --- test_maintenance_api (backend/tests/test_maintenance_api.py)
/**!
 * @brief Contract tests for Maintenance Banner API endpoints — T016, T025.
 * @complexity 3
 */

// --- test_start_returns_202 (backend/tests/test_maintenance_api.py)
/**!
 * @brief Valid request returns 202 with task_id and maintenance_id.
 * @complexity 2
 */

// --- test_start_missing_tables (backend/tests/test_maintenance_api.py)
/**!
 * @brief Missing tables field returns 422.
 * @complexity 2
 */

// --- test_start_end_time_before_start (backend/tests/test_maintenance_api.py)
/**!
 * @brief end_time before start_time returns 400.
 * @complexity 2
 */

// --- test_start_too_many_tables (backend/tests/test_maintenance_api.py)
/**!
 * @brief More than 100 tables returns 422 (Pydantic validation).
 * @complexity 2
 */

// --- test_start_idempotency (backend/tests/test_maintenance_api.py)
/**!
 * @brief Same (tables, start, end) returns already_active.
 * @complexity 2
 */

// --- test_end_returns_202 (backend/tests/test_maintenance_api.py)
/**!
 * @brief Valid maintenance_id returns 202.
 * @complexity 2
 */

// --- test_end_not_found (backend/tests/test_maintenance_api.py)
/**!
 * @brief Non-existent maintenance_id returns 404.
 * @complexity 2
 */

// --- test_end_all_returns_202 (backend/tests/test_maintenance_api.py)
/**!
 * @brief end-all returns 202.
 * @complexity 2
 */

// --- test_list_events (backend/tests/test_maintenance_api.py)
/**!
 * @brief Returns active and completed events.
 * @complexity 2
 */

// --- test_expired_event_auto_ends (backend/tests/test_maintenance_api.py)
/**!
 * @brief Event past end_time with ACTIVE status → create_task called with auto-end params.
 * @complexity 2
 */

// --- test_future_end_time_skipped (backend/tests/test_maintenance_api.py)
/**!
 * @brief Event with future end_time → no task created, skipped by < now filter.
 * @complexity 2
 */

// --- test_no_end_time_skipped (backend/tests/test_maintenance_api.py)
/**!
 * @brief Event with end_time=None → no task created, skipped by isnot(None) filter.
 * @complexity 2
 */

// --- test_list_banners (backend/tests/test_maintenance_api.py)
/**!
 * @brief Returns list of active banners.
 * @complexity 2
 */

// --- test_get_settings (backend/tests/test_maintenance_api.py)
/**!
 * @brief GET returns settings.
 * @complexity 2
 */

// --- test_put_settings (backend/tests/test_maintenance_api.py)
/**!
 * @brief PUT updates settings.
 * @complexity 2
 */

// --- test_maintenance_service (backend/tests/test_maintenance_service.py)
/**!
 * @brief Integration tests for MaintenanceService — T018, T026, T026a.
 * @complexity 3
 */

// --- test_basic_key (backend/tests/test_maintenance_service.py)
/**!
 * @brief Basic idempotency key with tables and times.
 * @complexity 2
 */

// --- test_key_without_end_time (backend/tests/test_maintenance_service.py)
/**!
 * @brief Idempotency key with None end_time.
 * @complexity 2
 */

// --- test_key_table_sorting (backend/tests/test_maintenance_service.py)
/**!
 * @brief Tables are sorted alphabetically in frozenset.
 * @complexity 2
 */

// --- test_empty_tables (backend/tests/test_maintenance_service.py)
/**!
 * @brief Empty tables list returns empty.
 * @complexity 2
 */

// --- test_table_based_match (backend/tests/test_maintenance_service.py)
/**!
 * @brief Table-based dataset matching.
 * @complexity 2
 */

// --- test_virtual_dataset_match (backend/tests/test_maintenance_service.py)
/**!
 * @brief Virtual SQL dataset matching via SqlTableExtractor.
 * @complexity 2
 */

// --- test_superset_api_failure (backend/tests/test_maintenance_service.py)
/**!
 * @brief Superset API failure propagates.
 * @complexity 2
 */

// --- test_creates_new_banner (backend/tests/test_maintenance_service.py)
/**!
 * @brief No existing banner — creates new chart and banner row.
 * @complexity 2
 */

// --- test_returns_existing_banner (backend/tests/test_maintenance_service.py)
/**!
 * @brief Existing active banner — returns it.
 * @complexity 2
 */

// --- test_chart_creation_failure (backend/tests/test_maintenance_service.py)
/**!
 * @brief Chart creation failure propagates.
 * @complexity 2
 */

// --- test_single_event (backend/tests/test_maintenance_service.py)
/**!
 * @brief Single event — direct substitution.
 * @complexity 2
 */

// --- test_multiple_events (backend/tests/test_maintenance_service.py)
/**!
 * @brief Multiple events — combined message.
 * @complexity 2
 */

// --- test_empty_events (backend/tests/test_maintenance_service.py)
/**!
 * @brief Empty events list returns empty string.
 * @complexity 2
 */

// --- test_missing_variables (backend/tests/test_maintenance_service.py)
/**!
 * @brief Missing variables replaced with empty string.
 * @complexity 2
 */

// --- test_html_escaping (backend/tests/test_maintenance_service.py)
/**!
 * @brief Message is HTML-escaped.
 * @complexity 2
 */

// --- test_happy_path (backend/tests/test_maintenance_service.py)
/**!
 * @brief Happy path: event with matching dashboards.
 * @complexity 2
 */

// --- test_no_matching_dashboards (backend/tests/test_maintenance_service.py)
/**!
 * @brief No dashboards match the tables.
 * @complexity 2
 */

// --- test_event_not_found (backend/tests/test_maintenance_service.py)
/**!
 * @brief Event ID not in DB.
 * @complexity 2
 */

// --- test_already_processed_event (backend/tests/test_maintenance_service.py)
/**!
 * @brief Event already ACTIVE — idempotent.
 * @complexity 2
 */

// --- test_rebuild_active_banner (backend/tests/test_maintenance_service.py)
/**!
 * @brief Active banner with active state — rebuilds text.
 * @complexity 2
 */

// --- test_banner_not_found (backend/tests/test_maintenance_service.py)
/**!
 * @brief Banner ID not found.
 * @complexity 2
 */

// --- test_end_active_event_single_banner (backend/tests/test_maintenance_service.py)
/**!
 * @brief End event with single active dashboard — banner removed entirely.
 * @complexity 2
 */

// --- test_end_event_shared_banner (backend/tests/test_maintenance_service.py)
/**!
 * @brief Two events, same dashboard — ending one rebuilds banner, doesn't delete.
 * @complexity 2
 */

// --- test_end_already_completed_event (backend/tests/test_maintenance_service.py)
/**!
 * @brief Already completed event — idempotent.
 * @complexity 2
 */

// --- test_end_all_active_events (backend/tests/test_maintenance_service.py)
/**!
 * @brief End all active events.
 * @complexity 2
 */

// --- test_no_active_events (backend/tests/test_maintenance_service.py)
/**!
 * @brief No active events.
 * @complexity 2
 */

// --- test_mixed_active_and_completed (backend/tests/test_maintenance_service.py)
/**!
 * @brief Mix of active and completed events — only active get ended.
 * @complexity 2
 */

// --- TestResourceHubs (backend/tests/test_resource_hubs.py)
/**!
 * @brief Contract tests for resource hub dashboards/datasets listing and pagination boundary validation.
 * @complexity 2
 * @layer Tests
 * @semantics tests, resource-hubs, dashboards, datasets, pagination, api
 */

// --- test_dashboards_api (backend/tests/test_resource_hubs.py)
/**!
 * @brief Verify GET /api/dashboards contract compliance
 * @complexity 2
 * @test_contract dashboards_query -> dashboards payload or not_found response
 * @test_invariant dashboards_route_contract_stays_observable -> VERIFIED_BY: [dashboards_env_found_returns_payload, dashboards_unknown_env_returns_not_found, dashboards_search_filters_results]
 * @test_scenario dashboards_search_filters_results -> Search narrows payload to matching dashboard title.
 */

// --- mock_deps (backend/tests/test_resource_hubs.py)
/**!
 * @brief Provide dependency override fixture for resource hub route tests.
 * @complexity 2
 * @invariant unconstrained mock — no spec= enforced; attribute typos will silently pass
 * @test_fixture resource_hub_overrides -> INLINE_JSON
 */

// --- test_get_dashboards_not_found (backend/tests/test_resource_hubs.py)
/**!
 * @brief Verify dashboards endpoint returns 404 for unknown environment identifier.
 * @complexity 2
 */

// --- test_get_dashboards_search (backend/tests/test_resource_hubs.py)
/**!
 * @brief Verify dashboards endpoint search filter returns matching subset.
 * @complexity 2
 */

// --- test_datasets_api (backend/tests/test_resource_hubs.py)
/**!
 * @brief Verify GET /api/datasets contract compliance
 * @complexity 2
 * @test_contract datasets_query -> datasets payload or error response
 * @test_invariant datasets_route_contract_stays_observable -> VERIFIED_BY: [datasets_env_found_returns_payload, datasets_unknown_env_returns_not_found, datasets_search_filters_results, datasets_service_failure_returns_503]
 * @test_scenario datasets_service_failure_returns_503 -> Backend fetch failure surfaces as HTTP 503.
 */

// --- test_get_datasets_not_found (backend/tests/test_resource_hubs.py)
/**!
 * @brief Verify datasets endpoint returns 404 for unknown environment identifier.
 * @complexity 2
 */

// --- test_get_datasets_search (backend/tests/test_resource_hubs.py)
/**!
 * @brief Verify datasets endpoint search filter returns matching dataset subset.
 * @complexity 2
 */

// --- test_get_datasets_service_failure (backend/tests/test_resource_hubs.py)
/**!
 * @brief Verify datasets endpoint surfaces backend fetch failure as HTTP 503.
 * @complexity 2
 */

// --- test_pagination_boundaries (backend/tests/test_resource_hubs.py)
/**!
 * @brief Verify pagination validation for GET endpoints
 * @complexity 2
 * @test_contract pagination_query -> validation error response
 * @test_edge external_fail -> Validation failure returns HTTP 400 without partial payload.
 * @test_invariant pagination_limits_apply_to_both_routes -> VERIFIED_BY: [dashboards_zero_page_rejected, dashboards_oversize_page_rejected, datasets_zero_page_rejected, datasets_oversize_page_rejected]
 * @test_scenario datasets_oversize_page_rejected -> page_size=101 returns HTTP 400.
 */

// --- test_get_dashboards_pagination_zero_page (backend/tests/test_resource_hubs.py)
/**!
 * @brief Verify dashboards endpoint rejects page=0 with HTTP 400 validation error.
 * @complexity 2
 * @test_edge pagination_zero_page -> {page: 0, status: 400}
 */

// --- test_get_dashboards_pagination_oversize (backend/tests/test_resource_hubs.py)
/**!
 * @brief Verify dashboards endpoint rejects oversized page_size with HTTP 400.
 * @complexity 2
 * @test_edge pagination_oversize -> {page_size: 101, status: 400}
 */

// --- test_get_datasets_pagination_zero_page (backend/tests/test_resource_hubs.py)
/**!
 * @brief Verify datasets endpoint rejects page=0 with HTTP 400.
 * @complexity 2
 * @test_edge pagination_zero_page_datasets -> {page: 0, status: 400}
 */

// --- test_get_datasets_pagination_oversize (backend/tests/test_resource_hubs.py)
/**!
 * @brief Verify datasets endpoint rejects oversized page_size with HTTP 400.
 * @complexity 2
 * @test_edge pagination_oversize_datasets -> {page_size: 101, status: 400}
 */

// --- TestSecurityAuditFixes (backend/tests/test_security_audit_fixes.py)
/**!
 * @brief Verify Class 1 security audit fixes — env-only secrets, crash-early, CORS parsing.
 * @complexity 3
 * @rationale AuthConfig constructor is broken due to pydantic-settings v2 Field(env=...) deprecation
 * @test_edge database_url_postgres_fallback -> POSTGRES_URL is used when DATABASE_URL is unset
 */

// --- test_missing_secret_key_crashes (backend/tests/test_security_audit_fixes.py)
/**!
 * @brief AuthConfig.validate_secret_key raises ValueError when value is empty (crash-early).
 * @complexity 2
 */

// --- test_missing_auth_db_url_crashes (backend/tests/test_security_audit_fixes.py)
/**!
 * @brief AuthConfig.validate_auth_db_url raises ValueError when URL is empty and DEV_MODE is off.
 * @complexity 2
 */

// --- test_auth_db_dev_fallback_works (backend/tests/test_security_audit_fixes.py)
/**!
 * @brief When DEV_MODE=true and AUTH_DATABASE_URL is unset, dev fallback is used without crash.
 * @complexity 2
 */

// --- test_allowed_origins_parsing (backend/tests/test_security_audit_fixes.py)
/**!
 * @brief os.getenv("ALLOWED_ORIGINS").split(",") correctly parses comma-separated origins.
 * @complexity 2
 */

// --- test_cors_wildcard_default (backend/tests/test_security_audit_fixes.py)
/**!
 * @brief When ALLOWED_ORIGINS is not set, default returns ["*"].
 * @complexity 2
 */

// --- test_cors_parsing_single_value (backend/tests/test_security_audit_fixes.py)
/**!
 * @brief Single origin returns single-element list.
 * @complexity 2
 */

// --- test_cors_parsing_with_trailing_spaces (backend/tests/test_security_audit_fixes.py)
/**!
 * @brief Origins with trailing spaces are preserved (no strip).
 * @complexity 2
 */

// --- test_database_url_env_override (backend/tests/test_security_audit_fixes.py)
/**!
 * @brief DATABASE_URL env var takes precedence over POSTGRES_URL.
 * @complexity 2
 */

// --- test_database_url_postgres_fallback (backend/tests/test_security_audit_fixes.py)
/**!
 * @brief POSTGRES_URL is used when DATABASE_URL is unset.
 * @complexity 2
 */

// --- test_database_url_raises_when_both_unset (backend/tests/test_security_audit_fixes.py)
/**!
 * @brief RuntimeError is expected when both DATABASE_URL and POSTGRES_URL are unset (non-dev).
 * @complexity 2
 */

// --- test_auth_config_module_contract (backend/tests/test_security_audit_fixes.py)
/**!
 * @brief AuthConfig contract: the class exists, validators are documented.
 * @complexity 2
 */

// --- test_sql_table_extractor (backend/tests/test_sql_table_extractor.py)
/**!
 * @brief Unit tests for SqlTableExtractor — T017. Verifies three-phase extraction of schema.table references from SQL+Jinja.
 * @complexity 3
 * @layer Tests
 * @test_contract extract_tables_from_sql(str) -> set[str]
 * @test_edge string_literal_false_positive -> filtered out by sqlparse
 * @test_fixture jinja_expr -> INLINE_SQL: "SELECT * FROM {{ source('raw', 'sales') }}"
 */

// --- test_simple_select (backend/tests/test_sql_table_extractor.py)
/**!
 * @brief Happy path: simple SELECT with FROM schema.table.
 * @complexity 2
 */

// --- test_multiple_tables (backend/tests/test_sql_table_extractor.py)
/**!
 * @brief JOIN with multiple schema-qualified tables.
 * @complexity 2
 */

// --- test_empty_input (backend/tests/test_sql_table_extractor.py)
/**!
 * @brief Empty string returns empty set.
 * @complexity 2
 */

// --- test_no_schema_qualified_tables (backend/tests/test_sql_table_extractor.py)
/**!
 * @brief Unqualified table names are NOT matched.
 * @complexity 2
 */

// --- test_case_insensitive (backend/tests/test_sql_table_extractor.py)
/**!
 * @brief Matching is case-insensitive; result is lowercased.
 * @complexity 2
 */

// --- test_string_literal_false_positive (backend/tests/test_sql_table_extractor.py)
/**!
 * @brief Date literal like '2026.04.30' must NOT be matched as schema.table.
 * @complexity 2
 */

// --- test_jinja_string_concat (backend/tests/test_sql_table_extractor.py)
/**!
 * @brief Table reference inside Jinja {{ 'raw.sales' }} as a direct string.
 * @complexity 2
 */

// --- test_jinja_set_block (backend/tests/test_sql_table_extractor.py)
/**!
 * @brief Table name in Jinja {% set %} block string value.
 * @complexity 2
 */

// --- test_mixed_jinja_and_sql (backend/tests/test_sql_table_extractor.py)
/**!
 * @brief Mixed Jinja string and plain SQL schema.table references.
 * @complexity 2
 */

// --- test_cte_with_schema_tables (backend/tests/test_sql_table_extractor.py)
/**!
 * @brief CTE body with schema-qualified table references.
 * @complexity 2
 */

// --- test_jinja_comment_excluded (backend/tests/test_sql_table_extractor.py)
/**!
 * @brief Jinja comment {# ... #} content should not produce table extraction (no string patterns inside comments).
 * @complexity 2
 */

// --- TestStorageAuditFixes (backend/tests/test_storage_audit_fixes.py)
/**!
 * @brief Verify Class 7 typo fix — "repositorys" → "repositories" across all storage/git modules.
 * @complexity 3
 * @test_edge git_typo_regression -> No "repositorys" string exists in storage/git source files
 */

// --- test_repository_typo_fixed (backend/tests/test_storage_audit_fixes.py)
/**!
 * @brief FileCategory.REPOSITORY equals "repositories", NOT "repositorys".
 * @complexity 2
 */

// --- test_repo_path_default_fixed (backend/tests/test_storage_audit_fixes.py)
/**!
 * @brief StorageConfig().repo_path defaults to "repositories".
 * @complexity 2
 */

// --- test_storage_model_compiles (backend/tests/test_storage_audit_fixes.py)
/**!
 * @brief All storage model classes import without errors.
 * @complexity 2
 */

// --- test_backup_category_unchanged (backend/tests/test_storage_audit_fixes.py)
/**!
 * @brief FileCategory.BACKUP still equals "backups" (not affected by typo fix).
 * @complexity 2
 */

// --- test_storage_config_fields_have_correct_types (backend/tests/test_storage_audit_fixes.py)
/**!
 * @brief StorageConfig fields are all strings with correct defaults.
 * @complexity 2
 */

// --- TestStorageConfigMigration (backend/tests/test_storage_config.py)
/**!
 * @brief Verify StorageConfig root_path change from "backups" to "/app/storage",
 * @complexity 3
 */

// --- TestStorageConfigDefaults (backend/tests/test_storage_config.py)
/**!
 * @brief Verify StorageConfig default field values after the root_path change.
 * @complexity 2
 */

// --- test_root_path_default (backend/tests/test_storage_config.py)
/**!
 * @brief StorageConfig().root_path must equal "/app/storage" (was "backups").
 * @complexity 2
 */

// --- test_root_path_is_string (backend/tests/test_storage_config.py)
/**!
 * @brief root_path is always a str (type safety).
 * @complexity 2
 */

// --- test_other_defaults_unchanged (backend/tests/test_storage_config.py)
/**!
 * @brief Other StorageConfig fields were not affected by the root_path change.
 * @complexity 2
 */

// --- test_global_settings_propagates_storage (backend/tests/test_storage_config.py)
/**!
 * @brief GlobalSettings().storage.root_path inherits the StorageConfig default.
 * @complexity 2
 */

// --- test_override_root_path (backend/tests/test_storage_config.py)
/**!
 * @brief Explicit root_path overrides the default.
 * @complexity 2
 */

// --- TestConfigManagerDefaults (backend/tests/test_storage_config.py)
/**!
 * @brief Verify ConfigManager produces correct defaults when no config.json exists.
 * @complexity 2
 */

// --- test_init_falls_to_defaults (backend/tests/test_storage_config.py)
/**!
 * @brief ConfigManager(…nonexistent…) loads defaults when both DB and config.json are absent.
 * @complexity 2
 * @rationale Full path: _load_config → no DB record → _load_from_legacy_file (absent)
 * @test_fixture tmp_path + mocked SessionLocal returning no record.
 */

// --- test_default_config_root_path (backend/tests/test_storage_config.py)
/**!
 * @brief _default_config() hardcodes root_path == "/app/storage" via StorageConfig default.
 * @complexity 2
 */

// --- test_features_from_env_still_applied (backend/tests/test_storage_config.py)
/**!
 * @brief Even without config.json, _apply_features_from_env runs during default init.
 * @complexity 2
 */

// --- TestValidatePath (backend/tests/test_storage_config.py)
/**!
 * @brief Verify ConfigManager.validate_path contract.
 * @complexity 2
 */

// --- test_validate_path_creates_directory (backend/tests/test_storage_config.py)
/**!
 * @brief validate_path creates the target directory and returns (True, "OK").
 * @complexity 2
 * @test_fixture tmp_path ensures no side effects on real storage.
 */

// --- test_validate_path_already_exists (backend/tests/test_storage_config.py)
/**!
 * @brief validate_path succeeds when the directory already exists.
 * @complexity 2
 */

// --- test_validate_path_nonexistent_root (backend/tests/test_storage_config.py)
/**!
 * @brief validate_path returns False for a path under / (non-writable by non-root).
 * @complexity 2
 * @rationale /nonexistent/path cannot be created by a non-root user.
 */

// --- test_validate_path_read_only_parent (backend/tests/test_storage_config.py)
/**!
 * @brief validate_path returns False when the parent directory is not writable.
 * @complexity 2
 */

// --- TestGitPluginConfigIntegration (backend/tests/test_storage_config.py)
/**!
 * @brief Verify GitPlugin uses shared config_manager from src.dependencies (no config.json fallback).
 * @complexity 2
 */

// --- test_git_plugin_uses_shared_config_manager (backend/tests/test_storage_config.py)
/**!
 * @brief GitPlugin.__init__ picks up the shared config_manager from src.dependencies.
 * @complexity 2
 * @test_fixture mock GitService to avoid real git initialisation.
 */

// --- test_git_plugin_fallback_creates_new (backend/tests/test_storage_config.py)
/**!
 * @brief When from src.dependencies import config_manager fails,
 * @complexity 2
 */

// --- TestRegressionGuard (backend/tests/test_storage_config.py)
/**!
 * @brief Guard against regressions in existing test contracts and stale assertions.
 * @complexity 2
 */

// --- test_existing_test_would_fail (backend/tests/test_storage_config.py)
/**!
 * @brief Existing test_storage_audit_fixes.py still asserts root_path=="backups" (WRONG).
 * @complexity 2
 * @rationale The sibling test at test_storage_audit_fixes.py:66 contains
 */

// --- test_storage_settings_endpoint_shape (backend/tests/test_storage_config.py)
/**!
 * @brief The API response shape for storage settings is still StorageConfig.
 * @complexity 2
 */

// --- test_task_manager (backend/tests/test_task_manager.py)
/**!
 * @brief Unit tests for TaskManager lifecycle, CRUD, log buffering, and filtering.
 * @complexity 2
 * @invariant TaskManager state changes are deterministic and testable with mocked dependencies.
 * @layer Core
 * @semantics task-manager, lifecycle, CRUD, log-buffer, filtering, tests
 */

// --- _make_manager (backend/tests/test_task_manager.py)
/**!
 * @complexity 2
 */

// --- _cleanup_manager (backend/tests/test_task_manager.py)
/**!
 * @complexity 2
 */

// --- test_task_persistence (backend/tests/test_task_persistence.py)
/**!
 * @brief Unit tests for TaskPersistenceService.
 * @complexity 2
 * @layer Tests
 * @semantics test, task, persistence, unit_test
 * @test_data valid_task -> {"id": "test-uuid-1", "plugin_id": "backup", "status": "PENDING"}
 */

// --- TestTaskPersistenceHelpers (backend/tests/test_task_persistence.py)
/**!
 * @brief Test suite for TaskPersistenceService static helper methods.
 * @complexity 2
 */

// --- test_json_load_if_needed_none (backend/tests/test_task_persistence.py)
/**!
 * @brief Test _json_load_if_needed with None input.
 * @complexity 2
 */

// --- test_json_load_if_needed_dict (backend/tests/test_task_persistence.py)
/**!
 * @brief Test _json_load_if_needed with dict input.
 * @complexity 2
 */

// --- test_json_load_if_needed_list (backend/tests/test_task_persistence.py)
/**!
 * @brief Test _json_load_if_needed with list input.
 * @complexity 2
 */

// --- test_json_load_if_needed_json_string (backend/tests/test_task_persistence.py)
/**!
 * @brief Test _json_load_if_needed with JSON string.
 * @complexity 2
 */

// --- test_json_load_if_needed_empty_string (backend/tests/test_task_persistence.py)
/**!
 * @brief Test _json_load_if_needed with empty/null strings.
 * @complexity 2
 */

// --- test_json_load_if_needed_plain_string (backend/tests/test_task_persistence.py)
/**!
 * @brief Test _json_load_if_needed with non-JSON string.
 * @complexity 2
 */

// --- test_json_load_if_needed_integer (backend/tests/test_task_persistence.py)
/**!
 * @brief Test _json_load_if_needed with integer.
 * @complexity 2
 */

// --- test_parse_datetime_none (backend/tests/test_task_persistence.py)
/**!
 * @brief Test _parse_datetime with None.
 * @complexity 2
 */

// --- test_parse_datetime_datetime_object (backend/tests/test_task_persistence.py)
/**!
 * @brief Test _parse_datetime with datetime object.
 * @complexity 2
 */

// --- test_parse_datetime_iso_string (backend/tests/test_task_persistence.py)
/**!
 * @brief Test _parse_datetime with ISO string.
 * @complexity 2
 */

// --- test_parse_datetime_invalid_string (backend/tests/test_task_persistence.py)
/**!
 * @brief Test _parse_datetime with invalid string.
 * @complexity 2
 */

// --- test_parse_datetime_integer (backend/tests/test_task_persistence.py)
/**!
 * @brief Test _parse_datetime with non-string, non-datetime.
 * @complexity 2
 */

// --- TestTaskPersistenceService (backend/tests/test_task_persistence.py)
/**!
 * @brief Test suite for TaskPersistenceService CRUD operations.
 * @complexity 2
 * @test_data valid_task -> {"id": "test-uuid-1", "plugin_id": "backup", "status": "PENDING"}
 */

// --- setup_class (backend/tests/test_task_persistence.py)
/**!
 * @brief Setup in-memory test database.
 * @complexity 2
 */

// --- teardown_class (backend/tests/test_task_persistence.py)
/**!
 * @brief Dispose of test database.
 * @complexity 2
 */

// --- setup_method (backend/tests/test_task_persistence.py)
/**!
 * @brief Clean task_records table before each test.
 * @complexity 2
 */

// --- test_persist_task_new (backend/tests/test_task_persistence.py)
/**!
 * @brief Test persisting a new task creates a record.
 * @complexity 2
 * @post TaskRecord exists in database.
 * @pre Empty database.
 */

// --- test_persist_task_update (backend/tests/test_task_persistence.py)
/**!
 * @brief Test updating an existing task.
 * @complexity 2
 * @post Task record updated with new status.
 * @pre Task already persisted.
 */

// --- test_persist_task_with_logs (backend/tests/test_task_persistence.py)
/**!
 * @brief Test persisting a task with log entries.
 * @complexity 2
 * @post Logs serialized as JSON in task record.
 * @pre Task has logs attached.
 */

// --- test_persist_task_failed_extracts_error (backend/tests/test_task_persistence.py)
/**!
 * @brief Test that FAILED task extracts last error message.
 * @complexity 2
 * @post record.error contains last error message.
 * @pre Task has FAILED status with ERROR logs.
 */

// --- test_persist_tasks_batch (backend/tests/test_task_persistence.py)
/**!
 * @brief Test persisting multiple tasks.
 * @complexity 2
 * @post All task records created.
 * @pre Empty database.
 */

// --- test_load_tasks (backend/tests/test_task_persistence.py)
/**!
 * @brief Test loading tasks from database.
 * @complexity 2
 * @post Returns list of Task objects with correct data.
 * @pre Tasks persisted.
 */

// --- test_load_tasks_with_status_filter (backend/tests/test_task_persistence.py)
/**!
 * @brief Test loading tasks filtered by status.
 * @complexity 2
 * @post Returns only tasks matching status filter.
 * @pre Tasks with different statuses persisted.
 */

// --- test_load_tasks_with_limit (backend/tests/test_task_persistence.py)
/**!
 * @brief Test loading tasks with limit.
 * @complexity 2
 * @post Returns at most `limit` tasks.
 * @pre Multiple tasks persisted.
 */

// --- test_delete_tasks (backend/tests/test_task_persistence.py)
/**!
 * @brief Test deleting tasks by ID list.
 * @complexity 2
 * @post Specified tasks deleted, others remain.
 * @pre Tasks persisted.
 */

// --- test_delete_tasks_empty_list (backend/tests/test_task_persistence.py)
/**!
 * @brief Test deleting with empty list (no-op).
 * @complexity 2
 * @post No error, no changes.
 * @pre None.
 */

// --- test_persist_task_with_datetime_in_params (backend/tests/test_task_persistence.py)
/**!
 * @brief Test json_serializable handles datetime in params.
 * @complexity 2
 * @post Params serialized correctly.
 * @pre Task params contain datetime values.
 */

// --- test_persist_task_resolves_environment_slug_to_existing_id (backend/tests/test_task_persistence.py)
/**!
 * @brief Ensure slug-like environment token resolves to environments.id before persisting task.
 * @complexity 2
 * @post task_records.environment_id stores actual environments.id and does not violate FK.
 * @pre environments table contains env with name convertible to provided slug token.
 */

// --- TranslateCorrectionTests (backend/tests/test_translate_corrections.py)
/**!
 * @brief Tests for term correction API endpoints and DictionaryManager correction methods.
 * @complexity 2
 * @layer Tests
 * @semantics tests, translate, corrections, dictionary
 * @test_contract CorrectionFlow ->
 */

// --- test_submit_correction_creates_entry (backend/tests/test_translate_corrections.py)
/**!
 * @brief Verify that a correction creates a new dictionary entry.
 * @complexity 2
 */

// --- test_submit_correction_conflict_detected (backend/tests/test_translate_corrections.py)
/**!
 * @brief Verify conflict detection when entry already exists.
 * @complexity 2
 */

// --- test_submit_correction_overwrite (backend/tests/test_translate_corrections.py)
/**!
 * @brief Verify that correction overwrites existing entry.
 * @complexity 2
 */

// --- test_bulk_corrections_atomic (backend/tests/test_translate_corrections.py)
/**!
 * @brief Verify bulk corrections are applied atomically.
 * @complexity 2
 */

// --- test_api_correction_missing_dict (backend/tests/test_translate_corrections.py)
/**!
 * @brief Verify POST corrections without dictionary_id returns 422.
 * @complexity 2
 */

// --- test_api_bulk_corrections (backend/tests/test_translate_corrections.py)
/**!
 * @brief Verify POST /corrections/bulk works.
 * @complexity 2
 */

// --- TestTranslateExecutorFilter (backend/tests/test_translate_executor_filter.py)
/**!
 * @brief Verify TranslationExecutor._filter_new_keys contracts — key dedup, empty-set, guard triggers.
 * @complexity 3
 * @test_edge null_source_data — None source_data is safely handled
 * @test_invariant new_key_only_filter -> VERIFIED_BY: [test_no_prior_run_returns_all_rows, test_filters_existing_keys, test_composite_keys]
 */

// --- test_no_prior_run_returns_all_rows (backend/tests/test_translate_executor_filter.py)
/**!
 * @complexity 1
 */

// --- test_filters_existing_keys (backend/tests/test_translate_executor_filter.py)
/**!
 * @complexity 1
 */

// --- test_composite_keys (backend/tests/test_translate_executor_filter.py)
/**!
 * @complexity 1
 */

// --- test_all_keys_existing_returns_empty (backend/tests/test_translate_executor_filter.py)
/**!
 * @complexity 1
 */

// --- test_empty_key_cols_returns_all_rows (backend/tests/test_translate_executor_filter.py)
/**!
 * @complexity 1
 */

// --- test_null_source_data_handled (backend/tests/test_translate_executor_filter.py)
/**!
 * @complexity 1
 */

// --- test_prior_run_no_records_returns_all (backend/tests/test_translate_executor_filter.py)
/**!
 * @complexity 1
 */

// --- test_key_cols_none_returns_all (backend/tests/test_translate_executor_filter.py)
/**!
 * @complexity 1
 */

// --- TranslateHistoryTests (backend/tests/test_translate_history.py)
/**!
 * @brief Tests for run history list/detail endpoints and metrics aggregation.
 * @complexity 2
 * @layer Tests
 * @semantics tests, translate, history, metrics
 * @test_contract HistoryFlow ->
 */

// --- test_list_runs_empty (backend/tests/test_translate_history.py)
/**!
 * @brief Verify runs list returns empty result initially.
 * @complexity 2
 */

// --- test_list_runs_with_data (backend/tests/test_translate_history.py)
/**!
 * @brief Verify runs list returns data when runs exist.
 * @complexity 2
 */

// --- test_list_runs_filter_job_id (backend/tests/test_translate_history.py)
/**!
 * @brief Verify filtering runs by job_id works.
 * @complexity 2
 */

// --- test_list_runs_filter_status (backend/tests/test_translate_history.py)
/**!
 * @brief Verify filtering runs by status works.
 * @complexity 2
 */

// --- test_get_run_detail (backend/tests/test_translate_history.py)
/**!
 * @brief Verify run detail returns config_snapshot, records, events.
 * @complexity 2
 */

// --- test_get_job_metrics (backend/tests/test_translate_history.py)
/**!
 * @brief Verify metrics endpoint returns aggregated data.
 * @complexity 2
 */

// --- test_get_all_metrics (backend/tests/test_translate_history.py)
/**!
 * @brief Verify global metrics endpoint returns data.
 * @complexity 2
 */

// --- test_metrics_empty_job (backend/tests/test_translate_history.py)
/**!
 * @brief Verify metrics for job with no runs returns zeros.
 * @complexity 2
 */

// --- test_run_detail_not_found (backend/tests/test_translate_history.py)
/**!
 * @brief Verify 404 on non-existent run detail.
 * @complexity 2
 */

// --- test_list_runs_includes_language_info (backend/tests/test_translate_history.py)
/**!
 * @brief Verify run list includes target_languages, total_translated, and language_stats.
 * @complexity 2
 */

// --- test_metrics_per_language_breakdown (backend/tests/test_translate_history.py)
/**!
 * @brief Verify metrics endpoint returns per_language_metrics.
 * @complexity 2
 */

// --- test_metric_snapshot_stores_per_language (backend/tests/test_translate_history.py)
/**!
 * @brief Verify MetricSnapshot stores per_language_metrics via prune_expired.
 * @complexity 2
 */

// --- test_combined_metrics_live_and_snapshot (backend/tests/test_translate_history.py)
/**!
 * @brief Verify combined metrics merge live + snapshot per-language data.
 * @complexity 2
 */

// --- TranslateJobTests (backend/tests/test_translate_jobs.py)
/**!
 * @brief Tests for translation job CRUD endpoints and service layer with column validation.
 * @complexity 2
 * @layer Tests
 * @semantics tests, translate, jobs, crud, validation
 * @test_contract TranslateJobCRUD ->
 */

// --- valid_job_payload (backend/tests/test_translate_jobs.py)
/**!
 * @brief Standard valid payload for creating a translation job.
 * @complexity 2
 */

// --- MockConfigManager (backend/tests/test_translate_jobs.py)
/**!
 * @brief Mock ConfigManager for service tests that returns a test environment.
 * @complexity 2
 */

// --- db_session (backend/tests/test_translate_jobs.py)
/**!
 * @brief Create a fresh DB session with transaction rollback for each test.
 * @complexity 2
 */

// --- mock_api_deps (backend/tests/test_translate_jobs.py)
/**!
 * @brief Override FastAPI dependencies (including get_db with in-memory SQLite) for API route tests.
 * @complexity 2
 * @rationale Uses the same in-memory SQLite engine as service tests to avoid real PostgreSQL dependency.
 * @rejected Mocking get_db with MagicMock — the route handlers need a real session for ORM queries.
 */

// --- client (backend/tests/test_translate_jobs.py)
/**!
 * @brief FastAPI TestClient for API route tests.
 * @complexity 2
 */

// --- test_create_job_valid (backend/tests/test_translate_jobs.py)
/**!
 * @brief Verify that a valid job payload creates a job successfully.
 * @complexity 2
 */

// --- test_create_job_missing_translation_column (backend/tests/test_translate_jobs.py)
/**!
 * @brief Verify that creating a job with datasource but no translation column raises ValueError.
 * @complexity 2
 */

// --- test_create_job_invalid_upsert_strategy (backend/tests/test_translate_jobs.py)
/**!
 * @brief Verify that an invalid upsert strategy is rejected.
 * @complexity 2
 */

// --- test_get_job (backend/tests/test_translate_jobs.py)
/**!
 * @brief Verify that a job can be retrieved by ID.
 * @complexity 2
 */

// --- test_get_job_not_found (backend/tests/test_translate_jobs.py)
/**!
 * @brief Verify that getting a non-existent job raises ValueError.
 * @complexity 2
 */

// --- test_list_jobs (backend/tests/test_translate_jobs.py)
/**!
 * @brief Verify that listing jobs returns all created jobs.
 * @complexity 2
 */

// --- test_list_jobs_with_status_filter (backend/tests/test_translate_jobs.py)
/**!
 * @brief Verify that listing jobs with a status filter works.
 * @complexity 2
 */

// --- test_update_job (backend/tests/test_translate_jobs.py)
/**!
 * @brief Verify that a job can be updated.
 * @complexity 2
 */

// --- test_delete_job (backend/tests/test_translate_jobs.py)
/**!
 * @brief Verify that a job can be deleted.
 * @complexity 2
 */

// --- test_duplicate_job (backend/tests/test_translate_jobs.py)
/**!
 * @brief Verify that a job can be duplicated.
 * @complexity 2
 */

// --- test_duplicate_job_custom_name (backend/tests/test_translate_jobs.py)
/**!
 * @brief Verify that a job can be duplicated with a custom name.
 * @complexity 2
 */

// --- test_detect_virtual_columns (backend/tests/test_translate_jobs.py)
/**!
 * @brief Verify virtual column detection from column metadata.
 * @complexity 2
 */

// --- test_get_dialect_from_database (backend/tests/test_translate_jobs.py)
/**!
 * @brief Verify dialect extraction from Superset database records.
 * @complexity 2
 */

// --- test_get_dialect_from_database_unsupported (backend/tests/test_translate_jobs.py)
/**!
 * @brief Verify that unsupported dialects raise ValueError.
 * @complexity 2
 */

// --- test_api_create_job (backend/tests/test_translate_jobs.py)
/**!
 * @brief Verify POST /api/translate/jobs returns 201 with valid payload.
 * @complexity 2
 */

// --- test_api_list_jobs (backend/tests/test_translate_jobs.py)
/**!
 * @brief Verify GET /api/translate/jobs returns 200.
 * @complexity 2
 */

// --- test_api_get_job_not_found (backend/tests/test_translate_jobs.py)
/**!
 * @brief Verify GET non-existent job returns 404.
 * @complexity 2
 */

// --- test_api_delete_job_not_found (backend/tests/test_translate_jobs.py)
/**!
 * @brief Verify DELETE non-existent job returns 404.
 * @complexity 2
 */

// --- test_api_duplicate_job_not_found (backend/tests/test_translate_jobs.py)
/**!
 * @brief Verify duplicating a non-existent job returns 404.
 * @complexity 2
 */

// --- test_api_create_job_422_missing_name (backend/tests/test_translate_jobs.py)
/**!
 * @brief Verify POST with missing required fields returns 422.
 * @complexity 2
 */

// --- test_api_datasource_columns_missing_env (backend/tests/test_translate_jobs.py)
/**!
 * @brief Verify datasource columns endpoint without env_id returns 422.
 * @complexity 2
 */

// --- test_api_datasource_columns_bad_env (backend/tests/test_translate_jobs.py)
/**!
 * @brief Verify datasource columns with unknown env returns 400.
 * @complexity 2
 */

// --- test_api_update_job_not_found (backend/tests/test_translate_jobs.py)
/**!
 * @brief Verify PUT non-existent job returns 404.
 * @complexity 2
 */

// --- TranslateSchedulerTests (backend/tests/test_translate_scheduler.py)
/**!
 * @brief Tests for TranslationScheduler CRUD and APScheduler integration.
 * @complexity 2
 * @layer Tests
 * @semantics tests, translate, scheduler
 * @test_contract ScheduleFlow ->
 */

// --- test_create_schedule (backend/tests/test_translate_scheduler.py)
/**!
 * @brief Verify schedule creation with valid params.
 * @complexity 2
 */

// --- test_update_schedule (backend/tests/test_translate_scheduler.py)
/**!
 * @brief Verify schedule update.
 * @complexity 2
 */

// --- test_delete_schedule (backend/tests/test_translate_scheduler.py)
/**!
 * @brief Verify schedule deletion.
 * @complexity 2
 */

// --- test_enable_disable_schedule (backend/tests/test_translate_scheduler.py)
/**!
 * @brief Verify enable/disable toggle.
 * @complexity 2
 */

// --- test_get_schedule_not_found (backend/tests/test_translate_scheduler.py)
/**!
 * @brief Verify ValueError on getting non-existent schedule.
 * @complexity 2
 */

// --- test_list_active_schedules (backend/tests/test_translate_scheduler.py)
/**!
 * @brief Verify listing only active schedules.
 * @complexity 2
 */

// --- test_get_next_executions (backend/tests/test_translate_scheduler.py)
/**!
 * @brief Verify next execution time computation.
 * @complexity 2
 */

// --- test_get_next_executions_invalid (backend/tests/test_translate_scheduler.py)
/**!
 * @brief Verify invalid cron returns empty list.
 * @complexity 2
 */

// --- TestTranslateSchedulerExecution (backend/tests/test_translate_scheduler_execution.py)
/**!
 * @brief Verify execute_scheduled_translation contracts — trigger_type dispatch, baseline expiry fallback.
 * @complexity 3
 * @test_edge execution_error_handled — run marked FAILED, schedule tracking updated
 * @test_invariant trigger_type_dispatch -> VERIFIED_BY: [test_new_key_only_mode, test_baseline_expired_fallback, test_full_mode_default]
 */

// --- test_new_key_only_mode (backend/tests/test_translate_scheduler_execution.py)
/**!
 * @complexity 1
 */

// --- test_baseline_expired_fallback (backend/tests/test_translate_scheduler_execution.py)
/**!
 * @complexity 1
 */

// --- test_full_mode_default (backend/tests/test_translate_scheduler_execution.py)
/**!
 * @complexity 1
 */

// --- test_inactive_schedule_skips (backend/tests/test_translate_scheduler_execution.py)
/**!
 * @complexity 1
 */

// --- test_schedule_not_found_skips (backend/tests/test_translate_scheduler_execution.py)
/**!
 * @complexity 1
 */

// --- test_baseline_expired_full_mode (backend/tests/test_translate_scheduler_execution.py)
/**!
 * @complexity 1
 */

// --- test_execution_error_handled (backend/tests/test_translate_scheduler_execution.py)
/**!
 * @complexity 1
 */

// --- TestTranslateSchedulerGuard (backend/tests/test_translate_scheduler_guard.py)
/**!
 * @brief Verify execute_scheduled_translation concurrency guard and stale-PENDING clearance contracts.
 * @complexity 3
 * @test_edge multiple_stale_pending_all_cleared — multiple stale PENDING runs → all cleared as FAILED, execution proceeds
 * @test_invariant stale_pending_clearance -> VERIFIED_BY: [test_stale_pending_cleared_and_proceeds, test_multiple_stale_pending_all_cleared]
 */

// --- test_concurrent_run_skips (backend/tests/test_translate_scheduler_guard.py)
/**!
 * @complexity 1
 */

// --- test_recent_pending_run_not_stale (backend/tests/test_translate_scheduler_guard.py)
/**!
 * @complexity 1
 */

// --- test_stale_pending_cleared_and_proceeds (backend/tests/test_translate_scheduler_guard.py)
/**!
 * @complexity 1
 */

// --- test_multiple_stale_pending_all_cleared (backend/tests/test_translate_scheduler_guard.py)
/**!
 * @complexity 1
 */

// --- docker.backend.Dockerfile (docker/backend.Dockerfile)
/**!
 * @brief Backend Dockerfile — Python 3.11 slim + Playwright + entrypoint с установкой сертификатов.
 * @complexity 3
 * @layer Infrastructure
 * @post Образ с backend API, Playwright, entrypoint для bootstrap admin и установки сертификатов.
 * @pre Docker builder context — корень проекта. backend/ и docker/ доступны.
 */

// --- docker.backend.entrypoint (docker/backend.entrypoint.sh)
/**!
 * @brief Container entrypoint — установка корп. сертификатов, Playwright (lazy), bootstrap admin,
 * @complexity 4
 */

// --- docker.backend.entrypoint.install_certificates (docker/backend.entrypoint.sh)
/**!
 * @brief Устанавливает корпоративные .crt сертификаты из CERTS_PATH в системное хранилище Debian.
 * @complexity 3
 * @pre CERTS_PATH указывает на директорию (может быть пуста или не существовать).
 */

// --- docker.backend.entrypoint.bootstrap_admin (docker/backend.entrypoint.sh)
/**!
 * @brief Создание admin пользователя из переменных окружения (идемпотентно).
 * @complexity 2
 * @layer Infrastructure
 * @post Admin пользователь создан в БД (если ещё не существовал).
 * @pre INITIAL_ADMIN_CREATE=true, INITIAL_ADMIN_USERNAME и INITIAL_ADMIN_PASSWORD заданы.
 */

// --- docker.backend.entrypoint.install_playwright (docker/backend.entrypoint.sh)
/**!
 * @brief Lazy установка Playwright Chromium (~377 MB) при первом запуске.
 * @complexity 2
 * @layer Infrastructure
 * @post Chromium установлен в PLAYWRIGHT_BROWSERS_PATH.
 * @pre ~/.cache/ms-playwright доступен (можно закешировать volume).
 */

// --- docker.frontend.Dockerfile (docker/frontend.Dockerfile)
/**!
 * @brief Frontend Dockerfile — сборка SvelteKit (node:20) + nginx runtime с опциональным SSL.
 * @complexity 3
 * @layer Infrastructure
 * @post nginx:alpine образ со статикой SvelteKit, entrypoint для выбора HTTP/SSL конфига.
 * @pre Docker builder context — корень проекта. frontend/ и docker/ доступны.
 */

// --- docker.frontend.entrypoint (docker/frontend.entrypoint.sh)
/**!
 * @brief Entrypoint для nginx-контейнера — установка корп. CA-сертификатов в Alpine,
 * @complexity 3
 */

// --- docker.frontend.entrypoint.install_ca_certificates (docker/frontend.entrypoint.sh)
/**!
 * @brief Устанавливает .crt файлы из /opt/certs в системное хранилище Alpine.
 * @complexity 2
 * @post Сертификаты скопированы в /usr/local/share/ca-certificates/ и добавлены в trust.
 * @pre /opt/certs может быть пуст или не существовать.
 */

// --- docker.frontend.entrypoint.select_nginx_config (docker/frontend.entrypoint.sh)
/**!
 * @brief Определяет, есть ли сертификаты для SSL, и копирует нужный nginx конфиг.
 * @complexity 2
 * @post Если есть оба файла — /etc/nginx/ssl/ создан, server.crt/key скопированы,
 * @pre /opt/certs/server.crt и /opt/certs/server.key — опциональные SSL-сертификаты.
 */

// --- docker.nginx.ssl.conf (docker/nginx.ssl.conf)
/**!
 * @brief Nginx config с опциональным SSL — HTTP (порт 80) + HTTPS (порт 443).
 * @complexity 3
 */

// --- AuthFixture (frontend/e2e/fixtures/auth.fixture.js)
/**!
 * @brief Playwright fixture for authenticated browser contexts.
 * @complexity 2
 * @ux_state LoginError -> Error banner visible on failed login.
 */

// --- GlobalSetup (frontend/e2e/fixtures/global-setup.js)
/**!
 * @brief Pre-flight check before any E2E tests run.
 * @complexity 2
 * @post Exits with 1 if either service is down, else sets ENV vars.
 * @pre Backend and frontend must be reachable.
 */

// --- ApiHelper (frontend/e2e/helpers/api.helper.js)
/**!
 * @brief Helper for backend API calls in E2E tests (settings CRUD, etc.)
 * @complexity 2
 */

// --- frontend/e2e/helpers/api.helper.js::getToken (frontend/e2e/helpers/api.helper.js)
/**!
 */

// --- frontend/e2e/helpers/api.helper.js::apiGet (frontend/e2e/helpers/api.helper.js)
/**!
 */

// --- frontend/e2e/helpers/api.helper.js::apiPost (frontend/e2e/helpers/api.helper.js)
/**!
 */

// --- frontend/e2e/helpers/api.helper.js::apiPut (frontend/e2e/helpers/api.helper.js)
/**!
 */

// --- frontend/e2e/helpers/api.helper.js::apiDelete (frontend/e2e/helpers/api.helper.js)
/**!
 */

// --- run-enterprise-clean-e2e (frontend/e2e/run-enterprise-clean-e2e.sh)
/**!
 * @brief Enterprise Clean E2E Orchestrator — полный протокол тестирования пустого образа перед передачей.
 * @complexity 5
 */

// --- EnterpriseCleanSetupE2E (frontend/e2e/tests/enterprise-clean-setup.e2e.js)
/**!
 * @brief Stage 1: E2E test for enterprise-clean empty image — first-run setup via StartupEnvironmentWizard.
@@RATIONALE All 4 tests pass after fixing: (1) button ambiguity — zero-state page and wizard modal both have 'Начать настройку' button, resolved by scoping to wizard modal via .fixed.inset-0.z-50; (2) wizard detection — changed from waitForSelector('text=...') to getByText() with regex for locale-robust matching; (3) form fill — connections.* i18n keys missing in Docker build, switched to placeholder-based locators scoped within wizard; (4) settings navigation — use authPage fixture for consistent login
@@REJECTED Using waitForSelector('text=...') fails for locale-sensitive text. getByLabel() with connections.* keys fails when i18n namespace missing. Using page.goto() with authPage fixture causes page reload issues
 * @complexity 4
 */

// --- GitE2E (frontend/e2e/tests/git.e2e.js)
/**!
 * @brief E2E tests for Git integration — config CRUD, connection test.
 * @complexity 3
 * @ux_state ConnectionTested -> Success/failure toast feedback.
 */

// --- LiveProjectCheckE2E (frontend/e2e/tests/live-project-check.e2e.js)
/**!
 * @brief Stage 2: E2E test for live project verification — validates dashboard LLM analysis,
 * @complexity 4
 */

// --- LoginE2E (frontend/e2e/tests/login.e2e.js)
/**!
 * @brief E2E tests for login/logout flow.
 * @complexity 3
 * @ux_state InvalidCredentials -> Error toast or message shown.
 */

// --- MigrationE2E (frontend/e2e/tests/migration.e2e.js)
/**!
 * @brief E2E tests for dataset/environment migration and sync.
 * @complexity 3
 * @ux_state MappingsLoaded -> Synchronized resources table populated.
 */

// --- SettingsE2E (frontend/e2e/tests/settings.e2e.js)
/**!
 * @brief E2E tests for Settings page — environments, LLM providers, Git config.
 * @complexity 3
 * @ux_state EnvironmentAdded -> New Superset env appears in list.
 */

// --- SmokeE2E (frontend/e2e/tests/smoke.e2e.js)
/**!
 * @brief Golden-path smoke test: login → settings → translate → git → verify.
 * @complexity 4
 * @rationale Single sequential test verifies the entire stack without per-test setup overhead.
 * @ux_state FullCycle -> All key user journeys executed sequentially.
 */

// --- TranslationE2E (frontend/e2e/tests/translation.e2e.js)
/**!
 * @brief E2E tests for the translation job lifecycle: create → preview → accept → run.
 * @complexity 3
 * @ux_state JobRunning -> Run object created with PENDING status.
 */

// --- PlaywrightConfig (frontend/playwright.config.js)
/**!
 * @brief Playwright E2E test configuration for superset-tools frontend.
 * @complexity 3
 * @invariant All E2E tests run against a fully deployed stack (DB + backend + frontend).
 * @ux_state ConfigLoaded -> Browser contexts are created with predefined env settings.
 */

// --- handleValidate:Function (frontend/src/components/DashboardGrid.svelte)
/**!
 * @brief Triggers dashboard validation task.
 */

// --- openGit:Function (frontend/src/components/DashboardGrid.svelte)
/**!
 * @brief Opens the Git management modal for a dashboard.
 */

// --- initializeForm:Function (frontend/src/components/DynamicForm.svelte)
/**!
 * @brief Initialize form data with default values from the schema.
 * @post formData is initialized with default values or empty strings.
 * @pre schema is provided and contains properties.
 */

// --- Footer (frontend/src/components/Footer.svelte)
/**!
 * @brief Displays the application footer with copyright information.
 * @complexity 3
 * @layer UI
 * @semantics footer, layout, copyright
 */

// --- updateMapping:Function (frontend/src/components/MappingTable.svelte)
/**!
 * @brief Updates a mapping for a specific source database.
 * @post Parent callback receives normalized mapping payload.
 * @pre sourceUuid and targetUuid are provided.
 */

// --- getSuggestion:Function (frontend/src/components/MappingTable.svelte)
/**!
 * @brief Finds a suggestion for a source database.
 * @post Returns matching suggestion object or undefined.
 * @pre sourceUuid is provided.
 */

// --- MissingMappingModal (frontend/src/components/MissingMappingModal.svelte)
/**!
 * @brief Prompts the user to provide a database mapping when one is missing during migration.
 * @complexity 3
 * @invariant Modal blocks migration progress until resolved or cancelled.
 * @layer Feature
 * @semantics modal, mapping, prompt, migration
 */

// --- resolve:Function (frontend/src/components/MissingMappingModal.svelte)
/**!
 * @brief Resolves the missing mapping via callback prop.
 * @post Parent callback receives mapping payload and modal closes.
 * @pre selectedTargetUuid must be set.
 */

// --- cancel:Function (frontend/src/components/MissingMappingModal.svelte)
/**!
 * @brief Cancels the mapping resolution modal.
 * @post Parent cancel callback is invoked and modal is hidden.
 * @pre Modal is open.
 */

// --- Navbar (frontend/src/components/Navbar.svelte)
/**!
 * @brief Main navigation bar for the application.
 * @complexity 3
 * @layer UI
 * @semantics navbar, navigation, header, layout
 * @ux_state Authenticated -> User identity and logout action are rendered.
 */

// --- PasswordPrompt (frontend/src/components/PasswordPrompt.svelte)
/**!
 * @brief A modal component to prompt the user for database passwords when a migration task is paused.
 * @complexity 3
 * @layer UI
 * @semantics password, prompt, modal, input, security
 */

// --- handleSubmit:Function (frontend/src/components/PasswordPrompt.svelte)
/**!
 * @brief Validates and forwards passwords to resume the task.
 * @post Parent resume callback receives passwords payload.
 * @pre All database passwords must be entered.
 */

// --- handleCancel:Function (frontend/src/components/PasswordPrompt.svelte)
/**!
 * @brief Cancels the password prompt.
 * @post Parent cancel callback is invoked and show is set to false.
 * @pre Modal is open.
 */

// --- handleSort:Function (frontend/src/components/RepositoryDashboardGrid.svelte)
/**!
 * @brief Toggles sort direction or changes sort column.
 * @post sortColumn and sortDirection state updated.
 * @pre column name is provided.
 */

// --- handleSelectionChange:Function (frontend/src/components/RepositoryDashboardGrid.svelte)
/**!
 * @brief Handles individual checkbox changes.
 * @post selectedIds array updated.
 * @pre dashboard ID and checked status provided.
 */

// --- handleSelectAll:Function (frontend/src/components/RepositoryDashboardGrid.svelte)
/**!
 * @brief Handles select all checkbox.
 * @post selectedIds array updated for all paginated items.
 * @pre checked status provided.
 */

// --- goToPage:Function (frontend/src/components/RepositoryDashboardGrid.svelte)
/**!
 * @brief Changes current page.
 * @post currentPage state updated if within valid range.
 * @pre page index is provided.
 */

// --- getRepositoryStatusToken:Function (frontend/src/components/RepositoryDashboardGrid.svelte)
/**!
 * @brief Returns normalized repository status token for a dashboard.
 * @post Returns one of loading|no_repo|synced|changes|behind_remote|ahead_remote|diverged|error.
 * @pre Dashboard exists.
 */

// --- isRepositoryReady:Function (frontend/src/components/RepositoryDashboardGrid.svelte)
/**!
 * @brief Determines whether git actions can run for a dashboard.
 */

// --- invalidateRepositoryStatuses:Function (frontend/src/components/RepositoryDashboardGrid.svelte)
/**!
 * @brief Marks dashboard statuses as loading so they are refetched.
 */

// --- resolveRepositoryStatusToken:Function (frontend/src/components/RepositoryDashboardGrid.svelte)
/**!
 * @brief Converts git status payload into a stable UI status token.
 */

// --- loadRepositoryStatuses:Function (frontend/src/components/RepositoryDashboardGrid.svelte)
/**!
 * @brief Hydrates repository status map for dashboards in repository mode.
 */

// --- runBulkGitAction:Function (frontend/src/components/RepositoryDashboardGrid.svelte)
/**!
 * @brief Executes git action for selected dashboards with limited parallelism.
 */

// --- handleBulkSync:Function (frontend/src/components/RepositoryDashboardGrid.svelte)
/**!
 */

// --- handleBulkCommit:Function (frontend/src/components/RepositoryDashboardGrid.svelte)
/**!
 */

// --- handleBulkPull:Function (frontend/src/components/RepositoryDashboardGrid.svelte)
/**!
 */

// --- handleBulkPush:Function (frontend/src/components/RepositoryDashboardGrid.svelte)
/**!
 */

// --- handleBulkDelete:Function (frontend/src/components/RepositoryDashboardGrid.svelte)
/**!
 * @brief Removes selected repositories from storage and binding table.
 */

// --- handleManageSelected:Function (frontend/src/components/RepositoryDashboardGrid.svelte)
/**!
 * @brief Opens Git manager for exactly one selected dashboard.
 */

// --- resolveDashboardRef:Function (frontend/src/components/RepositoryDashboardGrid.svelte)
/**!
 * @brief Resolves dashboard slug from payload fields.
 * @post Returns slug string or null if unavailable.
 * @pre Dashboard metadata is provided.
 */

// --- openGitManagerForDashboard:Function (frontend/src/components/RepositoryDashboardGrid.svelte)
/**!
 * @brief Opens Git manager for provided dashboard metadata.
 */

// --- handleInitializeRepositories:Function (frontend/src/components/RepositoryDashboardGrid.svelte)
/**!
 * @brief Opens Git manager from bulk actions to initialize selected repository.
 */

// --- getSortStatusValue:Function (frontend/src/components/RepositoryDashboardGrid.svelte)
/**!
 * @brief Returns sort value for status column based on mode.
 */

// --- getStatusLabel:Function (frontend/src/components/RepositoryDashboardGrid.svelte)
/**!
 * @brief Returns localized label for status column.
 */

// --- getStatusBadgeClass:Function (frontend/src/components/RepositoryDashboardGrid.svelte)
/**!
 * @brief Returns badge style for status column.
 */

// --- TaskHistory (frontend/src/components/TaskHistory.svelte)
/**!
 * @brief Displays a list of recent tasks with their status and allows selecting them for viewing logs.
 * @complexity 3
 * @layer UI
 * @semantics task, history, list, status, monitoring
 * @type {string | undefined} — if set, only shows tasks with this plugin_id (e.g. "superset-migration")
 */

// --- getStatusColor:Function (frontend/src/components/TaskHistory.svelte)
/**!
 * @brief Returns the CSS color class for a given task status.
 * @post Returns tailwind color class string.
 * @pre status string is provided.
 */

// --- onDestroy:Function (frontend/src/components/TaskHistory.svelte)
/**!
 * @brief Cleans up the polling interval when the component is destroyed.
 * @post Polling interval is cleared.
 * @pre Component is being destroyed.
 */

// --- TaskList (frontend/src/components/TaskList.svelte)
/**!
 * @brief Displays a list of tasks with their status and execution details.
 * @complexity 3
 * @layer Component
 * @semantics tasks, list, status, history
 */

// --- handleTaskClick:Function (frontend/src/components/TaskList.svelte)
/**!
 * @brief Forwards the selected task through a callback prop.
 * @post Parent callback receives task id and task payload.
 * @pre taskId is provided.
 */

// --- TaskLogViewer (frontend/src/components/TaskLogViewer.svelte)
/**!
 * @brief Displays task logs inline (in drawer) or as modal. Merges real-time WebSocket logs with polled historical logs.
 * @complexity 3
 * @invariant Real-time logs are always appended without duplicates.
 * @layer UI
 * @semantics task, log, viewer, inline, realtime
 * @ux_state Loading -> Default
 */

// --- connect:Function (frontend/src/components/TaskRunner.svelte)
/**!
 * @brief Establishes WebSocket connection with exponential backoff and filter parameters.
 * @post WebSocket instance created and listeners attached.
 * @pre selectedTask must be set in the store.
 */

// --- handleFilterChange:Function (frontend/src/components/TaskRunner.svelte)
/**!
 * @brief Handles filter changes and reconnects WebSocket with new parameters.
 * @post WebSocket reconnected with new filter parameters, logs cleared.
 * @pre event.detail contains source and level filter values.
 */

// --- fetchTargetDatabases:Function (frontend/src/components/TaskRunner.svelte)
/**!
 * @brief Fetches available databases from target environment for mapping.
 * @post targetDatabases array populated with available databases.
 * @pre selectedTask must have to_env parameter set.
 */

// --- handleMappingResolve:Function (frontend/src/components/TaskRunner.svelte)
/**!
 * @brief Resolves missing database mapping and continues migration.
 * @post Mapping created in backend, task resumed with resolution params.
 * @pre event.detail contains sourceDbUuid, targetDbUuid, targetDbName.
 */

// --- handlePasswordResume:Function (frontend/src/components/TaskRunner.svelte)
/**!
 * @brief Submits passwords and resumes paused migration task.
 * @post Task resumed with passwords, connection status restored to connected.
 * @pre event.detail contains passwords object.
 */

// --- startDataTimeout:Function (frontend/src/components/TaskRunner.svelte)
/**!
 * @brief Starts timeout timer to detect idle connection.
 * @post waitingForData set to true after 5 seconds if no data received.
 * @pre connectionStatus is 'connected'.
 */

// --- resetDataTimeout:Function (frontend/src/components/TaskRunner.svelte)
/**!
 * @brief Resets data timeout timer when new data arrives.
 * @post waitingForData reset to false, new timeout started.
 * @pre dataTimeout must be set.
 */

// --- Toast (frontend/src/components/Toast.svelte)
/**!
 * @brief Displays transient notifications (toasts) in the bottom-right corner.
 * @complexity 3
 * @layer UI
 * @semantics toast, notification, feedback, ui
 * @ux_state Visible -> Active toast items render with type-specific emphasis.
 */

// --- TaskLogViewerTest:Module (frontend/src/components/__tests__/task_log_viewer.test.js)
/**!
 * @brief Unit tests for TaskLogViewer component by mounting it and observing the DOM.
 * @invariant Duplicate logs are never appended. Polling only active for in-progress tasks.
 * @layer UI (Tests)
 * @semantics tests, task-log, viewer, mount, components
 * @test_contract TaskLogViewerPropsAndLogStream -> RenderedLogTimeline
 * @test_edge duplicate_realtime_entry -> Existing log is not duplicated when repeated in realtime stream.
 * @test_fixture valid_viewer -> INLINE_JSON
 * @test_invariant no_duplicate_log_rows -> VERIFIED_BY: [historical_and_realtime_merge, duplicate_realtime_entry]
 * @test_scenario historical_and_realtime_merge -> Historical logs render and realtime logs append without duplication.
 */

// --- verifySessionAndAccess:Function (frontend/src/components/auth/ProtectedRoute.svelte)
/**!
 * @brief Validates session and optional permission gate before allowing protected content render.
 * @data_contract Input[AuthState, requiredPermission, fallbackPath] -> Output[RouteDecision{login_redirect|fallback_redirect|grant}]
 * @post hasRouteAccess=true only when user identity is valid and permission check (if provided) passes.
 * @pre auth store is initialized and can provide token/user state; navigation is available.
 * @side_effect Mutates auth loading/user state, performs API I/O to /auth/me, and may redirect.
 */

// --- handleCreateBackup:Function (frontend/src/components/backups/BackupManager.svelte)
/**!
 * @brief Triggers a new backup task for the selected environment.
 * @post A new task is created on the backend.
 * @pre selectedEnvId must be a valid environment ID.
 * @return {Promise<void>}
 * @side_effect Dispatches a toast notification.
 */

// --- handleUpdateSchedule:Function (frontend/src/components/backups/BackupManager.svelte)
/**!
 * @brief Updates the backup schedule for the selected environment.
 * @post Environment config is updated on the backend.
 * @pre selectedEnvId must be set.
 */

// --- loadBranches:Function (frontend/src/components/git/BranchSelector.svelte)
/**!
 * @brief Загружает список веток для дашборда.
 * @post branches обновлен.
 * @pre dashboardId is provided.
 */

// --- handleSelect:Function (frontend/src/components/git/BranchSelector.svelte)
/**!
 * @brief Handles branch selection from dropdown.
 * @post handleCheckout is called with selected branch.
 * @pre event contains branch name.
 */

// --- handleCheckout:Function (frontend/src/components/git/BranchSelector.svelte)
/**!
 * @brief Переключает текущую ветку.
 * @param {string} branchName - Имя ветки.
 * @post currentBranch обновлен, родительский callback вызван.
 */

// --- handleCreate:Function (frontend/src/components/git/BranchSelector.svelte)
/**!
 * @brief Создает новую ветку.
 * @post Новая ветка создана и загружена; showCreate reset.
 * @pre newBranchName is not empty.
 */

// --- loadHistory:Function (frontend/src/components/git/CommitHistory.svelte)
/**!
 * @brief Fetch commit history from the backend.
 * @post history state is updated.
 * @pre dashboardId is valid.
 */

// --- handleGenerateMessage:Function (frontend/src/components/git/CommitModal.svelte)
/**!
 * @brief Generates a commit message using LLM.
 */

// --- loadStatus:Function (frontend/src/components/git/CommitModal.svelte)
/**!
 * @brief Загружает текущий статус репозитория и diff.
 * @pre dashboardId должен быть валидным.
 */

// --- handleCommit:Function (frontend/src/components/git/CommitModal.svelte)
/**!
 * @brief Создает коммит с указанным сообщением.
 * @post Коммит создан и модальное окно закрыто.
 * @pre message не должно быть пустым.
 */

// --- loadStatus:Watcher (frontend/src/components/git/DeploymentModal.svelte)
/**!
 */

// --- normalizeEnvStage:Function (frontend/src/components/git/DeploymentModal.svelte)
/**!
 * @brief Normalize environment stage with legacy production fallback.
 * @post Returns DEV/PREPROD/PROD.
 */

// --- resolveEnvUrl:Function (frontend/src/components/git/DeploymentModal.svelte)
/**!
 * @brief Resolve environment URL from consolidated or git-specific payload shape.
 * @post Returns stable URL string.
 */

// --- loadEnvironments:Function (frontend/src/components/git/DeploymentModal.svelte)
/**!
 * @brief Fetch available environments from API.
 * @post environments state is populated.
 * @side_effect Updates environments state.
 */

// --- handleDeploy:Function (frontend/src/components/git/DeploymentModal.svelte)
/**!
 * @brief Trigger deployment to selected environment.
 * @post Deploy request finishes and modal closes on success.
 * @pre selectedEnv must be set.
 * @side_effect Triggers API call, closes modal, shows toast.
 */

// --- GitInitPanel (frontend/src/components/git/GitInitPanel.svelte)
/**!
 * @brief Git initialization panel: select config, create remote repo, init local repo.
 * @complexity 3
 * @layer UI
 * @ux_state Loading -> Buttons disabled, spinner visible.
 */

// --- GitManager (frontend/src/components/git/GitManager.svelte)
/**!
 * @brief Central Git management UI — thin shell delegating to sub-panels and composable handlers.
 * @complexity 4
 * @layer UI
 * @rationale Decomposed from 1220→~370 lines by extracting sub-panels, utils, and composable handlers per INV_7.
 * @rejected Keeping all logic inline was rejected because it exceeded 150-line contract limit.
 * @ux_state MergeDialog -> Recovery overlay.
 */

// --- GitMergeDialog (frontend/src/components/git/GitMergeDialog.svelte)
/**!
 * @brief Unfinished merge recovery dialog: abort, continue, resolve conflicts.
 * @complexity 3
 * @layer UI
 * @ux_state Loading -> Recovery state loading spinner.
 */

// --- GitOperationsPanel (frontend/src/components/git/GitOperationsPanel.svelte)
/**!
 * @brief Git server operations panel: pull, push, and deploy actions.
 * @complexity 2
 * @layer UI
 */

// --- GitReleasePanel (frontend/src/components/git/GitReleasePanel.svelte)
/**!
 * @brief Git release panel: promote branches via MR or direct mode.
 * @complexity 3
 * @layer UI
 * @ux_state Advanced -> Expandable branch/reason settings.
 */

// --- GitWorkspacePanel (frontend/src/components/git/GitWorkspacePanel.svelte)
/**!
 * @brief Git workspace panel: sync, commit message input, diff viewer, commit action.
 * @complexity 3
 * @layer UI
 * @ux_state Error -> Toast on failure.
 */

// --- GitManagerUnfinishedMergeIntegrationTest:Module (frontend/src/components/git/__tests__/git_manager.unfinished_merge.integration.test.js)
/**!
 * @brief Protect unresolved-merge dialog contract in GitManager pull flow.
 * @semantics git-manager, unfinished-merge, dialog, integration-test
 */

// --- UseGitManager (frontend/src/components/git/useGitManager.js)
/**!
 * @brief Composable for GitManager handler functions — extracted to reduce component size per INV_7.
 * @complexity 3
 * @rationale Extracted handler logic from GitManager (1220→~350 lines) to meet INV_7 <150 line contract limit.
 */

// --- DocPreview (frontend/src/components/llm/DocPreview.svelte)
/**!
 * @brief UI component for previewing generated dataset documentation before saving.
 * @complexity 3
 * @layer UI
 * @type {Object}
 * @ux_state Loading -> Default
 */

// --- ProviderConfig (frontend/src/components/llm/ProviderConfig.svelte)
/**!
 * @brief UI form for managing LLM provider configurations.
 * @complexity 3
 * @layer UI
 * @ux_state Loading -> Default
 */

// --- ValidationReport (frontend/src/components/llm/ValidationReport.svelte)
/**!
 * @brief Displays the results of an LLM-based dashboard validation task.
 * @complexity 3
 * @layer UI
 */

// --- provider_config_edit_contract_tests:Function (frontend/src/components/llm/__tests__/provider_config.integration.test.js)
/**!
 * @brief Validate edit and delete handler wiring plus normalized edit form state mapping.
 * @post Contract checks ensure edit click cannot degrade into no-op flow.
 * @pre ProviderConfig component source exists in expected path.
 */

// --- isDirectory:Function (frontend/src/components/storage/FileList.svelte)
/**!
 * @brief Checks if a file object represents a directory.
 * @param {Object} file - The file object to check.
 * @post Returns boolean.
 * @pre file object has mime_type property.
 * @return {boolean} True if it's a directory, false otherwise.
 */

// --- formatSize:Function (frontend/src/components/storage/FileList.svelte)
/**!
 * @brief Formats file size in bytes into a human-readable string.
 * @param {number} bytes - The size in bytes.
 * @post Returns formatted string.
 * @pre bytes is a number.
 * @return {string} Formatted size (e.g., "1.2 MB").
 */

// --- formatDate:Function (frontend/src/components/storage/FileList.svelte)
/**!
 * @brief Formats an ISO date string into a localized readable format.
 * @param {string} dateStr - The date string to format.
 * @post Returns localized string.
 * @pre dateStr is a valid date string.
 * @return {string} Localized date and time.
 */

// --- handleDownload:Function (frontend/src/components/storage/FileList.svelte)
/**!
 * @brief Downloads selected file through authenticated API request.
 * @post Browser download starts or user sees toast on failure.
 * @pre file is a non-directory storage entry with category/path.
 */

// --- handleUpload:Function (frontend/src/components/storage/FileUpload.svelte)
/**!
 * @brief Handles the file upload process.
 * @post The file is uploaded to the server and a success toast is shown.
 * @pre A file must be selected in the file input.
 */

// --- handleDrop:Function (frontend/src/components/storage/FileUpload.svelte)
/**!
 * @brief Handles the file drop event for drag-and-drop.
 * @param {DragEvent} event - The drop event.
 */

// --- LogEntryRow (frontend/src/components/tasks/LogEntryRow.svelte)
/**!
 * @brief Renders a single log entry with stacked layout optimized for narrow drawer panels.
 * @complexity 3
 * @layer UI
 * @semantics log, entry, row, ui
 * @type {Object} log - The log entry object
 * @ux_state Idle -> Displays log entry with color-coded level and source badges.
 */

// --- formatTime:Function (frontend/src/components/tasks/LogEntryRow.svelte)
/**!
 * @brief Format ISO timestamp to HH:MM:SS
 */

// --- LogFilterBar (frontend/src/components/tasks/LogFilterBar.svelte)
/**!
 * @brief Compact filter toolbar for logs — level, source, and text search in a single dense row.
 * @complexity 3
 * @layer UI
 * @semantics log, filter, ui
 * @ux_state Active -> Filters applied, clear button visible
 */

// --- TaskLogPanel (frontend/src/components/tasks/TaskLogPanel.svelte)
/**!
 * @brief Combines log filtering and display into a single cohesive light-themed panel.
 * @complexity 3
 * @invariant Must always display logs in chronological order and respect auto-scroll preference.
 * @layer UI
 * @semantics task, log, panel, filter, list
 * @ux_state AutoScroll -> Automatically scrolls to bottom on new logs
 */

// --- TaskResultPanel (frontend/src/components/tasks/TaskResultPanel.svelte)
/**!
 * @brief Displays formatted task result summary with status badges and result details.
 * @complexity 2
 * @layer UI
 * @ux_state Loaded -> Task result displayed with status color coding.
 */

// --- handleRunDebug:Function (frontend/src/components/tools/DebugTool.svelte)
/**!
 * @brief Triggers the debug task.
 * @post Task is started and polling begins.
 * @pre Required fields are selected.
 * @return {Promise<void>}
 */

// --- startPolling:Function (frontend/src/components/tools/DebugTool.svelte)
/**!
 * @brief Polls for task completion.
 * @param {string} taskId - ID of the task.
 * @post Polls until success/failure.
 * @pre Task ID is valid.
 * @return {void}
 */

// --- MapperTool (frontend/src/components/tools/MapperTool.svelte)
/**!
 * @brief UI component for mapping dataset column verbose names using Superset SQL Lab or Excel files.
 * @complexity 3
 * @layer UI
 * @semantics mapper, tool, dataset, sqllab, excel
 */

// --- fetchData:Function (frontend/src/components/tools/MapperTool.svelte)
/**!
 * @brief Fetches environments.
 * @post envs array is populated.
 * @pre None.
 */

// --- handleRunMapper:Function (frontend/src/components/tools/MapperTool.svelte)
/**!
 * @brief Triggers the MapperPlugin task via new sqllab/excel sources.
 * @post Mapper task is started and selectedTask is updated.
 * @pre selectedEnv and datasetId are set; source-specific fields are valid.
 */

// --- handleGenerateDocs:Function (frontend/src/components/tools/MapperTool.svelte)
/**!
 * @brief Triggers the LLM Documentation task.
 * @post Documentation task is started.
 * @pre selectedEnv and datasetId are set.
 */

// --- Counter (frontend/src/lib/Counter.svelte)
/**!
 * @brief Simple counter demo component
 * @complexity 2
 * @layer UI
 * @ux_state Incremented -> Count increases immediately after button activation.
 */

// --- ApiModule (frontend/src/lib/api.js)
/**!
 * @brief Handles all communication with the backend API via fetch wrappers with auth, error normalization, and toast feedback.
 * @complexity 3
 * @type {any}
 */

// --- ReportsApiTest (frontend/src/lib/api/__tests__/reports_api.test.js)
/**!
 * @brief Unit tests for reports API client functions: query string building, error normalization, and fetch wrappers.
 * @complexity 3
 */

// --- ReportsApiTest:Module (frontend/src/lib/api/__tests__/reports_api.test.js)
/**!
 * @brief Unit tests for reports API client functions: query string building, error normalization, and fetch wrappers.
 * @invariant Pure functions produce deterministic output. Async wrappers propagate structured errors.
 * @layer Tests
 * @semantics tests, reports, api-client, query-string, error-normalization
 */

// --- TestBuildReportQueryString:Class (frontend/src/lib/api/__tests__/reports_api.test.js)
/**!
 * @brief Validate query string construction from filter options.
 * @post Correct URLSearchParams string produced.
 * @pre Options object with various filter fields.
 */

// --- TestNormalizeApiError:Class (frontend/src/lib/api/__tests__/reports_api.test.js)
/**!
 * @brief Validate error normalization for UI-state mapping.
 * @post Always returns {message, code, retryable} object.
 * @pre Various error types (Error, string, object).
 */

// --- TestGetReportsAsync:Class (frontend/src/lib/api/__tests__/reports_api.test.js)
/**!
 * @brief Validate getReports and getReportDetail with mocked api.fetchApi.
 * @post Functions call correct endpoints and propagate results/errors.
 * @pre api.fetchApi is mocked via vi.mock.
 */

// --- AssistantApi (frontend/src/lib/api/assistant.js)
/**!
 * @brief API client wrapper for assistant chat, session-scoped prompts, confirmation actions, conversation management, and history retrieval.
 * @complexity 3
 */

// --- AssistantApi:Module (frontend/src/lib/api/assistant.js)
/**!
 * @brief API client wrapper for assistant chat, session-scoped prompts, confirmation actions, and history retrieval.
 * @invariant All assistant requests must use requestApi wrapper (no native fetch).
 * @layer API
 * @semantics assistant, api, client, chat, confirmation
 */

// --- sendAssistantMessage:Function (frontend/src/lib/api/assistant.js)
/**!
 * @brief Send a user message to assistant orchestrator endpoint.
 * @post Returns assistant response object with deterministic state.
 * @pre payload.message is a non-empty string.
 */

// --- buildAssistantSeedMessage:Function (frontend/src/lib/api/assistant.js)
/**!
 * @brief Compose visible assistant seed text from context label and prompt body.
 * @post Returns trimmed seed message string for prefilled input.
 * @pre prompt contains the user-visible request.
 */

// --- confirmAssistantOperation:Function (frontend/src/lib/api/assistant.js)
/**!
 * @brief Confirm a pending risky assistant operation.
 * @post Returns execution response (started/success/failed).
 * @pre confirmationId references an existing pending token.
 */

// --- cancelAssistantOperation:Function (frontend/src/lib/api/assistant.js)
/**!
 * @brief Cancel a pending risky assistant operation.
 * @post Operation is cancelled and cannot be executed by this token.
 * @pre confirmationId references an existing pending token.
 */

// --- getAssistantHistory:Function (frontend/src/lib/api/assistant.js)
/**!
 * @brief Retrieve paginated assistant conversation history.
 * @post Returns a paginated payload with history items.
 * @pre page/pageSize are positive integers.
 */

// --- getAssistantConversations:Function (frontend/src/lib/api/assistant.js)
/**!
 * @brief Retrieve paginated conversation list for assistant sidebar/history switcher.
 * @post Returns paginated conversation summaries.
 * @pre page/pageSize are positive integers.
 */

// --- deleteAssistantConversation:Function (frontend/src/lib/api/assistant.js)
/**!
 * @brief Soft-delete or hard-delete a conversation.
 * @post Returns success status.
 * @pre conversationId string is provided.
 */

// --- DatasetReviewApi (frontend/src/lib/api/datasetReview.js)
/**!
 * @brief Shared frontend helpers for dataset review session-scoped API requests, optimistic-lock propagation, and session DTO normalization.
 * @complexity 3
 */

// --- DatasetReviewApi:Module (frontend/src/lib/api/datasetReview.js)
/**!
 * @brief Provide shared frontend helpers for dataset review session-scoped API requests, optimistic-lock propagation, and refreshed session DTO normalization.
 * @layer API
 * @semantics dataset-review, api, session-version, headers, conflict-handling
 */

// --- buildDatasetReviewRequestOptions:Function (frontend/src/lib/api/datasetReview.js)
/**!
 * @brief Attach optimistic-lock session version header when the current version is known.
 * @post Returns requestApi-compatible options object.
 * @pre sessionVersion may be null when no loaded session version exists yet.
 */

// --- requestDatasetReviewApi:Function (frontend/src/lib/api/datasetReview.js)
/**!
 * @brief Proxy dataset review mutations through requestApi with optional optimistic-lock headers.
 * @post Executes requestApi with X-Session-Version only when a session version is known.
 * @pre endpoint and method are valid requestApi inputs.
 */

// --- isDatasetReviewConflictError:Function (frontend/src/lib/api/datasetReview.js)
/**!
 * @brief Detect optimistic-lock conflicts from dataset review mutations.
 * @post Returns true when the mutation failed with 409 conflict semantics.
 * @pre error may be null or a normalized API error.
 */

// --- getDatasetReviewConflictMessage:Function (frontend/src/lib/api/datasetReview.js)
/**!
 * @brief Return explicit 409-style guidance for stale dataset review mutations.
 * @post Returns a user-facing conflict message string.
 * @pre error may be null or a normalized API error.
 */

// --- extractDatasetReviewVersion:Function (frontend/src/lib/api/datasetReview.js)
/**!
 * @brief Resolve the latest session version from refreshed DTO fragments.
 * @post Returns the newest known session version or null.
 * @pre payload may be a session summary, a detail payload, or a mutation fragment.
 */

// --- normalizeDatasetReviewDetail:Function (frontend/src/lib/api/datasetReview.js)
/**!
 * @brief Normalize refreshed session-detail DTOs into the legacy route-friendly workspace shape.
 * @post Returns a shape with flattened summary fields plus refreshed collections and version metadata.
 * @pre detail may already be legacy-flat or refreshed with nested session/session_version fields.
 */

// --- MaintenanceApi (frontend/src/lib/api/maintenance.js)
/**!
 * @brief API client for Maintenance Banner endpoints. Uses requestApi for all calls.
 * @complexity 2
 * @layer Frontend
 */

// --- frontend/src/lib/api/maintenance.js::startMaintenance (frontend/src/lib/api/maintenance.js)
/**!
 */

// --- frontend/src/lib/api/maintenance.js::endMaintenance (frontend/src/lib/api/maintenance.js)
/**!
 */

// --- frontend/src/lib/api/maintenance.js::endAllMaintenance (frontend/src/lib/api/maintenance.js)
/**!
 */

// --- frontend/src/lib/api/maintenance.js::getSettings (frontend/src/lib/api/maintenance.js)
/**!
 */

// --- frontend/src/lib/api/maintenance.js::updateSettings (frontend/src/lib/api/maintenance.js)
/**!
 */

// --- frontend/src/lib/api/maintenance.js::listEvents (frontend/src/lib/api/maintenance.js)
/**!
 */

// --- frontend/src/lib/api/maintenance.js::listDashboardBanners (frontend/src/lib/api/maintenance.js)
/**!
 */

// --- ReportsApi (frontend/src/lib/api/reports.js)
/**!
 * @brief Wrapper-based reports API client for list/detail retrieval through the shared API wrapper.
 * @complexity 4
 * @post Report list and detail helpers return backend payloads or normalized UI-safe errors.
 * @pre Shared API wrapper is configured for the current frontend auth/session context.
 * @side_effect Performs authenticated report HTTP requests through the shared API wrapper.
 */

// --- ReportsApi:Module (frontend/src/lib/api/reports.js)
/**!
 * @brief Wrapper-based reports API client for list/detail retrieval without direct native fetch usage.
 * @invariant Uses existing api wrapper methods and returns structured errors for UI-state mapping.
 * @layer Infra
 * @post Report list and detail helpers return backend payloads or normalized UI-safe errors.
 * @pre Shared API wrapper is configured for the current frontend auth/session context.
 * @semantics frontend, api_client, reports, wrapper
 * @side_effect Performs authenticated report HTTP requests through the shared API wrapper.
 */

// --- buildReportQueryString:Function (frontend/src/lib/api/reports.js)
/**!
 * @brief Build query string for reports list endpoint from filter options.
 * @post Returns URL query string without leading '?'.
 * @pre options is an object with optional report query fields.
 */

// --- normalizeApiError:Function (frontend/src/lib/api/reports.js)
/**!
 * @brief Convert unknown API exceptions into deterministic UI-consumable error objects.
 * @post Returns structured error object.
 * @pre error may be Error/string/object.
 */

// --- getReports:Function (frontend/src/lib/api/reports.js)
/**!
 * @brief Fetch unified report list using existing request wrapper.
 * @post Returns parsed payload or structured error for UI-state mapping.
 * @pre valid auth context for protected endpoint.
 * @test_contract GetReportsApi ->
 */

// --- getReportDetail:Function (frontend/src/lib/api/reports.js)
/**!
 * @brief Fetch one report detail by report_id.
 * @post Returns parsed detail payload or structured error object.
 * @pre reportId is non-empty string; valid auth context.
 */

// --- TranslateApi (frontend/src/lib/api/translate.js)
/**!
 * @brief Barrel module re-exporting all translate API functions from domain-split modules.
 * @complexity 2
 * @rationale Decomposed from 664->~30 lines by splitting into domain modules per INV_7.
 * @rejected Keeping all APIs in one file was rejected because it exceeded the 400-line module limit.
 */

// --- TargetSchemaApiTest (frontend/src/lib/api/translate/__tests__/test-target-schema.test.js)
/**!
 * @brief Unit tests for checkTargetTableSchema API client fetch wrapper.
 * @complexity 2
 * @layer Tests
 * @test_contract checkTargetTableSchema -> returns schema validation result with all fields
 * @test_edge success_response -> Returns parsed response with all fields
 */

// --- test_success (frontend/src/lib/api/translate/__tests__/test-target-schema.test.js)
/**!
 * @brief Happy path — API returns full validation result.
 */

// --- test_api_error (frontend/src/lib/api/translate/__tests__/test-target-schema.test.js)
/**!
 * @brief API error returns fallback response with error message.
 */

// --- test_error_string_fallback (frontend/src/lib/api/translate/__tests__/test-target-schema.test.js)
/**!
 * @brief String error is captured as message.
 */

// --- TranslateCorrectionsApi (frontend/src/lib/api/translate/corrections.js)
/**!
 * @brief API client for translation corrections — inline edits, dictionary submission, bulk find-and-replace, CSV download.
 * @complexity 2
 */

// --- TranslateDatasourcesApi (frontend/src/lib/api/translate/datasources.js)
/**!
 * @brief API client for translation datasources — column fetching, preview, row-level review actions.
 * @complexity 2
 */

// --- TranslateDictionariesApi (frontend/src/lib/api/translate/dictionaries.js)
/**!
 * @brief API client for translation dictionary CRUD — list, create, update, delete, entries, import.
 * @complexity 2
 */

// --- TranslateJobsApi (frontend/src/lib/api/translate/jobs.js)
/**!
 * @brief API client for translation job CRUD — list, create, update, delete, duplicate.
 * @complexity 2
 */

// --- TranslateRunsApi (frontend/src/lib/api/translate/runs.js)
/**!
 * @brief API client for translation run control — trigger, status, history, records, retry, cancel, metrics.
 * @complexity 2
 */

// --- TranslateSchedulesApi (frontend/src/lib/api/translate/schedules.js)
/**!
 * @brief API client for translation job scheduling — CRUD, enable/disable, next executions.
 * @complexity 2
 */

// --- TranslateTargetSchemaApi (frontend/src/lib/api/translate/target-schema.js)
/**!
 * @brief API client for target table schema validation.
 * @complexity 1
 */

// --- frontend/src/lib/api/translate/target-schema.js::checkTargetTableSchema (frontend/src/lib/api/translate/target-schema.js)
/**!
 */

// --- ValidationApi (frontend/src/lib/api/validation.js)
/**!
 * @brief API client functions for the Validation section — tasks and runs CRUD.
 * @complexity 2
 * @rationale Centralized API module for all validation endpoints — single import point for pages, consistent error handling through shared fetchApi/postApi/deleteApi wrappers, and easy mocking in tests.
 * @rejected Inline fetch calls in each page rejected — would duplicate base URL construction and auth header logic; centralized module enables consistent error handling and simplifies test mocking.
 */

// --- buildParams:Function (frontend/src/lib/api/validation.js)
/**!
 * @brief Build URLSearchParams from a params object, skipping null/undefined/empty values.
 * @complexity 1
 * @param {Record<string, any>} params
 */

// --- frontend/src/lib/api/validation.js::buildParams (frontend/src/lib/api/validation.js)
/**!
 */

// --- frontend/src/lib/api/validation.js::fetchTasks (frontend/src/lib/api/validation.js)
/**!
 */

// --- createTask:Function (frontend/src/lib/api/validation.js)
/**!
 * @complexity 1
 * @param {Record<string, any>} data
 */

// --- frontend/src/lib/api/validation.js::createTask (frontend/src/lib/api/validation.js)
/**!
 */

// --- fetchTask:Function (frontend/src/lib/api/validation.js)
/**!
 * @complexity 1
 * @param {string} id
 */

// --- frontend/src/lib/api/validation.js::fetchTask (frontend/src/lib/api/validation.js)
/**!
 */

// --- updateTask:Function (frontend/src/lib/api/validation.js)
/**!
 * @complexity 1
 * @param {string} id @param {Record<string, any>} data
 */

// --- frontend/src/lib/api/validation.js::updateTask (frontend/src/lib/api/validation.js)
/**!
 */

// --- deleteTask:Function (frontend/src/lib/api/validation.js)
/**!
 * @complexity 1
 * @param {string} id @param {boolean} [deleteRuns]
 */

// --- frontend/src/lib/api/validation.js::deleteTask (frontend/src/lib/api/validation.js)
/**!
 */

// --- triggerRun:Function (frontend/src/lib/api/validation.js)
/**!
 * @complexity 1
 * @param {string} id
 */

// --- frontend/src/lib/api/validation.js::triggerRun (frontend/src/lib/api/validation.js)
/**!
 */

// --- duplicateTask:Function (frontend/src/lib/api/validation.js)
/**!
 * @complexity 1
 * @param {string} id
 */

// --- frontend/src/lib/api/validation.js::duplicateTask (frontend/src/lib/api/validation.js)
/**!
 */

// --- fetchRuns:Function (frontend/src/lib/api/validation.js)
/**!
 * @complexity 1
 * @param {{ task_id?: string, dashboard_id?: string, environment_id?: string, status?: string, date_from?: string, date_to?: string, page?: number, page_size?: number }} [params]
 */

// --- frontend/src/lib/api/validation.js::fetchRuns (frontend/src/lib/api/validation.js)
/**!
 */

// --- fetchRunDetail:Function (frontend/src/lib/api/validation.js)
/**!
 * @complexity 1
 * @param {string} id
 */

// --- frontend/src/lib/api/validation.js::fetchRunDetail (frontend/src/lib/api/validation.js)
/**!
 */

// --- deleteRun:Function (frontend/src/lib/api/validation.js)
/**!
 * @complexity 1
 * @param {string} id
 */

// --- frontend/src/lib/api/validation.js::deleteRun (frontend/src/lib/api/validation.js)
/**!
 */

// --- PermissionsTest (frontend/src/lib/auth/__tests__/permissions.test.js)
/**!
 * @brief Verifies frontend RBAC permission parsing and access checks.
 * @complexity 3
 */

// --- PermissionsTest:Module (frontend/src/lib/auth/__tests__/permissions.test.js)
/**!
 * @brief Verifies frontend RBAC permission parsing and access checks.
 * @layer UI (Tests)
 * @semantics tests, auth, permissions, rbac
 */

// --- PermissionsModule (frontend/src/lib/auth/permissions.js)
/**!
 * @brief Shared frontend RBAC utilities for route guards, permission checks, and menu visibility based on user roles.
 * @complexity 3
 */

// --- Permissions:Module (frontend/src/lib/auth/permissions.js)
/**!
 * @brief Shared frontend RBAC utilities for route guards and menu visibility.
 * @invariant Admin role always bypasses explicit permission checks.
 * @layer Domain
 * @semantics auth, permissions, rbac, roles
 */

// --- normalizePermissionRequirement:Function (frontend/src/lib/auth/permissions.js)
/**!
 * @brief Convert permission requirement string to canonical resource/action tuple.
 * @post Returns normalized object with action in uppercase.
 * @pre Permission can be "resource" or "resource:ACTION" where resource itself may contain ":".
 */

// --- isAdminUser:Function (frontend/src/lib/auth/permissions.js)
/**!
 * @brief Determine whether user has Admin role.
 * @post Returns true when at least one role name equals "Admin" (case-insensitive).
 * @pre user can be null or partially populated.
 */

// --- hasPermission:Function (frontend/src/lib/auth/permissions.js)
/**!
 * @brief Check if user has a required resource/action permission.
 * @post Returns true when requirement is empty, user is admin, or matching permission exists.
 * @pre user contains roles with permissions from /api/auth/me payload.
 */

// --- AuthStore (frontend/src/lib/auth/store.ts)
/**!
 * @brief Manages the global authentication state including JWT token, user profile, and login/logout lifecycle.
 * @complexity 3
 * @ux_state Unauthenticated -> No valid session, login required
 */

// --- authStore:Store (frontend/src/lib/auth/store.ts)
/**!
 * @brief Manages the global authentication state on the frontend.
 * @layer Feature
 * @semantics auth, store, svelte, jwt, session
 */

// --- AuthState:Interface (frontend/src/lib/auth/store.ts)
/**!
 * @brief Defines the structure of the authentication state.
 */

// --- frontend/src/lib/auth/store.ts::AuthState (frontend/src/lib/auth/store.ts)
/**!
 */

// --- createAuthStore:Function (frontend/src/lib/auth/store.ts)
/**!
 * @brief Creates and configures the auth store with helper methods.
 * @post Returns configured auth store with subscribe, setToken, setUser, logout, setLoading methods.
 * @pre No preconditions - initialization function.
 * @return {Writable<AuthState>}
 */

// --- frontend/src/lib/auth/store.ts::createAuthStore (frontend/src/lib/auth/store.ts)
/**!
 * @post Returns configured auth store with subscribe, setToken, setUser, logout, setLoading methods.
 * @pre No preconditions - initialization function.
 */

// --- setToken:Function (frontend/src/lib/auth/store.ts)
/**!
 * @brief Updates the store with a new JWT token.
 * @param {string} token - The JWT access token.
 * @post Store updated with new token, isAuthenticated set to true.
 * @pre token must be a valid JWT string.
 */

// --- setUser:Function (frontend/src/lib/auth/store.ts)
/**!
 * @brief Sets the current user profile data.
 * @param {any} user - The user profile object.
 * @post Store updated with user, isAuthenticated true, loading false.
 * @pre User object must contain valid profile data.
 */

// --- logout:Function (frontend/src/lib/auth/store.ts)
/**!
 * @brief Clears authentication state and storage.
 * @post Auth token removed from localStorage, store reset to initial state.
 * @pre User is currently authenticated.
 */

// --- setLoading:Function (frontend/src/lib/auth/store.ts)
/**!
 * @brief Updates the loading state.
 * @param {boolean} loading - Loading status.
 * @post Store loading state updated.
 * @pre None.
 */

// --- AssistantClarificationCard (frontend/src/lib/components/assistant/AssistantClarificationCard.svelte)
/**!
 * @brief Render the active dataset-review clarification queue inside AssistantChatPanel so users can answer, skip, defer, and resume questions without leaving the assistant workspace.
 * @complexity 3
 * @data_contract Input[{sessionId, disabled}] -> Output[{clarification_state|clarification_session|current_question|session}] via onupdated callback.
 * @layer UI
 * @post Clarification queue state is readable in-chat and answer mutations refresh the active question state without requiring a dedicated dialog.
 * @pre sessionId belongs to the current dataset review workspace and the assistant drawer is open for session-scoped work.
 * @semantics assistant, clarification, dataset-review, mixed-initiative, resumable
 * @side_effect Reads and mutates clarification state through dataset orchestration APIs.
 * @ux_feedback Save, skip, resume, and feedback results surface inline without hiding the queue context.
 * @ux_reactivity Uses $props, $state, $derived, and $effect only; no legacy reactive syntax.
 * @ux_recovery Users can resume the queue, provide a custom answer, or mark the item for expert review from the same assistant surface.
 * @ux_state Completed -> No active question remains and resume plus feedback actions stay available.
 */

// --- readJson:Function (frontend/src/lib/components/assistant/__tests__/assistant_chat.integration.test.js)
/**!
 * @brief Read and parse JSON fixture file from disk.
 * @post Returns parsed object representation.
 * @pre filePath points to existing UTF-8 JSON file.
 */

// --- AssistantClarificationIntegrationTest:Module (frontend/src/lib/components/assistant/__tests__/assistant_clarification.integration.test.js)
/**!
 * @brief Verify AssistantChatPanel hosts the resumable dataset-review clarification flow inside the assistant drawer and refreshes workspace session state after answering.
 * @layer UI (Tests)
 * @semantics assistant, clarification, integration-test, dataset-review, mixed-initiative
 */

// --- AssistantFirstMessageIntegrationTest:Module (frontend/src/lib/components/assistant/__tests__/assistant_first_message.integration.test.js)
/**!
 * @brief Verify first optimistic user message stays visible while a new conversation request is pending.
 * @invariant Starting a new conversation must not trigger history reload that overwrites the first local user message.
 * @layer UI (Tests)
 * @semantics assistant, integration-test, optimistic-message, conversation-race
 */

// --- assistant_first_message_tests:Function (frontend/src/lib/components/assistant/__tests__/assistant_first_message.integration.test.js)
/**!
 * @brief Guard optimistic first-message UX against history reload race in new conversation flow.
 * @post First user message remains visible before pending send request resolves.
 * @pre Assistant panel renders with open state and mocked network dependencies.
 */

// --- CompiledSQLPreview (frontend/src/lib/components/dataset-review/CompiledSQLPreview.svelte)
/**!
 * @brief Present the exact Superset-generated compiled SQL preview, expose readiness or staleness clearly, and preserve readable recovery paths when preview generation fails.
 * @complexity 3
 * @data_contract Input -> Dataset review preview payload { sessionId, preview, previewState }; Output -> onupdated({ preview, preview_state }) route-shell refresh payload and onjump({ target }) recovery navigation signal.
 * @layer UI
 * @post Users can distinguish missing, pending, ready, stale, and error preview states and can trigger only Superset-backed preview generation.
 * @pre Session id is available and preview state comes from the current ownership-scoped session detail payload.
 * @semantics dataset-review, compiled-sql-preview, superset-preview, stale-state, diagnostics
 * @side_effect Requests preview generation through dataset orchestration APIs and updates route shell preview state when Superset responds.
 * @ux_feedback Preview refresh updates status pill, timestamps, and inline generation feedback.
 * @ux_reactivity Uses $props, $state, and $derived only; no legacy reactive syntax.
 * @ux_recovery Users can retry preview generation and jump back to mapping review when diagnostics point to execution-input issues.
 * @ux_state Error -> Show readable Superset compilation diagnostics and preserve remediation action.
 */

// --- ExecutionMappingReview (frontend/src/lib/components/dataset-review/ExecutionMappingReview.svelte)
/**!
 * @brief Review imported-filter to template-variable mappings, surface effective values and blockers, and require explicit approval for warning-sensitive execution inputs before preview or launch.
 * @complexity 3
 * @data_contract Input -> Dataset review execution payload { sessionId, mappings[], importedFilters[], templateVariables[] }; Output -> onupdated({ mapping | mappings, preview_state }) route-shell refresh payload.
 * @layer UI
 * @post Users can review effective mapping values, approve warning-sensitive transformations, or manually override them while unresolved required-value blockers remain visible.
 * @pre Session id, execution mappings, imported filters, and template variables belong to the current ownership-scoped session payload.
 * @semantics dataset-review, execution-mapping, warning-approval, manual-override, required-values
 * @side_effect Persists mapping approvals or manual overrides through dataset orchestration APIs and may invalidate the current preview truth for the route shell.
 * @ux_feedback Mapping approvals and manual overrides expose inline success, saving, and error feedback per row.
 * @ux_reactivity Uses $props, $state, and $derived only; no legacy reactive syntax.
 * @ux_recovery Users can replace transformed values manually instead of approving them as-is and can retry failed mutations in place.
 * @ux_state Approved -> All launch-sensitive mappings are approved or no explicit approval is required.
 */

// --- LaunchConfirmationPanel (frontend/src/lib/components/dataset-review/LaunchConfirmationPanel.svelte)
/**!
 * @brief Summarize final execution context, surface launch blockers explicitly, and confirm only a gate-complete SQL Lab launch request.
 * @complexity 3
 * @data_contract Input -> Dataset review launch payload { sessionId, session, findings[], mappings[], preview, previewState, latestRunContext }; Output -> onupdated({ launch_result, preview_state }) workspace refresh payload and onjump({ target }) remediation navigation signal.
 * @layer UI
 * @post Users can see why launch is blocked or confirm a run-ready launch with explicit SQL Lab handoff evidence.
 * @pre Session detail, mappings, findings, preview state, and latest run context belong to the current ownership-scoped session payload.
 * @semantics dataset-review, launch-confirmation, run-gates, sql-lab, audited-execution
 * @side_effect Submits the launch request through dataset orchestration APIs and updates the workspace with returned run context state.
 * @ux_feedback Launch button, blocker list, and success state all reflect current gate truth instead of generic confirmation copy.
 * @ux_reactivity Uses $props, $state, and $derived only; no legacy reactive syntax.
 * @ux_recovery Blocked launch state provides jump paths back to mapping review, preview generation, or validation remediation.
 * @ux_state Submitted -> SQL Lab handoff and audited run context reference are shown after launch request succeeds.
 */

// --- SemanticLayerReview (frontend/src/lib/components/dataset-review/SemanticLayerReview.svelte)
/**!
 * @brief Surface field-level semantic decisions with provenance, confidence, candidate acceptance, and manual override safeguards for US2 review flow.
 * @complexity 3
 * @data_contract Input -> Dataset review session detail { sessionId, fields[], semanticSources[] }; Output -> onupdated(updatedField | { fields: updatedFields }) refresh payload.
 * @layer UI
 * @post Users can review the current semantic value, accept a candidate, apply manual override, and lock or unlock field state without violating backend provenance rules.
 * @pre Session id is available and semantic field entries come from the current ownership-scoped session detail payload.
 * @semantics dataset-review, semantic-layer, candidate-review, manual-override, field-lock
 * @side_effect Persists semantic field decisions, lock state, and optional thumbs feedback through dataset orchestration endpoints.
 * @ux_feedback Save, lock, unlock, and feedback actions expose inline success or error state on the affected field.
 * @ux_reactivity Uses $props, $state, and $derived only; no legacy reactive syntax.
 * @ux_recovery Users can cancel local edits, unlock a manual override for re-review, or retry failed mutations in place.
 * @ux_state Manual -> One field enters local draft mode and persists as locked manual override on save.
 */

// --- SourceIntakePanel (frontend/src/lib/components/dataset-review/SourceIntakePanel.svelte)
/**!
 * @brief Collect initial dataset source input through Superset link paste or dataset selection entry paths.
 * @complexity 3
 * @layer UI
 * @semantics dataset-review, intake, superset-link, dataset-selection, validation
 * @ux_feedback Recognized links are acknowledged before deeper recovery finishes.
 * @ux_reactivity Uses $props, $state, and $derived only; no legacy reactive syntax.
 * @ux_recovery Users can correct invalid input in place without resetting the page.
 * @ux_state Rejected -> Input error shown with corrective hint.
 */

// --- ValidationFindingsPanel (frontend/src/lib/components/dataset-review/ValidationFindingsPanel.svelte)
/**!
 * @brief Present validation findings grouped by severity with explicit resolution and actionability signals.
 * @complexity 3
 * @layer UI
 * @semantics dataset-review, findings, severity, readiness, actionability
 * @ux_feedback Resolving or approving an item updates readiness state immediately.
 * @ux_reactivity Uses $props and $derived only; no legacy reactive syntax.
 * @ux_recovery Users can jump from a finding directly to the relevant remediation area.
 * @ux_state Informational -> Low-priority findings are collapsed or secondary.
 */

// --- SourceIntakePanelUxTests:Module (frontend/src/lib/components/dataset-review/__tests__/source_intake_panel.ux.test.js)
/**!
 * @brief Verify source intake entry paths, validation feedback, and submit payload behavior for US1.
 * @layer UI
 * @semantics dataset-review, source-intake, ux-tests, validation, recovery
 * @test_contract SourceIntakePanelProps -> ObservableIntakeUX
 * @test_edge external_fail -> Submit callback failure is rendered inline.
 * @test_invariant intake_contract_remains_observable -> VERIFIED_BY: [invalid_superset_link_shows_rejected_state, recognized_superset_link_submits_payload, dataset_selection_mode_changes_cta]
 * @test_scenario dataset_selection_mode_changes_cta -> Dataset selection path switches CTA and payload source kind.
 * @ux_state Rejected -> Invalid source input remains local and exposes recovery guidance.
 */

// --- DatasetReviewUs2WorkspaceUxTests:Module (frontend/src/lib/components/dataset-review/__tests__/us2_semantic_workspace.ux.test.js)
/**!
 * @brief Verify US2 dataset review surfaces keep semantic review actionable, route clarification through AssistantChatPanel, and preserve explicit preview/mapping gates.
 * @layer UI
 * @semantics dataset-review, semantics, assistant, workspace, ux-tests, mapping-review
 * @test_edge external_fail -> Failed request surfaces inline recovery message.
 * @test_scenario mapping_review_marks_row_focused_and_requires_explicit_approval -> Mapping review keeps warning approvals explicit and highlightable.
 */

// --- DatasetReviewUs3UxTests:Module (frontend/src/lib/components/dataset-review/__tests__/us3_execution_batch.ux.test.js)
/**!
 * @brief Verify US3 mapping review, Superset preview, and launch confirmation UX contracts.
 * @layer UI
 * @semantics dataset-review, execution, mapping, preview, launch, ux-tests
 * @test_contract Us3ExecutionProps -> ObservableExecutionUx
 * @test_edge invalid_type -> Mixed values stringify without crashing.
 * @test_invariant execution_gates_remain_visible -> VERIFIED_BY: [mapping_review_approves_warning_sensitive_row, preview_panel_requests_superset_compilation_and_renders_sql, launch_panel_blocks_then_submits_sql_lab_launch]
 * @test_scenario launch_panel_blocks_then_submits_sql_lab_launch -> Launch lists gates first and shows audited handoff after success.
 * @ux_state Blocked -> Launch panel lists blockers instead of allowing hidden bypass.
 */

// --- ValidationFindingsPanelUxTests:Module (frontend/src/lib/components/dataset-review/__tests__/validation_findings_panel.ux.test.js)
/**!
 * @brief Verify grouped findings visibility, empty state, and remediation jump behavior for US1.
 * @layer UI
 * @semantics dataset-review, findings, severity, jump, ux-tests
 * @test_contract FindingsPanelProps -> ObservableFindingsUX
 * @test_edge external_fail -> Jump callback remains optional.
 * @test_invariant findings_groups_remain_actionable -> VERIFIED_BY: [blocking_warning_info_groups_render, jump_action_maps_area_to_workspace_target, empty_findings_show_success_state]
 * @test_scenario empty_findings_show_success_state -> Empty list shows ready feedback.
 * @ux_state Informational -> Informational notes stay readable without competing with blockers.
 */

// --- HealthMatrix (frontend/src/lib/components/health/HealthMatrix.svelte)
/**!
 * @brief Visual grid summary representing dashboard health status counts.
 * @complexity 3
 * @layer UI
 * @type {{
 * @ux_reactivity Uses $derived to keep aggregate totals consistent with the count props.
 * @ux_state Error -> Displays an error message with a retry option.
 */

// --- PolicyForm (frontend/src/lib/components/health/PolicyForm.svelte)
/**!
 * @brief Form for creating and editing validation policies.
 * @complexity 3
 * @layer UI
 * @post Form submission forwards the current draft to onSave and cancel delegates dismissal to the parent callback without mutating external state directly.
 * @pre Parent provides callable onSave/onCancel handlers and an environments collection that may be empty but remains array-like.
 * @type {{ policy: any, environments: any[], onSave: (p: any) => void, onCancel: () => void }}
 * @ux_feedback Error -> Invalid field or submit failures keep the draft visible for correction.
 * @ux_reactivity Uses $state for mutable form data and $derived values for window health checks.
 * @ux_state Submitting -> Disables inputs and shows a loading state.
 */

// --- ScheduleAtAGlance (frontend/src/lib/components/health/ScheduleAtAGlance.svelte)
/**!
 * @brief Compact weekly schedule widget showing active validation tasks with day grid, time windows, and cross-referenced health status.
 * @complexity 3
 * @type {{ healthItems: Array<{task_id?: string, status: string}>, selectedEnvId?: string, appTimezone?: string }}
 * @ux_feedback Click on policy row navigates to validation task edit page
 * @ux_reactivity Props -> healthItems, selectedEnvId. LocalState -> tasks, loading, error
 * @ux_state Error -> Compact error banner with retry
 * @ux_test Ready -> {mock: fetchTasks returns 1 task, expected: grid + policy list + nextUpcoming}
 */

// --- Sidebar (frontend/src/lib/components/layout/Sidebar.svelte)
/**!
 * @brief Persistent left sidebar with grouped sections (Resources/Operations/System), expand/collapse, health indicators, RBAC filtering, profile footer.
 * @complexity 4
 * @layer UI
 * @ux_feedback Profile footer shows user avatar and username.
 * @ux_recovery Click outside on mobile closes overlay.
 * @ux_state MobileOpen -> Overlay and sidebar visible until dismissed.
 */

// --- disconnectWebSocket:Function (frontend/src/lib/components/layout/TaskDrawer.svelte)
/**!
 * @brief Disconnects the active WebSocket connection
 * @post ws is closed and set to null
 * @pre ws may or may not be initialized
 * @ux_state Loading -> Default
 */

// --- loadRecentTasks:Function (frontend/src/lib/components/layout/TaskDrawer.svelte)
/**!
 * @brief Load recent tasks for list mode display
 * @post recentTasks array populated with task list
 * @pre User is on task drawer or api is ready.
 */

// --- selectTask:Function (frontend/src/lib/components/layout/TaskDrawer.svelte)
/**!
 * @brief Select a task from list to view details
 * @post drawer state updated to show task details
 * @pre task is a valid task object
 */

// --- goBackToList:Function (frontend/src/lib/components/layout/TaskDrawer.svelte)
/**!
 * @brief Return to task list view from task details
 * @post Drawer switches to list view and reloads tasks
 * @pre Drawer is open and activeTaskId is set
 * @ux_state Loading -> Default
 */

// --- SidebarNavigationTest:Module (frontend/src/lib/components/layout/__tests__/sidebarNavigation.test.js)
/**!
 * @brief Verifies RBAC-based sidebar sections and category visibility.
 * @layer UI (Tests)
 * @semantics tests, sidebar, navigation, rbac, permissions
 */

// --- BreadcrumbsContractTest:Module (frontend/src/lib/components/layout/__tests__/test_breadcrumbs.svelte.js)
/**!
 * @brief Contract-focused unit tests for Breadcrumbs.svelte logic and UX annotations
 * @layer UI
 * @ux_state Loading -> Default
 */

// --- SidebarStoreTest:Module (frontend/src/lib/components/layout/__tests__/test_sidebar.svelte.js)
/**!
 * @brief Unit tests for Sidebar.svelte component
 * @layer UI
 * @ux_state Loading -> Default
 */

// --- TaskDrawerStoreTest:Module (frontend/src/lib/components/layout/__tests__/test_taskDrawer.svelte.js)
/**!
 * @brief Unit tests for TaskDrawer.svelte component
 * @layer UI
 * @ux_state Loading -> Default
 */

// --- TopNavbarStoreTest:Module (frontend/src/lib/components/layout/__tests__/test_topNavbar.svelte.js)
/**!
 * @brief Unit tests for TopNavbar.svelte component
 * @layer UI
 * @ux_state Loading -> Default
 */

// --- PageContracts (frontend/src/lib/components/layout/sidebarNavigation.js)
/**!
 * @brief Contract implemented by all Svelte route pages — defines page-level behavior and routing structure.
 * @complexity 2
 */

// --- NavigationContracts (frontend/src/lib/components/layout/sidebarNavigation.js)
/**!
 * @brief Contract for navigation structure — sidebar sections, route categories, and menu item hierarchy.
 * @complexity 2
 */

// --- SidebarNavigation:Module (frontend/src/lib/components/layout/sidebarNavigation.js)
/**!
 * @brief Build sidebar navigation sections and categories filtered by user permissions and feature flags.
 * @invariant Admin role can access all categories and subitems through permission utility.
 * @layer UI
 * @semantics navigation, sidebar, rbac, menu, filtering
 */

// --- isItemAllowed:Function (frontend/src/lib/components/layout/sidebarNavigation.js)
/**!
 * @brief Check whether a single menu node can be shown for a given user.
 * @post Returns true when no permission is required or permission check passes.
 * @pre item can contain optional requiredPermission/requiredAction.
 */

// --- isFeatureEnabled:Function (frontend/src/lib/components/layout/sidebarNavigation.js)
/**!
 */

// --- buildSidebarSections:Function (frontend/src/lib/components/layout/sidebarNavigation.js)
/**!
 * @brief Build translated sidebar sections with categories, filtered by RBAC permissions and feature flags.
 * @post Returns only sections/categories/subitems available for provided user and enabled features.
 * @pre i18nState provides nav labels; user can be null; features default to {} (all enabled).
 */

// --- ReportCardTest:Module (frontend/src/lib/components/reports/__tests__/report_card.ux.test.js)
/**!
 * @brief Test UX states and transitions for ReportCard component
 * @invariant Each test asserts at least one observable UX contract outcome.
 * @layer UI
 * @semantics reports, ux-tests, card, states, recovery
 * @test_contract ReportCardInputProps -> ObservableUXOutput
 * @test_edge missing_optional_fields -> Partial report keeps component interactive and emits select.
 * @test_fixture valid_report_card -> INLINE_JSON
 * @test_invariant report_card_state_is_observable -> VERIFIED_BY: [ready_state_shows_summary_status_type, empty_report_object, random_status]
 * @test_scenario ready_state_shows_summary_status_type -> Ready state renders summary/status/type labels.
 */

// --- ReportDetailIntegrationTest:Module (frontend/src/lib/components/reports/__tests__/report_detail.integration.test.js)
/**!
 * @brief Validate detail-panel behavior for failed reports and recovery guidance visibility.
 * @invariant Failed report detail exposes actionable next actions when available.
 * @layer UI (Tests)
 * @semantics tests, reports, detail, recovery-guidance, integration
 */

// --- ReportDetailUxTest:Module (frontend/src/lib/components/reports/__tests__/report_detail.ux.test.js)
/**!
 * @brief Test UX states and recovery for ReportDetailPanel component
 * @invariant Detail UX tests keep placeholder-safe rendering and recovery visibility verifiable.
 * @layer UI
 * @semantics reports, ux-tests, detail, diagnostics, recovery
 */

// --- [EXT:frontend:ReportTypeProfiles]Test:Module (frontend/src/lib/components/reports/__tests__/report_type_profiles.test.js)
/**!
 * @brief Validate report type profile mapping and unknown fallback behavior.
 * @invariant Unknown task_type always resolves to the fallback profile.
 * @layer UI (Tests)
 * @semantics tests, reports, type-profiles, fallback
 */

// --- ReportsFilterPerformanceTest:Module (frontend/src/lib/components/reports/__tests__/reports_filter_performance.test.js)
/**!
 * @brief Guard test for report filter responsiveness on moderate in-memory dataset.
 * @layer UI (Tests)
 * @semantics tests, reports, performance, filtering
 */

// --- ReportsListTest:Module (frontend/src/lib/components/reports/__tests__/reports_list.ux.test.js)
/**!
 * @brief Test ReportsList component iteration and event forwarding.
 * @layer UI
 * @semantics reports, list, ux-tests, events, iteration
 * @test_contract ReportsListProps -> rendered cards and forwarded select events
 * @test_fixture reports_list_examples -> INLINE_JSON
 * @test_invariant report_iteration_and_select_contract -> VERIFIED_BY: [renders_report_cards_for_each_item, renders_empty_list_container, forwards_select_event]
 * @test_scenario forwards_select_event -> Child click forwards select payload to parent listener.
 */

// --- ReportsPageTest:Module (frontend/src/lib/components/reports/__tests__/reports_page.integration.test.js)
/**!
 * @brief Integration-style checks for unified mixed-type reports rendering expectations.
 * @invariant Mixed fixture includes all supported report types in one list.
 * @layer UI (Tests)
 * @semantics tests, reports, integration, mixed-types, rendering
 */

// --- ReportTypeProfiles:Module (frontend/src/lib/components/reports/reportTypeProfiles.js)
/**!
 * @brief Deterministic mapping from report task_type to visual profile with one fallback.
 */

// --- getReportTypeProfile:Function (frontend/src/lib/components/reports/reportTypeProfiles.js)
/**!
 * @brief Resolve visual profile by task type with guaranteed fallback.
 * @post Returns one profile object.
 * @pre taskType may be known/unknown/empty.
 * @test_contract GetReportTypeProfileModel ->
 */

// --- ApiKeysTab (frontend/src/lib/components/settings/ApiKeysTab.svelte)
/**!
 * @brief API Key management tab — list, generate (one-time reveal), and revoke API keys.
 * @complexity 3
 * @layer UI
 * @ux_feedback Toast on generate success/error, revoke success/error
 * @ux_reactivity Props -> $props(), LocalState -> $state(keys, isLoading, error)
 * @ux_recovery Retry button on load error
 * @ux_state Revealing -> Warning panel with raw key and copy button
 */

// --- BulkCorrectionSidebar (frontend/src/lib/components/translate/BulkCorrectionSidebar.svelte)
/**!
 * @brief Component component: lib/components/translate/BulkCorrectionSidebar.svelte
 * @complexity 3
 * @type {'closed'|'collecting'|'reviewing'|'submitting'|'submitted'}
 * @ux_feedback Toast on success/error; count badge on toggle button
 * @ux_recovery Remove individual items; retry submission
 * @ux_state submitted -> Success feedback
 */

// --- BulkReplaceModal (frontend/src/lib/components/translate/BulkReplaceModal.svelte)
/**!
 * @brief Modal dialog for bulk find-and-replace on translated values within a completed run.
 * @complexity 3
 * @layer UI
 * @type {'closed'|'configuring'|'previewing'|'preview_error'|'confirming'|'applying'|'applied'|'apply_error'}
 * @ux_state apply_error -> Apply failed with error message
 */

// --- CorrectionCell (frontend/src/lib/components/translate/CorrectionCell.svelte)
/**!
 * @brief Inline-editable cell for translation run results with edit-save-cancel UX and submit-to-dictionary flow.
 * @complexity 3
 * @layer UI
 * @type {'view'|'editing'|'saving'|'saved'|'submitting_to_dict'|'dict_submitted'|'error'}
 * @ux_state error -> Error state with retry option
 */

// --- ScheduleConfig (frontend/src/lib/components/translate/ScheduleConfig.svelte)
/**!
 * @brief Component component: lib/components/translate/ScheduleConfig.svelte
 * @complexity 3
 * @type {'idle'|'editing'|'enabled'|'disabled'|'no_prior_run_warning'}
 * @ux_feedback Next-3-executions preview; toast on save/error
 * @ux_recovery Enable/disable toggle; delete schedule
 * @ux_state no_prior_run_warning -> No prior manual run, show warning
 */

// --- TargetSchemaHint (frontend/src/lib/components/translate/TargetSchemaHint.svelte)
/**!
 * @brief Подсказка о колонках целевой таблицы + кнопка "Проверить схему".
 * @complexity 3
 */

// --- TermCorrectionPopup (frontend/src/lib/components/translate/TermCorrectionPopup.svelte)
/**!
 * @brief Component component: lib/components/translate/TermCorrectionPopup.svelte
 * @complexity 3
 * @type {'closed'|'selecting'|'editing'|'submitting'|'conflict_detected'|'submitted'}
 * @ux_feedback Toast on success/error; conflict dialog with action buttons
 * @ux_recovery Cancel button returns to previous state
 * @ux_state submitted -> Success feedback
 */

// --- TranslationMetricsDashboard (frontend/src/lib/components/translate/TranslationMetricsDashboard.svelte)
/**!
 * @brief Component component: lib/components/translate/TranslationMetricsDashboard.svelte
 * @complexity 3
 * @type {'loading'|'loaded'|'error'|'empty'}
 * @ux_feedback Spinner during load; card grid for totals; table for per-job breakdown
 * @ux_recovery Retry button on error
 * @ux_state empty -> No metrics data available
 */

// --- TranslationPreview (frontend/src/lib/components/translate/TranslationPreview.svelte)
/**!
 * @brief Component component: lib/components/translate/TranslationPreview.svelte
 * @complexity 3
 * @type {'idle'|'loading'|'preview_loaded'|'preview_error'|'accepted'|'stale_config'}
 * @ux_feedback spinner during preview; visual distinction for LLM vs edited translations; cost warning for large previews.
 * @ux_recovery retry preview; re-fetch with updated config.
 * @ux_state stale_config -> Configuration changed since preview was generated
 */

// --- TranslationRunGlobalIndicator (frontend/src/lib/components/translate/TranslationRunGlobalIndicator.svelte)
/**!
 * @brief Persistent rich progress panel for active translation runs, rendered in root layout.
 * @complexity 3
 * @ux_feedback Rich stats during active run; compact auto-dismiss for terminal states
 * @ux_state cancelled -> Compact gray banner with auto-dismiss after 8s
 */

// --- TranslationRunProgress (frontend/src/lib/components/translate/TranslationRunProgress.svelte)
/**!
 * @brief Component component: lib/components/translate/TranslationRunProgress.svelte
 * @complexity 3
 * @type {{ runId: string, onRetry?: () => void, onRetryInsert?: () => void, onComplete?: (statusData: any) => void }}
 * @ux_feedback progress bar with percentage; batch counter; per-phase counts; cancel button during running/inserting.
 * @ux_recovery retry on failure states.
 * @ux_state cancelled -> Run was cancelled
 */

// --- TranslationRunResult (frontend/src/lib/components/translate/TranslationRunResult.svelte)
/**!
 * @brief Component component: lib/components/translate/TranslationRunResult.svelte
 * @complexity 3
 * @type {'completed'|'partial'|'failed'|'insert_failed'}
 * @ux_feedback Tabular statistics; click to copy Superset query ID; collapsible SQL block.
 * @ux_recovery Retry failed batches; retry insert.
 * @ux_state insert_failed -> Insert phase failed, retry-insert available
 */

// --- TargetSchemaHintTest (frontend/src/lib/components/translate/__tests__/TargetSchemaHint.test.js)
/**!
 * @brief Contract-focused unit tests for TargetSchemaHint.svelte component.
 * @complexity 2
 * @layer Tests
 * @test_contract TargetSchemaHint -> idle, checking, complete, error UX states
 * @test_edge error_state -> Error state shows red border
 */

// --- test_component_exists (frontend/src/lib/components/translate/__tests__/TargetSchemaHint.test.js)
/**!
 * @brief Verify component file exists.
 */

// --- test_ux_state_contracts (frontend/src/lib/components/translate/__tests__/TargetSchemaHint.test.js)
/**!
 * @brief Component contains required UX state tags.
 */

// --- test_props_definition (frontend/src/lib/components/translate/__tests__/TargetSchemaHint.test.js)
/**!
 * @brief Component accepts required props.
 */

// --- test_button_check_disabled_logic (frontend/src/lib/components/translate/__tests__/TargetSchemaHint.test.js)
/**!
 * @brief Button disabled logic: canCheck derived checks all required props.
 */

// --- test_idle_state (frontend/src/lib/components/translate/__tests__/TargetSchemaHint.test.js)
/**!
 * @brief Idle state shows hint text and check button.
 */

// --- test_checking_state (frontend/src/lib/components/translate/__tests__/TargetSchemaHint.test.js)
/**!
 * @brief Checking state shows spinner and disables button.
 */

// --- test_complete_state (frontend/src/lib/components/translate/__tests__/TargetSchemaHint.test.js)
/**!
 * @brief Complete state shows result with green/yellow/red indicators.
 */

// --- test_error_state (frontend/src/lib/components/translate/__tests__/TargetSchemaHint.test.js)
/**!
 * @brief Error state shows connection error message.
 */

// --- test_i18n_usage (frontend/src/lib/components/translate/__tests__/TargetSchemaHint.test.js)
/**!
 * @brief Component uses i18n _() for all user-facing strings with fallbacks.
 */

// --- test_abort_controller (frontend/src/lib/components/translate/__tests__/TargetSchemaHint.test.js)
/**!
 * @brief Component uses AbortController for request cancellation.
 */

// --- BulkReplaceModalTests (frontend/src/lib/components/translate/__tests__/test_bulk_replace_modal.svelte.js)
/**!
 * @brief Contract-focused unit tests for BulkReplaceModal.svelte component.
 * @complexity 2
 * @layer Tests
 * @test_contract BulkReplaceModal -> configuring, preview, confirm, apply flow
 * @test_edge applied -> Success state
 */

// --- CorrectionCellTests (frontend/src/lib/components/translate/__tests__/test_correction_cell.svelte.js)
/**!
 * @brief Contract-focused unit tests for CorrectionCell.svelte component.
 * @complexity 2
 * @layer Tests
 * @test_contract CorrectionCell -> renders value, click-to-edit, save, submit-to-dictionary
 * @test_edge submit_with_context -> Submit payload includes context_data and usage_notes
 */

// --- test_component_file_exists:Function (frontend/src/lib/components/translate/__tests__/test_translation_preview.svelte.js)
/**!
 * @brief Verify component file exists and has required contracts
 */

// --- TranslateApiTests:Class (frontend/src/lib/components/translate/__tests__/test_translation_preview.svelte.js)
/**!
 * @brief Unit tests for translate API preview functions.
 */

// --- test_fetchPreview:Function (frontend/src/lib/components/translate/__tests__/test_translation_preview.svelte.js)
/**!
 * @brief Verify fetchPreview calls postApi with correct endpoint and payload.
 */

// --- test_approveRow:Function (frontend/src/lib/components/translate/__tests__/test_translation_preview.svelte.js)
/**!
 * @brief Verify approveRow calls requestApi with correct action.
 */

// --- test_editRow:Function (frontend/src/lib/components/translate/__tests__/test_translation_preview.svelte.js)
/**!
 * @brief Verify editRow calls requestApi with edit action and translation.
 */

// --- test_rejectRow:Function (frontend/src/lib/components/translate/__tests__/test_translation_preview.svelte.js)
/**!
 * @brief Verify rejectRow calls requestApi with reject action.
 */

// --- test_acceptPreview:Function (frontend/src/lib/components/translate/__tests__/test_translation_preview.svelte.js)
/**!
 * @brief Verify acceptPreview calls postApi with correct endpoint.
 */

// --- test_fetchPreviewRecords:Function (frontend/src/lib/components/translate/__tests__/test_translation_preview.svelte.js)
/**!
 * @brief Verify fetchPreviewRecords calls fetchApi with correct endpoint.
 */

// --- test_normalizeTranslateError:Function (frontend/src/lib/components/translate/__tests__/test_translation_preview.svelte.js)
/**!
 * @brief Verify API errors are normalized consistently.
 */

// --- I18nModule (frontend/src/lib/i18n/index.ts)
/**!
 * @brief Centralized internationalization management using Svelte stores with Russian and English locale support persisted in LocalStorage.
 * @complexity 3
 */

// --- i18n:Module (frontend/src/lib/i18n/index.ts)
/**!
 * @brief Centralized internationalization management using Svelte stores.
 * @invariant Persistence is handled via LocalStorage.
 * @layer Infra
 * @semantics i18n, localization, svelte-store, translation
 */

// --- locale:Store (frontend/src/lib/i18n/index.ts)
/**!
 * @brief Holds the current active locale string.
 * @side_effect Writes to LocalStorage on change.
 */

// --- t:Store (frontend/src/lib/i18n/index.ts)
/**!
 * @brief Derived store providing the translation dictionary.
 */

// --- _:Function (frontend/src/lib/i18n/index.ts)
/**!
 * @brief Get translation by key path.
 * @param key - Translation key path (e.g., 'nav.dashboard')
 * @return Translation string or key if not found
 */

// --- frontend/src/lib/i18n/index.ts::_ (frontend/src/lib/i18n/index.ts)
/**!
 */

// --- StoresModule (frontend/src/lib/stores.js)
/**!
 * @brief Global Svelte writable stores for plugins, tasks, and UI page state management.
 * @complexity 3
 */

// --- stores_module:Module (frontend/src/lib/stores.js)
/**!
 * @brief Global state management using Svelte stores.
 * @layer UI
 * @semantics state, stores, svelte, plugins, tasks
 */

// --- plugins:Data (frontend/src/lib/stores.js)
/**!
 * @brief Store for the list of available plugins.
 */

// --- tasks:Data (frontend/src/lib/stores.js)
/**!
 * @brief Store for the list of tasks.
 */

// --- selectedPlugin:Data (frontend/src/lib/stores.js)
/**!
 * @brief Store for the currently selected plugin.
 */

// --- selectedTask:Data (frontend/src/lib/stores.js)
/**!
 * @brief Store for the currently selected task.
 */

// --- currentPage:Data (frontend/src/lib/stores.js)
/**!
 * @brief Store for the current page.
 */

// --- taskLogs:Data (frontend/src/lib/stores.js)
/**!
 * @brief Store for the logs of the currently selected task.
 */

// --- fetchPlugins:Function (frontend/src/lib/stores.js)
/**!
 * @brief Fetches plugins from the API and updates the plugins store.
 * @post plugins store is updated with data from the API.
 * @pre None.
 */

// --- fetchTasks:Function (frontend/src/lib/stores.js)
/**!
 * @brief Fetches tasks from the API and updates the tasks store.
 * @post tasks store is updated with data from the API.
 * @pre None.
 */

// --- [EXT:frontend:AssistantChatTest]s (frontend/src/lib/stores/__tests__/assistantChat.test.js)
/**!
 * @brief Unit tests for assistant chat store validating open/close/toggle, conversation binding, session context, and seed message state transitions.
 * @complexity 3
 */

// --- [EXT:frontend:AssistantChatTest]:Module (frontend/src/lib/stores/__tests__/assistantChat.test.js)
/**!
 * @brief Validate assistant chat store visibility and conversation binding transitions.
 * @invariant Each test starts from default closed state.
 * @layer UI (Tests)
 * @semantics test, store, assistant, toggle, conversation
 */

// --- assistantChatStore_tests:Function (frontend/src/lib/stores/__tests__/assistantChat.test.js)
/**!
 * @brief Group store unit scenarios for assistant panel behavior.
 * @post Open/close/toggle/conversation transitions are validated.
 * @pre Store can be reset to baseline state in beforeEach hook.
 */

// --- MockEnvPublic (frontend/src/lib/stores/__tests__/mocks/env_public.js)
/**!
 * @complexity 1
 */

// --- mock_env_public:Module (frontend/src/lib/stores/__tests__/mocks/env_public.js)
/**!
 * @brief Mock for $env/static/public SvelteKit module in vitest
 * @layer UI (Tests)
 */

// --- EnvironmentMock (frontend/src/lib/stores/__tests__/mocks/environment.js)
/**!
 * @brief Mock for $app/environment in vitest, supplying browser, dev, and building flags.
 * @complexity 2
 */

// --- EnvironmentMock:Module (frontend/src/lib/stores/__tests__/mocks/environment.js)
/**!
 * @brief Mock for $app/environment in tests
 * @layer UI (Tests)
 */

// --- NavigationMock (frontend/src/lib/stores/__tests__/mocks/navigation.js)
/**!
 * @brief Mock for $app/navigation in vitest, supplying goto, push, replace, prefetch, and prefetchRoutes stubs.
 * @complexity 2
 */

// --- NavigationMock:Module (frontend/src/lib/stores/__tests__/mocks/navigation.js)
/**!
 * @brief Mock for $app/navigation in tests
 * @invariant Includes SvelteKit v1-only APIs (push, prefetchRoutes) as compatibility surface for legacy test consumers; keep until all imports migrate to SvelteKit v2-compatible mocks.
 * @semantics mock, navigation, sveltekit-v1-legacy-surface
 */

// --- StateMock (frontend/src/lib/stores/__tests__/mocks/state.js)
/**!
 * @brief Mock for $app/state page data in vitest route/component tests, supplying default params, route, URL, status, and data.
 * @complexity 2
 */

// --- state_mock:Module (frontend/src/lib/stores/__tests__/mocks/state.js)
/**!
 * @brief Mock for AppState in vitest route/component tests.
 * @layer UI (Tests)
 */

// --- StoresMock (frontend/src/lib/stores/__tests__/mocks/stores.js)
/**!
 * @complexity 1
 */

// --- StoresMock:Module (frontend/src/lib/stores/__tests__/mocks/stores.js)
/**!
 * @brief Mock for $app/stores in tests
 * @invariant Mocks $app/stores which is a SvelteKit v1 module; SvelteKit v2 uses $app/state. Verify no active test files import this mock before removal.
 * @semantics mock, stores, sveltekit-v1-legacy-surface
 */

// --- SetupTestsModule (frontend/src/lib/stores/__tests__/setupTests.js)
/**!
 * @brief Global vitest test setup with mocks for SvelteKit modules ($app/environment, $app/stores, $app/navigation, localStorage).
 * @complexity 3
 */

// --- setupTests:Module (frontend/src/lib/stores/__tests__/setupTests.js)
/**!
 * @brief Global test setup with mocks for SvelteKit modules
 * @layer UI
 * @ux_state Idle -> Global test environment exposes stable mocked browser services.
 */

// --- SidebarTest (frontend/src/lib/stores/__tests__/sidebar.test.js)
/**!
 * @brief Unit tests for sidebar store validating expansion toggles, active item selection, and mobile open/close transitions.
 * @complexity 3
 */

// --- SidebarTest:Module (frontend/src/lib/stores/__tests__/sidebar.test.js)
/**!
 * @brief Unit tests for sidebar store
 * @invariant Sidebar store transitions must be deterministic across desktop/mobile toggles.
 * @layer Tests
 * @semantics sidebar, store, tests, mobile, navigation
 */

// --- test_sidebar_initial_state:Function (frontend/src/lib/stores/__tests__/sidebar.test.js)
/**!
 * @brief Verify initial sidebar store values when no persisted state is available.
 * @post Default state is { isExpanded: true, activeCategory: 'dashboards', activeItem: '/dashboards', isMobileOpen: false }
 * @pre No localStorage state
 * @test Store initializes with default values
 */

// --- test_toggleSidebar:Function (frontend/src/lib/stores/__tests__/sidebar.test.js)
/**!
 * @brief Verify desktop sidebar expansion toggles deterministically.
 * @post isExpanded is toggled from previous value
 * @pre Store is initialized
 * @test toggleSidebar toggles isExpanded state
 */

// --- test_setActiveItem:Function (frontend/src/lib/stores/__tests__/sidebar.test.js)
/**!
 * @brief Verify active-category updates remain deterministic after item selection.
 * @post activeCategory and activeItem are updated
 * @pre Store is initialized
 * @test setActiveItem updates activeCategory and activeItem
 */

// --- test_mobile_functions:Function (frontend/src/lib/stores/__tests__/sidebar.test.js)
/**!
 * @brief Verify mobile sidebar helpers update open-state transitions predictably.
 * @post isMobileOpen is correctly updated
 * @pre Store is initialized
 * @test Mobile functions correctly update isMobileOpen
 */

// --- TaskDrawerTests (frontend/src/lib/stores/__tests__/taskDrawer.test.js)
/**!
 * @brief Unit tests for task drawer store validating open/close, preference-aware opening, resource task mapping, and status-driven cleanup.
 * @complexity 3
 */

// --- ActivityTestModule (frontend/src/lib/stores/__tests__/test_activity.js)
/**!
 * @brief Unit tests validating activity store derived count and recent task tracking behavior.
 * @complexity 3
 */

// --- ActivityTest:Module (frontend/src/lib/stores/__tests__/test_activity.js)
/**!
 * @brief Unit tests for activity store
 */

// --- DatasetReviewSessionTests (frontend/src/lib/stores/__tests__/test_datasetReviewSession.js)
/**!
 * @brief Unit tests for dataset review session store: session set/reset, loading, error, dirty flag, and patch operations.
 * @complexity 3
 */

// --- DatasetReviewSessionStoreTests:Module (frontend/src/lib/stores/__tests__/test_datasetReviewSession.js)
/**!
 * @brief Unit tests for dataset review session store.
 * @layer UI
 * @semantics dataset-review, store, session, tests
 * @ux_state Idle -> Store helpers are exercised without asynchronous UI transitions.
 */

// --- SidebarTestModule (frontend/src/lib/stores/__tests__/test_sidebar.js)
/**!
 * @brief Unit tests for sidebar store validating initial state, toggle, navigation, mobile overlay, and localStorage persistence.
 * @complexity 3
 */

// --- SidebarIntegrationTest:Module (frontend/src/lib/stores/__tests__/test_sidebar.js)
/**!
 * @brief Unit tests for sidebar store
 * @layer UI
 */

// --- TaskDrawerTestModule (frontend/src/lib/stores/__tests__/test_taskDrawer.js)
/**!
 * @brief Unit tests for task drawer store validating open/close transitions, preference-aware opening, and resource-task mapping lifecycle.
 * @complexity 3
 */

// --- TaskDrawerTest:Module (frontend/src/lib/stores/__tests__/test_taskDrawer.js)
/**!
 * @brief Unit tests for task drawer store
 * @invariant Store state transitions remain deterministic for open/close and task-status mapping.
 * @layer UI
 * @semantics task-drawer, store, mapping, tests
 */

// --- ActivityStore (frontend/src/lib/stores/activity.js)
/**!
 * @brief Derived store that counts active running tasks for navbar indicator badge.
 * @complexity 2
 */

// --- activity:Store (frontend/src/lib/stores/activity.js)
/**!
 * @brief Track active task count for navbar indicator
 * @layer UI
 */

// --- AssistantChatStore (frontend/src/lib/stores/assistantChat.js)
/**!
 * @brief Control assistant chat panel visibility, conversation binding, session context, and seeded prompts.
 * @complexity 3
 * @ux_state Open -> Chat panel visible with active conversation
 */

// --- assistantChat:Store (frontend/src/lib/stores/assistantChat.js)
/**!
 * @brief Control assistant chat panel visibility and active conversation binding.
 */

// --- toggleAssistantChat:Function (frontend/src/lib/stores/assistantChat.js)
/**!
 * @brief Toggle assistant panel visibility.
 * @post isOpen value inverted.
 * @pre Store is initialized.
 */

// --- openAssistantChat:Function (frontend/src/lib/stores/assistantChat.js)
/**!
 * @brief Open assistant panel.
 * @post isOpen = true.
 * @pre Store is initialized.
 */

// --- openAssistantChatWithContext:Function (frontend/src/lib/stores/assistantChat.js)
/**!
 * @brief Open assistant panel with dataset review session context and optional seeded prompt/focus target.
 * @post Assistant drawer opens with session binding and visible focus metadata.
 * @pre Context payload may be partial.
 */

// --- closeAssistantChat:Function (frontend/src/lib/stores/assistantChat.js)
/**!
 * @brief Close assistant panel.
 * @post isOpen = false.
 * @pre Store is initialized.
 */

// --- setAssistantConversationId:Function (frontend/src/lib/stores/assistantChat.js)
/**!
 * @brief Bind current conversation id in UI state.
 * @post store.conversationId updated.
 * @pre conversationId is string-like identifier.
 */

// --- setAssistantDatasetReviewSessionId:Function (frontend/src/lib/stores/assistantChat.js)
/**!
 * @brief Bind active dataset review session to assistant state.
 * @post store.datasetReviewSessionId updated.
 * @pre session identifier may be null when workspace context is cleared.
 */

// --- setAssistantSeedMessage:Function (frontend/src/lib/stores/assistantChat.js)
/**!
 * @brief Stage a seeded assistant prompt for contextual send UX.
 * @post store.seedMessage updated.
 * @pre seedMessage can be empty to clear staged draft.
 */

// --- setAssistantFocusTarget:Function (frontend/src/lib/stores/assistantChat.js)
/**!
 * @brief Track the workspace entity currently referenced by assistant context.
 * @post store.focusTarget updated.
 * @pre focusTarget may be null to clear prior focus.
 */

// --- DatasetReviewSessionStore (frontend/src/lib/stores/datasetReviewSession.js)
/**!
 * @brief Manage active dataset review session state including loading, local edits, error capture, and reset semantics.
 * @complexity 4
 * @post Store transitions keep session, loading, error, and dirty flags internally consistent after each helper call.
 * @pre Consumers provide session-shaped payloads and initialize the store before reading derived session fields.
 * @side_effect Mutates the writable dataset review session store in frontend memory.
 * @ux_state Error -> Failed to load or update session
 */

// --- datasetReviewSession:Store (frontend/src/lib/stores/datasetReviewSession.js)
/**!
 * @brief Manage active dataset review session state, including loading, local edits, error capture, and reset semantics for the active review workspace.
 * @data_contract Input[SessionDetail | Partial<SessionDetail> | boolean | string | null] -> Output[DatasetReviewSessionStoreState]
 * @layer UI
 * @post Store transitions keep session, loading, error, and dirty flags internally consistent after each helper call.
 * @pre Consumers provide session-shaped payloads when setting or patching state and initialize the store before reading derived session fields.
 * @side_effect Mutates the writable dataset review session store in frontend memory.
 * @ux_reactivity Uses Svelte writable store for session aggregate.
 * @ux_state LaunchBlocked -> Session remains reviewable while explicit launch blockers are unresolved.
 */

// --- frontend/src/lib/stores/datasetReviewSession.js::setSession (frontend/src/lib/stores/datasetReviewSession.js)
/**!
 */

// --- frontend/src/lib/stores/datasetReviewSession.js::setLoading (frontend/src/lib/stores/datasetReviewSession.js)
/**!
 */

// --- frontend/src/lib/stores/datasetReviewSession.js::setError (frontend/src/lib/stores/datasetReviewSession.js)
/**!
 */

// --- frontend/src/lib/stores/datasetReviewSession.js::setDirty (frontend/src/lib/stores/datasetReviewSession.js)
/**!
 */

// --- frontend/src/lib/stores/datasetReviewSession.js::resetSession (frontend/src/lib/stores/datasetReviewSession.js)
/**!
 */

// --- frontend/src/lib/stores/datasetReviewSession.js::patchSession (frontend/src/lib/stores/datasetReviewSession.js)
/**!
 */

// --- frontend/src/lib/stores/datasetReviewSession.js::getSessionUiPhase (frontend/src/lib/stores/datasetReviewSession.js)
/**!
 */

// --- EnvironmentContextStore (frontend/src/lib/stores/environmentContext.js)
/**!
 * @brief Global selected environment context for navigation, safety cues, and environment-based filtering.
 * @complexity 3
 * @ux_state Error -> Failed to load environments
 */

// --- environmentContext:Store (frontend/src/lib/stores/environmentContext.js)
/**!
 * @brief Global selected environment context for navigation and safety cues.
 * @layer UI
 */

// --- HealthStore (frontend/src/lib/stores/health.js)
/**!
 * @brief Manage dashboard health summary state and failing counts for UI badges.
 * @complexity 3
 * @ux_state Error -> Error state with retry option
 */

// --- health_store:Store (frontend/src/lib/stores/health.js)
/**!
 * @brief Manage dashboard health summary state and failing counts for UI badges.
 * @layer UI
 * @property {Date|null} lastUpdated - Last successful fetch timestamp
 * @typedef {Object} HealthState
 * @ux_state Loading -> Default
 */

// --- frontend/src/lib/stores/health.js::createHealthStore (frontend/src/lib/stores/health.js)
/**!
 */

// --- frontend/src/lib/stores/health.js::refresh (frontend/src/lib/stores/health.js)
/**!
 */

// --- MaintenanceStore (frontend/src/lib/stores/maintenance.svelte.js)
/**!
 * @brief Svelte 5 (Runes) store for maintenance banner state. Auto-polls events every 30s via interval.
 * @complexity 3
 * @layer Frontend
 * @return {object} Maintenance store with runes state and methods.
 * @ux_reactivity $state for events/settings/banners. Manual setInterval for polling.
 * @ux_recovery Error toast on failure. Retry via loadEvents/loadSettings.
 * @ux_state Error -> error state populated with message
 */

// --- frontend/src/lib/stores/maintenance.svelte.js::createMaintenanceStore (frontend/src/lib/stores/maintenance.svelte.js)
/**!
 */

// --- MaintenanceStore.state (frontend/src/lib/stores/maintenance.svelte.js)
/**!
 * @complexity 1
 */

// --- MaintenanceStore.methods (frontend/src/lib/stores/maintenance.svelte.js)
/**!
 * @complexity 2
 */

// --- frontend/src/lib/stores/maintenance.svelte.js::loadEvents (frontend/src/lib/stores/maintenance.svelte.js)
/**!
 */

// --- frontend/src/lib/stores/maintenance.svelte.js::loadDashboardBanners (frontend/src/lib/stores/maintenance.svelte.js)
/**!
 */

// --- frontend/src/lib/stores/maintenance.svelte.js::loadSettings (frontend/src/lib/stores/maintenance.svelte.js)
/**!
 */

// --- frontend/src/lib/stores/maintenance.svelte.js::endEvent (frontend/src/lib/stores/maintenance.svelte.js)
/**!
 */

// --- frontend/src/lib/stores/maintenance.svelte.js::endAllEvents (frontend/src/lib/stores/maintenance.svelte.js)
/**!
 */

// --- frontend/src/lib/stores/maintenance.svelte.js::updateSettings (frontend/src/lib/stores/maintenance.svelte.js)
/**!
 */

// --- frontend/src/lib/stores/maintenance.svelte.js::init (frontend/src/lib/stores/maintenance.svelte.js)
/**!
 */

// --- frontend/src/lib/stores/maintenance.svelte.js::startPolling (frontend/src/lib/stores/maintenance.svelte.js)
/**!
 */

// --- frontend/src/lib/stores/maintenance.svelte.js::stopPolling (frontend/src/lib/stores/maintenance.svelte.js)
/**!
 */

// --- SidebarStore (frontend/src/lib/stores/sidebar.js)
/**!
 * @brief Manage sidebar visibility, expansion state, active navigation item, and mobile overlay.
 * @complexity 3
 * @ux_state Toggling -> Expand/collapse animation
 */

// --- sidebar:Store (frontend/src/lib/stores/sidebar.js)
/**!
 * @brief Manage sidebar visibility and navigation state
 * @invariant isExpanded state is always synced with localStorage
 * @layer UI
 * @ux_state Toggling -> Animation plays for 200ms
 */

// --- frontend/src/lib/stores/sidebar.js::toggleSidebar (frontend/src/lib/stores/sidebar.js)
/**!
 */

// --- frontend/src/lib/stores/sidebar.js::setActiveItem (frontend/src/lib/stores/sidebar.js)
/**!
 */

// --- frontend/src/lib/stores/sidebar.js::setMobileOpen (frontend/src/lib/stores/sidebar.js)
/**!
 */

// --- frontend/src/lib/stores/sidebar.js::closeMobile (frontend/src/lib/stores/sidebar.js)
/**!
 */

// --- frontend/src/lib/stores/sidebar.js::toggleMobileSidebar (frontend/src/lib/stores/sidebar.js)
/**!
 */

// --- TaskDrawerStore (frontend/src/lib/stores/taskDrawer.js)
/**!
 * @brief Manage Task Drawer visibility, active task binding, and resource-to-task mapping.
 * @complexity 3
 * @ux_state Open -> Drawer visible with task logs or task list
 */

// --- taskDrawer:Store (frontend/src/lib/stores/taskDrawer.js)
/**!
 * @brief Manage Task Drawer visibility and resource-to-task mapping
 */

// --- frontend/src/lib/stores/taskDrawer.js::openDrawerForTask (frontend/src/lib/stores/taskDrawer.js)
/**!
 */

// --- frontend/src/lib/stores/taskDrawer.js::setTaskDrawerAutoOpenPreference (frontend/src/lib/stores/taskDrawer.js)
/**!
 */

// --- frontend/src/lib/stores/taskDrawer.js::getTaskDrawerAutoOpenPreference (frontend/src/lib/stores/taskDrawer.js)
/**!
 */

// --- frontend/src/lib/stores/taskDrawer.js::openDrawerForTaskIfPreferred (frontend/src/lib/stores/taskDrawer.js)
/**!
 */

// --- frontend/src/lib/stores/taskDrawer.js::openDrawer (frontend/src/lib/stores/taskDrawer.js)
/**!
 */

// --- frontend/src/lib/stores/taskDrawer.js::closeDrawer (frontend/src/lib/stores/taskDrawer.js)
/**!
 */

// --- frontend/src/lib/stores/taskDrawer.js::updateResourceTask (frontend/src/lib/stores/taskDrawer.js)
/**!
 */

// --- frontend/src/lib/stores/taskDrawer.js::getTaskForResource (frontend/src/lib/stores/taskDrawer.js)
/**!
 */

// --- TranslationRunStore (frontend/src/lib/stores/translationRun.js)
/**!
 * @brief Global store for active translation run progress — survives page navigation.
 * @complexity 3
 * @property {boolean} isActive - Derived: true when polling is active
 * @typedef {Object} TranslationRunState
 */

// --- frontend/src/lib/stores/translationRun.js::clearOnCompleteCallback (frontend/src/lib/stores/translationRun.js)
/**!
 */

// --- frontend/src/lib/stores/translationRun.js::startTranslationRun (frontend/src/lib/stores/translationRun.js)
/**!
 */

// --- frontend/src/lib/stores/translationRun.js::stopTranslationRun (frontend/src/lib/stores/translationRun.js)
/**!
 */

// --- frontend/src/lib/stores/translationRun.js::resetTranslationRun (frontend/src/lib/stores/translationRun.js)
/**!
 */

// --- frontend/src/lib/stores/translationRun.js::updateTranslationRunState (frontend/src/lib/stores/translationRun.js)
/**!
 */

// --- frontend/src/lib/stores/translationRun.js::pollStatus (frontend/src/lib/stores/translationRun.js)
/**!
 */

// --- ToastsModule (frontend/src/lib/toasts.js)
/**!
 * @brief Manages toast notifications using a Svelte writable store with deduplication and auto-removal.
 * @complexity 3
 */

// --- toasts_module:Module (frontend/src/lib/toasts.js)
/**!
 * @brief Manages toast notifications using a Svelte writable store.
 * @layer UI
 * @semantics notification, toast, feedback, state
 */

// --- toasts:Data (frontend/src/lib/toasts.js)
/**!
 * @brief Writable store containing the list of active toasts.
 */

// --- addToast:Function (frontend/src/lib/toasts.js)
/**!
 * @brief Adds a new toast message.
 * @param duration (number) - Duration in ms before the toast is removed.
 * @post New toast is added to the store and scheduled for removal.
 * @pre message string is provided.
 */

// --- removeToast:Function (frontend/src/lib/toasts.js)
/**!
 * @brief Removes a toast message by ID.
 * @param id (string) - The ID of the toast to remove.
 * @post Toast is removed from the store.
 * @pre id is provided.
 */

// --- Button (frontend/src/lib/ui/Button.svelte)
/**!
 * @brief Standardized button component with variants and loading states.
 * @complexity 2
 * @invariant Supports accessible labels and keyboard navigation.
 * @layer Atom
 * @semantics button, ui-atom, interactive
 * @ux_state Loading -> Spinner replaces the leading area and interaction is disabled.
 */

// --- Card (frontend/src/lib/ui/Card.svelte)
/**!
 * @brief Standardized container with padding and elevation.
 * @complexity 2
 * @layer Atom
 * @semantics card, container, ui-atom
 * @ux_state Titled -> Header row appears above the padded content area.
 */

// --- Icon (frontend/src/lib/ui/Icon.svelte)
/**!
 * @brief Render the shared inline SVG icon set with consistent sizing and stroke props.
 * @complexity 1
 * @invariant Icon output remains aria-hidden because labels belong to the interactive parent.
 * @layer Atom
 * @semantics icon, ui-atom, svg
 * @ux_state Fallback -> Unknown icon names resolve to the dashboard glyph.
 */

// --- Input (frontend/src/lib/ui/Input.svelte)
/**!
 * @brief Standardized text input component with label and error handling.
 * @complexity 2
 * @invariant Consistent spacing and focus states.
 * @layer Atom
 * @semantics input, form-field, ui-atom
 * @ux_state Disabled -> Native disabled state prevents editing while preserving value visibility.
 */

// --- LanguageSwitcher (frontend/src/lib/ui/LanguageSwitcher.svelte)
/**!
 * @brief Dropdown component to switch between supported languages.
 * @complexity 1
 * @layer Atom
 * @semantics language-switcher, i18n-ui, ui-atom
 * @ux_state Switching -> Bound locale updates immediately after selection.
 */

// --- PageHeader (frontend/src/lib/ui/PageHeader.svelte)
/**!
 * @brief Standardized page header with title and action area.
 * @complexity 2
 * @layer Atom
 * @semantics page-header, layout-atom
 * @ux_state WithContext -> Subtitle and action slots expand the header composition.
 */

// --- Select (frontend/src/lib/ui/Select.svelte)
/**!
 * @brief Standardized dropdown selection component.
 * @complexity 2
 * @layer Atom
 * @semantics select, dropdown, form-field, ui-atom
 * @ux_state Disabled -> Native disabled state prevents selection changes.
 */

// --- ui:Module (frontend/src/lib/ui/index.ts)
/**!
 * @brief Central export point for standardized UI components.
 * @invariant All components exported here must follow Semantic Protocol.
 * @layer Atom
 * @semantics ui, components, library, atomic-design
 */

// --- UtilsModule (frontend/src/lib/utils.js)
/**!
 * @complexity 1
 */

// --- Utils:Module (frontend/src/lib/utils.js)
/**!
 * @brief General utility functions (class merging)
 * @layer Infra
 */

// --- frontend/src/lib/utils.js::cn (frontend/src/lib/utils.js)
/**!
 */

// --- DebounceModule (frontend/src/lib/utils/debounce.js)
/**!
 * @complexity 1
 */

// --- Debounce:Module (frontend/src/lib/utils/debounce.js)
/**!
 * @brief Debounce utility for limiting function execution rate
 * @layer Infra
 */

// --- frontend/src/lib/utils/debounce.js::debounce (frontend/src/lib/utils/debounce.js)
/**!
 */

// --- onMount:Function (frontend/src/pages/Dashboard.svelte)
/**!
 * @brief Fetch plugins when the component mounts.
 * @post plugins store is populated with available tools.
 * @pre Component is mounting.
 */

// --- selectPlugin:Function (frontend/src/pages/Dashboard.svelte)
/**!
 * @brief Selects a plugin to display its form.
 * @param {Object} plugin - The plugin object to select.
 * @post selectedPlugin store is updated.
 * @pre plugin object is provided.
 */

// --- loadSettings:Function (frontend/src/pages/Settings.svelte)
/**!
 * @brief Loads settings from the backend.
 * @post settings object is populated with backend data.
 * @pre Component mounted or refresh requested.
 */

// --- handleSaveGlobal:Function (frontend/src/pages/Settings.svelte)
/**!
 * @brief Saves global settings to the backend.
 * @post Backend global settings are updated.
 * @pre settings.settings contains valid configuration.
 */

// --- handleAddOrUpdateEnv:Function (frontend/src/pages/Settings.svelte)
/**!
 * @brief Adds or updates an environment.
 * @post Environment list is updated on backend and reloaded locally.
 * @pre newEnv contains valid environment details.
 */

// --- handleDeleteEnv:Function (frontend/src/pages/Settings.svelte)
/**!
 * @brief Deletes an environment.
 * @param {string} id - The ID of the environment to delete.
 * @post Environment is removed from backend and list is reloaded.
 * @pre id of environment to delete is provided.
 */

// --- handleTestEnv:Function (frontend/src/pages/Settings.svelte)
/**!
 * @brief Tests the connection to an environment.
 * @param {string} id - The ID of the environment to test.
 * @post Connection test result is displayed via toast.
 * @pre Environment ID is valid.
 */

// --- editEnv:Function (frontend/src/pages/Settings.svelte)
/**!
 * @brief Sets the form to edit an existing environment.
 * @param {Object} env - The environment object to edit.
 * @post newEnv is populated with env data and editingEnvId is set.
 * @pre env object is provided.
 */

// --- resetEnvForm:Function (frontend/src/pages/Settings.svelte)
/**!
 * @brief Resets the environment form.
 * @post newEnv is reset to initial state and editingEnvId is cleared.
 * @pre None.
 */

// --- ErrorPage (frontend/src/routes/+error.svelte)
/**!
 * @brief Global error page displaying HTTP status code and error message with navigation back to dashboard.
 * @complexity 2
 * @layer Page
 * @ux_state Error -> Displays error code and message with "Back to Dashboard" link.
 */

// --- RootLayout (frontend/src/routes/+layout.svelte)
/**!
 * @brief Root layout component providing global UI structure: Sidebar, TopNavbar, Footer, TaskDrawer, Toasts.
 * @complexity 3
 * @invariant Sidebar width adapts (ml-60 vs ml-16) based on sidebar expanded state.
 * @layer Layout
 * @ux_feedback Toast notifications rendered globally.
 * @ux_state Authenticated -> Full shell rendered with Sidebar, TopNavbar, Footer, global components.
 */

// --- RootLayoutConfig:Module (frontend/src/routes/+layout.ts)
/**!
 * @brief Root layout configuration (SPA mode)
 * @layer Infra
 */

// --- HomePage (frontend/src/routes/+page.svelte)
/**!
 * @brief Redirect to preferred start page (dashboards/datasets/reports) based on profile settings, with safe fallback.
 * @complexity 3
 * @invariant Redirect target resolves to one of /dashboards, /datasets, /reports.
 * @layer Page
 * @ux_feedback Redirects to preferred start page once profile or local fallback is resolved.
 * @ux_state Loading -> Shows centered spinner while resolving the preferred landing route.
 */

// --- load:Function (frontend/src/routes/+page.ts)
/**!
 * @brief Loads initial plugin data for the dashboard.
 * @post Returns an object with plugins or an error message.
 * @pre None.
 */

// --- frontend/src/routes/+page.ts::load (frontend/src/routes/+page.ts)
/**!
 */

// --- openCreateModal:Function (frontend/src/routes/admin/roles/+page.svelte)
/**!
 * @brief Initializes state for creating a new role.
 * @post showModal is true, roleForm is reset.
 * @pre None.
 */

// --- openEditModal:Function (frontend/src/routes/admin/roles/+page.svelte)
/**!
 * @brief Initializes state for editing an existing role.
 * @post showModal is true, roleForm is populated.
 * @pre role object is provided.
 */

// --- handleSaveRole:Function (frontend/src/routes/admin/roles/+page.svelte)
/**!
 * @brief Submits role data (create or update).
 * @post Role is saved, modal closed, data reloaded.
 * @pre roleForm contains valid data.
 */

// --- handleDeleteRole:Function (frontend/src/routes/admin/roles/+page.svelte)
/**!
 * @brief Deletes a role after confirmation.
 * @post Role is deleted if confirmed, data reloaded.
 * @pre role object is provided.
 */

// --- handleCreateMapping:Function (frontend/src/routes/admin/settings/+page.svelte)
/**!
 * @brief Submits a new AD Group to Role mapping to the backend.
 * @post A new mapping is created in the database and the table is refreshed.
 * @pre 'newMapping' object contains valid 'ad_group' and 'role_id'.
 * @return {Promise<void>}
 * @side_effect Closes the modal on success, shows alert on failure.
 */

// --- loadLoggingConfig:Function (frontend/src/routes/admin/settings/+page.svelte)
/**!
 * @brief Fetches current logging configuration from the backend.
 * @post loggingConfig variable is updated with backend data.
 * @pre Component is mounted and user has active session.
 * @return {Promise<void>}
 */

// --- saveLoggingConfig:Function (frontend/src/routes/admin/settings/+page.svelte)
/**!
 * @brief Saves logging configuration to the backend.
 * @post Configuration is saved and feedback is shown.
 * @pre loggingConfig contains valid values.
 * @return {Promise<void>}
 */

// --- LLMReportPage (frontend/src/routes/admin/settings/llm/+page.svelte)
/**!
 * @brief Admin settings page for LLM provider configuration.
 * @complexity 3
 * @layer UI
 * @semantics admin, llm, provider, config, prompt
 * @ux_state Loading -> Default
 */

// --- handleSaveUser:Function (frontend/src/routes/admin/users/+page.svelte)
/**!
 * @brief Submits user data to the backend (create or update).
 * @post User created or updated, modal closed, data reloaded.
 * @pre userForm must be valid.
 * @side_effect Triggers API call to adminService.
 */

// --- handleDeleteUser:Function (frontend/src/routes/admin/users/+page.svelte)
/**!
 * @brief Deletes a user after confirmation.
 * @param {Object} user - The user to delete.
 * @post User deleted if confirmed, data reloaded.
 * @pre user object must be valid.
 * @side_effect Triggers API call to adminService.
 */

// --- DashboardHub.normalizeTaskStatus:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Normalize raw task status to stable lowercase token for UI.
 * @post returns null or normalized token without enum namespace.
 * @pre status can be enum-like string or null.
 */

// --- DashboardHub.normalizeValidationStatus:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Normalize validation status to pass/fail/warn/unknown.
 * @post returns one of pass|fail|warn|unknown.
 * @pre status can be any scalar.
 */

// --- DashboardHub.getValidationBadgeClass:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Map validation level to badge class tuple.
 * @post returns deterministic tailwind class string.
 * @pre level in pass|fail|warn|unknown.
 */

// --- DashboardHub.getValidationLabel:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Map normalized validation level to compact UI label.
 * @post returns uppercase status label.
 * @pre level in pass|fail|warn|unknown.
 */

// --- DashboardHub.normalizeOwners:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Normalize owners payload to unique non-empty display labels.
 * @post Returns owner labels preserving source order.
 * @pre owners can be null, list of strings, or list of user objects.
 */

// --- DashboardHub.loadDashboards:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Load full dashboard dataset for current environment and hydrate grid projection.
 * @post allDashboards, dashboards, pagination and selection state are synchronized.
 * @pre selectedEnv is not null.
 * @ux_state Error -> `error` populated when request fails.
 */

// --- DashboardHub.handleTemporaryShowAll:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Temporarily disable profile-default dashboard filter for current page context.
 * @post Next request is sent with override_show_all=true.
 * @pre Dashboards list is loaded in dashboards_main context.
 */

// --- DashboardHub.handleRestoreProfileFilter:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Re-enable persisted profile-default filtering after temporary override.
 * @post Next request is sent with override_show_all=false.
 * @pre Current page is in override mode.
 */

// --- DashboardHub.formatDate:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Convert ISO timestamp to locale date string.
 * @post returns formatted date or "-".
 * @pre value may be null or invalid date string.
 */

// --- DashboardHub.getGitSummaryLabel:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Compute stable text label for git state column.
 * @post returns localized summary string.
 * @pre dashboard has git projection fields.
 */

// --- DashboardHub.getLlmSummaryLabel:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Compute normalized LLM validation summary label.
 * @post returns UNKNOWN fallback for missing status.
 * @pre dashboard may have null lastTask.
 */

// --- DashboardHub.getColumnCellValue:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Resolve comparable/filterable display value for any grid column.
 * @post returns non-empty scalar display value.
 * @pre column belongs to filterable column set.
 */

// --- DashboardHub.getFilterOptions:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Build unique sorted value list for a column filter dropdown.
 * @post returns de-duplicated sorted options.
 * @pre allDashboards is hydrated.
 */

// --- DashboardHub.getVisibleFilterOptions:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Apply in-dropdown search over full filter options.
 * @post returns subset for current filter popover list.
 * @pre columnFilterSearch contains search token for column.
 */

// --- DashboardHub.toggleFilterDropdown:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Toggle active column filter popover.
 * @post openFilterColumn updated.
 * @pre column is valid filter key.
 */

// --- DashboardHub.toggleFilterValue:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Add/remove specific filter value and reapply projection.
 * @post columnFilters updated and grid reprojected from page 1.
 * @pre value comes from option list of the same column.
 */

// --- DashboardHub.clearColumnFilter:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Reset selected values for one column.
 * @post filter cleared and projection refreshed.
 * @pre column is valid filter key.
 */

// --- DashboardHub.selectAllColumnFilterValues:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Select all currently visible values in filter popover.
 * @post column filter equals current visible option set.
 * @pre visible options computed for current search token.
 */

// --- DashboardHub.updateColumnFilterSearch:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Update local search token for one filter popover.
 * @post columnFilterSearch updated immutably.
 * @pre value is text from input.
 */

// --- DashboardHub.hasColumnFilter:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Determine if column has active selected values.
 * @post returns boolean activation marker.
 * @pre column is valid filter key.
 */

// --- DashboardHub.doesDashboardPassColumnFilters:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Evaluate dashboard row against all active column filters.
 * @post returns true only when row matches every active filter.
 * @pre dashboard contains projected values for each filterable column.
 */

// --- DashboardHub.getSortValue:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Compute stable comparable sort key for chosen column.
 * @post returns string/number key suitable for deterministic comparison.
 * @pre column belongs to sortable set.
 */

// --- DashboardHub.handleSort:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Toggle or switch sort order and reapply grid projection.
 * @post sortColumn/sortDirection updated and page reset to 1.
 * @pre column belongs to sortable set.
 */

// --- DashboardHub.getSortIndicator:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Return visual indicator for active/inactive sort header.
 * @post returns one of ↕ | ↑ | ↓.
 * @pre column belongs to sortable set.
 */

// --- DashboardHub.applyGridTransforms:Function (frontend/src/routes/dashboards/+page.svelte)
/**!
 * @brief Apply search + column filters + sort + pagination to grid data.
 * @post filteredDashboards/dashboards/total/totalPages are synchronized.
 * @pre allDashboards is current source collection.
 * @ux_state Loaded -> visible rows reflect all active controls deterministically.
 */

// --- DashboardHeader (frontend/src/routes/dashboards/[id]/components/DashboardHeader.svelte)
/**!
 * @brief Top title area, breadcrumb, Git branch selector, and action buttons for dashboard detail.
 * @complexity 2
 * @layer UI
 * @ux_state Idle -> Header with back button, title, Git status badge, and action buttons.
 */

// --- DashboardProfileOverrideIntegrationTest:Module (frontend/src/routes/dashboards/__tests__/dashboard-profile-override.integration.test.js)
/**!
 * @brief Verifies temporary show-all override and restore-on-return behavior for profile-default dashboard filtering.
 * @layer UI (Tests)
 * @semantics tests, dashboards, profile-filter, override, restore
 * @type {any}
 */

// --- HealthCenterPage (frontend/src/routes/dashboards/health/+page.svelte)
/**!
 * @brief Main page for the Dashboard Health Center showing health matrix table with environment filtering.
 * @complexity 3
 * @layer Page
 * @ux_state Error -> Error message displayed inline.
 */

// --- loadData:Function (frontend/src/routes/dashboards/health/+page.svelte)
/**!
 * @brief Load health summary rows and environment options for the current filter.
 * @post `healthData` and `environments` reflect latest backend response.
 * @pre Page is mounted or environment selection changed.
 * @side_effect Calls backend API endpoints for health summary and environments.
 */

// --- handleEnvChange:Function (frontend/src/routes/dashboards/health/+page.svelte)
/**!
 * @brief Apply environment filter and trigger health summary reload.
 * @post selectedEnvId is updated and new data load starts.
 * @pre DOM change event carries target value.
 */

// --- handleDeleteReport:Function (frontend/src/routes/dashboards/health/+page.svelte)
/**!
 * @brief Delete one health report row with confirmation and optimistic button lock.
 * @post Row is removed from backend and page data is reloaded on success.
 * @pre item contains `record_id` from health summary payload.
 * @side_effect Calls DELETE health API and emits toast notifications.
 */

// --- HealthPageIntegrationTest:Module (frontend/src/routes/dashboards/health/__tests__/health_page.integration.test.js)
/**!
 * @brief Lock dashboard health page contract for slug navigation and report deletion.
 * @layer UI (Tests)
 * @semantics health-page, integration-test, slug-link, delete-flow
 */

// --- DatasetHub (frontend/src/routes/datasets/+page.svelte)
/**!
 * @complexity 5
 */

// --- ColumnsTable (frontend/src/routes/datasets/ColumnsTable.svelte)
/**!
 * @brief Table of dataset columns with type chips, description, and inline-edit capability.
 * @complexity 4
 * @layer UI
 * @ux_reactivity Props -> columns, datasetId
 * @ux_state Editing -> One row in edit mode (textarea), others dimmed.
 */

// --- DatasetList (frontend/src/routes/datasets/DatasetList.svelte)
/**!
 * @brief Renders paginated dataset cards with mapping progress bars, checkboxes, and quick actions.
 * @complexity 4
 * @rationale Action buttons switched from bg-primary solid to border-outline style, card padding reduced from p-3 to p-2.5, row gap from gap-3 to gap-2.5 — fixes "huge buttons" visual complaint.
 * @rejected Solid blue action buttons rejected — too visually heavy on each card line.
 * @ux_reactivity Props -> datasets, selectedIds, isLoading, error, total, page, totalPages, pageSize, onselect, onaction, onpagechange, onsearch, oncheckbox
 * @ux_state Empty -> "No datasets found" after search/filter.
 */

// --- DatasetPreview (frontend/src/routes/datasets/DatasetPreview.svelte)
/**!
 * @brief Right panel showing dataset detail: header info, columns table, metrics table, linked dashboards. Presentational.
 * @complexity 3
 * @layer UI
 * @ux_state Error -> Error banner with retry.
 */

// --- MetricsTable (frontend/src/routes/datasets/MetricsTable.svelte)
/**!
 * @brief Table of dataset metrics with expression, description, and inline-edit capability.
 * @complexity 4
 * @layer UI
 * @ux_reactivity Props -> metrics, datasetId
 * @ux_state Editing -> One row in edit mode.
 */

// --- StatsBar (frontend/src/routes/datasets/StatsBar.svelte)
/**!
 * @brief Compact filter pills showing aggregate counts (All, Without mapping, Mapped, Linked).
 * @complexity 3
 * @rationale Converted from card tiles (p-3, text-2xl) to compact pills (rounded-full px-3 py-1 text-sm) to fix oversized buttons complaint.
 * @rejected Card-tile filter buttons rejected — were too visually heavy at 12px padding + 24px font, dominating the page top.
 * @ux_reactivity Events -> onfilter(filterKey) emitted on pill click
 * @ux_state Filtered -> selected pill has filled background; parent reloads with filter param.
 */

// --- DatasetReviewWorkspaceEntry (frontend/src/routes/datasets/review/+page.svelte)
/**!
 * @brief Entry route for Dataset Review Workspace — start a new resumable review session or navigate to existing sessions.
 * @complexity 3
 * @layer Page
 * @ux_recovery User can correct invalid input and retry without losing environment selection.
 * @ux_state Error -> Inline error shown while keeping intake editable.
 */

// --- ReviewWorkspaceHeader (frontend/src/routes/datasets/review/ReviewWorkspaceHeader.svelte)
/**!
 * @brief Header section for the dataset review workspace with title, description, and status badges.
 * @complexity 2
 * @layer UI
 */

// --- ReviewWorkspaceLeftSidebar (frontend/src/routes/datasets/review/ReviewWorkspaceLeftSidebar.svelte)
/**!
 * @brief Left sidebar for dataset review workspace: source info, import status, session summary, clarification focus, primary actions.
 * @complexity 3
 * @layer UI
 */

// --- ReviewWorkspaceRightRail (frontend/src/routes/datasets/review/ReviewWorkspaceRightRail.svelte)
/**!
 * @brief Right rail for dataset review workspace: next action, blockers, health counts, exports, SQL preview, launch panel.
 * @complexity 3
 * @layer UI
 */

// --- DatasetReviewWorkspace (frontend/src/routes/datasets/review/[id]/+page.svelte)
/**!
 * @brief Main dataset review workspace — thin shell delegating to extracted components.
 * @complexity 4
 * @deprecated N/A — active workspace page.
 * @layer Page
 * @rationale Decomposed from 1202→~380 lines by extracting helpers, composables, and sidebar/rail/header components per INV_7.
 * @rejected Keeping all logic inline was rejected — exceeded 150-line contract limit and cyclomatic complexity thresholds.
 * @replaced_by N/A
 * @ux_state Review -> 3-column layout.
 */

// --- DatasetReviewEntryUxTests (frontend/src/routes/datasets/review/__tests__/dataset_review_entry.test.js)
/**!
 * @brief Verify dataset review entry route exposes resumable sessions alongside the new session intake flow.
 * @complexity 3
 * @layer UI
 * @semantics dataset-review, workspace-entry, resume, source-intake, ux-tests
 * @test_scenario submits_new_session_without_regression
 * @ux_state ResumeError -> inline error and retry action remain visible without removing new session flow.
 */

// --- DatasetReviewEntryUxPageTests (frontend/src/routes/datasets/review/__tests__/dataset_review_entry.ux.test.js)
/**!
 * @brief Verify dataset review entry route exposes resumable sessions alongside the new session intake flow.
 * @complexity 3
 * @layer UI
 * @semantics dataset-review, workspace-entry, resume, source-intake, ux-tests
 * @test_scenario submits_new_session_without_regression
 * @ux_state ResumeError -> inline error and retry action remain visible without removing new session flow.
 */

// --- ReviewWorkspaceHelpers (frontend/src/routes/datasets/review/review-workspace-helpers.js)
/**!
 * @brief Shared helper functions for the dataset review workspace.
 * @complexity 2
 * @rationale Extracted from DatasetReviewWorkspace to reduce page script size per INV_7.
 */

// --- frontend/src/routes/datasets/review/review-workspace-helpers.js::buildImportMilestones (frontend/src/routes/datasets/review/review-workspace-helpers.js)
/**!
 */

// --- frontend/src/routes/datasets/review/review-workspace-helpers.js::buildWorkspaceLaunchBlockers (frontend/src/routes/datasets/review/review-workspace-helpers.js)
/**!
 */

// --- frontend/src/routes/datasets/review/review-workspace-helpers.js::buildAssistantSeedPrompt (frontend/src/routes/datasets/review/review-workspace-helpers.js)
/**!
 */

// --- frontend/src/routes/datasets/review/review-workspace-helpers.js::buildAssistantContextPrompt (frontend/src/routes/datasets/review/review-workspace-helpers.js)
/**!
 */

// --- frontend/src/routes/datasets/review/review-workspace-helpers.js::getWorkspaceStateLabel (frontend/src/routes/datasets/review/review-workspace-helpers.js)
/**!
 */

// --- frontend/src/routes/datasets/review/review-workspace-helpers.js::getRecommendedActionLabel (frontend/src/routes/datasets/review/review-workspace-helpers.js)
/**!
 */

// --- frontend/src/routes/datasets/review/review-workspace-helpers.js::getPrimaryActionCtaLabel (frontend/src/routes/datasets/review/review-workspace-helpers.js)
/**!
 */

// --- frontend/src/routes/datasets/review/review-workspace-helpers.js::mergeCollectionItem (frontend/src/routes/datasets/review/review-workspace-helpers.js)
/**!
 */

// --- frontend/src/routes/datasets/review/review-workspace-helpers.js::stringifyValue (frontend/src/routes/datasets/review/review-workspace-helpers.js)
/**!
 */

// --- UseReviewSession (frontend/src/routes/datasets/review/useReviewSession.js)
/**!
 * @brief Composable for dataset review session state management — load, update, export, and clarify.
 * @complexity 3
 */

// --- GitDashboardPage (frontend/src/routes/git/+page.svelte)
/**!
 * @brief Git integration page for selecting environments and managing dashboard repositories.
 * @complexity 3
 * @layer Page
 * @ux_feedback Toast notifications on API errors.
 * @ux_recovery User can retry by changing environment or refreshing.
 * @ux_state Error -> Toast-driven failure feedback preserves filter selection.
 */

// --- LoginPage (frontend/src/routes/login/+page.svelte)
/**!
 * @brief Provides the user interface for local (username/password) and ADFS SSO authentication.
 * @complexity 3
 * @invariant Shows both local login form and ADFS SSO button.
 * @layer Page
 * @ux_feedback Loading text on submit button while authenticating.
 * @ux_recovery User can retry login after error.
 * @ux_state Success -> User authenticated, redirected to homepage.
 */

// --- MaintenanceBannerPage (frontend/src/routes/maintenance/+page.svelte)
/**!
 * @brief Maintenance Banners management page. Composes SettingsPanel and EventsTable from store.
 * @complexity 3
 * @layer Page
 * @ux_feedback Toast via addToast() from $lib/toasts.js
 * @ux_recovery Refresh via maintenanceStore.loadEvents().
 * @ux_state Error -> Error toast shown.
 */

// --- ReactiveDashboardFetch:Block (frontend/src/routes/migration/+page.svelte)
/**!
 * @brief Automatically fetch dashboards when the source environment is changed.
 * @post fetchDashboards is called with the new sourceEnvId.
 * @pre sourceEnvId is not empty.
 * @ux_state [Loading] -> Triggered when sourceEnvId changes.
 */

// --- handleMappingUpdate:Function (frontend/src/routes/migration/+page.svelte)
/**!
 * @brief Saves a mapping to the backend.
 * @post Mapping is saved and local mappings list is updated.
 * @pre event.detail contains sourceUuid and targetUuid.
 */

// --- handleViewLogs:Function (frontend/src/routes/migration/+page.svelte)
/**!
 * @brief Opens the log viewer for a specific task.
 * @post logViewer state updated and showLogViewer set to true.
 * @pre event.detail contains task object.
 */

// --- handlePasswordPrompt:Function (frontend/src/routes/migration/+page.svelte)
/**!
 * @brief Reactive logic to show password prompt when a task is awaiting input.
 * @post showPasswordPrompt set to true with request data.
 * @pre selectedTask status is AWAITING_INPUT.
 */

// --- ReactivePasswordPrompt:Block (frontend/src/routes/migration/+page.svelte)
/**!
 * @brief Monitor selected task for input requests and trigger password prompt.
 * @post showPasswordPrompt is set to true if input_request is database_password.
 * @pre $selectedTask is not null and status is AWAITING_INPUT.
 * @ux_state [AwaitingInput] -> Password prompt modal is displayed.
 */

// --- handleResumeMigration:Function (frontend/src/routes/migration/+page.svelte)
/**!
 * @brief Resumes a migration task with provided passwords.
 * @post resumeTask is called and showPasswordPrompt is hidden on success.
 * @pre event.detail contains passwords.
 */

// --- startMigration:Function (frontend/src/routes/migration/+page.svelte)
/**!
 * @brief Initiates the migration process by sending the selection to the backend.
 * @post A migration task is created and selectedTask store is updated.
 * @pre sourceEnvId and targetEnvId are set and different; at least one dashboard is selected.
 * @side_effect Resets dryRunResult; updates error state on failure.
 * @ux_state [Loading] -> [Success] or [Error]
 */

// --- startDryRun:Function (frontend/src/routes/migration/+page.svelte)
/**!
 * @brief Performs a dry-run migration to identify potential risks and changes.
 * @post dryRunResult is populated with the pre-flight analysis.
 * @pre source/target environments and selected dashboards are valid.
 * @ux_feedback User sees summary cards + risk block + JSON details after success.
 * @ux_recovery User can adjust selection and press Dry Run again.
 * @ux_state [Loading] -> [Success] or [Error]
 */

// --- MigrationMappingsPage (frontend/src/routes/migration/mappings/+page.svelte)
/**!
 * @brief Render and orchestrate mapping management UI for source/target environments with backend persistence.
 * @complexity 3
 * @critical_trace Frontend scope; Python belief_scope/logger are not applicable in Svelte runtime. Reflective tracing, when added, must use console prefix [ID][REFLECT].
 * @data_contract Input(Event: update{sourceUuid,targetUuid}) -> Model(MappingPayload); Output(UIState{environments,databases,mappings,suggestions,status})
 * @invariant Persisted mapping state in backend remains the source of truth for rendered mapping pairs.
 * @layer UI
 * @post UI exposes deterministic Idle/Loading/Error/Success states for environment loading, database fetch, and mapping save.
 * @pre Translation store and API client are available; route is mounted in authenticated UI shell.
 * @semantics migration, mapping, environment, fuzzy-matching, persistence
 * @side_effect Performs network I/O to environment/database/mapping endpoints and mutates local UI state.
 * @test_contract [Valid source/target env IDs + fetch click] -> [Databases, mappings, suggestions rendered]
 * @test_edge [external_fail] ->[API request rejection => error state]
 * @test_fixture [migration_mapping_pair] -> file:backend/tests/fixtures/migration_dry_run_fixture.json
 * @test_invariant [backend_source_of_truth] -> VERIFIED_BY: [save_mapping_success, fetch_env_fail]
 * @test_scenario [fetch_env_fail] -> [error banner appears and loading state exits]
 * @ux_feedback Error panel for failed API calls; success panel for persisted mapping confirmation.
 * @ux_reactivity Svelte bind/on directives and reactive template branches coordinate state transitions (legacy route; no semantic logic mutation in this task).
 * @ux_recovery Retry via "fetch databases" action; reselection of environments clears stale arrays.
 * @ux_state Success -> Render green confirmation panel after mapping save.
 */

// --- MappingsPageScript:Block (frontend/src/routes/migration/mappings/+page.svelte)
/**!
 * @brief Define imports, state, and handlers that drive migration mappings page FSM.
 */

// --- Imports:Block (frontend/src/routes/migration/mappings/+page.svelte)
/**!
 */

// --- UiState:Store (frontend/src/routes/migration/mappings/+page.svelte)
/**!
 * @brief Maintain local page state for environments, fetched databases, mappings, suggestions, and UX messages.
 */

// --- belief_scope:Function (frontend/src/routes/migration/mappings/+page.svelte)
/**!
 * @brief Frontend semantic scope wrapper for CRITICAL trace boundaries without changing business behavior.
 * @data_contract Input(scopeId:string, run:() => Promise<T>) -> Output(Promise<T>)
 * @post Executes run exactly once and returns/rejects with the same outcome.
 * @pre scopeId is non-empty and run is callable.
 * @side_effect Emits trace logs for semantic scope entrance/exit.
 */

// --- fetchDatabases:Function (frontend/src/routes/migration/mappings/+page.svelte)
/**!
 * @brief Fetch both environment database catalogs, existing mappings, and suggested matches.
 * @data_contract Input({sourceEnvId,targetEnvId}) -> Output({sourceDatabases,targetDatabases,mappings,suggestions})
 * @post fetchingDbs=false and sourceDatabases/targetDatabases/mappings/suggestions updated or error set.
 * @pre sourceEnvId and targetEnvId are both selected and non-empty.
 * @side_effect Concurrent network I/O to environments, mappings, and suggestion endpoints; clears transient messages.
 */

// --- handleUpdate:Function (frontend/src/routes/migration/mappings/+page.svelte)
/**!
 * @brief Persist a selected mapping pair and reconcile local mapping list by source database UUID.
 * @data_contract Input(CustomEvent<{sourceUuid:string,targetUuid:string}>) -> Output(MappingRecord persisted + UI feedback)
 * @post mapping persisted; local mappings replaced for same source UUID; success or error feedback shown.
 * @pre event.detail includes sourceUuid/targetUuid and matching source/target database records exist.
 * @side_effect POST /mappings network I/O; mutates mappings/success/error.
 */

// --- MappingsPageTemplate (frontend/src/routes/migration/mappings/+page.svelte)
/**!
 * @brief Mapping page template with environment selectors, database mapping table, and action buttons.
 * @complexity 2
 */

// --- ProfilePage (frontend/src/routes/profile/+page.svelte)
/**!
 * @brief User profile page for viewing and editing personal preferences and settings.
 * @complexity 3
 * @layer Page
 * @ux_feedback Success toast on profile update.
 * @ux_state Error -> Error message shown.
 */

// --- ProfileFixtures:Module (frontend/src/routes/profile/__tests__/fixtures/profile.fixtures.js)
/**!
 * @brief Shared deterministic fixture inputs for profile page integration tests.
 * @invariant lookupFailedManualFallback.warning is a hardcoded English string; drift risk if i18n key profile.lookup_error changes without updating this fixture.
 * @semantics fixtures, profile, ui
 */

// --- ProfilePreferencesIntegrationTest (frontend/src/routes/profile/__tests__/profile-preferences.integration.test.js)
/**!
 * @brief Verifies profile page loads preferences and saves them.
 * @complexity 3
 * @layer UI (Tests)
 * @semantics tests, profile, integration, load, save
 */

// --- ProfileSettingsStateIntegrationTest (frontend/src/routes/profile/__tests__/profile-settings-state.integration.test.js)
/**!
 * @brief Verifies profile loads preferences, allows changes, and saves correctly.
 * @complexity 3
 * @layer UI (Tests)
 * @semantics tests, profile, integration, load, change, save
 */

// --- UnifiedReportsPage (frontend/src/routes/reports/+page.svelte)
/**!
 * @brief Unified reports page with task-type and status filtering, list selection, detail panel, and resilient UX states for mixed task types.
 * @complexity 3
 * @layer Page
 * @ux_feedback Selecting a report loads its detail in the right panel.
 * @ux_recovery Retry and clear-filters actions available.
 * @ux_state Error -> Inline error with retry preserving filter selections.
 */

// --- ReportPageContractTest:Module (frontend/src/routes/reports/llm/[taskId]/report_page.contract.test.js)
/**!
 * @brief Protect the LLM report page from self-triggering screenshot load effects.
 * @layer UI (Tests)
 * @semantics llm-report, svelte-effect, screenshot-loading, regression-test
 */

// --- llm_report_screenshot_effect_contract:Function (frontend/src/routes/reports/llm/[taskId]/report_page.contract.test.js)
/**!
 * @brief Ensure screenshot loading stays untracked from blob-url mutation state.
 * @post Contract fails if screenshot loading effect can subscribe to screenshotBlobUrls updates.
 * @pre Report page source exists.
 */

// --- SettingsPage (frontend/src/routes/settings/+page.svelte)
/**!
 * @brief Consolidated Settings Page shell — thin layout that delegates each tab to its own component.
 * @complexity 4
 * @deprecated N/A
 * @layer Page
 * @post Page exposes consolidated settings tabs; each tab manages its own state.
 * @pre Route is loaded in the authenticated UI shell.
 * @rationale Decomposed from 1451→287 lines by extracting 6 tab components and centralizing state in the page shell. The C4 rating reflects the page's role as tab orchestrator with settings load/save lifecycle.
 * @rejected Keeping all tab content inline was rejected due to INV_7 violations (single contract exceeded 150 lines, cyclomatic complexity > 10).
 * @replaced_by N/A
 * @side_effect Loads settings data on mount.
 * @ux_feedback Toast on save.
 * @ux_recovery Refresh button reloads settings.
 * @ux_state Error -> Error banner with retry.
 */

// --- frontend/src/routes/settings/+page.ts::load (frontend/src/routes/settings/+page.ts)
/**!
 */

// --- FeaturesSettings (frontend/src/routes/settings/FeaturesSettings.svelte)
/**!
 * @brief Feature flags configuration tab: enable/disable top-level application features.
 * @complexity 2
 * @layer UI
 * @post User can toggle feature flags.
 * @pre settings object with features config is provided.
 */

// --- LlmSettings (frontend/src/routes/settings/LlmSettings.svelte)
/**!
 * @brief LLM configuration tab: providers, bindings, prompts for chatbot and validation.
 * @complexity 3
 * @layer UI
 * @post User can configure LLM provider bindings and prompts.
 * @pre settings object with llm config and llm_providers list is provided.
 * @ux_feedback Toast on save.
 * @ux_state Loaded -> Full LLM settings panel with provider config, bindings, and prompts.
 */

// --- LoggingSettings (frontend/src/routes/settings/LoggingSettings.svelte)
/**!
 * @brief Logging configuration tab: log level, task log level, belief state toggle.
 * @complexity 3
 * @layer UI
 * @post User can adjust logging levels and toggle belief state.
 * @pre settings object with logging config is provided.
 * @ux_feedback Toast on save.
 * @ux_state Loaded -> Form controls for logging configuration.
 */

// --- MigrationMappingsTable (frontend/src/routes/settings/MigrationMappingsTable.svelte)
/**!
 * @brief Mappings data table with search, filtering, and pagination for migration sync resources. Isolated from the main MigrationSettings to keep each module < 400 lines.
 * @complexity 3
 * @layer UI
 * @post User can search, filter by environment/type, and paginate through resource mappings.
 * @pre API client initialized, refreshKey provided by parent.
 * @ux_reactivity Props -> refreshKey triggers reload via $effect.
 * @ux_state Empty -> "No mappings" row.
 */

// --- MigrationSettings (frontend/src/routes/settings/MigrationSettings.svelte)
/**!
 * @brief Migration sync configuration tab: cron schedule, sync now, mappings table with filtering and pagination.
 * @complexity 3
 * @layer UI
 * @post User can configure sync schedule, trigger sync, and browse resource mappings.
 * @pre API client initialized.
 * @ux_feedback Toast on save/sync/failure.
 * @ux_state Loaded -> Full migration sync panel with schedule and mappings table.
 */

// --- StorageSettings (frontend/src/routes/settings/StorageSettings.svelte)
/**!
 * @brief Storage configuration tab: root path, backup path, repo path.
 * @complexity 2
 * @layer UI
 * @post User can view and edit storage paths.
 * @pre settings object with storage config is provided.
 */

// --- SystemSettings (frontend/src/routes/settings/SystemSettings.svelte)
/**!
 * @brief System settings tab: timezone configuration and API key management.
 * @complexity 3
 * @post User can select the application timezone and manage API keys.
 * @pre settings object is provided with app_timezone field.
 */

// --- SettingsPageUxTest:Module (frontend/src/routes/settings/__tests__/settings_page.ux.test.js)
/**!
 * @brief Test UX states and transitions
 * @layer UI (Tests)
 * @semantics settings, page, ux-tests, save-flow
 */

// --- AutomationPage (frontend/src/routes/settings/automation/+page.svelte)
/**!
 * @brief Settings page for managing validation policies.
 * @complexity 3
 * @layer Page
 * @ux_reactivity State: $state, Derived: $derived.
 * @ux_state Loading -> Shows a loading spinner while fetching policies.
 */

// --- loadConfigs:Function (frontend/src/routes/settings/git/+page.svelte)
/**!
 * @brief Fetches existing git configurations.
 * @post configs state is populated.
 * @pre Component is mounted.
 */

// --- handleTest:Function (frontend/src/routes/settings/git/+page.svelte)
/**!
 * @brief Tests connection to a git server with current form data.
 * @post testing state is managed; toast shown with result.
 * @pre newConfig contains valid provider, url, and pat.
 */

// --- handleSave:Function (frontend/src/routes/settings/git/+page.svelte)
/**!
 * @brief Saves a new git configuration.
 * @post New config is saved to DB and added to configs list.
 * @pre newConfig is valid and tested.
 */

// --- handleEdit:Function (frontend/src/routes/settings/git/+page.svelte)
/**!
 * @brief Populates the form with an existing config to edit.
 * @param {Object} config - Configuration object to edit.
 * @post Form is populated and isEditing state is set.
 */

// --- resetForm:Function (frontend/src/routes/settings/git/+page.svelte)
/**!
 * @brief Resets the configuration form.
 */

// --- loadGiteaRepos:Function (frontend/src/routes/settings/git/+page.svelte)
/**!
 * @brief Loads repositories from selected Gitea config.
 * @post giteaRepos state updated.
 * @pre selectedGiteaConfigId is set.
 */

// --- handleCreateGiteaRepo:Function (frontend/src/routes/settings/git/+page.svelte)
/**!
 * @brief Creates new repository on selected Gitea server.
 * @post Repository created and repos list reloaded.
 * @pre selectedGiteaConfigId and newGiteaRepo.name are set.
 */

// --- handleDeleteGiteaRepo:Function (frontend/src/routes/settings/git/+page.svelte)
/**!
 * @brief Deletes repository from selected Gitea server.
 * @post Repository deleted and repos list reloaded.
 * @pre selectedGiteaConfigId is set.
 */

// --- GitSettingsPageUxTest:Module (frontend/src/routes/settings/git/__tests__/git_settings_page.ux.test.js)
/**!
 * @brief Test UX states and transitions for the Git Settings page
 * @layer UI (Tests)
 * @semantics settings, git, page, ux-tests, form, toast
 */

// --- frontend/src/routes/settings/settings-utils.js::readTabFromUrl (frontend/src/routes/settings/settings-utils.js)
/**!
 */

// --- frontend/src/routes/settings/settings-utils.js::writeTabToUrl (frontend/src/routes/settings/settings-utils.js)
/**!
 */

// --- frontend/src/routes/settings/settings-utils.js::normalizeTab (frontend/src/routes/settings/settings-utils.js)
/**!
 */

// --- frontend/src/routes/settings/settings-utils.js::normalizeLlmSettings (frontend/src/routes/settings/settings-utils.js)
/**!
 */

// --- frontend/src/routes/settings/settings-utils.js::isDashboardValidationBindingValid (frontend/src/routes/settings/settings-utils.js)
/**!
 */

// --- frontend/src/routes/settings/settings-utils.js::getProviderById (frontend/src/routes/settings/settings-utils.js)
/**!
 */

// --- frontend/src/routes/settings/settings-utils.js::normalizeSupersetBaseUrl (frontend/src/routes/settings/settings-utils.js)
/**!
 */

// --- frontend/src/routes/settings/settings-utils.js::resolveEnvStage (frontend/src/routes/settings/settings-utils.js)
/**!
 */

// --- StorageIndexPage (frontend/src/routes/storage/+page.svelte)
/**!
 * @brief Redirect to the backups page as the default storage view.
 * @complexity 2
 * @invariant Always redirects to /storage/backups.
 * @layer Page
 * @ux_state Redirecting -> Immediately transfers the user to /storage/backups.
 */

// --- BackupsRedirectPage (frontend/src/routes/storage/backups/+page.svelte)
/**!
 * @brief Temporary switch to legacy storage browser for backup UX validation.
 * @complexity 3
 * @invariant Always redirects to /tools/storage.
 * @layer Page
 * @semantics storage, backups, redirect, legacy
 * @ux_state Redirecting -> Immediately transfers the user to the legacy storage browser.
 */

// --- fetchEnvironments:Function (frontend/src/routes/storage/repos/+page.svelte)
/**!
 * @brief Fetches the list of available environments.
 * @post environments array is populated, selectedEnvId is set to first env if available.
 * @pre None.
 */

// --- fetchDashboards:Function (frontend/src/routes/storage/repos/+page.svelte)
/**!
 * @brief Fetches dashboards for a specific environment.
 * @post dashboards array is populated with metadata for the selected environment.
 * @pre envId is a valid environment ID.
 */

// --- filterDashboardsWithRepositories:Function (frontend/src/routes/storage/repos/+page.svelte)
/**!
 * @brief Keep only dashboards that already have initialized Git repositories.
 * @post Returns dashboards with status != NO_REPO.
 * @pre dashboards list is loaded for selected environment.
 */

// --- BackupsPage (frontend/src/routes/tools/backups/+page.svelte)
/**!
 * @brief Entry point for the Backup Management interface.
 * @complexity 3
 * @layer Page
 * @semantics backup, management, tools, workspace
 * @ux_state Error -> Nested manager feedback remains contained within the backup workspace.
 */

// --- DebugToolPage (frontend/src/routes/tools/debug/+page.svelte)
/**!
 * @brief Page for system diagnostics and debugging.
 * @complexity 3
 * @layer UI
 * @semantics debug, diagnostics, tool, task-runner
 * @ux_state Error -> Nested diagnostic failures remain scoped to the debug workspace.
 */

// --- MapperToolPage (frontend/src/routes/tools/mapper/+page.svelte)
/**!
 * @brief Page for the dataset column mapper tool.
 * @complexity 3
 * @layer UI
 * @semantics mapper, column, dataset, tool
 * @ux_state Error -> Mapping-specific validation or execution failures remain visible without route changes.
 */

// --- loadFiles:Function (frontend/src/routes/tools/storage/+page.svelte)
/**!
 * @brief Fetches the list of files from the server.
 * @post Updates the `files` array with the latest data.
 * @pre currentPath is a valid storage path or empty for root.
 */

// --- resolveStorageQueryFromPath:Function (frontend/src/routes/tools/storage/+page.svelte)
/**!
 * @brief Splits UI path into storage API category and category-local subpath.
 * @post Returns {category, subpath} compatible with /api/storage/files.
 * @pre uiPath may be empty or start with backups/repositorys.
 */

// --- handleDelete:Function (frontend/src/routes/tools/storage/+page.svelte)
/**!
 * @brief Handles the file deletion process.
 * @param {CustomEvent} event - The delete event containing category and path.
 * @post File is deleted and file list is refreshed.
 * @pre The event contains valid category and path.
 */

// --- handleNavigate:Function (frontend/src/routes/tools/storage/+page.svelte)
/**!
 * @brief Updates the current path and reloads files when navigating into a directory.
 * @param {CustomEvent} event - The navigation event containing the new path.
 * @post currentPath is updated and files are reloaded.
 * @pre The event contains a valid path string.
 */

// --- navigateUp:Function (frontend/src/routes/tools/storage/+page.svelte)
/**!
 * @brief Navigates one level up in the directory structure.
 * @post currentPath is moved up one directory level.
 * @pre currentPath is not root.
 */

// --- updateUploadCategory:Function (frontend/src/routes/tools/storage/+page.svelte)
/**!
 * @brief Keeps upload category aligned with the currently viewed top-level folder.
 * @post uploadCategory is either backups or repositorys.
 * @pre currentPath can be empty or a slash-delimited path.
 */

// --- TranslateJobList (frontend/src/routes/translate/+page.svelte)
/**!
 * @complexity 3
 * @type {string} idle | loading | empty | populated | error
 */

// --- TranslationJobConfig (frontend/src/routes/translate/[id]/+page.svelte)
/**!
 * @brief Translation job configuration page - orchestrates form state, datasource loading, LLM settings, run/schedule tabs.
 * @complexity 4
 * @deprecated N/A — active page.
 * @rationale Kept as C4 orchestration due to complex lifecycle: load→configure→validate→save→run→monitor across multiple tabs and API interactions.
 * @rejected Extracting all sub-tabs into separate page components was rejected due to deep state coupling between datasource selection, column loading, and form validation — would require a global store or excessive prop drilling.
 * @replaced_by N/A — no replacement.
 * @type {string} idle | loading | configured | saving | validation_error | datasource_unavailable
 */

// --- DictionariesPage (frontend/src/routes/translate/dictionaries/+page.svelte)
/**!
 * @complexity 3
 */

// --- DictionaryDetailPage (frontend/src/routes/translate/dictionaries/[id]/+page.svelte)
/**!
 * @complexity 3
 */

// --- TranslateHistoryPage (frontend/src/routes/translate/history/+page.svelte)
/**!
 * @complexity 3
 * @type {'idle'|'loading'|'empty'|'populated'|'detail_open'|'pruned'}
 */

// --- ValidationTaskList (frontend/src/routes/validation/+page.svelte)
/**!
 * @brief Validation task list page with status filter, task cards, and create/duplicate/delete actions.
 * @complexity 3
 * @param {string} status
 * @rationale Card layout chosen over table because tasks have rich metadata (schedule, provider, last run status, environment) that does not fit into table columns without excessive horizontal scrolling.
 * @rejected Table view for task list rejected — dashboard_id + environment_id + provider_id + schedule + last_run_status creates too many columns for a table; cards show all metadata vertically.
 * @type {'idle'|'loading'|'empty'|'populated'|'error'|'filtered_empty'}
 * @ux_state Populated -> Task cards grid
 */

// --- ValidationTaskConfig (frontend/src/routes/validation/[id]/+page.svelte)
/**!
 * @brief Validation task configuration page with Config and History tabs. Handles new and edit modes.
 * @complexity 4
 * @rationale 2-tab design separates task configuration from run history — users can edit settings (name, dashboard, provider, schedule) without scrolling past potentially long run history data.
 * @rejected Single scrollable page with config above history rejected — task config form is long (Basic Info + Dashboard & Environment + LLM Provider + Schedule + Active toggle); history would be pushed far below the fold.
 * @type {'idle'|'loading'|'configured'|'saving'|'error'|'not_found'}
 * @ux_feedback Toast notifications on save/run/delete actions
 * @ux_reactivity Props -> $props(), URL params -> $page.params, LocalState -> $state(...)
 * @ux_recovery Retry button on load errors, Go Back on not found
 * @ux_state Configured -> Form with Save/Cancel/Run Now buttons
 */

// --- ValidationHistory (frontend/src/routes/validation/history/+page.svelte)
/**!
 * @brief Validation run history page with filters, metrics summary, and run cards.
 * @complexity 3
 * @rationale Filter-driven design with 6 filter dimensions (task, status, dashboard, environment, date from/to) allows users to narrow runs for debugging — essential when hundreds of runs accumulate over time.
 * @rejected Unfiltered chronological list rejected — users need to filter by task/status/environment to find relevant runs among hundreds; without filters the page is unusable at scale.
 * @type {'idle'|'loading'|'empty'|'filtered_empty'|'populated'|'error'}
 * @ux_state Populated -> Metrics grid + run cards + pagination
 */

// --- GitServiceContractTests (frontend/src/services/__tests__/gitService.test.js)
/**!
 * @brief API client tests ensuring correct endpoints are called per contract for Git service operations.
 * @complexity 3
 */

// --- gitServiceContractTests:Module (frontend/src/services/__tests__/gitService.test.js)
/**!
 * @brief API client tests ensuring correct endpoints are called per contract
 * @layer Tests
 * @post Returns promotion metadata
 * @pre Repo initialized
 * @semantics git-service, api-client, contract-tests
 */

// --- AdminService (frontend/src/services/adminService.js)
/**!
 * @brief Service for Admin-related API calls including User and Role management, AD group mappings, and logging configuration.
 * @complexity 3
 * @layer Service
 */

// --- adminService:Module (frontend/src/services/adminService.js)
/**!
 * @brief Service for Admin-related API calls (User and Role management).
 * @invariant All requests must include valid Admin JWT token (handled by api client).
 * @layer Service
 * @semantics admin, users, roles, ad-mappings, api
 */

// --- getUsers:Function (frontend/src/services/adminService.js)
/**!
 * @brief Fetches all registered users from the backend.
 * @post Returns an array of user objects.
 * @pre User must be authenticated with Admin privileges.
 * @return {Promise<Array>}
 */

// --- frontend/src/services/adminService.js::getUsers (frontend/src/services/adminService.js)
/**!
 * @post Returns an array of user objects.
 * @pre User must be authenticated with Admin privileges.
 */

// --- createUser:Function (frontend/src/services/adminService.js)
/**!
 * @brief Creates a new local user.
 * @param {Object} userData - User details (username, email, password, roles, is_active).
 * @post New user record created in auth.db.
 * @pre User must be authenticated with Admin privileges.
 * @return {Promise<Object>}
 */

// --- frontend/src/services/adminService.js::createUser (frontend/src/services/adminService.js)
/**!
 * @post New user record created in auth.db.
 * @pre User must be authenticated with Admin privileges.
 */

// --- getRoles:Function (frontend/src/services/adminService.js)
/**!
 * @brief Fetches all available system roles.
 * @post Returns an array of role objects.
 * @pre User must be authenticated with Admin privileges.
 * @return {Promise<Array>}
 */

// --- frontend/src/services/adminService.js::getRoles (frontend/src/services/adminService.js)
/**!
 * @post Returns an array of role objects.
 * @pre User must be authenticated with Admin privileges.
 */

// --- getADGroupMappings:Function (frontend/src/services/adminService.js)
/**!
 * @brief Fetches mappings between AD groups and local roles.
 * @post Returns an array of AD group mapping objects.
 * @pre User must be authenticated with Admin privileges.
 * @return {Promise<Array>}
 */

// --- frontend/src/services/adminService.js::getADGroupMappings (frontend/src/services/adminService.js)
/**!
 * @post Returns an array of AD group mapping objects.
 * @pre User must be authenticated with Admin privileges.
 */

// --- createADGroupMapping:Function (frontend/src/services/adminService.js)
/**!
 * @brief Creates or updates an AD group to Role mapping.
 * @param {Object} mappingData - Mapping details (ad_group, role_id).
 * @post New or updated mapping created in auth.db.
 * @pre User must be authenticated with Admin privileges.
 * @return {Promise<Object>}
 */

// --- frontend/src/services/adminService.js::createADGroupMapping (frontend/src/services/adminService.js)
/**!
 * @post New or updated mapping created in auth.db.
 * @pre User must be authenticated with Admin privileges.
 */

// --- updateUser:Function (frontend/src/services/adminService.js)
/**!
 * @brief Updates an existing user.
 * @param {Object} userData - Updated user data.
 * @post User record updated in auth.db.
 * @pre User must be authenticated with Admin privileges.
 * @return {Promise<Object>}
 */

// --- frontend/src/services/adminService.js::updateUser (frontend/src/services/adminService.js)
/**!
 * @post User record updated in auth.db.
 * @pre User must be authenticated with Admin privileges.
 */

// --- deleteUser:Function (frontend/src/services/adminService.js)
/**!
 * @brief Deletes a user.
 * @param {string} userId - Target user ID.
 * @post User record removed from auth.db.
 * @pre User must be authenticated with Admin privileges.
 * @return {Promise<void>}
 */

// --- frontend/src/services/adminService.js::deleteUser (frontend/src/services/adminService.js)
/**!
 * @post User record removed from auth.db.
 * @pre User must be authenticated with Admin privileges.
 */

// --- createRole:Function (frontend/src/services/adminService.js)
/**!
 * @brief Creates a new role.
 * @param {Object} roleData - Role details (name, description, permissions).
 * @post New role created in auth.db.
 * @pre User must be authenticated with Admin privileges.
 * @return {Promise<Object>}
 */

// --- frontend/src/services/adminService.js::createRole (frontend/src/services/adminService.js)
/**!
 * @post New role created in auth.db.
 * @pre User must be authenticated with Admin privileges.
 */

// --- updateRole:Function (frontend/src/services/adminService.js)
/**!
 * @brief Updates an existing role.
 * @param {Object} roleData - Updated role data.
 * @return {Promise<Object>}
 */

// --- frontend/src/services/adminService.js::updateRole (frontend/src/services/adminService.js)
/**!
 */

// --- deleteRole:Function (frontend/src/services/adminService.js)
/**!
 * @brief Deletes a role.
 * @param {string} roleId - Target role ID.
 * @return {Promise<void>}
 */

// --- frontend/src/services/adminService.js::deleteRole (frontend/src/services/adminService.js)
/**!
 */

// --- getPermissions:Function (frontend/src/services/adminService.js)
/**!
 * @brief Fetches all available permissions.
 * @return {Promise<Array>}
 */

// --- frontend/src/services/adminService.js::getPermissions (frontend/src/services/adminService.js)
/**!
 */

// --- getLoggingConfig:Function (frontend/src/services/adminService.js)
/**!
 * @brief Fetches current logging configuration.
 * @return {Promise<Object>} - Logging config with level, task_log_level, enable_belief_state.
 */

// --- frontend/src/services/adminService.js::getLoggingConfig (frontend/src/services/adminService.js)
/**!
 */

// --- updateLoggingConfig:Function (frontend/src/services/adminService.js)
/**!
 * @brief Updates logging configuration.
 * @param {Object} configData - Logging config (level, task_log_level, enable_belief_state).
 * @return {Promise<Object>}
 */

// --- frontend/src/services/adminService.js::updateLoggingConfig (frontend/src/services/adminService.js)
/**!
 */

// --- GitUtils (frontend/src/services/git-utils.js)
/**!
 * @brief Shared utility functions extracted from GitManager.svelte.
 * @complexity 2
 */

// --- frontend/src/services/git-utils.js::normalizeEnvStage (frontend/src/services/git-utils.js)
/**!
 */

// --- frontend/src/services/git-utils.js::stageBadgeClass (frontend/src/services/git-utils.js)
/**!
 */

// --- frontend/src/services/git-utils.js::resolveCurrentEnvironmentId (frontend/src/services/git-utils.js)
/**!
 */

// --- frontend/src/services/git-utils.js::applyGitflowStageDefaults (frontend/src/services/git-utils.js)
/**!
 */

// --- frontend/src/services/git-utils.js::isNumericDashboardRef (frontend/src/services/git-utils.js)
/**!
 */

// --- frontend/src/services/git-utils.js::getSelectedConfig (frontend/src/services/git-utils.js)
/**!
 */

// --- frontend/src/services/git-utils.js::resolveDefaultConfig (frontend/src/services/git-utils.js)
/**!
 */

// --- frontend/src/services/git-utils.js::resolvePushProviderLabel (frontend/src/services/git-utils.js)
/**!
 */

// --- frontend/src/services/git-utils.js::extractHttpHost (frontend/src/services/git-utils.js)
/**!
 */

// --- frontend/src/services/git-utils.js::buildSuggestedRepoName (frontend/src/services/git-utils.js)
/**!
 */

// --- frontend/src/services/git-utils.js::tryParseJsonObject (frontend/src/services/git-utils.js)
/**!
 */

// --- frontend/src/services/git-utils.js::extractUnfinishedMergeContext (frontend/src/services/git-utils.js)
/**!
 */

// --- StorageService (frontend/src/services/storageService.js)
/**!
 * @brief Frontend API client for file storage management including list, upload, download, and delete operations.
 * @complexity 3
 * @layer Service
 */

// --- storageService:Module (frontend/src/services/storageService.js)
/**!
 * @brief Frontend API client for file storage management.
 * @layer Service
 * @semantics storage, api, client
 */

// --- getStorageAuthHeaders:Function (frontend/src/services/storageService.js)
/**!
 * @brief Returns headers with Authorization for storage API calls.
 * @note Unlike api.js getAuthHeaders, this doesn't set Content-Type
 * @return {Object} Headers object with Authorization if token exists.
 */

// --- frontend/src/services/storageService.js::getStorageAuthHeaders (frontend/src/services/storageService.js)
/**!
 */

// --- encodeStoragePath:Function (frontend/src/services/storageService.js)
/**!
 * @brief Encodes a storage-relative path preserving slash separators.
 * @param {string} path - Relative storage path.
 * @return {string} Encoded path safe for URL segments.
 */

// --- frontend/src/services/storageService.js::encodeStoragePath (frontend/src/services/storageService.js)
/**!
 */

// --- listFiles:Function (frontend/src/services/storageService.js)
/**!
 * @brief Fetches the list of files for a given category and subpath.
 * @param {string} [path] - Optional subpath filter.
 * @post Returns a promise resolving to an array of StoredFile objects.
 * @pre category and path should be valid strings if provided.
 * @return {Promise<Array>}
 */

// --- frontend/src/services/storageService.js::listFiles (frontend/src/services/storageService.js)
/**!
 * @post Returns a promise resolving to an array of StoredFile objects.
 * @pre category and path should be valid strings if provided.
 */

// --- uploadFile:Function (frontend/src/services/storageService.js)
/**!
 * @brief Uploads a file to the storage system.
 * @param {string} [path] - Target subpath.
 * @post Returns a promise resolving to the metadata of the uploaded file.
 * @pre file must be a valid File object; category must be specified.
 * @return {Promise<Object>}
 */

// --- frontend/src/services/storageService.js::uploadFile (frontend/src/services/storageService.js)
/**!
 * @post Returns a promise resolving to the metadata of the uploaded file.
 * @pre file must be a valid File object; category must be specified.
 */

// --- deleteFile:Function (frontend/src/services/storageService.js)
/**!
 * @brief Deletes a file or directory from storage.
 * @param {string} path - Relative path of the item.
 * @post The specified file or directory is removed from storage.
 * @pre category and path must identify an existing file or directory.
 * @return {Promise<void>}
 */

// --- frontend/src/services/storageService.js::deleteFile (frontend/src/services/storageService.js)
/**!
 * @post The specified file or directory is removed from storage.
 * @pre category and path must identify an existing file or directory.
 */

// --- downloadFileUrl:Function (frontend/src/services/storageService.js)
/**!
 * @brief Returns the URL for downloading a file.
 * @note Downloads use browser navigation, so auth is handled via cookies
 * @param {string} path - Relative path of the file.
 * @post Returns a valid API URL for file download.
 * @pre category and path must identify an existing file.
 * @return {string}
 */

// --- frontend/src/services/storageService.js::downloadFileUrl (frontend/src/services/storageService.js)
/**!
 * @post Returns a valid API URL for file download.
 * @pre category and path must identify an existing file.
 */

// --- downloadFile:Function (frontend/src/services/storageService.js)
/**!
 * @brief Downloads a file using authenticated fetch and saves it in browser.
 * @param {string} [filename] - Optional preferred filename.
 * @post Browser download is triggered or an Error is thrown.
 * @pre category/path identify an existing file and user has READ permission.
 * @return {Promise<void>}
 */

// --- frontend/src/services/storageService.js::downloadFile (frontend/src/services/storageService.js)
/**!
 * @post Browser download is triggered or an Error is thrown.
 * @pre category/path identify an existing file and user has READ permission.
 */

// --- TaskService (frontend/src/services/taskService.js)
/**!
 * @brief Service for Task Management API interactions: listing, fetching details, resuming, resolving, and clearing tasks.
 * @complexity 3
 * @layer Service
 */

// --- getTasks:Function (frontend/src/services/taskService.js)
/**!
 * @brief Fetch a list of tasks with pagination and optional status filter.
 * @post Returns a promise resolving to a list of tasks.
 * @pre limit and offset are numbers.
 */

// --- frontend/src/services/taskService.js::getTasks (frontend/src/services/taskService.js)
/**!
 */

// --- getTask:Function (frontend/src/services/taskService.js)
/**!
 * @brief Fetch details for a specific task.
 * @post Returns a promise resolving to task details.
 * @pre taskId must be provided.
 */

// --- frontend/src/services/taskService.js::getTask (frontend/src/services/taskService.js)
/**!
 */

// --- getTaskLogs:Function (frontend/src/services/taskService.js)
/**!
 * @brief Fetch logs for a specific task.
 * @post Returns a promise resolving to a list of log entries.
 * @pre taskId must be provided.
 */

// --- frontend/src/services/taskService.js::getTaskLogs (frontend/src/services/taskService.js)
/**!
 */

// --- resumeTask:Function (frontend/src/services/taskService.js)
/**!
 * @brief Resume a task that is awaiting input (e.g., passwords).
 * @post Returns a promise resolving to the updated task object.
 * @pre taskId and passwords must be provided.
 */

// --- frontend/src/services/taskService.js::resumeTask (frontend/src/services/taskService.js)
/**!
 */

// --- resolveTask:Function (frontend/src/services/taskService.js)
/**!
 * @brief Resolve a task that is awaiting mapping.
 * @post Returns a promise resolving to the updated task object.
 * @pre taskId and resolutionParams must be provided.
 */

// --- frontend/src/services/taskService.js::resolveTask (frontend/src/services/taskService.js)
/**!
 */

// --- clearTasks:Function (frontend/src/services/taskService.js)
/**!
 * @brief Clear tasks based on status.
 * @post Returns a promise that resolves when tasks are cleared.
 * @pre status is a string or null.
 */

// --- frontend/src/services/taskService.js::clearTasks (frontend/src/services/taskService.js)
/**!
 */

// --- ToolsService (frontend/src/services/toolsService.js)
/**!
 * @brief Service for generic Task API communication used by Tools — run tasks and poll status.
 * @complexity 2
 */

// --- runTask:Function (frontend/src/services/toolsService.js)
/**!
 * @brief Start a new task for a given plugin.
 * @post Returns a promise resolving to the task instance.
 * @pre pluginId and params must be provided.
 */

// --- frontend/src/services/toolsService.js::runTask (frontend/src/services/toolsService.js)
/**!
 */

// --- getTaskStatus:Function (frontend/src/services/toolsService.js)
/**!
 * @brief Fetch details for a specific task (to poll status or get result).
 * @post Returns a promise resolving to task details.
 * @pre taskId must be provided.
 */

// --- frontend/src/services/toolsService.js::getTaskStatus (frontend/src/services/toolsService.js)
/**!
 */

// --- BackupTypes (frontend/src/types/backup.ts)
/**!
 * @complexity 1
 */

// --- frontend/src/types/backup.ts::Backup (frontend/src/types/backup.ts)
/**!
 */

// --- BackupTypes:Module (frontend/src/types/backup.ts)
/**!
 */

// --- DashboardTypes (frontend/src/types/dashboard.ts)
/**!
 * @complexity 1
 */

// --- DashboardTypes:Module (frontend/src/types/dashboard.ts)
/**!
 * @brief TypeScript interfaces for Dashboard entities
 * @layer Domain
 */

// --- frontend/src/types/dashboard.ts::DashboardMetadata (frontend/src/types/dashboard.ts)
/**!
 */

// --- MaintenanceStoreTests (frontend/tests/maintenance-store.test.ts)
/**!
 * @brief Unit tests for MaintenanceStore runes-based store.
 * @complexity 2
 */

// --- MaintenanceComponentTests (frontend/tests/maintenance.test.ts)
/**!
 * @brief Component tests for MaintenanceEventsTable and DashboardMaintenanceBadge.
 * @complexity 2
 */

// --- MergeSpec (merge_spec.py)
/**!
 * @complexity 2
 * @layer Infra
 */

// --- merge_spec (merge_spec.py)
/**!
 * @complexity 2
 * @layer Infra
 */

// --- BuildOfflineDockerBundle (scripts/build_offline_docker_bundle.sh)
/**!
 * @brief Thin wrapper — delegates to ./build.sh bundle (.tar.xz output)
 * @complexity 1
 * @rationale Unified into build.sh to avoid confusion; kept for backward compat.
 */

// --- venv/lib/python3.13/site-packages/greenlet/TThreadState.hpp::ThreadState (venv/lib/python3.13/site-packages/greenlet/TThreadState.hpp)
/**!
 */

// --- venv/lib/python3.13/site-packages/greenlet/greenlet_exceptions.hpp::PyFatalError (venv/lib/python3.13/site-packages/greenlet/greenlet_exceptions.hpp)
/**!
 */

